PageRenderTime 60ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php

https://github.com/ptheg/symfony
PHP | 904 lines | 614 code | 218 blank | 72 comment | 16 complexity | 988537710b7cc30bf805adff88c9689f 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. use Symfony\Component\Filesystem\Filesystem;
  12. /**
  13. * Test class for Filesystem.
  14. */
  15. class FilesystemTest extends \PHPUnit_Framework_TestCase
  16. {
  17. /**
  18. * @var string $workspace
  19. */
  20. private $workspace = null;
  21. /**
  22. * @var \Symfony\Component\Filesystem\Filesystem $filesystem
  23. */
  24. private $filesystem = null;
  25. private static $symlinkOnWindows = null;
  26. public static function setUpBeforeClass()
  27. {
  28. if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
  29. self::$symlinkOnWindows = true;
  30. $originDir = tempnam(sys_get_temp_dir(), 'sl');
  31. $targetDir = tempnam(sys_get_temp_dir(), 'sl');
  32. if (true !== @symlink($originDir, $targetDir)) {
  33. $report = error_get_last();
  34. if (is_array($report) && false !== strpos($report['message'], 'error code(1314)')) {
  35. self::$symlinkOnWindows = false;
  36. }
  37. }
  38. }
  39. }
  40. public function setUp()
  41. {
  42. $this->filesystem = new Filesystem();
  43. $this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000);
  44. mkdir($this->workspace, 0777, true);
  45. $this->workspace = realpath($this->workspace);
  46. }
  47. public function tearDown()
  48. {
  49. $this->clean($this->workspace);
  50. }
  51. /**
  52. * @param string $file
  53. */
  54. private function clean($file)
  55. {
  56. if (is_dir($file) && !is_link($file)) {
  57. $dir = new \FilesystemIterator($file);
  58. foreach ($dir as $childFile) {
  59. $this->clean($childFile);
  60. }
  61. rmdir($file);
  62. } else {
  63. unlink($file);
  64. }
  65. }
  66. public function testCopyCreatesNewFile()
  67. {
  68. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  69. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  70. file_put_contents($sourceFilePath, 'SOURCE FILE');
  71. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  72. $this->assertFileExists($targetFilePath);
  73. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  74. }
  75. /**
  76. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  77. */
  78. public function testCopyFails()
  79. {
  80. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  81. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  82. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  83. }
  84. public function testCopyOverridesExistingFileIfModified()
  85. {
  86. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  87. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  88. file_put_contents($sourceFilePath, 'SOURCE FILE');
  89. file_put_contents($targetFilePath, 'TARGET FILE');
  90. touch($targetFilePath, time() - 1000);
  91. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  92. $this->assertFileExists($targetFilePath);
  93. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  94. }
  95. public function testCopyDoesNotOverrideExistingFileByDefault()
  96. {
  97. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  98. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  99. file_put_contents($sourceFilePath, 'SOURCE FILE');
  100. file_put_contents($targetFilePath, 'TARGET FILE');
  101. // make sure both files have the same modification time
  102. $modificationTime = time() - 1000;
  103. touch($sourceFilePath, $modificationTime);
  104. touch($targetFilePath, $modificationTime);
  105. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  106. $this->assertFileExists($targetFilePath);
  107. $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
  108. }
  109. public function testCopyOverridesExistingFileIfForced()
  110. {
  111. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  112. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  113. file_put_contents($sourceFilePath, 'SOURCE FILE');
  114. file_put_contents($targetFilePath, 'TARGET FILE');
  115. // make sure both files have the same modification time
  116. $modificationTime = time() - 1000;
  117. touch($sourceFilePath, $modificationTime);
  118. touch($targetFilePath, $modificationTime);
  119. $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
  120. $this->assertFileExists($targetFilePath);
  121. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  122. }
  123. public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
  124. {
  125. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  126. $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  127. $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
  128. file_put_contents($sourceFilePath, 'SOURCE FILE');
  129. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  130. $this->assertTrue(is_dir($targetFileDirectory));
  131. $this->assertFileExists($targetFilePath);
  132. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  133. }
  134. public function testMkdirCreatesDirectoriesRecursively()
  135. {
  136. $directory = $this->workspace
  137. .DIRECTORY_SEPARATOR.'directory'
  138. .DIRECTORY_SEPARATOR.'sub_directory';
  139. $this->filesystem->mkdir($directory);
  140. $this->assertTrue(is_dir($directory));
  141. }
  142. public function testMkdirCreatesDirectoriesFromArray()
  143. {
  144. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  145. $directories = array(
  146. $basePath.'1', $basePath.'2', $basePath.'3'
  147. );
  148. $this->filesystem->mkdir($directories);
  149. $this->assertTrue(is_dir($basePath.'1'));
  150. $this->assertTrue(is_dir($basePath.'2'));
  151. $this->assertTrue(is_dir($basePath.'3'));
  152. }
  153. public function testMkdirCreatesDirectoriesFromTraversableObject()
  154. {
  155. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  156. $directories = new \ArrayObject(array(
  157. $basePath.'1', $basePath.'2', $basePath.'3'
  158. ));
  159. $this->filesystem->mkdir($directories);
  160. $this->assertTrue(is_dir($basePath.'1'));
  161. $this->assertTrue(is_dir($basePath.'2'));
  162. $this->assertTrue(is_dir($basePath.'3'));
  163. }
  164. /**
  165. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  166. */
  167. public function testMkdirCreatesDirectoriesFails()
  168. {
  169. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  170. $dir = $basePath.'2';
  171. file_put_contents($dir, '');
  172. $this->filesystem->mkdir($dir);
  173. }
  174. public function testTouchCreatesEmptyFile()
  175. {
  176. $file = $this->workspace.DIRECTORY_SEPARATOR.'1';
  177. $this->filesystem->touch($file);
  178. $this->assertFileExists($file);
  179. }
  180. /**
  181. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  182. */
  183. public function testTouchFails()
  184. {
  185. $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
  186. $this->filesystem->touch($file);
  187. }
  188. public function testTouchCreatesEmptyFilesFromArray()
  189. {
  190. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  191. $files = array(
  192. $basePath.'1', $basePath.'2', $basePath.'3'
  193. );
  194. $this->filesystem->touch($files);
  195. $this->assertFileExists($basePath.'1');
  196. $this->assertFileExists($basePath.'2');
  197. $this->assertFileExists($basePath.'3');
  198. }
  199. public function testTouchCreatesEmptyFilesFromTraversableObject()
  200. {
  201. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  202. $files = new \ArrayObject(array(
  203. $basePath.'1', $basePath.'2', $basePath.'3'
  204. ));
  205. $this->filesystem->touch($files);
  206. $this->assertFileExists($basePath.'1');
  207. $this->assertFileExists($basePath.'2');
  208. $this->assertFileExists($basePath.'3');
  209. }
  210. public function testRemoveCleansFilesAndDirectoriesIteratively()
  211. {
  212. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  213. mkdir($basePath);
  214. mkdir($basePath.'dir');
  215. touch($basePath.'file');
  216. $this->filesystem->remove($basePath);
  217. $this->assertTrue(!is_dir($basePath));
  218. }
  219. public function testRemoveCleansArrayOfFilesAndDirectories()
  220. {
  221. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  222. mkdir($basePath.'dir');
  223. touch($basePath.'file');
  224. $files = array(
  225. $basePath.'dir', $basePath.'file'
  226. );
  227. $this->filesystem->remove($files);
  228. $this->assertTrue(!is_dir($basePath.'dir'));
  229. $this->assertTrue(!is_file($basePath.'file'));
  230. }
  231. public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
  232. {
  233. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  234. mkdir($basePath.'dir');
  235. touch($basePath.'file');
  236. $files = new \ArrayObject(array(
  237. $basePath.'dir', $basePath.'file'
  238. ));
  239. $this->filesystem->remove($files);
  240. $this->assertTrue(!is_dir($basePath.'dir'));
  241. $this->assertTrue(!is_file($basePath.'file'));
  242. }
  243. public function testRemoveIgnoresNonExistingFiles()
  244. {
  245. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  246. mkdir($basePath.'dir');
  247. $files = array(
  248. $basePath.'dir', $basePath.'file'
  249. );
  250. $this->filesystem->remove($files);
  251. $this->assertTrue(!is_dir($basePath.'dir'));
  252. }
  253. public function testRemoveCleansInvalidLinks()
  254. {
  255. $this->markAsSkippedIfSymlinkIsMissing();
  256. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  257. mkdir($basePath);
  258. mkdir($basePath.'dir');
  259. // create symlink to unexisting file
  260. @symlink($basePath.'file', $basePath.'link');
  261. $this->filesystem->remove($basePath);
  262. $this->assertTrue(!is_dir($basePath));
  263. }
  264. public function testFilesExists()
  265. {
  266. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  267. mkdir($basePath);
  268. touch($basePath.'file1');
  269. mkdir($basePath.'folder');
  270. $this->assertTrue($this->filesystem->exists($basePath.'file1'));
  271. $this->assertTrue($this->filesystem->exists($basePath.'folder'));
  272. }
  273. public function testFilesExistsTraversableObjectOfFilesAndDirectories()
  274. {
  275. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  276. mkdir($basePath.'dir');
  277. touch($basePath.'file');
  278. $files = new \ArrayObject(array(
  279. $basePath.'dir', $basePath.'file'
  280. ));
  281. $this->assertTrue($this->filesystem->exists($files));
  282. }
  283. public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
  284. {
  285. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  286. mkdir($basePath.'dir');
  287. touch($basePath.'file');
  288. touch($basePath.'file2');
  289. $files = new \ArrayObject(array(
  290. $basePath.'dir', $basePath.'file', $basePath.'file2'
  291. ));
  292. unlink($basePath.'file');
  293. $this->assertFalse($this->filesystem->exists($files));
  294. }
  295. public function testInvalidFileNotExists()
  296. {
  297. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  298. $this->assertFalse($this->filesystem->exists($basePath.time()));
  299. }
  300. public function testChmodChangesFileMode()
  301. {
  302. $this->markAsSkippedIfChmodIsMissing();
  303. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  304. mkdir($dir);
  305. $file = $dir.DIRECTORY_SEPARATOR.'file';
  306. touch($file);
  307. $this->filesystem->chmod($file, 0400);
  308. $this->filesystem->chmod($dir, 0753);
  309. $this->assertEquals(753, $this->getFilePermissions($dir));
  310. $this->assertEquals(400, $this->getFilePermissions($file));
  311. }
  312. public function testChmodWrongMod()
  313. {
  314. $this->markAsSkippedIfChmodIsMissing();
  315. $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
  316. touch($dir);
  317. $this->filesystem->chmod($dir, 'Wrongmode');
  318. }
  319. public function testChmodRecursive()
  320. {
  321. $this->markAsSkippedIfChmodIsMissing();
  322. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  323. mkdir($dir);
  324. $file = $dir.DIRECTORY_SEPARATOR.'file';
  325. touch($file);
  326. $this->filesystem->chmod($file, 0400, 0000, true);
  327. $this->filesystem->chmod($dir, 0753, 0000, true);
  328. $this->assertEquals(753, $this->getFilePermissions($dir));
  329. $this->assertEquals(753, $this->getFilePermissions($file));
  330. }
  331. public function testChmodAppliesUmask()
  332. {
  333. $this->markAsSkippedIfChmodIsMissing();
  334. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  335. touch($file);
  336. $this->filesystem->chmod($file, 0770, 0022);
  337. $this->assertEquals(750, $this->getFilePermissions($file));
  338. }
  339. public function testChmodChangesModeOfArrayOfFiles()
  340. {
  341. $this->markAsSkippedIfChmodIsMissing();
  342. $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  343. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  344. $files = array($directory, $file);
  345. mkdir($directory);
  346. touch($file);
  347. $this->filesystem->chmod($files, 0753);
  348. $this->assertEquals(753, $this->getFilePermissions($file));
  349. $this->assertEquals(753, $this->getFilePermissions($directory));
  350. }
  351. public function testChmodChangesModeOfTraversableFileObject()
  352. {
  353. $this->markAsSkippedIfChmodIsMissing();
  354. $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  355. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  356. $files = new \ArrayObject(array($directory, $file));
  357. mkdir($directory);
  358. touch($file);
  359. $this->filesystem->chmod($files, 0753);
  360. $this->assertEquals(753, $this->getFilePermissions($file));
  361. $this->assertEquals(753, $this->getFilePermissions($directory));
  362. }
  363. public function testChown()
  364. {
  365. $this->markAsSkippedIfPosixIsMissing();
  366. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  367. mkdir($dir);
  368. $this->filesystem->chown($dir, $this->getFileOwner($dir));
  369. }
  370. public function testChownRecursive()
  371. {
  372. $this->markAsSkippedIfPosixIsMissing();
  373. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  374. mkdir($dir);
  375. $file = $dir.DIRECTORY_SEPARATOR.'file';
  376. touch($file);
  377. $this->filesystem->chown($dir, $this->getFileOwner($dir), true);
  378. }
  379. public function testChownSymlink()
  380. {
  381. $this->markAsSkippedIfSymlinkIsMissing();
  382. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  383. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  384. touch($file);
  385. $this->filesystem->symlink($file, $link);
  386. $this->filesystem->chown($link, $this->getFileOwner($link));
  387. }
  388. /**
  389. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  390. */
  391. public function testChownSymlinkFails()
  392. {
  393. $this->markAsSkippedIfSymlinkIsMissing();
  394. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  395. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  396. touch($file);
  397. $this->filesystem->symlink($file, $link);
  398. $this->filesystem->chown($link, 'user' . time() . mt_rand(1000, 9999));
  399. }
  400. /**
  401. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  402. */
  403. public function testChownFail()
  404. {
  405. $this->markAsSkippedIfPosixIsMissing();
  406. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  407. mkdir($dir);
  408. $this->filesystem->chown($dir, 'user' . time() . mt_rand(1000, 9999));
  409. }
  410. public function testChgrp()
  411. {
  412. $this->markAsSkippedIfPosixIsMissing();
  413. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  414. mkdir($dir);
  415. $this->filesystem->chgrp($dir, $this->getFileGroup($dir));
  416. }
  417. public function testChgrpRecursive()
  418. {
  419. $this->markAsSkippedIfPosixIsMissing();
  420. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  421. mkdir($dir);
  422. $file = $dir.DIRECTORY_SEPARATOR.'file';
  423. touch($file);
  424. $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
  425. }
  426. public function testChgrpSymlink()
  427. {
  428. $this->markAsSkippedIfSymlinkIsMissing();
  429. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  430. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  431. touch($file);
  432. $this->filesystem->symlink($file, $link);
  433. $this->filesystem->chgrp($link, $this->getFileGroup($link));
  434. }
  435. /**
  436. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  437. */
  438. public function testChgrpSymlinkFails()
  439. {
  440. $this->markAsSkippedIfSymlinkIsMissing();
  441. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  442. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  443. touch($file);
  444. $this->filesystem->symlink($file, $link);
  445. $this->filesystem->chgrp($link, 'user' . time() . mt_rand(1000, 9999));
  446. }
  447. /**
  448. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  449. */
  450. public function testChgrpFail()
  451. {
  452. $this->markAsSkippedIfPosixIsMissing();
  453. $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  454. mkdir($dir);
  455. $this->filesystem->chgrp($dir, 'user' . time() . mt_rand(1000, 9999));
  456. }
  457. public function testRename()
  458. {
  459. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  460. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  461. touch($file);
  462. $this->filesystem->rename($file, $newPath);
  463. $this->assertFileNotExists($file);
  464. $this->assertFileExists($newPath);
  465. }
  466. /**
  467. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  468. */
  469. public function testRenameThrowsExceptionIfTargetAlreadyExists()
  470. {
  471. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  472. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  473. touch($file);
  474. touch($newPath);
  475. $this->filesystem->rename($file, $newPath);
  476. }
  477. /**
  478. * @expectedException Symfony\Component\Filesystem\Exception\IOException
  479. */
  480. public function testRenameThrowsExceptionOnError()
  481. {
  482. $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid();
  483. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  484. $this->filesystem->rename($file, $newPath);
  485. }
  486. public function testSymlink()
  487. {
  488. $this->markAsSkippedIfSymlinkIsMissing();
  489. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  490. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  491. touch($file);
  492. $this->filesystem->symlink($file, $link);
  493. $this->assertTrue(is_link($link));
  494. $this->assertEquals($file, readlink($link));
  495. }
  496. /**
  497. * @depends testSymlink
  498. */
  499. public function testRemoveSymlink()
  500. {
  501. $this->markAsSkippedIfSymlinkIsMissing();
  502. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  503. $this->filesystem->remove($link);
  504. $this->assertTrue(!is_link($link));
  505. }
  506. public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
  507. {
  508. $this->markAsSkippedIfSymlinkIsMissing();
  509. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  510. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  511. touch($file);
  512. symlink($this->workspace, $link);
  513. $this->filesystem->symlink($file, $link);
  514. $this->assertTrue(is_link($link));
  515. $this->assertEquals($file, readlink($link));
  516. }
  517. public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
  518. {
  519. $this->markAsSkippedIfSymlinkIsMissing();
  520. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  521. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  522. touch($file);
  523. symlink($file, $link);
  524. $this->filesystem->symlink($file, $link);
  525. $this->assertTrue(is_link($link));
  526. $this->assertEquals($file, readlink($link));
  527. }
  528. public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
  529. {
  530. $this->markAsSkippedIfSymlinkIsMissing();
  531. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  532. $link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
  533. $link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
  534. touch($file);
  535. $this->filesystem->symlink($file, $link1);
  536. $this->filesystem->symlink($file, $link2);
  537. $this->assertTrue(is_link($link1));
  538. $this->assertEquals($file, readlink($link1));
  539. $this->assertTrue(is_link($link2));
  540. $this->assertEquals($file, readlink($link2));
  541. }
  542. /**
  543. * @dataProvider providePathsForMakePathRelative
  544. */
  545. public function testMakePathRelative($endPath, $startPath, $expectedPath)
  546. {
  547. $path = $this->filesystem->makePathRelative($endPath, $startPath);
  548. $this->assertEquals($expectedPath, $path);
  549. }
  550. /**
  551. * @return array
  552. */
  553. public function providePathsForMakePathRelative()
  554. {
  555. $paths = array(
  556. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
  557. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
  558. array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
  559. array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
  560. array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
  561. array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
  562. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
  563. array('/aa/bb', '/aa/bb', './'),
  564. array('/aa/bb', '/aa/bb/', './'),
  565. array('/aa/bb/', '/aa/bb', './'),
  566. array('/aa/bb/', '/aa/bb/', './'),
  567. array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
  568. array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
  569. array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
  570. array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
  571. array('/aa/bb/cc', '/aa', 'bb/cc/'),
  572. array('/aa/bb/cc', '/aa/', 'bb/cc/'),
  573. array('/aa/bb/cc/', '/aa', 'bb/cc/'),
  574. array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
  575. array('/a/aab/bb', '/a/aa', '../aab/bb/'),
  576. array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
  577. array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
  578. array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
  579. );
  580. if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
  581. $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
  582. }
  583. return $paths;
  584. }
  585. public function testMirrorCopiesFilesAndDirectoriesRecursively()
  586. {
  587. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  588. $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
  589. $file1 = $directory.'file1';
  590. $file2 = $sourcePath.'file2';
  591. mkdir($sourcePath);
  592. mkdir($directory);
  593. file_put_contents($file1, 'FILE1');
  594. file_put_contents($file2, 'FILE2');
  595. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  596. $this->filesystem->mirror($sourcePath, $targetPath);
  597. $this->assertTrue(is_dir($targetPath));
  598. $this->assertTrue(is_dir($targetPath.'directory'));
  599. $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
  600. $this->assertFileEquals($file2, $targetPath.'file2');
  601. }
  602. public function testMirrorCopiesLinks()
  603. {
  604. $this->markAsSkippedIfSymlinkIsMissing();
  605. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  606. mkdir($sourcePath);
  607. file_put_contents($sourcePath.'file1', 'FILE1');
  608. symlink($sourcePath.'file1', $sourcePath.'link1');
  609. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  610. $this->filesystem->mirror($sourcePath, $targetPath);
  611. $this->assertTrue(is_dir($targetPath));
  612. $this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
  613. $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
  614. }
  615. /**
  616. * @dataProvider providePathsForIsAbsolutePath
  617. */
  618. public function testIsAbsolutePath($path, $expectedResult)
  619. {
  620. $result = $this->filesystem->isAbsolutePath($path);
  621. $this->assertEquals($expectedResult, $result);
  622. }
  623. /**
  624. * @return array
  625. */
  626. public function providePathsForIsAbsolutePath()
  627. {
  628. return array(
  629. array('/var/lib', true),
  630. array('c:\\\\var\\lib', true),
  631. array('\\var\\lib', true),
  632. array('var/lib', false),
  633. array('../var/lib', false),
  634. array('', false),
  635. array(null, false)
  636. );
  637. }
  638. /**
  639. * Returns file permissions as three digits (i.e. 755)
  640. *
  641. * @param string $filepath
  642. *
  643. * @return integer
  644. */
  645. private function getFilePermissions($filePath)
  646. {
  647. return (int) substr(sprintf('%o', fileperms($filePath)), -3);
  648. }
  649. private function getFileOwner($filepath)
  650. {
  651. $this->markAsSkippedIfPosixIsMissing();
  652. $infos = stat($filepath);
  653. if ($datas = posix_getpwuid($infos['uid'])) {
  654. return $datas['name'];
  655. }
  656. }
  657. private function getFileGroup($filepath)
  658. {
  659. $this->markAsSkippedIfPosixIsMissing();
  660. $infos = stat($filepath);
  661. if ($datas = posix_getgrgid($infos['gid'])) {
  662. return $datas['name'];
  663. }
  664. }
  665. private function markAsSkippedIfSymlinkIsMissing()
  666. {
  667. if (!function_exists('symlink')) {
  668. $this->markTestSkipped('symlink is not supported');
  669. }
  670. if (defined('PHP_WINDOWS_VERSION_MAJOR') && false === self::$symlinkOnWindows) {
  671. $this->markTestSkipped('symlink requires "Create symbolic links" privilege on windows');
  672. }
  673. }
  674. private function markAsSkippedIfChmodIsMissing()
  675. {
  676. if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
  677. $this->markTestSkipped('chmod is not supported on windows');
  678. }
  679. }
  680. private function markAsSkippedIfPosixIsMissing()
  681. {
  682. if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('posix_isatty')) {
  683. $this->markTestSkipped('Posix is not supported');
  684. }
  685. }
  686. }