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 if (!getenv('USER') || 'root' === getenv('USER')) {
54 $this->markTestSkipped('This test will fail if run under superuser');
57 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
58 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
60 file_put_contents($sourceFilePath, 'SOURCE FILE');
62 // make sure target cannot be read
63 $this->filesystem->chmod($sourceFilePath, 0222);
65 $this->filesystem->copy($sourceFilePath, $targetFilePath);
68 public function testCopyOverridesExistingFileIfModified()
70 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
71 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
73 file_put_contents($sourceFilePath, 'SOURCE FILE');
74 file_put_contents($targetFilePath, 'TARGET FILE');
75 touch($targetFilePath, time() - 1000);
77 $this->filesystem->copy($sourceFilePath, $targetFilePath);
79 $this->assertFileExists($targetFilePath);
80 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
83 public function testCopyDoesNotOverrideExistingFileByDefault()
85 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
86 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
88 file_put_contents($sourceFilePath, 'SOURCE FILE');
89 file_put_contents($targetFilePath, 'TARGET FILE');
91 // make sure both files have the same modification time
92 $modificationTime = time() - 1000;
93 touch($sourceFilePath, $modificationTime);
94 touch($targetFilePath, $modificationTime);
96 $this->filesystem->copy($sourceFilePath, $targetFilePath);
98 $this->assertFileExists($targetFilePath);
99 $this->assertStringEqualsFile($targetFilePath, 'TARGET FILE');
102 public function testCopyOverridesExistingFileIfForced()
104 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
105 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
107 file_put_contents($sourceFilePath, 'SOURCE FILE');
108 file_put_contents($targetFilePath, 'TARGET FILE');
110 // make sure both files have the same modification time
111 $modificationTime = time() - 1000;
112 touch($sourceFilePath, $modificationTime);
113 touch($targetFilePath, $modificationTime);
115 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
117 $this->assertFileExists($targetFilePath);
118 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
122 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
124 public function testCopyWithOverrideWithReadOnlyTargetFails()
126 // skip test on Windows; PHP can't easily set file as unwritable on Windows
127 if ('\\' === \DIRECTORY_SEPARATOR) {
128 $this->markTestSkipped('This test cannot run on Windows.');
131 if (!getenv('USER') || 'root' === getenv('USER')) {
132 $this->markTestSkipped('This test will fail if run under superuser');
135 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
136 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
138 file_put_contents($sourceFilePath, 'SOURCE FILE');
139 file_put_contents($targetFilePath, 'TARGET FILE');
141 // make sure both files have the same modification time
142 $modificationTime = time() - 1000;
143 touch($sourceFilePath, $modificationTime);
144 touch($targetFilePath, $modificationTime);
146 // make sure target is read-only
147 $this->filesystem->chmod($targetFilePath, 0444);
149 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
152 public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
154 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
155 $targetFileDirectory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
156 $targetFilePath = $targetFileDirectory.\DIRECTORY_SEPARATOR.'copy_target_file';
158 file_put_contents($sourceFilePath, 'SOURCE FILE');
160 $this->filesystem->copy($sourceFilePath, $targetFilePath);
162 $this->assertTrue(is_dir($targetFileDirectory));
163 $this->assertFileExists($targetFilePath);
164 $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
170 public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy()
172 if (!\in_array('https', stream_get_wrappers())) {
173 $this->markTestSkipped('"https" stream wrapper is not enabled.');
175 $sourceFilePath = 'https://symfony.com/images/common/logo/logo_symfony_header.png';
176 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
178 file_put_contents($targetFilePath, 'TARGET FILE');
180 $this->filesystem->copy($sourceFilePath, $targetFilePath, false);
182 $this->assertFileExists($targetFilePath);
183 $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath));
186 public function testMkdirCreatesDirectoriesRecursively()
188 $directory = $this->workspace
189 .\DIRECTORY_SEPARATOR.'directory'
190 .\DIRECTORY_SEPARATOR.'sub_directory';
192 $this->filesystem->mkdir($directory);
194 $this->assertTrue(is_dir($directory));
197 public function testMkdirCreatesDirectoriesFromArray()
199 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
200 $directories = array(
201 $basePath.'1', $basePath.'2', $basePath.'3',
204 $this->filesystem->mkdir($directories);
206 $this->assertTrue(is_dir($basePath.'1'));
207 $this->assertTrue(is_dir($basePath.'2'));
208 $this->assertTrue(is_dir($basePath.'3'));
211 public function testMkdirCreatesDirectoriesFromTraversableObject()
213 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
214 $directories = new \ArrayObject(array(
215 $basePath.'1', $basePath.'2', $basePath.'3',
218 $this->filesystem->mkdir($directories);
220 $this->assertTrue(is_dir($basePath.'1'));
221 $this->assertTrue(is_dir($basePath.'2'));
222 $this->assertTrue(is_dir($basePath.'3'));
226 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
228 public function testMkdirCreatesDirectoriesFails()
230 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
231 $dir = $basePath.'2';
233 file_put_contents($dir, '');
235 $this->filesystem->mkdir($dir);
238 public function testTouchCreatesEmptyFile()
240 $file = $this->workspace.\DIRECTORY_SEPARATOR.'1';
242 $this->filesystem->touch($file);
244 $this->assertFileExists($file);
248 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
250 public function testTouchFails()
252 $file = $this->workspace.\DIRECTORY_SEPARATOR.'1'.\DIRECTORY_SEPARATOR.'2';
254 $this->filesystem->touch($file);
257 public function testTouchCreatesEmptyFilesFromArray()
259 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
261 $basePath.'1', $basePath.'2', $basePath.'3',
264 $this->filesystem->touch($files);
266 $this->assertFileExists($basePath.'1');
267 $this->assertFileExists($basePath.'2');
268 $this->assertFileExists($basePath.'3');
271 public function testTouchCreatesEmptyFilesFromTraversableObject()
273 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
274 $files = new \ArrayObject(array(
275 $basePath.'1', $basePath.'2', $basePath.'3',
278 $this->filesystem->touch($files);
280 $this->assertFileExists($basePath.'1');
281 $this->assertFileExists($basePath.'2');
282 $this->assertFileExists($basePath.'3');
285 public function testRemoveCleansFilesAndDirectoriesIteratively()
287 $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
290 mkdir($basePath.'dir');
291 touch($basePath.'file');
293 $this->filesystem->remove($basePath);
295 $this->assertFileNotExists($basePath);
298 public function testRemoveCleansArrayOfFilesAndDirectories()
300 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
302 mkdir($basePath.'dir');
303 touch($basePath.'file');
306 $basePath.'dir', $basePath.'file',
309 $this->filesystem->remove($files);
311 $this->assertFileNotExists($basePath.'dir');
312 $this->assertFileNotExists($basePath.'file');
315 public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
317 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
319 mkdir($basePath.'dir');
320 touch($basePath.'file');
322 $files = new \ArrayObject(array(
323 $basePath.'dir', $basePath.'file',
326 $this->filesystem->remove($files);
328 $this->assertFileNotExists($basePath.'dir');
329 $this->assertFileNotExists($basePath.'file');
332 public function testRemoveIgnoresNonExistingFiles()
334 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
336 mkdir($basePath.'dir');
339 $basePath.'dir', $basePath.'file',
342 $this->filesystem->remove($files);
344 $this->assertFileNotExists($basePath.'dir');
347 public function testRemoveCleansInvalidLinks()
349 $this->markAsSkippedIfSymlinkIsMissing();
351 $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
354 mkdir($basePath.'dir');
355 // create symlink to nonexistent file
356 @symlink($basePath.'file', $basePath.'file-link');
358 // create symlink to dir using trailing forward slash
359 $this->filesystem->symlink($basePath.'dir/', $basePath.'dir-link');
360 $this->assertTrue(is_dir($basePath.'dir-link'));
362 // create symlink to nonexistent dir
363 rmdir($basePath.'dir');
364 $this->assertFalse('\\' === \DIRECTORY_SEPARATOR ? @readlink($basePath.'dir-link') : is_dir($basePath.'dir-link'));
366 $this->filesystem->remove($basePath);
368 $this->assertFileNotExists($basePath);
371 public function testFilesExists()
373 $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
376 touch($basePath.'file1');
377 mkdir($basePath.'folder');
379 $this->assertTrue($this->filesystem->exists($basePath.'file1'));
380 $this->assertTrue($this->filesystem->exists($basePath.'folder'));
384 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
386 public function testFilesExistsFails()
388 if ('\\' !== \DIRECTORY_SEPARATOR) {
389 $this->markTestSkipped('Long file names are an issue on Windows');
391 $basePath = $this->workspace.'\\directory\\';
392 $maxPathLength = PHP_MAXPATHLEN - 2;
397 $file = str_repeat('T', $maxPathLength - \strlen($basePath) + 1);
398 $path = $basePath.$file;
399 exec('TYPE NUL >>'.$file); // equivalent of touch, we can not use the php touch() here because it suffers from the same limitation
400 $this->longPathNamesWindows[] = $path; // save this so we can clean up later
402 $this->filesystem->exists($path);
405 public function testFilesExistsTraversableObjectOfFilesAndDirectories()
407 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
409 mkdir($basePath.'dir');
410 touch($basePath.'file');
412 $files = new \ArrayObject(array(
413 $basePath.'dir', $basePath.'file',
416 $this->assertTrue($this->filesystem->exists($files));
419 public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
421 $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
423 mkdir($basePath.'dir');
424 touch($basePath.'file');
425 touch($basePath.'file2');
427 $files = new \ArrayObject(array(
428 $basePath.'dir', $basePath.'file', $basePath.'file2',
431 unlink($basePath.'file');
433 $this->assertFalse($this->filesystem->exists($files));
436 public function testInvalidFileNotExists()
438 $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
440 $this->assertFalse($this->filesystem->exists($basePath.time()));
443 public function testChmodChangesFileMode()
445 $this->markAsSkippedIfChmodIsMissing();
447 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
449 $file = $dir.\DIRECTORY_SEPARATOR.'file';
452 $this->filesystem->chmod($file, 0400);
453 $this->filesystem->chmod($dir, 0753);
455 $this->assertFilePermissions(753, $dir);
456 $this->assertFilePermissions(400, $file);
459 public function testChmodWithWrongModLeavesPreviousPermissionsUntouched()
461 $this->markAsSkippedIfChmodIsMissing();
463 if (\defined('HHVM_VERSION')) {
464 $this->markTestSkipped('chmod() changes permissions even when passing invalid modes on HHVM');
467 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'file';
470 $permissions = fileperms($dir);
472 $this->filesystem->chmod($dir, 'Wrongmode');
474 $this->assertSame($permissions, fileperms($dir));
477 public function testChmodRecursive()
479 $this->markAsSkippedIfChmodIsMissing();
481 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
483 $file = $dir.\DIRECTORY_SEPARATOR.'file';
486 $this->filesystem->chmod($file, 0400, 0000, true);
487 $this->filesystem->chmod($dir, 0753, 0000, true);
489 $this->assertFilePermissions(753, $dir);
490 $this->assertFilePermissions(753, $file);
493 public function testChmodAppliesUmask()
495 $this->markAsSkippedIfChmodIsMissing();
497 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
500 $this->filesystem->chmod($file, 0770, 0022);
501 $this->assertFilePermissions(750, $file);
504 public function testChmodChangesModeOfArrayOfFiles()
506 $this->markAsSkippedIfChmodIsMissing();
508 $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
509 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
510 $files = array($directory, $file);
515 $this->filesystem->chmod($files, 0753);
517 $this->assertFilePermissions(753, $file);
518 $this->assertFilePermissions(753, $directory);
521 public function testChmodChangesModeOfTraversableFileObject()
523 $this->markAsSkippedIfChmodIsMissing();
525 $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
526 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
527 $files = new \ArrayObject(array($directory, $file));
532 $this->filesystem->chmod($files, 0753);
534 $this->assertFilePermissions(753, $file);
535 $this->assertFilePermissions(753, $directory);
538 public function testChmodChangesZeroModeOnSubdirectoriesOnRecursive()
540 $this->markAsSkippedIfChmodIsMissing();
542 $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
543 $subdirectory = $directory.\DIRECTORY_SEPARATOR.'subdirectory';
546 mkdir($subdirectory);
547 chmod($subdirectory, 0000);
549 $this->filesystem->chmod($directory, 0753, 0000, true);
551 $this->assertFilePermissions(753, $subdirectory);
554 public function testChown()
556 $this->markAsSkippedIfPosixIsMissing();
558 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
561 $owner = $this->getFileOwner($dir);
562 $this->filesystem->chown($dir, $owner);
564 $this->assertSame($owner, $this->getFileOwner($dir));
567 public function testChownRecursive()
569 $this->markAsSkippedIfPosixIsMissing();
571 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
573 $file = $dir.\DIRECTORY_SEPARATOR.'file';
576 $owner = $this->getFileOwner($dir);
577 $this->filesystem->chown($dir, $owner, true);
579 $this->assertSame($owner, $this->getFileOwner($file));
582 public function testChownSymlink()
584 $this->markAsSkippedIfSymlinkIsMissing();
586 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
587 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
591 $this->filesystem->symlink($file, $link);
593 $owner = $this->getFileOwner($link);
594 $this->filesystem->chown($link, $owner);
596 $this->assertSame($owner, $this->getFileOwner($link));
599 public function testChownLink()
601 $this->markAsSkippedIfLinkIsMissing();
603 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
604 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
608 $this->filesystem->hardlink($file, $link);
610 $owner = $this->getFileOwner($link);
611 $this->filesystem->chown($link, $owner);
613 $this->assertSame($owner, $this->getFileOwner($link));
617 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
619 public function testChownSymlinkFails()
621 $this->markAsSkippedIfSymlinkIsMissing();
623 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
624 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
628 $this->filesystem->symlink($file, $link);
630 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
634 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
636 public function testChownLinkFails()
638 $this->markAsSkippedIfLinkIsMissing();
640 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
641 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
645 $this->filesystem->hardlink($file, $link);
647 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
651 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
653 public function testChownFail()
655 $this->markAsSkippedIfPosixIsMissing();
657 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
660 $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
663 public function testChgrp()
665 $this->markAsSkippedIfPosixIsMissing();
667 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
670 $group = $this->getFileGroup($dir);
671 $this->filesystem->chgrp($dir, $group);
673 $this->assertSame($group, $this->getFileGroup($dir));
676 public function testChgrpRecursive()
678 $this->markAsSkippedIfPosixIsMissing();
680 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
682 $file = $dir.\DIRECTORY_SEPARATOR.'file';
685 $group = $this->getFileGroup($dir);
686 $this->filesystem->chgrp($dir, $group, true);
688 $this->assertSame($group, $this->getFileGroup($file));
691 public function testChgrpSymlink()
693 $this->markAsSkippedIfSymlinkIsMissing();
695 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
696 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
700 $this->filesystem->symlink($file, $link);
702 $group = $this->getFileGroup($link);
703 $this->filesystem->chgrp($link, $group);
705 $this->assertSame($group, $this->getFileGroup($link));
708 public function testChgrpLink()
710 $this->markAsSkippedIfLinkIsMissing();
712 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
713 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
717 $this->filesystem->hardlink($file, $link);
719 $group = $this->getFileGroup($link);
720 $this->filesystem->chgrp($link, $group);
722 $this->assertSame($group, $this->getFileGroup($link));
726 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
728 public function testChgrpSymlinkFails()
730 $this->markAsSkippedIfSymlinkIsMissing();
732 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
733 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
737 $this->filesystem->symlink($file, $link);
739 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
743 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
745 public function testChgrpLinkFails()
747 $this->markAsSkippedIfLinkIsMissing();
749 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
750 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
754 $this->filesystem->hardlink($file, $link);
756 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
760 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
762 public function testChgrpFail()
764 $this->markAsSkippedIfPosixIsMissing();
766 $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
769 $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
772 public function testRename()
774 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
775 $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
778 $this->filesystem->rename($file, $newPath);
780 $this->assertFileNotExists($file);
781 $this->assertFileExists($newPath);
785 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
787 public function testRenameThrowsExceptionIfTargetAlreadyExists()
789 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
790 $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
795 $this->filesystem->rename($file, $newPath);
798 public function testRenameOverwritesTheTargetIfItAlreadyExists()
800 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
801 $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
806 $this->filesystem->rename($file, $newPath, true);
808 $this->assertFileNotExists($file);
809 $this->assertFileExists($newPath);
813 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
815 public function testRenameThrowsExceptionOnError()
817 $file = $this->workspace.\DIRECTORY_SEPARATOR.uniqid('fs_test_', true);
818 $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
820 $this->filesystem->rename($file, $newPath);
823 public function testSymlink()
825 if ('\\' === \DIRECTORY_SEPARATOR) {
826 $this->markTestSkipped('Windows does not support creating "broken" symlinks');
829 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
830 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
832 // $file does not exists right now: creating "broken" links is a wanted feature
833 $this->filesystem->symlink($file, $link);
835 $this->assertTrue(is_link($link));
837 // Create the linked file AFTER creating the link
840 $this->assertEquals($file, readlink($link));
844 * @depends testSymlink
846 public function testRemoveSymlink()
848 $this->markAsSkippedIfSymlinkIsMissing();
850 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
852 $this->filesystem->remove($link);
854 $this->assertFalse(is_link($link));
855 $this->assertFalse(is_file($link));
856 $this->assertFalse(is_dir($link));
859 public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
861 $this->markAsSkippedIfSymlinkIsMissing();
863 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
864 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
867 symlink($this->workspace, $link);
869 $this->filesystem->symlink($file, $link);
871 $this->assertTrue(is_link($link));
872 $this->assertEquals($file, readlink($link));
875 public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
877 $this->markAsSkippedIfSymlinkIsMissing();
879 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
880 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
883 symlink($file, $link);
885 $this->filesystem->symlink($file, $link);
887 $this->assertTrue(is_link($link));
888 $this->assertEquals($file, readlink($link));
891 public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
893 $this->markAsSkippedIfSymlinkIsMissing();
895 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
896 $link1 = $this->workspace.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'link';
897 $link2 = $this->workspace.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'subdir'.\DIRECTORY_SEPARATOR.'link';
901 $this->filesystem->symlink($file, $link1);
902 $this->filesystem->symlink($file, $link2);
904 $this->assertTrue(is_link($link1));
905 $this->assertEquals($file, readlink($link1));
906 $this->assertTrue(is_link($link2));
907 $this->assertEquals($file, readlink($link2));
910 public function testLink()
912 $this->markAsSkippedIfLinkIsMissing();
914 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
915 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
918 $this->filesystem->hardlink($file, $link);
920 $this->assertTrue(is_file($link));
921 $this->assertEquals(fileinode($file), fileinode($link));
927 public function testRemoveLink()
929 $this->markAsSkippedIfLinkIsMissing();
931 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
933 $this->filesystem->remove($link);
935 $this->assertTrue(!is_file($link));
938 public function testLinkIsOverwrittenIfPointsToDifferentTarget()
940 $this->markAsSkippedIfLinkIsMissing();
942 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
943 $file2 = $this->workspace.\DIRECTORY_SEPARATOR.'file2';
944 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
950 $this->filesystem->hardlink($file, $link);
952 $this->assertTrue(is_file($link));
953 $this->assertEquals(fileinode($file), fileinode($link));
956 public function testLinkIsNotOverwrittenIfAlreadyCreated()
958 $this->markAsSkippedIfLinkIsMissing();
960 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
961 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
966 $this->filesystem->hardlink($file, $link);
968 $this->assertTrue(is_file($link));
969 $this->assertEquals(fileinode($file), fileinode($link));
972 public function testLinkWithSeveralTargets()
974 $this->markAsSkippedIfLinkIsMissing();
976 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
977 $link1 = $this->workspace.\DIRECTORY_SEPARATOR.'link';
978 $link2 = $this->workspace.\DIRECTORY_SEPARATOR.'link2';
982 $this->filesystem->hardlink($file, array($link1, $link2));
984 $this->assertTrue(is_file($link1));
985 $this->assertEquals(fileinode($file), fileinode($link1));
986 $this->assertTrue(is_file($link2));
987 $this->assertEquals(fileinode($file), fileinode($link2));
990 public function testLinkWithSameTarget()
992 $this->markAsSkippedIfLinkIsMissing();
994 $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
995 $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
999 // practically same as testLinkIsNotOverwrittenIfAlreadyCreated
1000 $this->filesystem->hardlink($file, array($link, $link));
1002 $this->assertTrue(is_file($link));
1003 $this->assertEquals(fileinode($file), fileinode($link));
1006 public function testReadRelativeLink()
1008 $this->markAsSkippedIfSymlinkIsMissing();
1010 if ('\\' === \DIRECTORY_SEPARATOR) {
1011 $this->markTestSkipped('Relative symbolic links are not supported on Windows');
1014 $file = $this->workspace.'/file';
1015 $link1 = $this->workspace.'/dir/link';
1016 $link2 = $this->workspace.'/dir/link2';
1019 $this->filesystem->symlink('../file', $link1);
1020 $this->filesystem->symlink('link', $link2);
1022 $this->assertEquals($this->normalize('../file'), $this->filesystem->readlink($link1));
1023 $this->assertEquals('link', $this->filesystem->readlink($link2));
1024 $this->assertEquals($file, $this->filesystem->readlink($link1, true));
1025 $this->assertEquals($file, $this->filesystem->readlink($link2, true));
1026 $this->assertEquals($file, $this->filesystem->readlink($file, true));
1029 public function testReadAbsoluteLink()
1031 $this->markAsSkippedIfSymlinkIsMissing();
1033 $file = $this->normalize($this->workspace.'/file');
1034 $link1 = $this->normalize($this->workspace.'/dir/link');
1035 $link2 = $this->normalize($this->workspace.'/dir/link2');
1038 $this->filesystem->symlink($file, $link1);
1039 $this->filesystem->symlink($link1, $link2);
1041 $this->assertEquals($file, $this->filesystem->readlink($link1));
1042 $this->assertEquals($link1, $this->filesystem->readlink($link2));
1043 $this->assertEquals($file, $this->filesystem->readlink($link1, true));
1044 $this->assertEquals($file, $this->filesystem->readlink($link2, true));
1045 $this->assertEquals($file, $this->filesystem->readlink($file, true));
1048 public function testReadBrokenLink()
1050 $this->markAsSkippedIfSymlinkIsMissing();
1052 if ('\\' === \DIRECTORY_SEPARATOR) {
1053 $this->markTestSkipped('Windows does not support creating "broken" symlinks');
1056 $file = $this->workspace.'/file';
1057 $link = $this->workspace.'/link';
1059 $this->filesystem->symlink($file, $link);
1061 $this->assertEquals($file, $this->filesystem->readlink($link));
1062 $this->assertNull($this->filesystem->readlink($link, true));
1065 $this->assertEquals($file, $this->filesystem->readlink($link, true));
1068 public function testReadLinkDefaultPathDoesNotExist()
1070 $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'/invalid')));
1073 public function testReadLinkDefaultPathNotLink()
1075 $file = $this->normalize($this->workspace.'/file');
1078 $this->assertNull($this->filesystem->readlink($file));
1081 public function testReadLinkCanonicalizePath()
1083 $this->markAsSkippedIfSymlinkIsMissing();
1085 $file = $this->normalize($this->workspace.'/file');
1086 mkdir($this->normalize($this->workspace.'/dir'));
1089 $this->assertEquals($file, $this->filesystem->readlink($this->normalize($this->workspace.'/dir/../file'), true));
1092 public function testReadLinkCanonicalizedPathDoesNotExist()
1094 $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'invalid'), true));
1098 * @dataProvider providePathsForMakePathRelative
1100 public function testMakePathRelative($endPath, $startPath, $expectedPath)
1102 $path = $this->filesystem->makePathRelative($endPath, $startPath);
1104 $this->assertEquals($expectedPath, $path);
1107 public function providePathsForMakePathRelative()
1110 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
1111 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
1112 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
1113 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
1114 array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
1115 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
1116 array('/aa/bb', '/aa/bb', './'),
1117 array('/aa/bb', '/aa/bb/', './'),
1118 array('/aa/bb/', '/aa/bb', './'),
1119 array('/aa/bb/', '/aa/bb/', './'),
1120 array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
1121 array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
1122 array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
1123 array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
1124 array('/aa/bb/cc', '/aa', 'bb/cc/'),
1125 array('/aa/bb/cc', '/aa/', 'bb/cc/'),
1126 array('/aa/bb/cc/', '/aa', 'bb/cc/'),
1127 array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
1128 array('/a/aab/bb', '/a/aa', '../aab/bb/'),
1129 array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
1130 array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
1131 array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
1132 array('/a/aab/bb/', '/', 'a/aab/bb/'),
1133 array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
1134 array('/aab/bb', '/aa', '../aab/bb/'),
1135 array('/aab', '/aa', '../aab/'),
1136 array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1137 array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1138 array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'),
1139 array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1140 array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1141 array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1142 array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'),
1143 array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
1144 array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1145 array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
1148 if ('\\' === \DIRECTORY_SEPARATOR) {
1149 $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
1157 * @dataProvider provideLegacyPathsForMakePathRelativeWithRelativePaths
1158 * @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.
1160 public function testMakePathRelativeWithRelativePaths($endPath, $startPath, $expectedPath)
1162 $path = $this->filesystem->makePathRelative($endPath, $startPath);
1164 $this->assertEquals($expectedPath, $path);
1167 public function provideLegacyPathsForMakePathRelativeWithRelativePaths()
1170 array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
1171 array('aa/bb', 'aa/cc', '../bb/'),
1172 array('aa/cc', 'bb/cc', '../../aa/cc/'),
1173 array('aa/bb', 'aa/./cc', '../bb/'),
1174 array('aa/./bb', 'aa/cc', '../bb/'),
1175 array('aa/./bb', 'aa/./cc', '../bb/'),
1176 array('../../', '../../', './'),
1177 array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'),
1178 array('../../../', '../../', '../'),
1179 array('', '', './'),
1180 array('', 'aa/', '../'),
1181 array('aa/', '', 'aa/'),
1185 public function testMirrorCopiesFilesAndDirectoriesRecursively()
1187 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1188 $directory = $sourcePath.'directory'.\DIRECTORY_SEPARATOR;
1189 $file1 = $directory.'file1';
1190 $file2 = $sourcePath.'file2';
1194 file_put_contents($file1, 'FILE1');
1195 file_put_contents($file2, 'FILE2');
1197 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1199 $this->filesystem->mirror($sourcePath, $targetPath);
1201 $this->assertTrue(is_dir($targetPath));
1202 $this->assertTrue(is_dir($targetPath.'directory'));
1203 $this->assertFileEquals($file1, $targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1');
1204 $this->assertFileEquals($file2, $targetPath.'file2');
1206 $this->filesystem->remove($file1);
1208 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
1209 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
1211 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1212 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
1214 file_put_contents($file1, 'FILE1');
1216 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1217 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
1219 $this->filesystem->remove($directory);
1220 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1221 $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
1222 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
1225 public function testMirrorCreatesEmptyDirectory()
1227 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1231 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1233 $this->filesystem->mirror($sourcePath, $targetPath);
1235 $this->assertTrue(is_dir($targetPath));
1237 $this->filesystem->remove($sourcePath);
1240 public function testMirrorCopiesLinks()
1242 $this->markAsSkippedIfSymlinkIsMissing();
1244 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1247 file_put_contents($sourcePath.'file1', 'FILE1');
1248 symlink($sourcePath.'file1', $sourcePath.'link1');
1250 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1252 $this->filesystem->mirror($sourcePath, $targetPath);
1254 $this->assertTrue(is_dir($targetPath));
1255 $this->assertFileEquals($sourcePath.'file1', $targetPath.'link1');
1256 $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1'));
1259 public function testMirrorCopiesLinkedDirectoryContents()
1261 $this->markAsSkippedIfSymlinkIsMissing(true);
1263 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1265 mkdir($sourcePath.'nested/', 0777, true);
1266 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
1267 // Note: We symlink directory, not file
1268 symlink($sourcePath.'nested', $sourcePath.'link1');
1270 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1272 $this->filesystem->mirror($sourcePath, $targetPath);
1274 $this->assertTrue(is_dir($targetPath));
1275 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
1276 $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1'));
1279 public function testMirrorCopiesRelativeLinkedContents()
1281 $this->markAsSkippedIfSymlinkIsMissing(true);
1283 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1284 $oldPath = getcwd();
1286 mkdir($sourcePath.'nested/', 0777, true);
1287 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
1288 // Note: Create relative symlink
1290 symlink('nested', 'link1');
1294 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1296 $this->filesystem->mirror($sourcePath, $targetPath);
1298 $this->assertTrue(is_dir($targetPath));
1299 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
1300 $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1'));
1301 $this->assertEquals('\\' === \DIRECTORY_SEPARATOR ? realpath($sourcePath.'\nested') : 'nested', readlink($targetPath.\DIRECTORY_SEPARATOR.'link1'));
1304 public function testMirrorContentsWithSameNameAsSourceOrTargetWithoutDeleteOption()
1306 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1309 touch($sourcePath.'source');
1310 touch($sourcePath.'target');
1312 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1314 $oldPath = getcwd();
1315 chdir($this->workspace);
1317 $this->filesystem->mirror('source', $targetPath);
1321 $this->assertTrue(is_dir($targetPath));
1322 $this->assertFileExists($targetPath.'source');
1323 $this->assertFileExists($targetPath.'target');
1326 public function testMirrorContentsWithSameNameAsSourceOrTargetWithDeleteOption()
1328 $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
1331 touch($sourcePath.'source');
1333 $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
1336 touch($targetPath.'source');
1337 touch($targetPath.'target');
1339 $oldPath = getcwd();
1340 chdir($this->workspace);
1342 $this->filesystem->mirror('source', 'target', null, array('delete' => true));
1346 $this->assertTrue(is_dir($targetPath));
1347 $this->assertFileExists($targetPath.'source');
1348 $this->assertFileNotExists($targetPath.'target');
1352 * @dataProvider providePathsForIsAbsolutePath
1354 public function testIsAbsolutePath($path, $expectedResult)
1356 $result = $this->filesystem->isAbsolutePath($path);
1358 $this->assertEquals($expectedResult, $result);
1361 public function providePathsForIsAbsolutePath()
1364 array('/var/lib', true),
1365 array('c:\\\\var\\lib', true),
1366 array('\\var\\lib', true),
1367 array('var/lib', false),
1368 array('../var/lib', false),
1374 public function testTempnam()
1376 $dirname = $this->workspace;
1378 $filename = $this->filesystem->tempnam($dirname, 'foo');
1380 $this->assertFileExists($filename);
1383 public function testTempnamWithFileScheme()
1385 $scheme = 'file://';
1386 $dirname = $scheme.$this->workspace;
1388 $filename = $this->filesystem->tempnam($dirname, 'foo');
1390 $this->assertStringStartsWith($scheme, $filename);
1391 $this->assertFileExists($filename);
1394 public function testTempnamWithMockScheme()
1396 stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream');
1398 $scheme = 'mock://';
1399 $dirname = $scheme.$this->workspace;
1401 $filename = $this->filesystem->tempnam($dirname, 'foo');
1403 $this->assertStringStartsWith($scheme, $filename);
1404 $this->assertFileExists($filename);
1408 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1410 public function testTempnamWithZlibSchemeFails()
1412 $scheme = 'compress.zlib://';
1413 $dirname = $scheme.$this->workspace;
1415 // The compress.zlib:// stream does not support mode x: creates the file, errors "failed to open stream: operation failed" and returns false
1416 $this->filesystem->tempnam($dirname, 'bar');
1419 public function testTempnamWithPHPTempSchemeFails()
1421 $scheme = 'php://temp';
1424 $filename = $this->filesystem->tempnam($dirname, 'bar');
1426 $this->assertStringStartsWith($scheme, $filename);
1428 // The php://temp stream deletes the file after close
1429 $this->assertFileNotExists($filename);
1433 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1435 public function testTempnamWithPharSchemeFails()
1437 // Skip test if Phar disabled phar.readonly must be 0 in php.ini
1438 if (!\Phar::canWrite()) {
1439 $this->markTestSkipped('This test cannot run when phar.readonly is 1.');
1442 $scheme = 'phar://';
1443 $dirname = $scheme.$this->workspace;
1444 $pharname = 'foo.phar';
1446 new \Phar($this->workspace.'/'.$pharname, 0, $pharname);
1447 // 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
1448 $this->filesystem->tempnam($dirname, $pharname.'/bar');
1452 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1454 public function testTempnamWithHTTPSchemeFails()
1456 $scheme = 'http://';
1457 $dirname = $scheme.$this->workspace;
1459 // The http:// scheme is read-only
1460 $this->filesystem->tempnam($dirname, 'bar');
1463 public function testTempnamOnUnwritableFallsBackToSysTmp()
1465 $scheme = 'file://';
1466 $dirname = $scheme.$this->workspace.\DIRECTORY_SEPARATOR.'does_not_exist';
1468 $filename = $this->filesystem->tempnam($dirname, 'bar');
1469 $realTempDir = realpath(sys_get_temp_dir());
1470 $this->assertStringStartsWith(rtrim($scheme.$realTempDir, \DIRECTORY_SEPARATOR), $filename);
1471 $this->assertFileExists($filename);
1477 public function testDumpFile()
1479 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1481 // skip mode check on Windows
1482 if ('\\' !== \DIRECTORY_SEPARATOR) {
1483 $oldMask = umask(0002);
1486 $this->filesystem->dumpFile($filename, 'bar');
1487 $this->assertFileExists($filename);
1488 $this->assertStringEqualsFile($filename, 'bar');
1490 // skip mode check on Windows
1491 if ('\\' !== \DIRECTORY_SEPARATOR) {
1492 $this->assertFilePermissions(664, $filename);
1497 public function testDumpFileWithArray()
1499 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1501 $this->filesystem->dumpFile($filename, array('bar'));
1503 $this->assertFileExists($filename);
1504 $this->assertStringEqualsFile($filename, 'bar');
1507 public function testDumpFileWithResource()
1509 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1511 $resource = fopen('php://memory', 'rw');
1512 fwrite($resource, 'bar');
1513 fseek($resource, 0);
1515 $this->filesystem->dumpFile($filename, $resource);
1518 $this->assertFileExists($filename);
1519 $this->assertStringEqualsFile($filename, 'bar');
1522 public function testDumpFileOverwritesAnExistingFile()
1524 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt';
1525 file_put_contents($filename, 'FOO BAR');
1527 $this->filesystem->dumpFile($filename, 'bar');
1529 $this->assertFileExists($filename);
1530 $this->assertStringEqualsFile($filename, 'bar');
1533 public function testDumpFileWithFileScheme()
1535 if (\defined('HHVM_VERSION')) {
1536 $this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1539 $scheme = 'file://';
1540 $filename = $scheme.$this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1542 $this->filesystem->dumpFile($filename, 'bar');
1544 $this->assertFileExists($filename);
1545 $this->assertStringEqualsFile($filename, 'bar');
1548 public function testDumpFileWithZlibScheme()
1550 $scheme = 'compress.zlib://';
1551 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1553 $this->filesystem->dumpFile($filename, 'bar');
1555 // Zlib stat uses file:// wrapper so remove scheme
1556 $this->assertFileExists(str_replace($scheme, '', $filename));
1557 $this->assertStringEqualsFile($filename, 'bar');
1560 public function testAppendToFile()
1562 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'bar.txt';
1564 // skip mode check on Windows
1565 if ('\\' !== \DIRECTORY_SEPARATOR) {
1566 $oldMask = umask(0002);
1569 $this->filesystem->dumpFile($filename, 'foo');
1571 $this->filesystem->appendToFile($filename, 'bar');
1573 $this->assertFileExists($filename);
1574 $this->assertStringEqualsFile($filename, 'foobar');
1576 // skip mode check on Windows
1577 if ('\\' !== \DIRECTORY_SEPARATOR) {
1578 $this->assertFilePermissions(664, $filename);
1583 public function testAppendToFileWithScheme()
1585 if (\defined('HHVM_VERSION')) {
1586 $this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1589 $scheme = 'file://';
1590 $filename = $scheme.$this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1591 $this->filesystem->dumpFile($filename, 'foo');
1593 $this->filesystem->appendToFile($filename, 'bar');
1595 $this->assertFileExists($filename);
1596 $this->assertStringEqualsFile($filename, 'foobar');
1599 public function testAppendToFileWithZlibScheme()
1601 $scheme = 'compress.zlib://';
1602 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt';
1603 $this->filesystem->dumpFile($filename, 'foo');
1605 // Zlib stat uses file:// wrapper so remove it
1606 $this->assertStringEqualsFile(str_replace($scheme, '', $filename), 'foo');
1608 $this->filesystem->appendToFile($filename, 'bar');
1610 $this->assertFileExists($filename);
1611 $this->assertStringEqualsFile($filename, 'foobar');
1614 public function testAppendToFileCreateTheFileIfNotExists()
1616 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'bar.txt';
1618 // skip mode check on Windows
1619 if ('\\' !== \DIRECTORY_SEPARATOR) {
1620 $oldMask = umask(0002);
1623 $this->filesystem->appendToFile($filename, 'bar');
1625 // skip mode check on Windows
1626 if ('\\' !== \DIRECTORY_SEPARATOR) {
1627 $this->assertFilePermissions(664, $filename);
1631 $this->assertFileExists($filename);
1632 $this->assertStringEqualsFile($filename, 'bar');
1635 public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile()
1637 $this->markAsSkippedIfChmodIsMissing();
1639 $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt';
1640 file_put_contents($filename, 'FOO BAR');
1641 chmod($filename, 0745);
1643 $this->filesystem->dumpFile($filename, 'bar', null);
1645 $this->assertFilePermissions(745, $filename);
1648 public function testCopyShouldKeepExecutionPermission()
1650 $this->markAsSkippedIfChmodIsMissing();
1652 $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
1653 $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
1655 file_put_contents($sourceFilePath, 'SOURCE FILE');
1656 chmod($sourceFilePath, 0745);
1658 $this->filesystem->copy($sourceFilePath, $targetFilePath);
1660 $this->assertFilePermissions(767, $targetFilePath);
1664 * Normalize the given path (transform each blackslash into a real directory separator).
1666 * @param string $path
1670 private function normalize($path)
1672 return str_replace('/', \DIRECTORY_SEPARATOR, $path);