scratch – Blame information for rev 115

Subversion Repositories:
Rev:
Rev Author Line No. Line
115 office 1 <?php
2  
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11  
12 namespace Symfony\Component\Filesystem\Tests;
13  
14 /**
15 * Test class for Filesystem.
16 */
17 class FilesystemTest extends FilesystemTestCase
18 {
19 public function testCopyCreatesNewFile()
20 {
21 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
22 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
23  
24 file_put_contents($sourceFilePath, 'SOURCE FILE');
25  
26 $this->filesystem->copy($sourceFilePath, $targetFilePath);
27  
28 $this->assertFileExists($targetFilePath);
29 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
30 }
31  
32 /**
33 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
34 */
35 public function testCopyFails()
36 {
37 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
38 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
39  
40 $this->filesystem->copy($sourceFilePath, $targetFilePath);
41 }
42  
43 /**
44 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
45 */
46 public function testCopyUnreadableFileFails()
47 {
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.');
51 }
52  
53 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
54 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
55  
56 file_put_contents($sourceFilePath, 'SOURCE FILE');
57  
58 // make sure target cannot be read
59 $this->filesystem->chmod($sourceFilePath, 0222);
60  
61 $this->filesystem->copy($sourceFilePath, $targetFilePath);
62 }
63  
64 public function testCopyOverridesExistingFileIfModified()
65 {
66 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
67 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
68  
69 file_put_contents($sourceFilePath, 'SOURCE FILE');
70 file_put_contents($targetFilePath, 'TARGET FILE');
71 touch($targetFilePath, time() - 1000);
72  
73 $this->filesystem->copy($sourceFilePath, $targetFilePath);
74  
75 $this->assertFileExists($targetFilePath);
76 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
77 }
78  
79 public function testCopyDoesNotOverrideExistingFileByDefault()
80 {
81 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
82 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
83  
84 file_put_contents($sourceFilePath, 'SOURCE FILE');
85 file_put_contents($targetFilePath, 'TARGET FILE');
86  
87 // make sure both files have the same modification time
88 $modificationTime = time() - 1000;
89 touch($sourceFilePath, $modificationTime);
90 touch($targetFilePath, $modificationTime);
91  
92 $this->filesystem->copy($sourceFilePath, $targetFilePath);
93  
94 $this->assertFileExists($targetFilePath);
95 $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
96 }
97  
98 public function testCopyOverridesExistingFileIfForced()
99 {
100 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
101 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
102  
103 file_put_contents($sourceFilePath, 'SOURCE FILE');
104 file_put_contents($targetFilePath, 'TARGET FILE');
105  
106 // make sure both files have the same modification time
107 $modificationTime = time() - 1000;
108 touch($sourceFilePath, $modificationTime);
109 touch($targetFilePath, $modificationTime);
110  
111 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
112  
113 $this->assertFileExists($targetFilePath);
114 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
115 }
116  
117 /**
118 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
119 */
120 public function testCopyWithOverrideWithReadOnlyTargetFails()
121 {
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.');
125 }
126  
127 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
128 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
129  
130 file_put_contents($sourceFilePath, 'SOURCE FILE');
131 file_put_contents($targetFilePath, 'TARGET FILE');
132  
133 // make sure both files have the same modification time
134 $modificationTime = time() - 1000;
135 touch($sourceFilePath, $modificationTime);
136 touch($targetFilePath, $modificationTime);
137  
138 // make sure target is read-only
139 $this->filesystem->chmod($targetFilePath, 0444);
140  
141 $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
142 }
143  
144 public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
145 {
146 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
147 $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
148 $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
149  
150 file_put_contents($sourceFilePath, 'SOURCE FILE');
151  
152 $this->filesystem->copy($sourceFilePath, $targetFilePath);
153  
154 $this->assertTrue(is_dir($targetFileDirectory));
155 $this->assertFileExists($targetFilePath);
156 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
157 }
158  
159 /**
160 * @group network
161 */
162 public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy()
163 {
164 $sourceFilePath = 'http://symfony.com/images/common/logo/logo_symfony_header.png';
165 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
166  
167 file_put_contents($targetFilePath, 'TARGET FILE');
168  
169 $this->filesystem->copy($sourceFilePath, $targetFilePath, false);
170  
171 $this->assertFileExists($targetFilePath);
172 $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath));
173 }
174  
175 public function testMkdirCreatesDirectoriesRecursively()
176 {
177 $directory = $this->workspace
178 .DIRECTORY_SEPARATOR.'directory'
179 .DIRECTORY_SEPARATOR.'sub_directory';
180  
181 $this->filesystem->mkdir($directory);
182  
183 $this->assertTrue(is_dir($directory));
184 }
185  
186 public function testMkdirCreatesDirectoriesFromArray()
187 {
188 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
189 $directories = array(
190 $basePath.'1', $basePath.'2', $basePath.'3',
191 );
192  
193 $this->filesystem->mkdir($directories);
194  
195 $this->assertTrue(is_dir($basePath.'1'));
196 $this->assertTrue(is_dir($basePath.'2'));
197 $this->assertTrue(is_dir($basePath.'3'));
198 }
199  
200 public function testMkdirCreatesDirectoriesFromTraversableObject()
201 {
202 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
203 $directories = new \ArrayObject(array(
204 $basePath.'1', $basePath.'2', $basePath.'3',
205 ));
206  
207 $this->filesystem->mkdir($directories);
208  
209 $this->assertTrue(is_dir($basePath.'1'));
210 $this->assertTrue(is_dir($basePath.'2'));
211 $this->assertTrue(is_dir($basePath.'3'));
212 }
213  
214 /**
215 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
216 */
217 public function testMkdirCreatesDirectoriesFails()
218 {
219 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
220 $dir = $basePath.'2';
221  
222 file_put_contents($dir, '');
223  
224 $this->filesystem->mkdir($dir);
225 }
226  
227 public function testTouchCreatesEmptyFile()
228 {
229 $file = $this->workspace.DIRECTORY_SEPARATOR.'1';
230  
231 $this->filesystem->touch($file);
232  
233 $this->assertFileExists($file);
234 }
235  
236 /**
237 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
238 */
239 public function testTouchFails()
240 {
241 $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
242  
243 $this->filesystem->touch($file);
244 }
245  
246 public function testTouchCreatesEmptyFilesFromArray()
247 {
248 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
249 $files = array(
250 $basePath.'1', $basePath.'2', $basePath.'3',
251 );
252  
253 $this->filesystem->touch($files);
254  
255 $this->assertFileExists($basePath.'1');
256 $this->assertFileExists($basePath.'2');
257 $this->assertFileExists($basePath.'3');
258 }
259  
260 public function testTouchCreatesEmptyFilesFromTraversableObject()
261 {
262 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
263 $files = new \ArrayObject(array(
264 $basePath.'1', $basePath.'2', $basePath.'3',
265 ));
266  
267 $this->filesystem->touch($files);
268  
269 $this->assertFileExists($basePath.'1');
270 $this->assertFileExists($basePath.'2');
271 $this->assertFileExists($basePath.'3');
272 }
273  
274 public function testRemoveCleansFilesAndDirectoriesIteratively()
275 {
276 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
277  
278 mkdir($basePath);
279 mkdir($basePath.'dir');
280 touch($basePath.'file');
281  
282 $this->filesystem->remove($basePath);
283  
284 $this->assertFileNotExists($basePath);
285 }
286  
287 public function testRemoveCleansArrayOfFilesAndDirectories()
288 {
289 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
290  
291 mkdir($basePath.'dir');
292 touch($basePath.'file');
293  
294 $files = array(
295 $basePath.'dir', $basePath.'file',
296 );
297  
298 $this->filesystem->remove($files);
299  
300 $this->assertFileNotExists($basePath.'dir');
301 $this->assertFileNotExists($basePath.'file');
302 }
303  
304 public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
305 {
306 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
307  
308 mkdir($basePath.'dir');
309 touch($basePath.'file');
310  
311 $files = new \ArrayObject(array(
312 $basePath.'dir', $basePath.'file',
313 ));
314  
315 $this->filesystem->remove($files);
316  
317 $this->assertFileNotExists($basePath.'dir');
318 $this->assertFileNotExists($basePath.'file');
319 }
320  
321 public function testRemoveIgnoresNonExistingFiles()
322 {
323 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
324  
325 mkdir($basePath.'dir');
326  
327 $files = array(
328 $basePath.'dir', $basePath.'file',
329 );
330  
331 $this->filesystem->remove($files);
332  
333 $this->assertFileNotExists($basePath.'dir');
334 }
335  
336 public function testRemoveCleansInvalidLinks()
337 {
338 $this->markAsSkippedIfSymlinkIsMissing();
339  
340 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
341  
342 mkdir($basePath);
343 mkdir($basePath.'dir');
344 // create symlink to nonexistent file
345 @symlink($basePath.'file', $basePath.'file-link');
346  
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'));
350  
351 // create symlink to nonexistent dir
352 rmdir($basePath.'dir');
353 $this->assertFalse('\\' === DIRECTORY_SEPARATOR ? @readlink($basePath.'dir-link') : is_dir($basePath.'dir-link'));
354  
355 $this->filesystem->remove($basePath);
356  
357 $this->assertFileNotExists($basePath);
358 }
359  
360 public function testFilesExists()
361 {
362 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
363  
364 mkdir($basePath);
365 touch($basePath.'file1');
366 mkdir($basePath.'folder');
367  
368 $this->assertTrue($this->filesystem->exists($basePath.'file1'));
369 $this->assertTrue($this->filesystem->exists($basePath.'folder'));
370 }
371  
372 /**
373 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
374 */
375 public function testFilesExistsFails()
376 {
377 if ('\\' !== DIRECTORY_SEPARATOR) {
378 $this->markTestSkipped('Test covers edge case on Windows only.');
379 }
380  
381 $basePath = $this->workspace.'\\directory\\';
382  
383 $oldPath = getcwd();
384 mkdir($basePath);
385 chdir($basePath);
386 $file = str_repeat('T', 259 - strlen($basePath));
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
390 chdir($oldPath);
391 $this->filesystem->exists($path);
392 }
393  
394 public function testFilesExistsTraversableObjectOfFilesAndDirectories()
395 {
396 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
397  
398 mkdir($basePath.'dir');
399 touch($basePath.'file');
400  
401 $files = new \ArrayObject(array(
402 $basePath.'dir', $basePath.'file',
403 ));
404  
405 $this->assertTrue($this->filesystem->exists($files));
406 }
407  
408 public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
409 {
410 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
411  
412 mkdir($basePath.'dir');
413 touch($basePath.'file');
414 touch($basePath.'file2');
415  
416 $files = new \ArrayObject(array(
417 $basePath.'dir', $basePath.'file', $basePath.'file2',
418 ));
419  
420 unlink($basePath.'file');
421  
422 $this->assertFalse($this->filesystem->exists($files));
423 }
424  
425 public function testInvalidFileNotExists()
426 {
427 $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
428  
429 $this->assertFalse($this->filesystem->exists($basePath.time()));
430 }
431  
432 public function testChmodChangesFileMode()
433 {
434 $this->markAsSkippedIfChmodIsMissing();
435  
436 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
437 mkdir($dir);
438 $file = $dir.DIRECTORY_SEPARATOR.'file';
439 touch($file);
440  
441 $this->filesystem->chmod($file, 0400);
442 $this->filesystem->chmod($dir, 0753);
443  
444 $this->assertFilePermissions(753, $dir);
445 $this->assertFilePermissions(400, $file);
446 }
447  
448 public function testChmodWithWrongModLeavesPreviousPermissionsUntouched()
449 {
450 $this->markAsSkippedIfChmodIsMissing();
451  
452 if (defined('HHVM_VERSION')) {
453 $this->markTestSkipped('chmod() changes permissions even when passing invalid modes on HHVM');
454 }
455  
456 $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
457 touch($dir);
458  
459 $permissions = fileperms($dir);
460  
461 $this->filesystem->chmod($dir, 'Wrongmode');
462  
463 $this->assertSame($permissions, fileperms($dir));
464 }
465  
466 public function testChmodRecursive()
467 {
468 $this->markAsSkippedIfChmodIsMissing();
469  
470 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
471 mkdir($dir);
472 $file = $dir.DIRECTORY_SEPARATOR.'file';
473 touch($file);
474  
475 $this->filesystem->chmod($file, 0400, 0000, true);
476 $this->filesystem->chmod($dir, 0753, 0000, true);
477  
478 $this->assertFilePermissions(753, $dir);
479 $this->assertFilePermissions(753, $file);
480 }
481  
482 public function testChmodAppliesUmask()
483 {
484 $this->markAsSkippedIfChmodIsMissing();
485  
486 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
487 touch($file);
488  
489 $this->filesystem->chmod($file, 0770, 0022);
490 $this->assertFilePermissions(750, $file);
491 }
492  
493 public function testChmodChangesModeOfArrayOfFiles()
494 {
495 $this->markAsSkippedIfChmodIsMissing();
496  
497 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
498 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
499 $files = array($directory, $file);
500  
501 mkdir($directory);
502 touch($file);
503  
504 $this->filesystem->chmod($files, 0753);
505  
506 $this->assertFilePermissions(753, $file);
507 $this->assertFilePermissions(753, $directory);
508 }
509  
510 public function testChmodChangesModeOfTraversableFileObject()
511 {
512 $this->markAsSkippedIfChmodIsMissing();
513  
514 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
515 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
516 $files = new \ArrayObject(array($directory, $file));
517  
518 mkdir($directory);
519 touch($file);
520  
521 $this->filesystem->chmod($files, 0753);
522  
523 $this->assertFilePermissions(753, $file);
524 $this->assertFilePermissions(753, $directory);
525 }
526  
527 public function testChmodChangesZeroModeOnSubdirectoriesOnRecursive()
528 {
529 $this->markAsSkippedIfChmodIsMissing();
530  
531 $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
532 $subdirectory = $directory.DIRECTORY_SEPARATOR.'subdirectory';
533  
534 mkdir($directory);
535 mkdir($subdirectory);
536 chmod($subdirectory, 0000);
537  
538 $this->filesystem->chmod($directory, 0753, 0000, true);
539  
540 $this->assertFilePermissions(753, $subdirectory);
541 }
542  
543 public function testChown()
544 {
545 $this->markAsSkippedIfPosixIsMissing();
546  
547 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
548 mkdir($dir);
549  
550 $owner = $this->getFileOwner($dir);
551 $this->filesystem->chown($dir, $owner);
552  
553 $this->assertSame($owner, $this->getFileOwner($dir));
554 }
555  
556 public function testChownRecursive()
557 {
558 $this->markAsSkippedIfPosixIsMissing();
559  
560 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
561 mkdir($dir);
562 $file = $dir.DIRECTORY_SEPARATOR.'file';
563 touch($file);
564  
565 $owner = $this->getFileOwner($dir);
566 $this->filesystem->chown($dir, $owner, true);
567  
568 $this->assertSame($owner, $this->getFileOwner($file));
569 }
570  
571 public function testChownSymlink()
572 {
573 $this->markAsSkippedIfSymlinkIsMissing();
574  
575 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
576 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
577  
578 touch($file);
579  
580 $this->filesystem->symlink($file, $link);
581  
582 $owner = $this->getFileOwner($link);
583 $this->filesystem->chown($link, $owner);
584  
585 $this->assertSame($owner, $this->getFileOwner($link));
586 }
587  
588 public function testChownLink()
589 {
590 $this->markAsSkippedIfLinkIsMissing();
591  
592 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
593 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
594  
595 touch($file);
596  
597 $this->filesystem->hardlink($file, $link);
598  
599 $owner = $this->getFileOwner($link);
600 $this->filesystem->chown($link, $owner);
601  
602 $this->assertSame($owner, $this->getFileOwner($link));
603 }
604  
605 /**
606 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
607 */
608 public function testChownSymlinkFails()
609 {
610 $this->markAsSkippedIfSymlinkIsMissing();
611  
612 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
613 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
614  
615 touch($file);
616  
617 $this->filesystem->symlink($file, $link);
618  
619 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
620 }
621  
622 /**
623 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
624 */
625 public function testChownLinkFails()
626 {
627 $this->markAsSkippedIfLinkIsMissing();
628  
629 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
630 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
631  
632 touch($file);
633  
634 $this->filesystem->hardlink($file, $link);
635  
636 $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
637 }
638  
639 /**
640 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
641 */
642 public function testChownFail()
643 {
644 $this->markAsSkippedIfPosixIsMissing();
645  
646 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
647 mkdir($dir);
648  
649 $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
650 }
651  
652 public function testChgrp()
653 {
654 $this->markAsSkippedIfPosixIsMissing();
655  
656 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
657 mkdir($dir);
658  
659 $group = $this->getFileGroup($dir);
660 $this->filesystem->chgrp($dir, $group);
661  
662 $this->assertSame($group, $this->getFileGroup($dir));
663 }
664  
665 public function testChgrpRecursive()
666 {
667 $this->markAsSkippedIfPosixIsMissing();
668  
669 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
670 mkdir($dir);
671 $file = $dir.DIRECTORY_SEPARATOR.'file';
672 touch($file);
673  
674 $group = $this->getFileGroup($dir);
675 $this->filesystem->chgrp($dir, $group, true);
676  
677 $this->assertSame($group, $this->getFileGroup($file));
678 }
679  
680 public function testChgrpSymlink()
681 {
682 $this->markAsSkippedIfSymlinkIsMissing();
683  
684 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
685 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
686  
687 touch($file);
688  
689 $this->filesystem->symlink($file, $link);
690  
691 $group = $this->getFileGroup($link);
692 $this->filesystem->chgrp($link, $group);
693  
694 $this->assertSame($group, $this->getFileGroup($link));
695 }
696  
697 public function testChgrpLink()
698 {
699 $this->markAsSkippedIfLinkIsMissing();
700  
701 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
702 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
703  
704 touch($file);
705  
706 $this->filesystem->hardlink($file, $link);
707  
708 $group = $this->getFileGroup($link);
709 $this->filesystem->chgrp($link, $group);
710  
711 $this->assertSame($group, $this->getFileGroup($link));
712 }
713  
714 /**
715 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
716 */
717 public function testChgrpSymlinkFails()
718 {
719 $this->markAsSkippedIfSymlinkIsMissing();
720  
721 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
722 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
723  
724 touch($file);
725  
726 $this->filesystem->symlink($file, $link);
727  
728 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
729 }
730  
731 /**
732 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
733 */
734 public function testChgrpLinkFails()
735 {
736 $this->markAsSkippedIfLinkIsMissing();
737  
738 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
739 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
740  
741 touch($file);
742  
743 $this->filesystem->hardlink($file, $link);
744  
745 $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
746 }
747  
748 /**
749 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
750 */
751 public function testChgrpFail()
752 {
753 $this->markAsSkippedIfPosixIsMissing();
754  
755 $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
756 mkdir($dir);
757  
758 $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
759 }
760  
761 public function testRename()
762 {
763 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
764 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
765 touch($file);
766  
767 $this->filesystem->rename($file, $newPath);
768  
769 $this->assertFileNotExists($file);
770 $this->assertFileExists($newPath);
771 }
772  
773 /**
774 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
775 */
776 public function testRenameThrowsExceptionIfTargetAlreadyExists()
777 {
778 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
779 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
780  
781 touch($file);
782 touch($newPath);
783  
784 $this->filesystem->rename($file, $newPath);
785 }
786  
787 public function testRenameOverwritesTheTargetIfItAlreadyExists()
788 {
789 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
790 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
791  
792 touch($file);
793 touch($newPath);
794  
795 $this->filesystem->rename($file, $newPath, true);
796  
797 $this->assertFileNotExists($file);
798 $this->assertFileExists($newPath);
799 }
800  
801 /**
802 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
803 */
804 public function testRenameThrowsExceptionOnError()
805 {
806 $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid('fs_test_', true);
807 $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
808  
809 $this->filesystem->rename($file, $newPath);
810 }
811  
812 public function testSymlink()
813 {
814 if ('\\' === DIRECTORY_SEPARATOR) {
815 $this->markTestSkipped('Windows does not support creating "broken" symlinks');
816 }
817  
818 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
819 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
820  
821 // $file does not exists right now: creating "broken" links is a wanted feature
822 $this->filesystem->symlink($file, $link);
823  
824 $this->assertTrue(is_link($link));
825  
826 // Create the linked file AFTER creating the link
827 touch($file);
828  
829 $this->assertEquals($file, readlink($link));
830 }
831  
832 /**
833 * @depends testSymlink
834 */
835 public function testRemoveSymlink()
836 {
837 $this->markAsSkippedIfSymlinkIsMissing();
838  
839 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
840  
841 $this->filesystem->remove($link);
842  
843 $this->assertTrue(!is_link($link));
844 $this->assertTrue(!is_file($link));
845 $this->assertTrue(!is_dir($link));
846 }
847  
848 public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
849 {
850 $this->markAsSkippedIfSymlinkIsMissing();
851  
852 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
853 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
854  
855 touch($file);
856 symlink($this->workspace, $link);
857  
858 $this->filesystem->symlink($file, $link);
859  
860 $this->assertTrue(is_link($link));
861 $this->assertEquals($file, readlink($link));
862 }
863  
864 public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
865 {
866 $this->markAsSkippedIfSymlinkIsMissing();
867  
868 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
869 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
870  
871 touch($file);
872 symlink($file, $link);
873  
874 $this->filesystem->symlink($file, $link);
875  
876 $this->assertTrue(is_link($link));
877 $this->assertEquals($file, readlink($link));
878 }
879  
880 public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
881 {
882 $this->markAsSkippedIfSymlinkIsMissing();
883  
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';
887  
888 touch($file);
889  
890 $this->filesystem->symlink($file, $link1);
891 $this->filesystem->symlink($file, $link2);
892  
893 $this->assertTrue(is_link($link1));
894 $this->assertEquals($file, readlink($link1));
895 $this->assertTrue(is_link($link2));
896 $this->assertEquals($file, readlink($link2));
897 }
898  
899 public function testLink()
900 {
901 $this->markAsSkippedIfLinkIsMissing();
902  
903 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
904 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
905  
906 touch($file);
907 $this->filesystem->hardlink($file, $link);
908  
909 $this->assertTrue(is_file($link));
910 $this->assertEquals(fileinode($file), fileinode($link));
911 }
912  
913 /**
914 * @depends testLink
915 */
916 public function testRemoveLink()
917 {
918 $this->markAsSkippedIfLinkIsMissing();
919  
920 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
921  
922 $this->filesystem->remove($link);
923  
924 $this->assertTrue(!is_file($link));
925 }
926  
927 public function testLinkIsOverwrittenIfPointsToDifferentTarget()
928 {
929 $this->markAsSkippedIfLinkIsMissing();
930  
931 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
932 $file2 = $this->workspace.DIRECTORY_SEPARATOR.'file2';
933 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
934  
935 touch($file);
936 touch($file2);
937 link($file2, $link);
938  
939 $this->filesystem->hardlink($file, $link);
940  
941 $this->assertTrue(is_file($link));
942 $this->assertEquals(fileinode($file), fileinode($link));
943 }
944  
945 public function testLinkIsNotOverwrittenIfAlreadyCreated()
946 {
947 $this->markAsSkippedIfLinkIsMissing();
948  
949 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
950 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
951  
952 touch($file);
953 link($file, $link);
954  
955 $this->filesystem->hardlink($file, $link);
956  
957 $this->assertTrue(is_file($link));
958 $this->assertEquals(fileinode($file), fileinode($link));
959 }
960  
961 public function testLinkWithSeveralTargets()
962 {
963 $this->markAsSkippedIfLinkIsMissing();
964  
965 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
966 $link1 = $this->workspace.DIRECTORY_SEPARATOR.'link';
967 $link2 = $this->workspace.DIRECTORY_SEPARATOR.'link2';
968  
969 touch($file);
970  
971 $this->filesystem->hardlink($file, array($link1, $link2));
972  
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));
977 }
978  
979 public function testLinkWithSameTarget()
980 {
981 $this->markAsSkippedIfLinkIsMissing();
982  
983 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
984 $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
985  
986 touch($file);
987  
988 // practically same as testLinkIsNotOverwrittenIfAlreadyCreated
989 $this->filesystem->hardlink($file, array($link, $link));
990  
991 $this->assertTrue(is_file($link));
992 $this->assertEquals(fileinode($file), fileinode($link));
993 }
994  
995 public function testReadRelativeLink()
996 {
997 $this->markAsSkippedIfSymlinkIsMissing();
998  
999 if ('\\' === DIRECTORY_SEPARATOR) {
1000 $this->markTestSkipped('Relative symbolic links are not supported on Windows');
1001 }
1002  
1003 $file = $this->workspace.'/file';
1004 $link1 = $this->workspace.'/dir/link';
1005 $link2 = $this->workspace.'/dir/link2';
1006 touch($file);
1007  
1008 $this->filesystem->symlink('../file', $link1);
1009 $this->filesystem->symlink('link', $link2);
1010  
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));
1016 }
1017  
1018 public function testReadAbsoluteLink()
1019 {
1020 $this->markAsSkippedIfSymlinkIsMissing();
1021  
1022 $file = $this->normalize($this->workspace.'/file');
1023 $link1 = $this->normalize($this->workspace.'/dir/link');
1024 $link2 = $this->normalize($this->workspace.'/dir/link2');
1025 touch($file);
1026  
1027 $this->filesystem->symlink($file, $link1);
1028 $this->filesystem->symlink($link1, $link2);
1029  
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));
1035 }
1036  
1037 public function testReadBrokenLink()
1038 {
1039 $this->markAsSkippedIfSymlinkIsMissing();
1040  
1041 if ('\\' === DIRECTORY_SEPARATOR) {
1042 $this->markTestSkipped('Windows does not support creating "broken" symlinks');
1043 }
1044  
1045 $file = $this->workspace.'/file';
1046 $link = $this->workspace.'/link';
1047  
1048 $this->filesystem->symlink($file, $link);
1049  
1050 $this->assertEquals($file, $this->filesystem->readlink($link));
1051 $this->assertNull($this->filesystem->readlink($link, true));
1052  
1053 touch($file);
1054 $this->assertEquals($file, $this->filesystem->readlink($link, true));
1055 }
1056  
1057 public function testReadLinkDefaultPathDoesNotExist()
1058 {
1059 $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'/invalid')));
1060 }
1061  
1062 public function testReadLinkDefaultPathNotLink()
1063 {
1064 $file = $this->normalize($this->workspace.'/file');
1065 touch($file);
1066  
1067 $this->assertNull($this->filesystem->readlink($file));
1068 }
1069  
1070 public function testReadLinkCanonicalizePath()
1071 {
1072 $this->markAsSkippedIfSymlinkIsMissing();
1073  
1074 $file = $this->normalize($this->workspace.'/file');
1075 mkdir($this->normalize($this->workspace.'/dir'));
1076 touch($file);
1077  
1078 $this->assertEquals($file, $this->filesystem->readlink($this->normalize($this->workspace.'/dir/../file'), true));
1079 }
1080  
1081 public function testReadLinkCanonicalizedPathDoesNotExist()
1082 {
1083 $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'invalid'), true));
1084 }
1085  
1086 /**
1087 * @dataProvider providePathsForMakePathRelative
1088 */
1089 public function testMakePathRelative($endPath, $startPath, $expectedPath)
1090 {
1091 $path = $this->filesystem->makePathRelative($endPath, $startPath);
1092  
1093 $this->assertEquals($expectedPath, $path);
1094 }
1095  
1096 /**
1097 * @return array
1098 */
1099 public function providePathsForMakePathRelative()
1100 {
1101 $paths = array(
1102 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
1103 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
1104 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
1105 array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
1106 array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
1107 array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
1108 array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
1109 array('/aa/bb', '/aa/bb', './'),
1110 array('/aa/bb', '/aa/bb/', './'),
1111 array('/aa/bb/', '/aa/bb', './'),
1112 array('/aa/bb/', '/aa/bb/', './'),
1113 array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
1114 array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
1115 array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
1116 array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
1117 array('/aa/bb/cc', '/aa', 'bb/cc/'),
1118 array('/aa/bb/cc', '/aa/', 'bb/cc/'),
1119 array('/aa/bb/cc/', '/aa', 'bb/cc/'),
1120 array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
1121 array('/a/aab/bb', '/a/aa', '../aab/bb/'),
1122 array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
1123 array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
1124 array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
1125 array('/a/aab/bb/', '/', 'a/aab/bb/'),
1126 array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
1127 array('/aab/bb', '/aa', '../aab/bb/'),
1128 array('/aab', '/aa', '../aab/'),
1129 array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1130 array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1131 array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'),
1132 array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1133 array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1134 array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1135 array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'),
1136 array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
1137 array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1138 array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
1139 );
1140  
1141 if ('\\' === DIRECTORY_SEPARATOR) {
1142 $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
1143 }
1144  
1145 return $paths;
1146 }
1147  
1148 public function testMirrorCopiesFilesAndDirectoriesRecursively()
1149 {
1150 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1151 $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
1152 $file1 = $directory.'file1';
1153 $file2 = $sourcePath.'file2';
1154  
1155 mkdir($sourcePath);
1156 mkdir($directory);
1157 file_put_contents($file1, 'FILE1');
1158 file_put_contents($file2, 'FILE2');
1159  
1160 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1161  
1162 $this->filesystem->mirror($sourcePath, $targetPath);
1163  
1164 $this->assertTrue(is_dir($targetPath));
1165 $this->assertTrue(is_dir($targetPath.'directory'));
1166 $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
1167 $this->assertFileEquals($file2, $targetPath.'file2');
1168  
1169 $this->filesystem->remove($file1);
1170  
1171 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
1172 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1173  
1174 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1175 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1176  
1177 file_put_contents($file1, 'FILE1');
1178  
1179 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1180 $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1181  
1182 $this->filesystem->remove($directory);
1183 $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
1184 $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
1185 $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
1186 }
1187  
1188 public function testMirrorCreatesEmptyDirectory()
1189 {
1190 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1191  
1192 mkdir($sourcePath);
1193  
1194 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1195  
1196 $this->filesystem->mirror($sourcePath, $targetPath);
1197  
1198 $this->assertTrue(is_dir($targetPath));
1199  
1200 $this->filesystem->remove($sourcePath);
1201 }
1202  
1203 public function testMirrorCopiesLinks()
1204 {
1205 $this->markAsSkippedIfSymlinkIsMissing();
1206  
1207 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1208  
1209 mkdir($sourcePath);
1210 file_put_contents($sourcePath.'file1', 'FILE1');
1211 symlink($sourcePath.'file1', $sourcePath.'link1');
1212  
1213 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1214  
1215 $this->filesystem->mirror($sourcePath, $targetPath);
1216  
1217 $this->assertTrue(is_dir($targetPath));
1218 $this->assertFileEquals($sourcePath.'file1', $targetPath.'link1');
1219 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
1220 }
1221  
1222 public function testMirrorCopiesLinkedDirectoryContents()
1223 {
1224 $this->markAsSkippedIfSymlinkIsMissing(true);
1225  
1226 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1227  
1228 mkdir($sourcePath.'nested/', 0777, true);
1229 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
1230 // Note: We symlink directory, not file
1231 symlink($sourcePath.'nested', $sourcePath.'link1');
1232  
1233 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1234  
1235 $this->filesystem->mirror($sourcePath, $targetPath);
1236  
1237 $this->assertTrue(is_dir($targetPath));
1238 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
1239 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
1240 }
1241  
1242 public function testMirrorCopiesRelativeLinkedContents()
1243 {
1244 $this->markAsSkippedIfSymlinkIsMissing(true);
1245  
1246 $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
1247 $oldPath = getcwd();
1248  
1249 mkdir($sourcePath.'nested/', 0777, true);
1250 file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
1251 // Note: Create relative symlink
1252 chdir($sourcePath);
1253 symlink('nested', 'link1');
1254  
1255 chdir($oldPath);
1256  
1257 $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
1258  
1259 $this->filesystem->mirror($sourcePath, $targetPath);
1260  
1261 $this->assertTrue(is_dir($targetPath));
1262 $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
1263 $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
1264 $this->assertEquals('\\' === DIRECTORY_SEPARATOR ? realpath($sourcePath.'\nested') : 'nested', readlink($targetPath.DIRECTORY_SEPARATOR.'link1'));
1265 }
1266  
1267 /**
1268 * @dataProvider providePathsForIsAbsolutePath
1269 */
1270 public function testIsAbsolutePath($path, $expectedResult)
1271 {
1272 $result = $this->filesystem->isAbsolutePath($path);
1273  
1274 $this->assertEquals($expectedResult, $result);
1275 }
1276  
1277 /**
1278 * @return array
1279 */
1280 public function providePathsForIsAbsolutePath()
1281 {
1282 return array(
1283 array('/var/lib', true),
1284 array('c:\\\\var\\lib', true),
1285 array('\\var\\lib', true),
1286 array('var/lib', false),
1287 array('../var/lib', false),
1288 array('', false),
1289 array(null, false),
1290 );
1291 }
1292  
1293 public function testTempnam()
1294 {
1295 $dirname = $this->workspace;
1296  
1297 $filename = $this->filesystem->tempnam($dirname, 'foo');
1298  
1299 $this->assertFileExists($filename);
1300 }
1301  
1302 public function testTempnamWithFileScheme()
1303 {
1304 $scheme = 'file://';
1305 $dirname = $scheme.$this->workspace;
1306  
1307 $filename = $this->filesystem->tempnam($dirname, 'foo');
1308  
1309 $this->assertStringStartsWith($scheme, $filename);
1310 $this->assertFileExists($filename);
1311 }
1312  
1313 public function testTempnamWithMockScheme()
1314 {
1315 stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream');
1316  
1317 $scheme = 'mock://';
1318 $dirname = $scheme.$this->workspace;
1319  
1320 $filename = $this->filesystem->tempnam($dirname, 'foo');
1321  
1322 $this->assertStringStartsWith($scheme, $filename);
1323 $this->assertFileExists($filename);
1324 }
1325  
1326 /**
1327 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1328 */
1329 public function testTempnamWithZlibSchemeFails()
1330 {
1331 $scheme = 'compress.zlib://';
1332 $dirname = $scheme.$this->workspace;
1333  
1334 // The compress.zlib:// stream does not support mode x: creates the file, errors "failed to open stream: operation failed" and returns false
1335 $this->filesystem->tempnam($dirname, 'bar');
1336 }
1337  
1338 public function testTempnamWithPHPTempSchemeFails()
1339 {
1340 $scheme = 'php://temp';
1341 $dirname = $scheme;
1342  
1343 $filename = $this->filesystem->tempnam($dirname, 'bar');
1344  
1345 $this->assertStringStartsWith($scheme, $filename);
1346  
1347 // The php://temp stream deletes the file after close
1348 $this->assertFileNotExists($filename);
1349 }
1350  
1351 /**
1352 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1353 */
1354 public function testTempnamWithPharSchemeFails()
1355 {
1356 // Skip test if Phar disabled phar.readonly must be 0 in php.ini
1357 if (!\Phar::canWrite()) {
1358 $this->markTestSkipped('This test cannot run when phar.readonly is 1.');
1359 }
1360  
1361 $scheme = 'phar://';
1362 $dirname = $scheme.$this->workspace;
1363 $pharname = 'foo.phar';
1364  
1365 new \Phar($this->workspace.'/'.$pharname, 0, $pharname);
1366 // 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
1367 $this->filesystem->tempnam($dirname, $pharname.'/bar');
1368 }
1369  
1370 /**
1371 * @expectedException \Symfony\Component\Filesystem\Exception\IOException
1372 */
1373 public function testTempnamWithHTTPSchemeFails()
1374 {
1375 $scheme = 'http://';
1376 $dirname = $scheme.$this->workspace;
1377  
1378 // The http:// scheme is read-only
1379 $this->filesystem->tempnam($dirname, 'bar');
1380 }
1381  
1382 public function testTempnamOnUnwritableFallsBackToSysTmp()
1383 {
1384 $scheme = 'file://';
1385 $dirname = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'does_not_exist';
1386  
1387 $filename = $this->filesystem->tempnam($dirname, 'bar');
1388 $realTempDir = realpath(sys_get_temp_dir());
1389 $this->assertStringStartsWith(rtrim($scheme.$realTempDir, DIRECTORY_SEPARATOR), $filename);
1390 $this->assertFileExists($filename);
1391  
1392 // Tear down
1393 @unlink($filename);
1394 }
1395  
1396 public function testDumpFile()
1397 {
1398 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1399  
1400 // skip mode check on Windows
1401 if ('\\' !== DIRECTORY_SEPARATOR) {
1402 $oldMask = umask(0002);
1403 }
1404  
1405 $this->filesystem->dumpFile($filename, 'bar');
1406 $this->assertFileExists($filename);
1407 $this->assertSame('bar', file_get_contents($filename));
1408  
1409 // skip mode check on Windows
1410 if ('\\' !== DIRECTORY_SEPARATOR) {
1411 $this->assertFilePermissions(664, $filename);
1412 umask($oldMask);
1413 }
1414 }
1415  
1416 public function testDumpFileOverwritesAnExistingFile()
1417 {
1418 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
1419 file_put_contents($filename, 'FOO BAR');
1420  
1421 $this->filesystem->dumpFile($filename, 'bar');
1422  
1423 $this->assertFileExists($filename);
1424 $this->assertSame('bar', file_get_contents($filename));
1425 }
1426  
1427 public function testDumpFileWithFileScheme()
1428 {
1429 if (defined('HHVM_VERSION')) {
1430 $this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1431 }
1432  
1433 $scheme = 'file://';
1434 $filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1435  
1436 $this->filesystem->dumpFile($filename, 'bar');
1437  
1438 $this->assertFileExists($filename);
1439 $this->assertSame('bar', file_get_contents($filename));
1440 }
1441  
1442 public function testDumpFileWithZlibScheme()
1443 {
1444 $scheme = 'compress.zlib://';
1445 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1446  
1447 $this->filesystem->dumpFile($filename, 'bar');
1448  
1449 // Zlib stat uses file:// wrapper so remove scheme
1450 $this->assertFileExists(str_replace($scheme, '', $filename));
1451 $this->assertSame('bar', file_get_contents($filename));
1452 }
1453  
1454 public function testAppendToFile()
1455 {
1456 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.txt';
1457  
1458 // skip mode check on Windows
1459 if ('\\' !== DIRECTORY_SEPARATOR) {
1460 $oldMask = umask(0002);
1461 }
1462  
1463 $this->filesystem->dumpFile($filename, 'foo');
1464  
1465 $this->filesystem->appendToFile($filename, 'bar');
1466  
1467 $this->assertFileExists($filename);
1468 $this->assertSame('foobar', file_get_contents($filename));
1469  
1470 // skip mode check on Windows
1471 if ('\\' !== DIRECTORY_SEPARATOR) {
1472 $this->assertFilePermissions(664, $filename, 'The written file should keep the same permissions as before.');
1473 umask($oldMask);
1474 }
1475 }
1476  
1477 public function testAppendToFileWithScheme()
1478 {
1479 if (defined('HHVM_VERSION')) {
1480 $this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1481 }
1482  
1483 $scheme = 'file://';
1484 $filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1485 $this->filesystem->dumpFile($filename, 'foo');
1486  
1487 $this->filesystem->appendToFile($filename, 'bar');
1488  
1489 $this->assertFileExists($filename);
1490 $this->assertSame('foobar', file_get_contents($filename));
1491 }
1492  
1493 public function testAppendToFileWithZlibScheme()
1494 {
1495 $scheme = 'compress.zlib://';
1496 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1497 $this->filesystem->dumpFile($filename, 'foo');
1498  
1499 // Zlib stat uses file:// wrapper so remove it
1500 $this->assertSame('foo', file_get_contents(str_replace($scheme, '', $filename)));
1501  
1502 $this->filesystem->appendToFile($filename, 'bar');
1503  
1504 $this->assertFileExists($filename);
1505 $this->assertSame('foobar', file_get_contents($filename));
1506 }
1507  
1508 public function testAppendToFileCreateTheFileIfNotExists()
1509 {
1510 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.txt';
1511  
1512 // skip mode check on Windows
1513 if ('\\' !== DIRECTORY_SEPARATOR) {
1514 $oldMask = umask(0002);
1515 }
1516  
1517 $this->filesystem->appendToFile($filename, 'bar');
1518  
1519 // skip mode check on Windows
1520 if ('\\' !== DIRECTORY_SEPARATOR) {
1521 $this->assertFilePermissions(664, $filename);
1522 umask($oldMask);
1523 }
1524  
1525 $this->assertFileExists($filename);
1526 $this->assertSame('bar', file_get_contents($filename));
1527 }
1528  
1529 public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile()
1530 {
1531 $this->markAsSkippedIfChmodIsMissing();
1532  
1533 $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
1534 file_put_contents($filename, 'FOO BAR');
1535 chmod($filename, 0745);
1536  
1537 $this->filesystem->dumpFile($filename, 'bar', null);
1538  
1539 $this->assertFilePermissions(745, $filename);
1540 }
1541  
1542 public function testCopyShouldKeepExecutionPermission()
1543 {
1544 $this->markAsSkippedIfChmodIsMissing();
1545  
1546 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
1547 $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
1548  
1549 file_put_contents($sourceFilePath, 'SOURCE FILE');
1550 chmod($sourceFilePath, 0745);
1551  
1552 $this->filesystem->copy($sourceFilePath, $targetFilePath);
1553  
1554 $this->assertFilePermissions(767, $targetFilePath);
1555 }
1556  
1557 /**
1558 * Normalize the given path (transform each blackslash into a real directory separator).
1559 *
1560 * @param string $path
1561 *
1562 * @return string
1563 */
1564 private function normalize($path)
1565 {
1566 return str_replace('/', DIRECTORY_SEPARATOR, $path);
1567 }
1568 }