4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Filesystem\Tests;
15 * Test class for Filesystem.
17 class FilesystemTest extends FilesystemTestCase
19 public function testCopyCreatesNewFile()
21 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
22 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
24 file_put_contents($sourceFilePath, 'SOURCE FILE');
26 $this->filesystem->copy($sourceFilePath, $targetFilePath);
28 $this->assertFileExists($targetFilePath);
29 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
33 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
35 public function testCopyFails()
37 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
38 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
40 $this->filesystem->copy($sourceFilePath, $targetFilePath);
44 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
46 public function testCopyUnreadableFileFails()
48 // skip test on Windows; PHP can't easily set file as unreadable on Windows
49 if ('\\' === DIRECTORY_SEPARATOR) {
50 $this->markTestSkipped('This test cannot run on Windows.');
53 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
54 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
56 file_put_contents($sourceFilePath, 'SOURCE FILE');
58 // make sure target cannot be read
59 $this->filesystem->chmod($sourceFilePath, 0222);
61 $this->filesystem->copy($sourceFilePath, $targetFilePath);
64 public function testCopyOverridesExistingFileIfModified()
66 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
67 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
69 file_put_contents($sourceFilePath, 'SOURCE FILE');
70 file_put_contents($targetFilePath, 'TARGET FILE');
71 touch($targetFilePath, time() - 1000);
73 $this->filesystem->copy($sourceFilePath, $targetFilePath);
75 $this->assertFileExists($targetFilePath);
76 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
79 public function testCopyDoesNotOverrideExistingFileByDefault()
81 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
82 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
84 file_put_contents($sourceFilePath, 'SOURCE FILE');
85 file_put_contents($targetFilePath, 'TARGET FILE');
87 // make sure both files have the same modification time
88 $modificationTime = time() - 1000;
89 touch($sourceFilePath, $modificationTime);
90 touch($targetFilePath, $modificationTime);
92 $this->filesystem->copy($sourceFilePath, $targetFilePath);
94 $this->assertFileExists($targetFilePath);
95 $this->assertStringEqualsFile($targetFilePath, 'TARGET FILE');
98 public function testCopyOverridesExistingFileIfForced()
100 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
101 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
103 file_put_contents($sourceFilePath, 'SOURCE FILE');
104 file_put_contents($targetFilePath, 'TARGET FILE');
106 // make sure both files have the same modification time
107 $modificationTime = time() - 1000;
108 touch($sourceFilePath, $modificationTime);
109 touch($targetFilePath, $modificationTime);
111 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
113 $this->assertFileExists($targetFilePath);
114 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
118 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
120 public function testCopyWithOverrideWithReadOnlyTargetFails()
122 // skip test on Windows; PHP can't easily set file as unwritable on Windows
123 if ('\\' === DIRECTORY_SEPARATOR) {
124 $this->markTestSkipped('This test cannot run on Windows.');
127 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
128 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
130 file_put_contents($sourceFilePath, 'SOURCE FILE');
131 file_put_contents($targetFilePath, 'TARGET FILE');
133 // make sure both files have the same modification time
134 $modificationTime = time() - 1000;
135 touch($sourceFilePath, $modificationTime);
136 touch($targetFilePath, $modificationTime);
138 // make sure target is read-only
139 $this->filesystem->chmod($targetFilePath, 0444);
141 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
144 public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
146 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
147 $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
148 $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
150 file_put_contents($sourceFilePath, 'SOURCE FILE');
152 $this->filesystem->copy($sourceFilePath, $targetFilePath);
154 $this->assertTrue(is_dir($targetFileDirectory));
155 $this->assertFileExists($targetFilePath);
156 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
162 public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy()
164 $sourceFilePath = 'http://symfony.com/images/common/logo/logo_symfony_header.png';
165 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
167 file_put_contents($targetFilePath, 'TARGET FILE');
169 $this->filesystem->copy($sourceFilePath, $targetFilePath, false);
171 $this->assertFileExists($targetFilePath);
172 $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath));
175 public function testMkdirCreatesDirectoriesRecursively()
177 $directory = $this->workspace
178 .DIRECTORY_SEPARATOR.'directory'
179 .DIRECTORY_SEPARATOR.'sub_directory';
181 $this->filesystem->mkdir($directory);
183 $this->assertTrue(is_dir($directory));
186 public function testMkdirCreatesDirectoriesFromArray()
188 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
189 $directories = array(
190 $basePath.'1', $basePath.'2', $basePath.'3',
193 $this->filesystem->mkdir($directories);
195 $this->assertTrue(is_dir($basePath.'1'));
196 $this->assertTrue(is_dir($basePath.'2'));
197 $this->assertTrue(is_dir($basePath.'3'));
200 public function testMkdirCreatesDirectoriesFromTraversableObject()
202 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
203 $directories = new \ArrayObject(array(
204 $basePath.'1', $basePath.'2', $basePath.'3',
207 $this->filesystem->mkdir($directories);
209 $this->assertTrue(is_dir($basePath.'1'));
210 $this->assertTrue(is_dir($basePath.'2'));
211 $this->assertTrue(is_dir($basePath.'3'));
215 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
217 public function testMkdirCreatesDirectoriesFails()
219 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
220 $dir = $basePath.'2';
222 file_put_contents($dir, '');
224 $this->filesystem->mkdir($dir);
227 public function testTouchCreatesEmptyFile()
229 $file = $this->workspace.DIRECTORY_SEPARATOR.'1';
231 $this->filesystem->touch($file);
233 $this->assertFileExists($file);
237 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
239 public function testTouchFails()
241 $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
243 $this->filesystem->touch($file);
246 public function testTouchCreatesEmptyFilesFromArray()
248 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
250 $basePath.'1', $basePath.'2', $basePath.'3',
253 $this->filesystem->touch($files);
255 $this->assertFileExists($basePath.'1');
256 $this->assertFileExists($basePath.'2');
257 $this->assertFileExists($basePath.'3');
260 public function testTouchCreatesEmptyFilesFromTraversableObject()
262 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
263 $files = new \ArrayObject(array(
264 $basePath.'1', $basePath.'2', $basePath.'3',
267 $this->filesystem->touch($files);
269 $this->assertFileExists($basePath.'1');
270 $this->assertFileExists($basePath.'2');
271 $this->assertFileExists($basePath.'3');
274 public function testRemoveCleansFilesAndDirectoriesIteratively()
276 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
279 mkdir($basePath.'dir');
280 touch($basePath.'file');
282 $this->filesystem->remove($basePath);
284 $this->assertFileNotExists($basePath);
287 public function testRemoveCleansArrayOfFilesAndDirectories()
289 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
291 mkdir($basePath.'dir');
292 touch($basePath.'file');
295 $basePath.'dir', $basePath.'file',
298 $this->filesystem->remove($files);
300 $this->assertFileNotExists($basePath.'dir');
301 $this->assertFileNotExists($basePath.'file');
304 public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
306 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
308 mkdir($basePath.'dir');
309 touch($basePath.'file');
311 $files = new \ArrayObject(array(
312 $basePath.'dir', $basePath.'file',
315 $this->filesystem->remove($files);
317 $this->assertFileNotExists($basePath.'dir');
318 $this->assertFileNotExists($basePath.'file');
321 public function testRemoveIgnoresNonExistingFiles()
323 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
325 mkdir($basePath.'dir');
328 $basePath.'dir', $basePath.'file',
331 $this->filesystem->remove($files);
333 $this->assertFileNotExists($basePath.'dir');
336 public function testRemoveCleansInvalidLinks()
338 $this->markAsSkippedIfSymlinkIsMissing();
340 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
343 mkdir($basePath.'dir');
344 // create symlink to nonexistent file
345 @symlink($basePath.'file', $basePath.'file-link');
347 // create symlink to dir using trailing forward slash
348 $this->filesystem->symlink($basePath.'dir/', $basePath.'dir-link');
349 $this->assertTrue(is_dir($basePath.'dir-link'));
351 // create symlink to nonexistent dir
352 rmdir($basePath.'dir');
353 $this->assertFalse('\\' === DIRECTORY_SEPARATOR ? @readlink($basePath.'dir-link') : is_dir($basePath.'dir-link'));
355 $this->filesystem->remove($basePath);
357 $this->assertFileNotExists($basePath);
360 public function testFilesExists()
362 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
365 touch($basePath.'file1');
366 mkdir($basePath.'folder');
368 $this->assertTrue($this->filesystem->exists($basePath.'file1'));
369 $this->assertTrue($this->filesystem->exists($basePath.'folder'));
373 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
375 public function testFilesExistsFails()
377 if ('\\' !== DIRECTORY_SEPARATOR) {
378 $this->markTestSkipped('Long file names are an issue on Windows');
380 $basePath = $this->workspace.'\\directory\\';
381 $maxPathLength = PHP_MAXPATHLEN - 2;
386 $file = str_repeat('T', $maxPathLength - strlen($basePath) + 1);
387 $path = $basePath.$file;
388 exec('TYPE NUL >>'.$file); // equivalent of touch, we can not use the php touch() here because it suffers from the same limitation
389 $this->longPathNamesWindows[] = $path; // save this so we can clean up later
391 $this->filesystem->exists($path);
394 public function testFilesExistsTraversableObjectOfFilesAndDirectories()
396 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
398 mkdir($basePath.'dir');
399 touch($basePath.'file');
401 $files = new \ArrayObject(array(
402 $basePath.'dir', $basePath.'file',
405 $this->assertTrue($this->filesystem->exists($files));
408 public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
410 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
412 mkdir($basePath.'dir');
413 touch($basePath.'file');
414 touch($basePath.'file2');
416 $files = new \ArrayObject(array(
417 $basePath.'dir', $basePath.'file', $basePath.'file2',
420 unlink($basePath.'file');
422 $this->assertFalse($this->filesystem->exists($files));
425 public function testInvalidFileNotExists()
427 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
429 $this->assertFalse($this->filesystem->exists($basePath.time()));
432 public function testChmodChangesFileMode()
434 $this->markAsSkippedIfChmodIsMissing();
436 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
438 $file = $dir.DIRECTORY_SEPARATOR.'file';
441 $this->filesystem->chmod($file, 0400);
442 $this->filesystem->chmod($dir, 0753);
444 $this->assertFilePermissions(753, $dir);
445 $this->assertFilePermissions(400, $file);
448 public function testChmodWithWrongModLeavesPreviousPermissionsUntouched()
450 $this->markAsSkippedIfChmodIsMissing();
452 if (defined('HHVM_VERSION')) {
453 $this->markTestSkipped('chmod() changes permissions even when passing invalid modes on HHVM');
456 $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
459 $permissions = fileperms($dir);
461 $this->filesystem->chmod($dir, 'Wrongmode');
463 $this->assertSame($permissions, fileperms($dir));
466 public function testChmodRecursive()
468 $this->markAsSkippedIfChmodIsMissing();
470 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
472 $file = $dir.DIRECTORY_SEPARATOR.'file';
475 $this->filesystem->chmod($file, 0400, 0000, true);
476 $this->filesystem->chmod($dir, 0753, 0000, true);
478 $this->assertFilePermissions(753, $dir);
479 $this->assertFilePermissions(753, $file);
482 public function testChmodAppliesUmask()
484 $this->markAsSkippedIfChmodIsMissing();
486 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
489 $this->filesystem->chmod($file, 0770, 0022);
490 $this->assertFilePermissions(750, $file);
493 public function testChmodChangesModeOfArrayOfFiles()
495 $this->markAsSkippedIfChmodIsMissing();
497 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
498 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
499 $files = array($directory, $file);
504 $this->filesystem->chmod($files, 0753);
506 $this->assertFilePermissions(753, $file);
507 $this->assertFilePermissions(753, $directory);
510 public function testChmodChangesModeOfTraversableFileObject()
512 $this->markAsSkippedIfChmodIsMissing();
514 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
515 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
516 $files = new \ArrayObject(array($directory, $file));
521 $this->filesystem->chmod($files, 0753);
523 $this->assertFilePermissions(753, $file);
524 $this->assertFilePermissions(753, $directory);
527 public function testChmodChangesZeroModeOnSubdirectoriesOnRecursive()
529 $this->markAsSkippedIfChmodIsMissing();
531 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
532 $subdirectory = $directory.DIRECTORY_SEPARATOR.'subdirectory';
535 mkdir($subdirectory);
536 chmod($subdirectory, 0000);
538 $this->filesystem->chmod($directory, 0753, 0000, true);
540 $this->assertFilePermissions(753, $subdirectory);
543 public function testChown()
545 $this->markAsSkippedIfPosixIsMissing();
547 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
550 $owner = $this->getFileOwner($dir);
551 $this->filesystem->chown($dir, $owner);
553 $this->assertSame($owner, $this->getFileOwner($dir));
556 public function testChownRecursive()
558 $this->markAsSkippedIfPosixIsMissing();
560 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
562 $file = $dir.DIRECTORY_SEPARATOR.'file';
565 $owner = $this->getFileOwner($dir);
566 $this->filesystem->chown($dir, $owner, true);
568 $this->assertSame($owner, $this->getFileOwner($file));
571 public function testChownSymlink()
573 $this->markAsSkippedIfSymlinkIsMissing();
575 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
576 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
580 $this->filesystem->symlink($file, $link);
582 $owner = $this->getFileOwner($link);
583 $this->filesystem->chown($link, $owner);
585 $this->assertSame($owner, $this->getFileOwner($link));
588 public function testChownLink()
590 $this->markAsSkippedIfLinkIsMissing();
592 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
593 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
597 $this->filesystem->hardlink($file, $link);
599 $owner = $this->getFileOwner($link);
600 $this->filesystem->chown($link, $owner);
602 $this->assertSame($owner, $this->getFileOwner($link));
606 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
608 public function testChownSymlinkFails()
610 $this->markAsSkippedIfSymlinkIsMissing();
612 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
613 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
617 $this->filesystem->symlink($file, $link);
619 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
623 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
625 public function testChownLinkFails()
627 $this->markAsSkippedIfLinkIsMissing();
629 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
630 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
634 $this->filesystem->hardlink($file, $link);
636 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
640 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
642 public function testChownFail()
644 $this->markAsSkippedIfPosixIsMissing();
646 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
649 $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
652 public function testChgrp()
654 $this->markAsSkippedIfPosixIsMissing();
656 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
659 $group = $this->getFileGroup($dir);
660 $this->filesystem->chgrp($dir, $group);
662 $this->assertSame($group, $this->getFileGroup($dir));
665 public function testChgrpRecursive()
667 $this->markAsSkippedIfPosixIsMissing();
669 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
671 $file = $dir.DIRECTORY_SEPARATOR.'file';
674 $group = $this->getFileGroup($dir);
675 $this->filesystem->chgrp($dir, $group, true);
677 $this->assertSame($group, $this->getFileGroup($file));
680 public function testChgrpSymlink()
682 $this->markAsSkippedIfSymlinkIsMissing();
684 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
685 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
689 $this->filesystem->symlink($file, $link);
691 $group = $this->getFileGroup($link);
692 $this->filesystem->chgrp($link, $group);
694 $this->assertSame($group, $this->getFileGroup($link));
697 public function testChgrpLink()
699 $this->markAsSkippedIfLinkIsMissing();
701 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
702 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
706 $this->filesystem->hardlink($file, $link);
708 $group = $this->getFileGroup($link);
709 $this->filesystem->chgrp($link, $group);
711 $this->assertSame($group, $this->getFileGroup($link));
715 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
717 public function testChgrpSymlinkFails()
719 $this->markAsSkippedIfSymlinkIsMissing();
721 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
722 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
726 $this->filesystem->symlink($file, $link);
728 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
732 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
734 public function testChgrpLinkFails()
736 $this->markAsSkippedIfLinkIsMissing();
738 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
739 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
743 $this->filesystem->hardlink($file, $link);
745 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
749 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
751 public function testChgrpFail()
753 $this->markAsSkippedIfPosixIsMissing();
755 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
758 $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
761 public function testRename()
763 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
764 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
767 $this->filesystem->rename($file, $newPath);
769 $this->assertFileNotExists($file);
770 $this->assertFileExists($newPath);
774 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
776 public function testRenameThrowsExceptionIfTargetAlreadyExists()
778 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
779 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
784 $this->filesystem->rename($file, $newPath);
787 public function testRenameOverwritesTheTargetIfItAlreadyExists()
789 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
790 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
795 $this->filesystem->rename($file, $newPath, true);
797 $this->assertFileNotExists($file);
798 $this->assertFileExists($newPath);
802 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
804 public function testRenameThrowsExceptionOnError()
806 $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid('fs_test_', true);
807 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
809 $this->filesystem->rename($file, $newPath);
812 public function testSymlink()
814 if ('\\' === DIRECTORY_SEPARATOR) {
815 $this->markTestSkipped('Windows does not support creating "broken" symlinks');
818 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
819 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
821 // $file does not exists right now: creating "broken" links is a wanted feature
822 $this->filesystem->symlink($file, $link);
824 $this->assertTrue(is_link($link));
826 // Create the linked file AFTER creating the link
829 $this->assertEquals($file, readlink($link));
833 * @depends testSymlink
835 public function testRemoveSymlink()
837 $this->markAsSkippedIfSymlinkIsMissing();
839 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
841 $this->filesystem->remove($link);
843 $this->assertFalse(is_link($link));
844 $this->assertFalse(is_file($link));
845 $this->assertFalse(is_dir($link));
848 public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
850 $this->markAsSkippedIfSymlinkIsMissing();
852 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
853 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
856 symlink($this->workspace, $link);
858 $this->filesystem->symlink($file, $link);
860 $this->assertTrue(is_link($link));
861 $this->assertEquals($file, readlink($link));
864 public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
866 $this->markAsSkippedIfSymlinkIsMissing();
868 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
869 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
872 symlink($file, $link);
874 $this->filesystem->symlink($file, $link);
876 $this->assertTrue(is_link($link));
877 $this->assertEquals($file, readlink($link));
880 public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
882 $this->markAsSkippedIfSymlinkIsMissing();
884 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
885 $link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
886 $link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
890 $this->filesystem->symlink($file, $link1);
891 $this->filesystem->symlink($file, $link2);
893 $this->assertTrue(is_link($link1));
894 $this->assertEquals($file, readlink($link1));
895 $this->assertTrue(is_link($link2));
896 $this->assertEquals($file, readlink($link2));
899 public function testLink()
901 $this->markAsSkippedIfLinkIsMissing();
903 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
904 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
907 $this->filesystem->hardlink($file, $link);
909 $this->assertTrue(is_file($link));
910 $this->assertEquals(fileinode($file), fileinode($link));
916 public function testRemoveLink()
918 $this->markAsSkippedIfLinkIsMissing();
920 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
922 $this->filesystem->remove($link);
924 $this->assertTrue(!is_file($link));
927 public function testLinkIsOverwrittenIfPointsToDifferentTarget()
929 $this->markAsSkippedIfLinkIsMissing();
931 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
932 $file2 = $this->workspace.DIRECTORY_SEPARATOR.'file2';
933 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
939 $this->filesystem->hardlink($file, $link);
941 $this->assertTrue(is_file($link));
942 $this->assertEquals(fileinode($file), fileinode($link));
945 public function testLinkIsNotOverwrittenIfAlreadyCreated()
947 $this->markAsSkippedIfLinkIsMissing();
949 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
950 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
955 $this->filesystem->hardlink($file, $link);
957 $this->assertTrue(is_file($link));
958 $this->assertEquals(fileinode($file), fileinode($link));
961 public function testLinkWithSeveralTargets()
963 $this->markAsSkippedIfLinkIsMissing();
965 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
966 $link1 = $this->workspace.DIRECTORY_SEPARATOR.'link';
967 $link2 = $this->workspace.DIRECTORY_SEPARATOR.'link2';
971 $this->filesystem->hardlink($file, array($link1, $link2));
973 $this->assertTrue(is_file($link1));
974 $this->assertEquals(fileinode($file), fileinode($link1));
975 $this->assertTrue(is_file($link2));
976 $this->assertEquals(fileinode($file), fileinode($link2));
979 public function testLinkWithSameTarget()
981 $this->markAsSkippedIfLinkIsMissing();
983 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
984 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
988 // practically same as testLinkIsNotOverwrittenIfAlreadyCreated
989 $this->filesystem->hardlink($file, array($link, $link));
991 $this->assertTrue(is_file($link));
992 $this->assertEquals(fileinode($file), fileinode($link));
995 public function testReadRelativeLink()
997 $this->markAsSkippedIfSymlinkIsMissing();
999 if ('\\' === DIRECTORY_SEPARATOR) {
1000 $this->markTestSkipped('Relative symbolic links are not supported on Windows');
1003 $file = $this->workspace.'/file';
1004 $link1 = $this->workspace.'/dir/link';
1005 $link2 = $this->workspace.'/dir/link2';
1008 $this->filesystem->symlink('../file', $link1);
1009 $this->filesystem->symlink('link', $link2);
1011 $this->assertEquals($this->normalize('../file'), $this->filesystem->readlink($link1));
1012 $this->assertEquals('link', $this->filesystem->readlink($link2));
1013 $this->assertEquals($file, $this->filesystem->readlink($link1, true));
1014 $this->assertEquals($file, $this->filesystem->readlink($link2, true));
1015 $this->assertEquals($file, $this->filesystem->readlink($file, true));
1018 public function testReadAbsoluteLink()
1020 $this->markAsSkippedIfSymlinkIsMissing();
1022 $file = $this->normalize($this->workspace.'/file');
1023 $link1 = $this->normalize($this->workspace.'/dir/link');
1024 $link2 = $this->normalize($this->workspace.'/dir/link2');
1027 $this->filesystem->symlink($file, $link1);
1028 $this->filesystem->symlink($link1, $link2);
1030 $this->assertEquals($file, $this->filesystem->readlink($link1));
1031 $this->assertEquals($link1, $this->filesystem->readlink($link2));
1032 $this->assertEquals($file, $this->filesystem->readlink($link1, true));
1033 $this->assertEquals($file, $this->filesystem->readlink($link2, true));
1034 $this->assertEquals($file, $this->filesystem->readlink($file, true));
1037 public function testReadBrokenLink()
1039 $this->markAsSkippedIfSymlinkIsMissing();
1041 if ('\\' === DIRECTORY_SEPARATOR) {
1042 $this->markTestSkipped('Windows does not support creating "broken" symlinks');
1045 $file = $this->workspace.'/file';
1046 $link = $this->workspace.'/link';
1048 $this->filesystem->symlink($file, $link);
1050 $this->assertEquals($file, $this->filesystem->readlink($link));
1051 $this->assertNull($this->filesystem->readlink($link, true));
1054 $this->assertEquals($file, $this->filesystem->readlink($link, true));
1057 public function testReadLinkDefaultPathDoesNotExist()
1059 $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'/invalid')));
1062 public function testReadLinkDefaultPathNotLink()
1064 $file = $this->normalize($this->workspace.'/file');
1067 $this->assertNull($this->filesystem->readlink($file));
1070 public function testReadLinkCanonicalizePath()
1072 $this->markAsSkippedIfSymlinkIsMissing();
1074 $file = $this->normalize($this->workspace.'/file');
1075 mkdir($this->normalize($this->workspace.'/dir'));
1078 $this->assertEquals($file, $this->filesystem->readlink($this->normalize($this->workspace.'/dir/../file'), true));
1081 public function testReadLinkCanonicalizedPathDoesNotExist()
1083 $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'invalid'), true));
1087 * @dataProvider providePathsForMakePathRelative
1089 public function testMakePathRelative($endPath, $startPath, $expectedPath)
1091 $path = $this->filesystem->makePathRelative($endPath, $startPath);
1093 $this->assertEquals($expectedPath, $path);
1096 public function providePathsForMakePathRelative()
1099 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
1100 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
1101 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
1102 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
1103 array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
1104 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
1105 array('/aa/bb', '/aa/bb', './'),
1106 array('/aa/bb', '/aa/bb/', './'),
1107 array('/aa/bb/', '/aa/bb', './'),
1108 array('/aa/bb/', '/aa/bb/', './'),
1109 array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
1110 array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
1111 array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
1112 array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
1113 array('/aa/bb/cc', '/aa', 'bb/cc/'),
1114 array('/aa/bb/cc', '/aa/', 'bb/cc/'),
1115 array('/aa/bb/cc/', '/aa', 'bb/cc/'),
1116 array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
1117 array('/a/aab/bb', '/a/aa', '../aab/bb/'),
1118 array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
1119 array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
1120 array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
1121 array('/a/aab/bb/', '/', 'a/aab/bb/'),
1122 array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
1123 array('/aab/bb', '/aa', '../aab/bb/'),
1124 array('/aab', '/aa', '../aab/'),
1125 array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1126 array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1127 array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'),
1128 array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1129 array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1130 array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1131 array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'),
1132 array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
1133 array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1134 array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
1137 if ('\\' === DIRECTORY_SEPARATOR) {
1138 $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
1146 * @dataProvider provideLegacyPathsForMakePathRelativeWithRelativePaths
1147 * @expectedDeprecation Support for passing relative paths to Symfony\Component\Filesystem\Filesystem::makePathRelative() is deprecated since Symfony 3.4 and will be removed in 4.0.
1149 public function testMakePathRelativeWithRelativePaths($endPath, $startPath, $expectedPath)
1151 $path = $this->filesystem->makePathRelative($endPath, $startPath);
1153 $this->assertEquals($expectedPath, $path);
1156 public function provideLegacyPathsForMakePathRelativeWithRelativePaths()
1159 array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
1160 array('aa/bb', 'aa/cc', '../bb/'),
1161 array('aa/cc', 'bb/cc', '../../aa/cc/'),
1162 array('aa/bb', 'aa/./cc', '../bb/'),
1163 array('aa/./bb', 'aa/cc', '../bb/'),
1164 array('aa/./bb', 'aa/./cc', '../bb/'),
1165 array('../../', '../../', './'),
1166 array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'),
1167 array('../../../', '../../', '../'),
1168 array('', '', './'),
1169 array('', 'aa/', '../'),
1170 array('aa/', '', 'aa/'),
1174 public function testMirrorCopiesFilesAndDirectoriesRecursively()
1176 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1177 $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
1178 $file1 = $directory.'file1';
1179 $file2 = $sourcePath.'file2';
1183 file_put_contents($file1, 'FILE1');
1184 file_put_contents($file2, 'FILE2');
1186 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1188 $this->filesystem->mirror($sourcePath, $targetPath);
1190 $this->assertTrue(is_dir($targetPath));
1191 $this->assertTrue(is_dir($targetPath.'directory'));
1192 $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
1193 $this->assertFileEquals($file2, $targetPath.'file2');
1195 $this->filesystem->remove($file1);
1197 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
1198 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1200 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1201 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1203 file_put_contents($file1, 'FILE1');
1205 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1206 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1208 $this->filesystem->remove($directory);
1209 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1210 $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
1211 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1214 public function testMirrorCreatesEmptyDirectory()
1216 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1220 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1222 $this->filesystem->mirror($sourcePath, $targetPath);
1224 $this->assertTrue(is_dir($targetPath));
1226 $this->filesystem->remove($sourcePath);
1229 public function testMirrorCopiesLinks()
1231 $this->markAsSkippedIfSymlinkIsMissing();
1233 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1236 file_put_contents($sourcePath.'file1', 'FILE1');
1237 symlink($sourcePath.'file1', $sourcePath.'link1');
1239 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1241 $this->filesystem->mirror($sourcePath, $targetPath);
1243 $this->assertTrue(is_dir($targetPath));
1244 $this->assertFileEquals($sourcePath.'file1', $targetPath.'link1');
1245 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
1248 public function testMirrorCopiesLinkedDirectoryContents()
1250 $this->markAsSkippedIfSymlinkIsMissing(true);
1252 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1254 mkdir($sourcePath.'nested/', 0777, true);
1255 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
1256 // Note: We symlink directory, not file
1257 symlink($sourcePath.'nested', $sourcePath.'link1');
1259 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1261 $this->filesystem->mirror($sourcePath, $targetPath);
1263 $this->assertTrue(is_dir($targetPath));
1264 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
1265 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
1268 public function testMirrorCopiesRelativeLinkedContents()
1270 $this->markAsSkippedIfSymlinkIsMissing(true);
1272 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1273 $oldPath = getcwd();
1275 mkdir($sourcePath.'nested/', 0777, true);
1276 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
1277 // Note: Create relative symlink
1279 symlink('nested', 'link1');
1283 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1285 $this->filesystem->mirror($sourcePath, $targetPath);
1287 $this->assertTrue(is_dir($targetPath));
1288 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
1289 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
1290 $this->assertEquals('\\' === DIRECTORY_SEPARATOR ? realpath($sourcePath.'\nested') : 'nested', readlink($targetPath.DIRECTORY_SEPARATOR.'link1'));
1293 public function testMirrorContentsWithSameNameAsSourceOrTargetWithoutDeleteOption()
1295 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1298 touch($sourcePath.'source');
1299 touch($sourcePath.'target');
1301 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1303 $oldPath = getcwd();
1304 chdir($this->workspace);
1306 $this->filesystem->mirror('source', $targetPath);
1310 $this->assertTrue(is_dir($targetPath));
1311 $this->assertFileExists($targetPath.'source');
1312 $this->assertFileExists($targetPath.'target');
1315 public function testMirrorContentsWithSameNameAsSourceOrTargetWithDeleteOption()
1317 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1320 touch($sourcePath.'source');
1322 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1325 touch($targetPath.'source');
1326 touch($targetPath.'target');
1328 $oldPath = getcwd();
1329 chdir($this->workspace);
1331 $this->filesystem->mirror('source', 'target', null, array('delete' => true));
1335 $this->assertTrue(is_dir($targetPath));
1336 $this->assertFileExists($targetPath.'source');
1337 $this->assertFileNotExists($targetPath.'target');
1341 * @dataProvider providePathsForIsAbsolutePath
1343 public function testIsAbsolutePath($path, $expectedResult)
1345 $result = $this->filesystem->isAbsolutePath($path);
1347 $this->assertEquals($expectedResult, $result);
1350 public function providePathsForIsAbsolutePath()
1353 array('/var/lib', true),
1354 array('c:\\\\var\\lib', true),
1355 array('\\var\\lib', true),
1356 array('var/lib', false),
1357 array('../var/lib', false),
1363 public function testTempnam()
1365 $dirname = $this->workspace;
1367 $filename = $this->filesystem->tempnam($dirname, 'foo');
1369 $this->assertFileExists($filename);
1372 public function testTempnamWithFileScheme()
1374 $scheme = 'file://';
1375 $dirname = $scheme.$this->workspace;
1377 $filename = $this->filesystem->tempnam($dirname, 'foo');
1379 $this->assertStringStartsWith($scheme, $filename);
1380 $this->assertFileExists($filename);
1383 public function testTempnamWithMockScheme()
1385 stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream');
1387 $scheme = 'mock://';
1388 $dirname = $scheme.$this->workspace;
1390 $filename = $this->filesystem->tempnam($dirname, 'foo');
1392 $this->assertStringStartsWith($scheme, $filename);
1393 $this->assertFileExists($filename);
1397 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1399 public function testTempnamWithZlibSchemeFails()
1401 $scheme = 'compress.zlib://';
1402 $dirname = $scheme.$this->workspace;
1404 // The compress.zlib:// stream does not support mode x: creates the file, errors "failed to open stream: operation failed" and returns false
1405 $this->filesystem->tempnam($dirname, 'bar');
1408 public function testTempnamWithPHPTempSchemeFails()
1410 $scheme = 'php://temp';
1413 $filename = $this->filesystem->tempnam($dirname, 'bar');
1415 $this->assertStringStartsWith($scheme, $filename);
1417 // The php://temp stream deletes the file after close
1418 $this->assertFileNotExists($filename);
1422 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1424 public function testTempnamWithPharSchemeFails()
1426 // Skip test if Phar disabled phar.readonly must be 0 in php.ini
1427 if (!\Phar::canWrite()) {
1428 $this->markTestSkipped('This test cannot run when phar.readonly is 1.');
1431 $scheme = 'phar://';
1432 $dirname = $scheme.$this->workspace;
1433 $pharname = 'foo.phar';
1435 new \Phar($this->workspace.'/'.$pharname, 0, $pharname);
1436 // The phar:// stream does not support mode x: fails to create file, errors "failed to open stream: phar error: "$filename" is not a file in phar "$pharname"" and returns false
1437 $this->filesystem->tempnam($dirname, $pharname.'/bar');
1441 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1443 public function testTempnamWithHTTPSchemeFails()
1445 $scheme = 'http://';
1446 $dirname = $scheme.$this->workspace;
1448 // The http:// scheme is read-only
1449 $this->filesystem->tempnam($dirname, 'bar');
1452 public function testTempnamOnUnwritableFallsBackToSysTmp()
1454 $scheme = 'file://';
1455 $dirname = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'does_not_exist';
1457 $filename = $this->filesystem->tempnam($dirname, 'bar');
1458 $realTempDir = realpath(sys_get_temp_dir());
1459 $this->assertStringStartsWith(rtrim($scheme.$realTempDir, DIRECTORY_SEPARATOR), $filename);
1460 $this->assertFileExists($filename);
1466 public function testDumpFile()
1468 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1470 // skip mode check on Windows
1471 if ('\\' !== DIRECTORY_SEPARATOR) {
1472 $oldMask = umask(0002);
1475 $this->filesystem->dumpFile($filename, 'bar');
1476 $this->assertFileExists($filename);
1477 $this->assertStringEqualsFile($filename, 'bar');
1479 // skip mode check on Windows
1480 if ('\\' !== DIRECTORY_SEPARATOR) {
1481 $this->assertFilePermissions(664, $filename);
1486 public function testDumpFileOverwritesAnExistingFile()
1488 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
1489 file_put_contents($filename, 'FOO BAR');
1491 $this->filesystem->dumpFile($filename, 'bar');
1493 $this->assertFileExists($filename);
1494 $this->assertStringEqualsFile($filename, 'bar');
1497 public function testDumpFileWithFileScheme()
1499 if (defined('HHVM_VERSION')) {
1500 $this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1503 $scheme = 'file://';
1504 $filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1506 $this->filesystem->dumpFile($filename, 'bar');
1508 $this->assertFileExists($filename);
1509 $this->assertStringEqualsFile($filename, 'bar');
1512 public function testDumpFileWithZlibScheme()
1514 $scheme = 'compress.zlib://';
1515 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1517 $this->filesystem->dumpFile($filename, 'bar');
1519 // Zlib stat uses file:// wrapper so remove scheme
1520 $this->assertFileExists(str_replace($scheme, '', $filename));
1521 $this->assertStringEqualsFile($filename, 'bar');
1524 public function testAppendToFile()
1526 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.txt';
1528 // skip mode check on Windows
1529 if ('\\' !== DIRECTORY_SEPARATOR) {
1530 $oldMask = umask(0002);
1533 $this->filesystem->dumpFile($filename, 'foo');
1535 $this->filesystem->appendToFile($filename, 'bar');
1537 $this->assertFileExists($filename);
1538 $this->assertStringEqualsFile($filename, 'foobar');
1540 // skip mode check on Windows
1541 if ('\\' !== DIRECTORY_SEPARATOR) {
1542 $this->assertFilePermissions(664, $filename);
1547 public function testAppendToFileWithScheme()
1549 if (defined('HHVM_VERSION')) {
1550 $this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1553 $scheme = 'file://';
1554 $filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1555 $this->filesystem->dumpFile($filename, 'foo');
1557 $this->filesystem->appendToFile($filename, 'bar');
1559 $this->assertFileExists($filename);
1560 $this->assertStringEqualsFile($filename, 'foobar');
1563 public function testAppendToFileWithZlibScheme()
1565 $scheme = 'compress.zlib://';
1566 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1567 $this->filesystem->dumpFile($filename, 'foo');
1569 // Zlib stat uses file:// wrapper so remove it
1570 $this->assertStringEqualsFile(str_replace($scheme, '', $filename), 'foo');
1572 $this->filesystem->appendToFile($filename, 'bar');
1574 $this->assertFileExists($filename);
1575 $this->assertStringEqualsFile($filename, 'foobar');
1578 public function testAppendToFileCreateTheFileIfNotExists()
1580 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.txt';
1582 // skip mode check on Windows
1583 if ('\\' !== DIRECTORY_SEPARATOR) {
1584 $oldMask = umask(0002);
1587 $this->filesystem->appendToFile($filename, 'bar');
1589 // skip mode check on Windows
1590 if ('\\' !== DIRECTORY_SEPARATOR) {
1591 $this->assertFilePermissions(664, $filename);
1595 $this->assertFileExists($filename);
1596 $this->assertStringEqualsFile($filename, 'bar');
1599 public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile()
1601 $this->markAsSkippedIfChmodIsMissing();
1603 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
1604 file_put_contents($filename, 'FOO BAR');
1605 chmod($filename, 0745);
1607 $this->filesystem->dumpFile($filename, 'bar', null);
1609 $this->assertFilePermissions(745, $filename);
1612 public function testCopyShouldKeepExecutionPermission()
1614 $this->markAsSkippedIfChmodIsMissing();
1616 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
1617 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
1619 file_put_contents($sourceFilePath, 'SOURCE FILE');
1620 chmod($sourceFilePath, 0745);
1622 $this->filesystem->copy($sourceFilePath, $targetFilePath);
1624 $this->assertFilePermissions(767, $targetFilePath);
1628 * Normalize the given path (transform each blackslash into a real directory separator).
1630 * @param string $path
1634 private function normalize($path)
1636 return str_replace('/', DIRECTORY_SEPARATOR, $path);