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

https://gitlab.com/techniconline/kmc · PHP · 1017 lines · 677 code · 264 blank · 76 comment · 6 complexity · 4d8121dd15928be06f0ddc4c41395908 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. array('/a/aab/bb/', '/', 'a/aab/bb/'),
  590. array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
  591. );
  592. if ('\\' === DIRECTORY_SEPARATOR) {
  593. $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
  594. }
  595. return $paths;
  596. }
  597. public function testMirrorCopiesFilesAndDirectoriesRecursively()
  598. {
  599. $sourcePath = $this->workspace . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR;
  600. $directory = $sourcePath . 'directory' . DIRECTORY_SEPARATOR;
  601. $file1 = $directory . 'file1';
  602. $file2 = $sourcePath . 'file2';
  603. mkdir($sourcePath);
  604. mkdir($directory);
  605. file_put_contents($file1, 'FILE1');
  606. file_put_contents($file2, 'FILE2');
  607. $targetPath = $this->workspace . DIRECTORY_SEPARATOR . 'target' . DIRECTORY_SEPARATOR;
  608. $this->filesystem->mirror($sourcePath, $targetPath);
  609. $this->assertTrue(is_dir($targetPath));
  610. $this->assertTrue(is_dir($targetPath . 'directory'));
  611. $this->assertFileEquals($file1, $targetPath . 'directory' . DIRECTORY_SEPARATOR . 'file1');
  612. $this->assertFileEquals($file2, $targetPath . 'file2');
  613. $this->filesystem->remove($file1);
  614. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
  615. $this->assertTrue($this->filesystem->exists($targetPath . 'directory' . DIRECTORY_SEPARATOR . 'file1'));
  616. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
  617. $this->assertFalse($this->filesystem->exists($targetPath . 'directory' . DIRECTORY_SEPARATOR . 'file1'));
  618. file_put_contents($file1, 'FILE1');
  619. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
  620. $this->assertTrue($this->filesystem->exists($targetPath . 'directory' . DIRECTORY_SEPARATOR . 'file1'));
  621. $this->filesystem->remove($directory);
  622. $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
  623. $this->assertFalse($this->filesystem->exists($targetPath . 'directory'));
  624. $this->assertFalse($this->filesystem->exists($targetPath . 'directory' . DIRECTORY_SEPARATOR . 'file1'));
  625. }
  626. public function testMirrorCreatesEmptyDirectory()
  627. {
  628. $sourcePath = $this->workspace . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR;
  629. mkdir($sourcePath);
  630. $targetPath = $this->workspace . DIRECTORY_SEPARATOR . 'target' . DIRECTORY_SEPARATOR;
  631. $this->filesystem->mirror($sourcePath, $targetPath);
  632. $this->assertTrue(is_dir($targetPath));
  633. $this->filesystem->remove($sourcePath);
  634. }
  635. public function testMirrorCopiesLinks()
  636. {
  637. $this->markAsSkippedIfSymlinkIsMissing();
  638. $sourcePath = $this->workspace . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR;
  639. mkdir($sourcePath);
  640. file_put_contents($sourcePath . 'file1', 'FILE1');
  641. symlink($sourcePath . 'file1', $sourcePath . 'link1');
  642. $targetPath = $this->workspace . DIRECTORY_SEPARATOR . 'target' . DIRECTORY_SEPARATOR;
  643. $this->filesystem->mirror($sourcePath, $targetPath);
  644. $this->assertTrue(is_dir($targetPath));
  645. $this->assertFileEquals($sourcePath . 'file1', $targetPath . DIRECTORY_SEPARATOR . 'link1');
  646. $this->assertTrue(is_link($targetPath . DIRECTORY_SEPARATOR . 'link1'));
  647. }
  648. public function testMirrorCopiesLinkedDirectoryContents()
  649. {
  650. $this->markAsSkippedIfSymlinkIsMissing();
  651. $sourcePath = $this->workspace . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR;
  652. mkdir($sourcePath . 'nested/', 0777, true);
  653. file_put_contents($sourcePath . '/nested/file1.txt', 'FILE1');
  654. // Note: We symlink directory, not file
  655. symlink($sourcePath . 'nested', $sourcePath . 'link1');
  656. $targetPath = $this->workspace . DIRECTORY_SEPARATOR . 'target' . DIRECTORY_SEPARATOR;
  657. $this->filesystem->mirror($sourcePath, $targetPath);
  658. $this->assertTrue(is_dir($targetPath));
  659. $this->assertFileEquals($sourcePath . '/nested/file1.txt', $targetPath . DIRECTORY_SEPARATOR . 'link1/file1.txt');
  660. $this->assertTrue(is_link($targetPath . DIRECTORY_SEPARATOR . 'link1'));
  661. }
  662. public function testMirrorCopiesRelativeLinkedContents()
  663. {
  664. $this->markAsSkippedIfSymlinkIsMissing();
  665. $sourcePath = $this->workspace . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR;
  666. $oldPath = getcwd();
  667. mkdir($sourcePath . 'nested/', 0777, true);
  668. file_put_contents($sourcePath . '/nested/file1.txt', 'FILE1');
  669. // Note: Create relative symlink
  670. chdir($sourcePath);
  671. symlink('nested', 'link1');
  672. chdir($oldPath);
  673. $targetPath = $this->workspace . DIRECTORY_SEPARATOR . 'target' . DIRECTORY_SEPARATOR;
  674. $this->filesystem->mirror($sourcePath, $targetPath);
  675. $this->assertTrue(is_dir($targetPath));
  676. $this->assertFileEquals($sourcePath . '/nested/file1.txt', $targetPath . DIRECTORY_SEPARATOR . 'link1/file1.txt');
  677. $this->assertTrue(is_link($targetPath . DIRECTORY_SEPARATOR . 'link1'));
  678. $this->assertEquals('\\' === DIRECTORY_SEPARATOR ? realpath($sourcePath . '\nested') : 'nested', readlink($targetPath . DIRECTORY_SEPARATOR . 'link1'));
  679. }
  680. /**
  681. * @dataProvider providePathsForIsAbsolutePath
  682. */
  683. public function testIsAbsolutePath($path, $expectedResult)
  684. {
  685. $result = $this->filesystem->isAbsolutePath($path);
  686. $this->assertEquals($expectedResult, $result);
  687. }
  688. /**
  689. * @return array
  690. */
  691. public function providePathsForIsAbsolutePath()
  692. {
  693. return array(
  694. array('/var/lib', true),
  695. array('c:\\\\var\\lib', true),
  696. array('\\var\\lib', true),
  697. array('var/lib', false),
  698. array('../var/lib', false),
  699. array('', false),
  700. array(null, false),
  701. );
  702. }
  703. public function testDumpFile()
  704. {
  705. $filename = $this->workspace . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'baz.txt';
  706. $this->filesystem->dumpFile($filename, 'bar');
  707. $this->assertFileExists($filename);
  708. $this->assertSame('bar', file_get_contents($filename));
  709. }
  710. /**
  711. * @group legacy
  712. */
  713. public function testDumpFileAndSetPermissions()
  714. {
  715. $filename = $this->workspace . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'baz.txt';
  716. $this->filesystem->dumpFile($filename, 'bar', 0753);
  717. $this->assertFileExists($filename);
  718. $this->assertSame('bar', file_get_contents($filename));
  719. // skip mode check on Windows
  720. if ('\\' !== DIRECTORY_SEPARATOR) {
  721. $this->assertFilePermissions(753, $filename);
  722. }
  723. }
  724. public function testDumpFileWithNullMode()
  725. {
  726. $filename = $this->workspace . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'baz.txt';
  727. $this->filesystem->dumpFile($filename, 'bar', null);
  728. $this->assertFileExists($filename);
  729. $this->assertSame('bar', file_get_contents($filename));
  730. // skip mode check on Windows
  731. if ('\\' !== DIRECTORY_SEPARATOR) {
  732. $this->assertFilePermissions(600, $filename);
  733. }
  734. }
  735. public function testDumpFileOverwritesAnExistingFile()
  736. {
  737. $filename = $this->workspace . DIRECTORY_SEPARATOR . 'foo.txt';
  738. file_put_contents($filename, 'FOO BAR');
  739. $this->filesystem->dumpFile($filename, 'bar');
  740. $this->assertFileExists($filename);
  741. $this->assertSame('bar', file_get_contents($filename));
  742. }
  743. public function testCopyShouldKeepExecutionPermission()
  744. {
  745. $this->markAsSkippedIfChmodIsMissing();
  746. $sourceFilePath = $this->workspace . DIRECTORY_SEPARATOR . 'copy_source_file';
  747. $targetFilePath = $this->workspace . DIRECTORY_SEPARATOR . 'copy_target_file';
  748. file_put_contents($sourceFilePath, 'SOURCE FILE');
  749. chmod($sourceFilePath, 0745);
  750. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  751. $this->assertFilePermissions(767, $targetFilePath);
  752. }
  753. }