/vendor/symfony/filesystem/Tests/FilesystemTest.php

https://gitlab.com/xolotsoft/pumasruiz · PHP · 1015 lines · 675 code · 264 blank · 76 comment · 6 complexity · 5f555724d514b2b6efc24fd1bc219a22 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Filesystem\Tests;
  11. /**
  12. * Test class for Filesystem.
  13. */
  14. class FilesystemTest extends FilesystemTestCase
  15. {
  16. public function testCopyCreatesNewFile()
  17. {
  18. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  19. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  20. file_put_contents($sourceFilePath, 'SOURCE FILE');
  21. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  22. $this->assertFileExists($targetFilePath);
  23. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  24. }
  25. /**
  26. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  27. */
  28. public function testCopyFails()
  29. {
  30. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  31. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  32. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  33. }
  34. /**
  35. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  36. */
  37. public function testCopyUnreadableFileFails()
  38. {
  39. // skip test on Windows; PHP can't easily set file as unreadable on Windows
  40. if ('\\' === DIRECTORY_SEPARATOR) {
  41. $this->markTestSkipped('This test cannot run on Windows.');
  42. }
  43. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  44. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  45. file_put_contents($sourceFilePath, 'SOURCE FILE');
  46. // make sure target cannot be read
  47. $this->filesystem->chmod($sourceFilePath, 0222);
  48. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  49. }
  50. public function testCopyOverridesExistingFileIfModified()
  51. {
  52. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  53. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  54. file_put_contents($sourceFilePath, 'SOURCE FILE');
  55. file_put_contents($targetFilePath, 'TARGET FILE');
  56. touch($targetFilePath, time() - 1000);
  57. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  58. $this->assertFileExists($targetFilePath);
  59. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  60. }
  61. public function testCopyDoesNotOverrideExistingFileByDefault()
  62. {
  63. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  64. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  65. file_put_contents($sourceFilePath, 'SOURCE FILE');
  66. file_put_contents($targetFilePath, 'TARGET FILE');
  67. // make sure both files have the same modification time
  68. $modificationTime = time() - 1000;
  69. touch($sourceFilePath, $modificationTime);
  70. touch($targetFilePath, $modificationTime);
  71. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  72. $this->assertFileExists($targetFilePath);
  73. $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
  74. }
  75. public function testCopyOverridesExistingFileIfForced()
  76. {
  77. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  78. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  79. file_put_contents($sourceFilePath, 'SOURCE FILE');
  80. file_put_contents($targetFilePath, 'TARGET FILE');
  81. // make sure both files have the same modification time
  82. $modificationTime = time() - 1000;
  83. touch($sourceFilePath, $modificationTime);
  84. touch($targetFilePath, $modificationTime);
  85. $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
  86. $this->assertFileExists($targetFilePath);
  87. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  88. }
  89. /**
  90. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  91. */
  92. public function testCopyWithOverrideWithReadOnlyTargetFails()
  93. {
  94. // skip test on Windows; PHP can't easily set file as unwritable on Windows
  95. if ('\\' === DIRECTORY_SEPARATOR) {
  96. $this->markTestSkipped('This test cannot run on Windows.');
  97. }
  98. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  99. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  100. file_put_contents($sourceFilePath, 'SOURCE FILE');
  101. file_put_contents($targetFilePath, 'TARGET FILE');
  102. // make sure both files have the same modification time
  103. $modificationTime = time() - 1000;
  104. touch($sourceFilePath, $modificationTime);
  105. touch($targetFilePath, $modificationTime);
  106. // make sure target is read-only
  107. $this->filesystem->chmod($targetFilePath, 0444);
  108. $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
  109. }
  110. public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
  111. {
  112. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  113. $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  114. $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
  115. file_put_contents($sourceFilePath, 'SOURCE FILE');
  116. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  117. $this->assertTrue(is_dir($targetFileDirectory));
  118. $this->assertFileExists($targetFilePath);
  119. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  120. }
  121. public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToNotCopy()
  122. {
  123. $sourceFilePath = 'http://symfony.com/images/common/logo/logo_symfony_header.png';
  124. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  125. file_put_contents($targetFilePath, 'TARGET FILE');
  126. $this->filesystem->copy($sourceFilePath, $targetFilePath, false);
  127. $this->assertFileExists($targetFilePath);
  128. $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath));
  129. }
  130. public function testMkdirCreatesDirectoriesRecursively()
  131. {
  132. $directory = $this->workspace
  133. .DIRECTORY_SEPARATOR.'directory'
  134. .DIRECTORY_SEPARATOR.'sub_directory';
  135. $this->filesystem->mkdir($directory);
  136. $this->assertTrue(is_dir($directory));
  137. }
  138. public function testMkdirCreatesDirectoriesFromArray()
  139. {
  140. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  141. $directories = array(
  142. $basePath.'1', $basePath.'2', $basePath.'3',
  143. );
  144. $this->filesystem->mkdir($directories);
  145. $this->assertTrue(is_dir($basePath.'1'));
  146. $this->assertTrue(is_dir($basePath.'2'));
  147. $this->assertTrue(is_dir($basePath.'3'));
  148. }
  149. public function testMkdirCreatesDirectoriesFromTraversableObject()
  150. {
  151. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  152. $directories = new \ArrayObject(array(
  153. $basePath.'1', $basePath.'2', $basePath.'3',
  154. ));
  155. $this->filesystem->mkdir($directories);
  156. $this->assertTrue(is_dir($basePath.'1'));
  157. $this->assertTrue(is_dir($basePath.'2'));
  158. $this->assertTrue(is_dir($basePath.'3'));
  159. }
  160. /**
  161. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  162. */
  163. public function testMkdirCreatesDirectoriesFails()
  164. {
  165. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  166. $dir = $basePath.'2';
  167. file_put_contents($dir, '');
  168. $this->filesystem->mkdir($dir);
  169. }
  170. public function testTouchCreatesEmptyFile()
  171. {
  172. $file = $this->workspace.DIRECTORY_SEPARATOR.'1';
  173. $this->filesystem->touch($file);
  174. $this->assertFileExists($file);
  175. }
  176. /**
  177. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  178. */
  179. public function testTouchFails()
  180. {
  181. $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
  182. $this->filesystem->touch($file);
  183. }
  184. public function testTouchCreatesEmptyFilesFromArray()
  185. {
  186. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  187. $files = array(
  188. $basePath.'1', $basePath.'2', $basePath.'3',
  189. );
  190. $this->filesystem->touch($files);
  191. $this->assertFileExists($basePath.'1');
  192. $this->assertFileExists($basePath.'2');
  193. $this->assertFileExists($basePath.'3');
  194. }
  195. public function testTouchCreatesEmptyFilesFromTraversableObject()
  196. {
  197. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  198. $files = new \ArrayObject(array(
  199. $basePath.'1', $basePath.'2', $basePath.'3',
  200. ));
  201. $this->filesystem->touch($files);
  202. $this->assertFileExists($basePath.'1');
  203. $this->assertFileExists($basePath.'2');
  204. $this->assertFileExists($basePath.'3');
  205. }
  206. public function testRemoveCleansFilesAndDirectoriesIteratively()
  207. {
  208. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  209. mkdir($basePath);
  210. mkdir($basePath.'dir');
  211. touch($basePath.'file');
  212. $this->filesystem->remove($basePath);
  213. $this->assertTrue(!is_dir($basePath));
  214. }
  215. public function testRemoveCleansArrayOfFilesAndDirectories()
  216. {
  217. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  218. mkdir($basePath.'dir');
  219. touch($basePath.'file');
  220. $files = array(
  221. $basePath.'dir', $basePath.'file',
  222. );
  223. $this->filesystem->remove($files);
  224. $this->assertTrue(!is_dir($basePath.'dir'));
  225. $this->assertTrue(!is_file($basePath.'file'));
  226. }
  227. public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
  228. {
  229. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  230. mkdir($basePath.'dir');
  231. touch($basePath.'file');
  232. $files = new \ArrayObject(array(
  233. $basePath.'dir', $basePath.'file',
  234. ));
  235. $this->filesystem->remove($files);
  236. $this->assertTrue(!is_dir($basePath.'dir'));
  237. $this->assertTrue(!is_file($basePath.'file'));
  238. }
  239. public function testRemoveIgnoresNonExistingFiles()
  240. {
  241. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  242. mkdir($basePath.'dir');
  243. $files = array(
  244. $basePath.'dir', $basePath.'file',
  245. );
  246. $this->filesystem->remove($files);
  247. $this->assertTrue(!is_dir($basePath.'dir'));
  248. }
  249. public function testRemoveCleansInvalidLinks()
  250. {
  251. $this->markAsSkippedIfSymlinkIsMissing();
  252. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  253. mkdir($basePath);
  254. mkdir($basePath.'dir');
  255. // create symlink to nonexistent file
  256. @symlink($basePath.'file', $basePath.'link');
  257. $this->filesystem->remove($basePath);
  258. $this->assertTrue(!is_dir($basePath));
  259. }
  260. public function testFilesExists()
  261. {
  262. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  263. mkdir($basePath);
  264. touch($basePath.'file1');
  265. mkdir($basePath.'folder');
  266. $this->assertTrue($this->filesystem->exists($basePath.'file1'));
  267. $this->assertTrue($this->filesystem->exists($basePath.'folder'));
  268. }
  269. public function testFilesExistsTraversableObjectOfFilesAndDirectories()
  270. {
  271. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  272. mkdir($basePath.'dir');
  273. touch($basePath.'file');
  274. $files = new \ArrayObject(array(
  275. $basePath.'dir', $basePath.'file',
  276. ));
  277. $this->assertTrue($this->filesystem->exists($files));
  278. }
  279. public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
  280. {
  281. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  282. mkdir($basePath.'dir');
  283. touch($basePath.'file');
  284. touch($basePath.'file2');
  285. $files = new \ArrayObject(array(
  286. $basePath.'dir', $basePath.'file', $basePath.'file2',
  287. ));
  288. unlink($basePath.'file');
  289. $this->assertFalse($this->filesystem->exists($files));
  290. }
  291. public function testInvalidFileNotExists()
  292. {
  293. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  294. $this->assertFalse($this->filesystem->exists($basePath.time()));
  295. }
  296. public function testChmodChangesFileMode()
  297. {
  298. $this->markAsSkippedIfChmodIsMissing();
  299. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  300. mkdir($dir);
  301. $file = $dir.DIRECTORY_SEPARATOR.'file';
  302. touch($file);
  303. $this->filesystem->chmod($file, 0400);
  304. $this->filesystem->chmod($dir, 0753);
  305. $this->assertFilePermissions(753, $dir);
  306. $this->assertFilePermissions(400, $file);
  307. }
  308. public function testChmodWrongMod()
  309. {
  310. $this->markAsSkippedIfChmodIsMissing();
  311. $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
  312. touch($dir);
  313. $this->filesystem->chmod($dir, 'Wrongmode');
  314. }
  315. public function testChmodRecursive()
  316. {
  317. $this->markAsSkippedIfChmodIsMissing();
  318. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  319. mkdir($dir);
  320. $file = $dir.DIRECTORY_SEPARATOR.'file';
  321. touch($file);
  322. $this->filesystem->chmod($file, 0400, 0000, true);
  323. $this->filesystem->chmod($dir, 0753, 0000, true);
  324. $this->assertFilePermissions(753, $dir);
  325. $this->assertFilePermissions(753, $file);
  326. }
  327. public function testChmodAppliesUmask()
  328. {
  329. $this->markAsSkippedIfChmodIsMissing();
  330. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  331. touch($file);
  332. $this->filesystem->chmod($file, 0770, 0022);
  333. $this->assertFilePermissions(750, $file);
  334. }
  335. public function testChmodChangesModeOfArrayOfFiles()
  336. {
  337. $this->markAsSkippedIfChmodIsMissing();
  338. $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  339. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  340. $files = array($directory, $file);
  341. mkdir($directory);
  342. touch($file);
  343. $this->filesystem->chmod($files, 0753);
  344. $this->assertFilePermissions(753, $file);
  345. $this->assertFilePermissions(753, $directory);
  346. }
  347. public function testChmodChangesModeOfTraversableFileObject()
  348. {
  349. $this->markAsSkippedIfChmodIsMissing();
  350. $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  351. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  352. $files = new \ArrayObject(array($directory, $file));
  353. mkdir($directory);
  354. touch($file);
  355. $this->filesystem->chmod($files, 0753);
  356. $this->assertFilePermissions(753, $file);
  357. $this->assertFilePermissions(753, $directory);
  358. }
  359. public function testChown()
  360. {
  361. $this->markAsSkippedIfPosixIsMissing();
  362. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  363. mkdir($dir);
  364. $this->filesystem->chown($dir, $this->getFileOwner($dir));
  365. }
  366. public function testChownRecursive()
  367. {
  368. $this->markAsSkippedIfPosixIsMissing();
  369. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  370. mkdir($dir);
  371. $file = $dir.DIRECTORY_SEPARATOR.'file';
  372. touch($file);
  373. $this->filesystem->chown($dir, $this->getFileOwner($dir), true);
  374. }
  375. public function testChownSymlink()
  376. {
  377. $this->markAsSkippedIfSymlinkIsMissing();
  378. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  379. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  380. touch($file);
  381. $this->filesystem->symlink($file, $link);
  382. $this->filesystem->chown($link, $this->getFileOwner($link));
  383. }
  384. /**
  385. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  386. */
  387. public function testChownSymlinkFails()
  388. {
  389. $this->markAsSkippedIfSymlinkIsMissing();
  390. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  391. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  392. touch($file);
  393. $this->filesystem->symlink($file, $link);
  394. $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
  395. }
  396. /**
  397. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  398. */
  399. public function testChownFail()
  400. {
  401. $this->markAsSkippedIfPosixIsMissing();
  402. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  403. mkdir($dir);
  404. $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
  405. }
  406. public function testChgrp()
  407. {
  408. $this->markAsSkippedIfPosixIsMissing();
  409. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  410. mkdir($dir);
  411. $this->filesystem->chgrp($dir, $this->getFileGroup($dir));
  412. }
  413. public function testChgrpRecursive()
  414. {
  415. $this->markAsSkippedIfPosixIsMissing();
  416. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  417. mkdir($dir);
  418. $file = $dir.DIRECTORY_SEPARATOR.'file';
  419. touch($file);
  420. $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
  421. }
  422. public function testChgrpSymlink()
  423. {
  424. $this->markAsSkippedIfSymlinkIsMissing();
  425. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  426. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  427. touch($file);
  428. $this->filesystem->symlink($file, $link);
  429. $this->filesystem->chgrp($link, $this->getFileGroup($link));
  430. }
  431. /**
  432. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  433. */
  434. public function testChgrpSymlinkFails()
  435. {
  436. $this->markAsSkippedIfSymlinkIsMissing();
  437. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  438. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  439. touch($file);
  440. $this->filesystem->symlink($file, $link);
  441. $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
  442. }
  443. /**
  444. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  445. */
  446. public function testChgrpFail()
  447. {
  448. $this->markAsSkippedIfPosixIsMissing();
  449. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  450. mkdir($dir);
  451. $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
  452. }
  453. public function testRename()
  454. {
  455. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  456. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  457. touch($file);
  458. $this->filesystem->rename($file, $newPath);
  459. $this->assertFileNotExists($file);
  460. $this->assertFileExists($newPath);
  461. }
  462. /**
  463. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  464. */
  465. public function testRenameThrowsExceptionIfTargetAlreadyExists()
  466. {
  467. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  468. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  469. touch($file);
  470. touch($newPath);
  471. $this->filesystem->rename($file, $newPath);
  472. }
  473. public function testRenameOverwritesTheTargetIfItAlreadyExists()
  474. {
  475. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  476. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  477. touch($file);
  478. touch($newPath);
  479. $this->filesystem->rename($file, $newPath, true);
  480. $this->assertFileNotExists($file);
  481. $this->assertFileExists($newPath);
  482. }
  483. /**
  484. * @expectedException \Symfony\Component\Filesystem\Exception\IOException
  485. */
  486. public function testRenameThrowsExceptionOnError()
  487. {
  488. $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid('fs_test_', true);
  489. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  490. $this->filesystem->rename($file, $newPath);
  491. }
  492. public function testSymlink()
  493. {
  494. if ('\\' === DIRECTORY_SEPARATOR) {
  495. $this->markTestSkipped('Windows does not support creating "broken" symlinks');
  496. }
  497. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  498. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  499. // $file does not exists right now: creating "broken" links is a wanted feature
  500. $this->filesystem->symlink($file, $link);
  501. $this->assertTrue(is_link($link));
  502. // Create the linked file AFTER creating the link
  503. touch($file);
  504. $this->assertEquals($file, readlink($link));
  505. }
  506. /**
  507. * @depends testSymlink
  508. */
  509. public function testRemoveSymlink()
  510. {
  511. $this->markAsSkippedIfSymlinkIsMissing();
  512. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  513. $this->filesystem->remove($link);
  514. $this->assertTrue(!is_link($link));
  515. }
  516. public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
  517. {
  518. $this->markAsSkippedIfSymlinkIsMissing();
  519. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  520. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  521. touch($file);
  522. symlink($this->workspace, $link);
  523. $this->filesystem->symlink($file, $link);
  524. $this->assertTrue(is_link($link));
  525. $this->assertEquals($file, readlink($link));
  526. }
  527. public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
  528. {
  529. $this->markAsSkippedIfSymlinkIsMissing();
  530. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  531. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  532. touch($file);
  533. symlink($file, $link);
  534. $this->filesystem->symlink($file, $link);
  535. $this->assertTrue(is_link($link));
  536. $this->assertEquals($file, readlink($link));
  537. }
  538. public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
  539. {
  540. $this->markAsSkippedIfSymlinkIsMissing();
  541. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  542. $link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
  543. $link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
  544. touch($file);
  545. $this->filesystem->symlink($file, $link1);
  546. $this->filesystem->symlink($file, $link2);
  547. $this->assertTrue(is_link($link1));
  548. $this->assertEquals($file, readlink($link1));
  549. $this->assertTrue(is_link($link2));
  550. $this->assertEquals($file, readlink($link2));
  551. }
  552. /**
  553. * @dataProvider providePathsForMakePathRelative
  554. */
  555. public function testMakePathRelative($endPath, $startPath, $expectedPath)
  556. {
  557. $path = $this->filesystem->makePathRelative($endPath, $startPath);
  558. $this->assertEquals($expectedPath, $path);
  559. }
  560. /**
  561. * @return array
  562. */
  563. public function providePathsForMakePathRelative()
  564. {
  565. $paths = array(
  566. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
  567. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
  568. array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
  569. array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
  570. array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
  571. array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
  572. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
  573. array('/aa/bb', '/aa/bb', './'),
  574. array('/aa/bb', '/aa/bb/', './'),
  575. array('/aa/bb/', '/aa/bb', './'),
  576. array('/aa/bb/', '/aa/bb/', './'),
  577. array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
  578. array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
  579. array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
  580. array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
  581. array('/aa/bb/cc', '/aa', 'bb/cc/'),
  582. array('/aa/bb/cc', '/aa/', 'bb/cc/'),
  583. array('/aa/bb/cc/', '/aa', 'bb/cc/'),
  584. array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
  585. array('/a/aab/bb', '/a/aa', '../aab/bb/'),
  586. array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
  587. array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
  588. array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
  589. );
  590. if ('\\' === DIRECTORY_SEPARATOR) {
  591. $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
  592. }
  593. return $paths;
  594. }
  595. public function testMirrorCopiesFilesAndDirectoriesRecursively()
  596. {
  597. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  598. $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
  599. $file1 = $directory.'file1';
  600. $file2 = $sourcePath.'file2';
  601. mkdir($sourcePath);
  602. mkdir($directory);
  603. file_put_contents($file1, 'FILE1');
  604. file_put_contents($file2, 'FILE2');
  605. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  606. $this->filesystem->mirror($sourcePath, $targetPath);
  607. $this->assertTrue(is_dir($targetPath));
  608. $this->assertTrue(is_dir($targetPath.'directory'));
  609. $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
  610. $this->assertFileEquals($file2, $targetPath.'file2');
  611. $this->filesystem->remove($file1);
  612. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
  613. $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
  614. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
  615. $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
  616. file_put_contents($file1, 'FILE1');
  617. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
  618. $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
  619. $this->filesystem->remove($directory);
  620. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
  621. $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
  622. $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
  623. }
  624. public function testMirrorCreatesEmptyDirectory()
  625. {
  626. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  627. mkdir($sourcePath);
  628. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  629. $this->filesystem->mirror($sourcePath, $targetPath);
  630. $this->assertTrue(is_dir($targetPath));
  631. $this->filesystem->remove($sourcePath);
  632. }
  633. public function testMirrorCopiesLinks()
  634. {
  635. $this->markAsSkippedIfSymlinkIsMissing();
  636. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  637. mkdir($sourcePath);
  638. file_put_contents($sourcePath.'file1', 'FILE1');
  639. symlink($sourcePath.'file1', $sourcePath.'link1');
  640. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  641. $this->filesystem->mirror($sourcePath, $targetPath);
  642. $this->assertTrue(is_dir($targetPath));
  643. $this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
  644. $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
  645. }
  646. public function testMirrorCopiesLinkedDirectoryContents()
  647. {
  648. $this->markAsSkippedIfSymlinkIsMissing();
  649. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  650. mkdir($sourcePath.'nested/', 0777, true);
  651. file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
  652. // Note: We symlink directory, not file
  653. symlink($sourcePath.'nested', $sourcePath.'link1');
  654. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  655. $this->filesystem->mirror($sourcePath, $targetPath);
  656. $this->assertTrue(is_dir($targetPath));
  657. $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
  658. $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
  659. }
  660. public function testMirrorCopiesRelativeLinkedContents()
  661. {
  662. $this->markAsSkippedIfSymlinkIsMissing();
  663. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  664. $oldPath = getcwd();
  665. mkdir($sourcePath.'nested/', 0777, true);
  666. file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
  667. // Note: Create relative symlink
  668. chdir($sourcePath);
  669. symlink('nested', 'link1');
  670. chdir($oldPath);
  671. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  672. $this->filesystem->mirror($sourcePath, $targetPath);
  673. $this->assertTrue(is_dir($targetPath));
  674. $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
  675. $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
  676. $this->assertEquals($sourcePath.'nested', readlink($targetPath.DIRECTORY_SEPARATOR.'link1'));
  677. }
  678. /**
  679. * @dataProvider providePathsForIsAbsolutePath
  680. */
  681. public function testIsAbsolutePath($path, $expectedResult)
  682. {
  683. $result = $this->filesystem->isAbsolutePath($path);
  684. $this->assertEquals($expectedResult, $result);
  685. }
  686. /**
  687. * @return array
  688. */
  689. public function providePathsForIsAbsolutePath()
  690. {
  691. return array(
  692. array('/var/lib', true),
  693. array('c:\\\\var\\lib', true),
  694. array('\\var\\lib', true),
  695. array('var/lib', false),
  696. array('../var/lib', false),
  697. array('', false),
  698. array(null, false),
  699. );
  700. }
  701. public function testDumpFile()
  702. {
  703. $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
  704. $this->filesystem->dumpFile($filename, 'bar');
  705. $this->assertFileExists($filename);
  706. $this->assertSame('bar', file_get_contents($filename));
  707. }
  708. /**
  709. * @group legacy
  710. */
  711. public function testDumpFileAndSetPermissions()
  712. {
  713. $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
  714. $this->filesystem->dumpFile($filename, 'bar', 0753);
  715. $this->assertFileExists($filename);
  716. $this->assertSame('bar', file_get_contents($filename));
  717. // skip mode check on Windows
  718. if ('\\' !== DIRECTORY_SEPARATOR) {
  719. $this->assertFilePermissions(753, $filename);
  720. }
  721. }
  722. public function testDumpFileWithNullMode()
  723. {
  724. $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
  725. $this->filesystem->dumpFile($filename, 'bar', null);
  726. $this->assertFileExists($filename);
  727. $this->assertSame('bar', file_get_contents($filename));
  728. // skip mode check on Windows
  729. if ('\\' !== DIRECTORY_SEPARATOR) {
  730. $this->assertFilePermissions(600, $filename);
  731. }
  732. }
  733. public function testDumpFileOverwritesAnExistingFile()
  734. {
  735. $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
  736. file_put_contents($filename, 'FOO BAR');
  737. $this->filesystem->dumpFile($filename, 'bar');
  738. $this->assertFileExists($filename);
  739. $this->assertSame('bar', file_get_contents($filename));
  740. }
  741. public function testCopyShouldKeepExecutionPermission()
  742. {
  743. $this->markAsSkippedIfChmodIsMissing();
  744. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  745. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  746. file_put_contents($sourceFilePath, 'SOURCE FILE');
  747. chmod($sourceFilePath, 0745);
  748. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  749. $this->assertFilePermissions(767, $targetFilePath);
  750. }
  751. }