aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php')
-rw-r--r--vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php982
1 files changed, 982 insertions, 0 deletions
diff --git a/vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php
new file mode 100644
index 00000000..02969f30
--- /dev/null
+++ b/vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php
@@ -0,0 +1,982 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Filesystem\Tests;
13
14use Symfony\Component\Filesystem\Filesystem;
15
16/**
17 * Test class for Filesystem.
18 */
19class FilesystemTest extends \PHPUnit_Framework_TestCase
20{
21 /**
22 * @var string $workspace
23 */
24 private $workspace = null;
25
26 /**
27 * @var \Symfony\Component\Filesystem\Filesystem $filesystem
28 */
29 private $filesystem = null;
30
31 private static $symlinkOnWindows = null;
32
33 public static function setUpBeforeClass()
34 {
35 if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
36 self::$symlinkOnWindows = true;
37 $originDir = tempnam(sys_get_temp_dir(), 'sl');
38 $targetDir = tempnam(sys_get_temp_dir(), 'sl');
39 if (true !== @symlink($originDir, $targetDir)) {
40 $report = error_get_last();
41 if (is_array($report) && false !== strpos($report['message'], 'error code(1314)')) {
42 self::$symlinkOnWindows = false;
43 }
44 }
45 }
46 }
47
48 public function setUp()
49 {
50 $this->filesystem = new Filesystem();
51 $this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000);
52 mkdir($this->workspace, 0777, true);
53 $this->workspace = realpath($this->workspace);
54 }
55
56 public function tearDown()
57 {
58 $this->clean($this->workspace);
59 }
60
61 /**
62 * @param string $file
63 */
64 private function clean($file)
65 {
66 if (is_dir($file) && !is_link($file)) {
67 $dir = new \FilesystemIterator($file);
68 foreach ($dir as $childFile) {
69 $this->clean($childFile);
70 }
71
72 rmdir($file);
73 } else {
74 unlink($file);
75 }
76 }
77
78 public function testCopyCreatesNewFile()
79 {
80 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
81 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
82
83 file_put_contents($sourceFilePath, 'SOURCE FILE');
84
85 $this->filesystem->copy($sourceFilePath, $targetFilePath);
86
87 $this->assertFileExists($targetFilePath);
88 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
89 }
90
91 /**
92 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
93 */
94 public function testCopyFails()
95 {
96 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
97 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
98
99 $this->filesystem->copy($sourceFilePath, $targetFilePath);
100 }
101
102 public function testCopyOverridesExistingFileIfModified()
103 {
104 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
105 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
106
107 file_put_contents($sourceFilePath, 'SOURCE FILE');
108 file_put_contents($targetFilePath, 'TARGET FILE');
109 touch($targetFilePath, time() - 1000);
110
111 $this->filesystem->copy($sourceFilePath, $targetFilePath);
112
113 $this->assertFileExists($targetFilePath);
114 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
115 }
116
117 public function testCopyDoesNotOverrideExistingFileByDefault()
118 {
119 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
120 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
121
122 file_put_contents($sourceFilePath, 'SOURCE FILE');
123 file_put_contents($targetFilePath, 'TARGET FILE');
124
125 // make sure both files have the same modification time
126 $modificationTime = time() - 1000;
127 touch($sourceFilePath, $modificationTime);
128 touch($targetFilePath, $modificationTime);
129
130 $this->filesystem->copy($sourceFilePath, $targetFilePath);
131
132 $this->assertFileExists($targetFilePath);
133 $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
134 }
135
136 public function testCopyOverridesExistingFileIfForced()
137 {
138 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
139 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
140
141 file_put_contents($sourceFilePath, 'SOURCE FILE');
142 file_put_contents($targetFilePath, 'TARGET FILE');
143
144 // make sure both files have the same modification time
145 $modificationTime = time() - 1000;
146 touch($sourceFilePath, $modificationTime);
147 touch($targetFilePath, $modificationTime);
148
149 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
150
151 $this->assertFileExists($targetFilePath);
152 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
153 }
154
155 public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
156 {
157 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
158 $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
159 $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
160
161 file_put_contents($sourceFilePath, 'SOURCE FILE');
162
163 $this->filesystem->copy($sourceFilePath, $targetFilePath);
164
165 $this->assertTrue(is_dir($targetFileDirectory));
166 $this->assertFileExists($targetFilePath);
167 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
168 }
169
170 public function testMkdirCreatesDirectoriesRecursively()
171 {
172 $directory = $this->workspace
173 .DIRECTORY_SEPARATOR.'directory'
174 .DIRECTORY_SEPARATOR.'sub_directory';
175
176 $this->filesystem->mkdir($directory);
177
178 $this->assertTrue(is_dir($directory));
179 }
180
181 public function testMkdirCreatesDirectoriesFromArray()
182 {
183 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
184 $directories = array(
185 $basePath.'1', $basePath.'2', $basePath.'3'
186 );
187
188 $this->filesystem->mkdir($directories);
189
190 $this->assertTrue(is_dir($basePath.'1'));
191 $this->assertTrue(is_dir($basePath.'2'));
192 $this->assertTrue(is_dir($basePath.'3'));
193 }
194
195 public function testMkdirCreatesDirectoriesFromTraversableObject()
196 {
197 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
198 $directories = new \ArrayObject(array(
199 $basePath.'1', $basePath.'2', $basePath.'3'
200 ));
201
202 $this->filesystem->mkdir($directories);
203
204 $this->assertTrue(is_dir($basePath.'1'));
205 $this->assertTrue(is_dir($basePath.'2'));
206 $this->assertTrue(is_dir($basePath.'3'));
207 }
208
209 /**
210 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
211 */
212 public function testMkdirCreatesDirectoriesFails()
213 {
214 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
215 $dir = $basePath.'2';
216
217 file_put_contents($dir, '');
218
219 $this->filesystem->mkdir($dir);
220 }
221
222 public function testTouchCreatesEmptyFile()
223 {
224 $file = $this->workspace.DIRECTORY_SEPARATOR.'1';
225
226 $this->filesystem->touch($file);
227
228 $this->assertFileExists($file);
229 }
230
231 /**
232 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
233 */
234 public function testTouchFails()
235 {
236 $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
237
238 $this->filesystem->touch($file);
239 }
240
241 public function testTouchCreatesEmptyFilesFromArray()
242 {
243 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
244 $files = array(
245 $basePath.'1', $basePath.'2', $basePath.'3'
246 );
247
248 $this->filesystem->touch($files);
249
250 $this->assertFileExists($basePath.'1');
251 $this->assertFileExists($basePath.'2');
252 $this->assertFileExists($basePath.'3');
253 }
254
255 public function testTouchCreatesEmptyFilesFromTraversableObject()
256 {
257 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
258 $files = new \ArrayObject(array(
259 $basePath.'1', $basePath.'2', $basePath.'3'
260 ));
261
262 $this->filesystem->touch($files);
263
264 $this->assertFileExists($basePath.'1');
265 $this->assertFileExists($basePath.'2');
266 $this->assertFileExists($basePath.'3');
267 }
268
269 public function testRemoveCleansFilesAndDirectoriesIteratively()
270 {
271 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
272
273 mkdir($basePath);
274 mkdir($basePath.'dir');
275 touch($basePath.'file');
276
277 $this->filesystem->remove($basePath);
278
279 $this->assertTrue(!is_dir($basePath));
280 }
281
282 public function testRemoveCleansArrayOfFilesAndDirectories()
283 {
284 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
285
286 mkdir($basePath.'dir');
287 touch($basePath.'file');
288
289 $files = array(
290 $basePath.'dir', $basePath.'file'
291 );
292
293 $this->filesystem->remove($files);
294
295 $this->assertTrue(!is_dir($basePath.'dir'));
296 $this->assertTrue(!is_file($basePath.'file'));
297 }
298
299 public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
300 {
301 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
302
303 mkdir($basePath.'dir');
304 touch($basePath.'file');
305
306 $files = new \ArrayObject(array(
307 $basePath.'dir', $basePath.'file'
308 ));
309
310 $this->filesystem->remove($files);
311
312 $this->assertTrue(!is_dir($basePath.'dir'));
313 $this->assertTrue(!is_file($basePath.'file'));
314 }
315
316 public function testRemoveIgnoresNonExistingFiles()
317 {
318 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
319
320 mkdir($basePath.'dir');
321
322 $files = array(
323 $basePath.'dir', $basePath.'file'
324 );
325
326 $this->filesystem->remove($files);
327
328 $this->assertTrue(!is_dir($basePath.'dir'));
329 }
330
331 public function testRemoveCleansInvalidLinks()
332 {
333 $this->markAsSkippedIfSymlinkIsMissing();
334
335 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
336
337 mkdir($basePath);
338 mkdir($basePath.'dir');
339 // create symlink to unexisting file
340 @symlink($basePath.'file', $basePath.'link');
341
342 $this->filesystem->remove($basePath);
343
344 $this->assertTrue(!is_dir($basePath));
345 }
346
347 public function testFilesExists()
348 {
349 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
350
351 mkdir($basePath);
352 touch($basePath.'file1');
353 mkdir($basePath.'folder');
354
355 $this->assertTrue($this->filesystem->exists($basePath.'file1'));
356 $this->assertTrue($this->filesystem->exists($basePath.'folder'));
357 }
358
359 public function testFilesExistsTraversableObjectOfFilesAndDirectories()
360 {
361 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
362
363 mkdir($basePath.'dir');
364 touch($basePath.'file');
365
366 $files = new \ArrayObject(array(
367 $basePath.'dir', $basePath.'file'
368 ));
369
370 $this->assertTrue($this->filesystem->exists($files));
371 }
372
373 public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
374 {
375 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
376
377 mkdir($basePath.'dir');
378 touch($basePath.'file');
379 touch($basePath.'file2');
380
381 $files = new \ArrayObject(array(
382 $basePath.'dir', $basePath.'file', $basePath.'file2'
383 ));
384
385 unlink($basePath.'file');
386
387 $this->assertFalse($this->filesystem->exists($files));
388 }
389
390 public function testInvalidFileNotExists()
391 {
392 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
393
394 $this->assertFalse($this->filesystem->exists($basePath.time()));
395 }
396
397 public function testChmodChangesFileMode()
398 {
399 $this->markAsSkippedIfChmodIsMissing();
400
401 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
402 mkdir($dir);
403 $file = $dir.DIRECTORY_SEPARATOR.'file';
404 touch($file);
405
406 $this->filesystem->chmod($file, 0400);
407 $this->filesystem->chmod($dir, 0753);
408
409 $this->assertEquals(753, $this->getFilePermissions($dir));
410 $this->assertEquals(400, $this->getFilePermissions($file));
411 }
412
413 public function testChmodWrongMod()
414 {
415 $this->markAsSkippedIfChmodIsMissing();
416
417 $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
418 touch($dir);
419
420 $this->filesystem->chmod($dir, 'Wrongmode');
421 }
422
423 public function testChmodRecursive()
424 {
425 $this->markAsSkippedIfChmodIsMissing();
426
427 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
428 mkdir($dir);
429 $file = $dir.DIRECTORY_SEPARATOR.'file';
430 touch($file);
431
432 $this->filesystem->chmod($file, 0400, 0000, true);
433 $this->filesystem->chmod($dir, 0753, 0000, true);
434
435 $this->assertEquals(753, $this->getFilePermissions($dir));
436 $this->assertEquals(753, $this->getFilePermissions($file));
437 }
438
439 public function testChmodAppliesUmask()
440 {
441 $this->markAsSkippedIfChmodIsMissing();
442
443 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
444 touch($file);
445
446 $this->filesystem->chmod($file, 0770, 0022);
447 $this->assertEquals(750, $this->getFilePermissions($file));
448 }
449
450 public function testChmodChangesModeOfArrayOfFiles()
451 {
452 $this->markAsSkippedIfChmodIsMissing();
453
454 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
455 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
456 $files = array($directory, $file);
457
458 mkdir($directory);
459 touch($file);
460
461 $this->filesystem->chmod($files, 0753);
462
463 $this->assertEquals(753, $this->getFilePermissions($file));
464 $this->assertEquals(753, $this->getFilePermissions($directory));
465 }
466
467 public function testChmodChangesModeOfTraversableFileObject()
468 {
469 $this->markAsSkippedIfChmodIsMissing();
470
471 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
472 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
473 $files = new \ArrayObject(array($directory, $file));
474
475 mkdir($directory);
476 touch($file);
477
478 $this->filesystem->chmod($files, 0753);
479
480 $this->assertEquals(753, $this->getFilePermissions($file));
481 $this->assertEquals(753, $this->getFilePermissions($directory));
482 }
483
484 public function testChown()
485 {
486 $this->markAsSkippedIfPosixIsMissing();
487
488 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
489 mkdir($dir);
490
491 $this->filesystem->chown($dir, $this->getFileOwner($dir));
492 }
493
494 public function testChownRecursive()
495 {
496 $this->markAsSkippedIfPosixIsMissing();
497
498 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
499 mkdir($dir);
500 $file = $dir.DIRECTORY_SEPARATOR.'file';
501 touch($file);
502
503 $this->filesystem->chown($dir, $this->getFileOwner($dir), true);
504 }
505
506 public function testChownSymlink()
507 {
508 $this->markAsSkippedIfSymlinkIsMissing();
509
510 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
511 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
512
513 touch($file);
514
515 $this->filesystem->symlink($file, $link);
516
517 $this->filesystem->chown($link, $this->getFileOwner($link));
518 }
519
520 /**
521 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
522 */
523 public function testChownSymlinkFails()
524 {
525 $this->markAsSkippedIfSymlinkIsMissing();
526
527 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
528 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
529
530 touch($file);
531
532 $this->filesystem->symlink($file, $link);
533
534 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
535 }
536
537 /**
538 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
539 */
540 public function testChownFail()
541 {
542 $this->markAsSkippedIfPosixIsMissing();
543
544 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
545 mkdir($dir);
546
547 $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
548 }
549
550 public function testChgrp()
551 {
552 $this->markAsSkippedIfPosixIsMissing();
553
554 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
555 mkdir($dir);
556
557 $this->filesystem->chgrp($dir, $this->getFileGroup($dir));
558 }
559
560 public function testChgrpRecursive()
561 {
562 $this->markAsSkippedIfPosixIsMissing();
563
564 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
565 mkdir($dir);
566 $file = $dir.DIRECTORY_SEPARATOR.'file';
567 touch($file);
568
569 $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
570 }
571
572 public function testChgrpSymlink()
573 {
574 $this->markAsSkippedIfSymlinkIsMissing();
575
576 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
577 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
578
579 touch($file);
580
581 $this->filesystem->symlink($file, $link);
582
583 $this->filesystem->chgrp($link, $this->getFileGroup($link));
584 }
585
586 /**
587 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
588 */
589 public function testChgrpSymlinkFails()
590 {
591 $this->markAsSkippedIfSymlinkIsMissing();
592
593 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
594 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
595
596 touch($file);
597
598 $this->filesystem->symlink($file, $link);
599
600 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
601 }
602
603 /**
604 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
605 */
606 public function testChgrpFail()
607 {
608 $this->markAsSkippedIfPosixIsMissing();
609
610 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
611 mkdir($dir);
612
613 $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
614 }
615
616 public function testRename()
617 {
618 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
619 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
620 touch($file);
621
622 $this->filesystem->rename($file, $newPath);
623
624 $this->assertFileNotExists($file);
625 $this->assertFileExists($newPath);
626 }
627
628 /**
629 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
630 */
631 public function testRenameThrowsExceptionIfTargetAlreadyExists()
632 {
633 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
634 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
635
636 touch($file);
637 touch($newPath);
638
639 $this->filesystem->rename($file, $newPath);
640 }
641
642 public function testRenameOverwritesTheTargetIfItAlreadyExists()
643 {
644 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
645 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
646
647 touch($file);
648 touch($newPath);
649
650 $this->filesystem->rename($file, $newPath, true);
651
652 $this->assertFileNotExists($file);
653 $this->assertFileExists($newPath);
654 }
655
656 /**
657 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
658 */
659 public function testRenameThrowsExceptionOnError()
660 {
661 $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid();
662 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
663
664 $this->filesystem->rename($file, $newPath);
665 }
666
667 public function testSymlink()
668 {
669 $this->markAsSkippedIfSymlinkIsMissing();
670
671 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
672 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
673
674 touch($file);
675
676 $this->filesystem->symlink($file, $link);
677
678 $this->assertTrue(is_link($link));
679 $this->assertEquals($file, readlink($link));
680 }
681
682 /**
683 * @depends testSymlink
684 */
685 public function testRemoveSymlink()
686 {
687 $this->markAsSkippedIfSymlinkIsMissing();
688
689 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
690
691 $this->filesystem->remove($link);
692
693 $this->assertTrue(!is_link($link));
694 }
695
696 public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
697 {
698 $this->markAsSkippedIfSymlinkIsMissing();
699
700 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
701 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
702
703 touch($file);
704 symlink($this->workspace, $link);
705
706 $this->filesystem->symlink($file, $link);
707
708 $this->assertTrue(is_link($link));
709 $this->assertEquals($file, readlink($link));
710 }
711
712 public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
713 {
714 $this->markAsSkippedIfSymlinkIsMissing();
715
716 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
717 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
718
719 touch($file);
720 symlink($file, $link);
721
722 $this->filesystem->symlink($file, $link);
723
724 $this->assertTrue(is_link($link));
725 $this->assertEquals($file, readlink($link));
726 }
727
728 public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
729 {
730 $this->markAsSkippedIfSymlinkIsMissing();
731
732 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
733 $link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
734 $link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
735
736 touch($file);
737
738 $this->filesystem->symlink($file, $link1);
739 $this->filesystem->symlink($file, $link2);
740
741 $this->assertTrue(is_link($link1));
742 $this->assertEquals($file, readlink($link1));
743 $this->assertTrue(is_link($link2));
744 $this->assertEquals($file, readlink($link2));
745 }
746
747 /**
748 * @dataProvider providePathsForMakePathRelative
749 */
750 public function testMakePathRelative($endPath, $startPath, $expectedPath)
751 {
752 $path = $this->filesystem->makePathRelative($endPath, $startPath);
753
754 $this->assertEquals($expectedPath, $path);
755 }
756
757 /**
758 * @return array
759 */
760 public function providePathsForMakePathRelative()
761 {
762 $paths = array(
763 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
764 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
765 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
766 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
767 array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
768 array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
769 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
770 array('/aa/bb', '/aa/bb', './'),
771 array('/aa/bb', '/aa/bb/', './'),
772 array('/aa/bb/', '/aa/bb', './'),
773 array('/aa/bb/', '/aa/bb/', './'),
774 array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
775 array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
776 array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
777 array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
778 array('/aa/bb/cc', '/aa', 'bb/cc/'),
779 array('/aa/bb/cc', '/aa/', 'bb/cc/'),
780 array('/aa/bb/cc/', '/aa', 'bb/cc/'),
781 array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
782 array('/a/aab/bb', '/a/aa', '../aab/bb/'),
783 array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
784 array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
785 array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
786 );
787
788 if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
789 $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
790 }
791
792 return $paths;
793 }
794
795 public function testMirrorCopiesFilesAndDirectoriesRecursively()
796 {
797 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
798 $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
799 $file1 = $directory.'file1';
800 $file2 = $sourcePath.'file2';
801
802 mkdir($sourcePath);
803 mkdir($directory);
804 file_put_contents($file1, 'FILE1');
805 file_put_contents($file2, 'FILE2');
806
807 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
808
809 $this->filesystem->mirror($sourcePath, $targetPath);
810
811 $this->assertTrue(is_dir($targetPath));
812 $this->assertTrue(is_dir($targetPath.'directory'));
813 $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
814 $this->assertFileEquals($file2, $targetPath.'file2');
815
816 $this->filesystem->remove($file1);
817
818 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
819 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
820
821 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
822 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
823
824 file_put_contents($file1, 'FILE1');
825
826 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
827 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
828
829 $this->filesystem->remove($directory);
830 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
831 $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
832 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
833 }
834
835 public function testMirrorCopiesLinks()
836 {
837 $this->markAsSkippedIfSymlinkIsMissing();
838
839 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
840
841 mkdir($sourcePath);
842 file_put_contents($sourcePath.'file1', 'FILE1');
843 symlink($sourcePath.'file1', $sourcePath.'link1');
844
845 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
846
847 $this->filesystem->mirror($sourcePath, $targetPath);
848
849 $this->assertTrue(is_dir($targetPath));
850 $this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
851 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
852 }
853
854 public function testMirrorCopiesLinkedDirectoryContents()
855 {
856 $this->markAsSkippedIfSymlinkIsMissing();
857
858 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
859
860 mkdir($sourcePath.'nested/', 0777, true);
861 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
862 // Note: We symlink directory, not file
863 symlink($sourcePath.'nested', $sourcePath.'link1');
864
865 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
866
867 $this->filesystem->mirror($sourcePath, $targetPath);
868
869 $this->assertTrue(is_dir($targetPath));
870 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
871 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
872 }
873
874 /**
875 * @dataProvider providePathsForIsAbsolutePath
876 */
877 public function testIsAbsolutePath($path, $expectedResult)
878 {
879 $result = $this->filesystem->isAbsolutePath($path);
880
881 $this->assertEquals($expectedResult, $result);
882 }
883
884 /**
885 * @return array
886 */
887 public function providePathsForIsAbsolutePath()
888 {
889 return array(
890 array('/var/lib', true),
891 array('c:\\\\var\\lib', true),
892 array('\\var\\lib', true),
893 array('var/lib', false),
894 array('../var/lib', false),
895 array('', false),
896 array(null, false)
897 );
898 }
899
900 public function testDumpFile()
901 {
902 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
903
904 $this->filesystem->dumpFile($filename, 'bar', 0753);
905
906 $this->assertFileExists($filename);
907 $this->assertSame('bar', file_get_contents($filename));
908
909 // skip mode check on windows
910 if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
911 $this->assertEquals(753, $this->getFilePermissions($filename));
912 }
913 }
914
915 public function testDumpFileOverwritesAnExistingFile()
916 {
917 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
918 file_put_contents($filename, 'FOO BAR');
919
920 $this->filesystem->dumpFile($filename, 'bar');
921
922 $this->assertFileExists($filename);
923 $this->assertSame('bar', file_get_contents($filename));
924 }
925
926 /**
927 * Returns file permissions as three digits (i.e. 755)
928 *
929 * @param string $filePath
930 *
931 * @return integer
932 */
933 private function getFilePermissions($filePath)
934 {
935 return (int) substr(sprintf('%o', fileperms($filePath)), -3);
936 }
937
938 private function getFileOwner($filepath)
939 {
940 $this->markAsSkippedIfPosixIsMissing();
941
942 $infos = stat($filepath);
943 if ($datas = posix_getpwuid($infos['uid'])) {
944 return $datas['name'];
945 }
946 }
947
948 private function getFileGroup($filepath)
949 {
950 $this->markAsSkippedIfPosixIsMissing();
951
952 $infos = stat($filepath);
953 if ($datas = posix_getgrgid($infos['gid'])) {
954 return $datas['name'];
955 }
956 }
957
958 private function markAsSkippedIfSymlinkIsMissing()
959 {
960 if (!function_exists('symlink')) {
961 $this->markTestSkipped('symlink is not supported');
962 }
963
964 if (defined('PHP_WINDOWS_VERSION_MAJOR') && false === self::$symlinkOnWindows) {
965 $this->markTestSkipped('symlink requires "Create symbolic links" privilege on windows');
966 }
967 }
968
969 private function markAsSkippedIfChmodIsMissing()
970 {
971 if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
972 $this->markTestSkipped('chmod is not supported on windows');
973 }
974 }
975
976 private function markAsSkippedIfPosixIsMissing()
977 {
978 if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('posix_isatty')) {
979 $this->markTestSkipped('Posix is not supported');
980 }
981 }
982}