PageRenderTime 30ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/Exercise/symfony
PHP | 556 lines | 376 code | 132 blank | 48 comment | 4 complexity | b1716b65b0e8c9741ab6dbeb49c170df 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. public function setUp()
  26. {
  27. $this->filesystem = new Filesystem();
  28. $this->workspace = sys_get_temp_dir().DIRECTORY_SEPARATOR.time().rand(0, 1000);
  29. mkdir($this->workspace, 0777, true);
  30. }
  31. public function tearDown()
  32. {
  33. $this->clean($this->workspace);
  34. }
  35. /**
  36. * @param string $file
  37. */
  38. private function clean($file)
  39. {
  40. if (is_dir($file) && !is_link($file)) {
  41. $dir = new \FilesystemIterator($file);
  42. foreach ($dir as $childFile) {
  43. $this->clean($childFile);
  44. }
  45. rmdir($file);
  46. } else {
  47. unlink($file);
  48. }
  49. }
  50. public function testCopyCreatesNewFile()
  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. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  56. $this->assertFileExists($targetFilePath);
  57. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  58. }
  59. public function testCopyOverridesExistingFileIfModified()
  60. {
  61. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  62. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  63. file_put_contents($sourceFilePath, 'SOURCE FILE');
  64. file_put_contents($targetFilePath, 'TARGET FILE');
  65. touch($targetFilePath, time() - 1000);
  66. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  67. $this->assertFileExists($targetFilePath);
  68. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  69. }
  70. public function testCopyDoesNotOverrideExistingFileByDefault()
  71. {
  72. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  73. $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  74. file_put_contents($sourceFilePath, 'SOURCE FILE');
  75. file_put_contents($targetFilePath, 'TARGET FILE');
  76. // make sure both files have the same modification time
  77. $modificationTime = time() - 1000;
  78. touch($sourceFilePath, $modificationTime);
  79. touch($targetFilePath, $modificationTime);
  80. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  81. $this->assertFileExists($targetFilePath);
  82. $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
  83. }
  84. public function testCopyOverridesExistingFileIfForced()
  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. // make sure both files have the same modification time
  91. $modificationTime = time() - 1000;
  92. touch($sourceFilePath, $modificationTime);
  93. touch($targetFilePath, $modificationTime);
  94. $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
  95. $this->assertFileExists($targetFilePath);
  96. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  97. }
  98. public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
  99. {
  100. $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  101. $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  102. $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
  103. file_put_contents($sourceFilePath, 'SOURCE FILE');
  104. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  105. $this->assertTrue(is_dir($targetFileDirectory));
  106. $this->assertFileExists($targetFilePath);
  107. $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
  108. }
  109. public function testMkdirCreatesDirectoriesRecursively()
  110. {
  111. $directory = $this->workspace
  112. .DIRECTORY_SEPARATOR.'directory'
  113. .DIRECTORY_SEPARATOR.'sub_directory';
  114. $result = $this->filesystem->mkdir($directory);
  115. $this->assertTrue($result);
  116. $this->assertTrue(is_dir($directory));
  117. }
  118. public function testMkdirCreatesDirectoriesFromArray()
  119. {
  120. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  121. $directories = array(
  122. $basePath.'1', $basePath.'2', $basePath.'3'
  123. );
  124. $result = $this->filesystem->mkdir($directories);
  125. $this->assertTrue($result);
  126. $this->assertTrue(is_dir($basePath.'1'));
  127. $this->assertTrue(is_dir($basePath.'2'));
  128. $this->assertTrue(is_dir($basePath.'3'));
  129. }
  130. public function testMkdirCreatesDirectoriesFromTraversableObject()
  131. {
  132. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  133. $directories = new \ArrayObject(array(
  134. $basePath.'1', $basePath.'2', $basePath.'3'
  135. ));
  136. $result = $this->filesystem->mkdir($directories);
  137. $this->assertTrue($result);
  138. $this->assertTrue(is_dir($basePath.'1'));
  139. $this->assertTrue(is_dir($basePath.'2'));
  140. $this->assertTrue(is_dir($basePath.'3'));
  141. }
  142. public function testMkdirCreatesDirectoriesEvenIfItFailsToCreateOneOfThem()
  143. {
  144. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  145. $directories = array(
  146. $basePath.'1', $basePath.'2', $basePath.'3'
  147. );
  148. // create a file to make that directory cannot be created
  149. file_put_contents($basePath.'2', '');
  150. $result = $this->filesystem->mkdir($directories);
  151. $this->assertFalse($result);
  152. $this->assertTrue(is_dir($basePath.'1'));
  153. $this->assertFalse(is_dir($basePath.'2'));
  154. $this->assertTrue(is_dir($basePath.'3'));
  155. }
  156. public function testTouchCreatesEmptyFile()
  157. {
  158. $file = $this->workspace.DIRECTORY_SEPARATOR.'1';
  159. $this->filesystem->touch($file);
  160. $this->assertFileExists($file);
  161. }
  162. public function testTouchCreatesEmptyFilesFromArray()
  163. {
  164. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  165. $files = array(
  166. $basePath.'1', $basePath.'2', $basePath.'3'
  167. );
  168. $this->filesystem->touch($files);
  169. $this->assertFileExists($basePath.'1');
  170. $this->assertFileExists($basePath.'2');
  171. $this->assertFileExists($basePath.'3');
  172. }
  173. public function testTouchCreatesEmptyFilesFromTraversableObject()
  174. {
  175. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  176. $files = new \ArrayObject(array(
  177. $basePath.'1', $basePath.'2', $basePath.'3'
  178. ));
  179. $this->filesystem->touch($files);
  180. $this->assertFileExists($basePath.'1');
  181. $this->assertFileExists($basePath.'2');
  182. $this->assertFileExists($basePath.'3');
  183. }
  184. public function testRemoveCleansFilesAndDirectoriesIteratively()
  185. {
  186. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  187. mkdir($basePath);
  188. mkdir($basePath.'dir');
  189. touch($basePath.'file');
  190. $this->filesystem->remove($basePath);
  191. $this->assertTrue(!is_dir($basePath));
  192. }
  193. public function testRemoveCleansArrayOfFilesAndDirectories()
  194. {
  195. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  196. mkdir($basePath.'dir');
  197. touch($basePath.'file');
  198. $files = array(
  199. $basePath.'dir', $basePath.'file'
  200. );
  201. $this->filesystem->remove($files);
  202. $this->assertTrue(!is_dir($basePath.'dir'));
  203. $this->assertTrue(!is_file($basePath.'file'));
  204. }
  205. public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
  206. {
  207. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  208. mkdir($basePath.'dir');
  209. touch($basePath.'file');
  210. $files = new \ArrayObject(array(
  211. $basePath.'dir', $basePath.'file'
  212. ));
  213. $this->filesystem->remove($files);
  214. $this->assertTrue(!is_dir($basePath.'dir'));
  215. $this->assertTrue(!is_file($basePath.'file'));
  216. }
  217. public function testRemoveIgnoresNonExistingFiles()
  218. {
  219. $basePath = $this->workspace.DIRECTORY_SEPARATOR;
  220. mkdir($basePath.'dir');
  221. $files = array(
  222. $basePath.'dir', $basePath.'file'
  223. );
  224. $this->filesystem->remove($files);
  225. $this->assertTrue(!is_dir($basePath.'dir'));
  226. }
  227. public function testRemoveCleansInvalidLinks()
  228. {
  229. $this->markAsSkippeIfSymlinkIsMissing();
  230. $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
  231. mkdir($basePath);
  232. mkdir($basePath.'dir');
  233. // create symlink to unexisting file
  234. symlink($basePath.'file', $basePath.'link');
  235. $this->filesystem->remove($basePath);
  236. $this->assertTrue(!is_dir($basePath));
  237. }
  238. public function testChmodChangesFileMode()
  239. {
  240. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  241. touch($file);
  242. $this->filesystem->chmod($file, 0753);
  243. $this->assertEquals(753, $this->getFilePermisions($file));
  244. }
  245. public function testChmodChangesModeOfArrayOfFiles()
  246. {
  247. $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  248. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  249. $files = array($directory, $file);
  250. mkdir($directory);
  251. touch($file);
  252. $this->filesystem->chmod($files, 0753);
  253. $this->assertEquals(753, $this->getFilePermisions($file));
  254. $this->assertEquals(753, $this->getFilePermisions($directory));
  255. }
  256. public function testChmodChangesModeOfTraversableFileObject()
  257. {
  258. $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
  259. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  260. $files = new \ArrayObject(array($directory, $file));
  261. mkdir($directory);
  262. touch($file);
  263. $this->filesystem->chmod($files, 0753);
  264. $this->assertEquals(753, $this->getFilePermisions($file));
  265. $this->assertEquals(753, $this->getFilePermisions($directory));
  266. }
  267. public function testRename()
  268. {
  269. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  270. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  271. touch($file);
  272. $this->filesystem->rename($file, $newPath);
  273. $this->assertFileNotExists($file);
  274. $this->assertFileExists($newPath);
  275. }
  276. /**
  277. * @expectedException \RuntimeException
  278. */
  279. public function testRenameThrowsExceptionIfTargetAlreadyExists()
  280. {
  281. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  282. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  283. touch($file);
  284. touch($newPath);
  285. $this->filesystem->rename($file, $newPath);
  286. }
  287. /**
  288. * @expectedException \RuntimeException
  289. */
  290. public function testRenameThrowsExceptionOnError()
  291. {
  292. $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid();
  293. $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
  294. $this->filesystem->rename($file, $newPath);
  295. }
  296. public function testSymlink()
  297. {
  298. $this->markAsSkippeIfSymlinkIsMissing();
  299. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  300. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  301. touch($file);
  302. $this->filesystem->symlink($file, $link);
  303. $this->assertTrue(is_link($link));
  304. $this->assertEquals($file, readlink($link));
  305. }
  306. public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
  307. {
  308. $this->markAsSkippeIfSymlinkIsMissing();
  309. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  310. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  311. touch($file);
  312. symlink($this->workspace, $link);
  313. $this->filesystem->symlink($file, $link);
  314. $this->assertTrue(is_link($link));
  315. $this->assertEquals($file, readlink($link));
  316. }
  317. public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
  318. {
  319. $this->markAsSkippeIfSymlinkIsMissing();
  320. $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  321. $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  322. touch($file);
  323. symlink($file, $link);
  324. $this->filesystem->symlink($file, $link);
  325. $this->assertTrue(is_link($link));
  326. $this->assertEquals($file, readlink($link));
  327. }
  328. /**
  329. * @dataProvider providePathsForMakePathRelative
  330. */
  331. public function testMakePathRelative($endPath, $startPath, $expectedPath)
  332. {
  333. $path = $this->filesystem->makePathRelative($endPath, $startPath);
  334. $this->assertEquals($expectedPath, $path);
  335. }
  336. /**
  337. * @return array
  338. */
  339. public function providePathsForMakePathRelative()
  340. {
  341. $paths = array(
  342. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
  343. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
  344. array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
  345. array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
  346. array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
  347. array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
  348. array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
  349. );
  350. // fix directory separator
  351. foreach ($paths as $i => $pathItems) {
  352. foreach ($pathItems as $k => $path) {
  353. $paths[$i][$k] = str_replace('/', DIRECTORY_SEPARATOR, $path);
  354. }
  355. }
  356. return $paths;
  357. }
  358. public function testMirrorCopiesFilesAndDirectoriesRecursively()
  359. {
  360. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  361. $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
  362. $file1 = $directory.'file1';
  363. $file2 = $sourcePath.'file2';
  364. mkdir($sourcePath);
  365. mkdir($directory);
  366. file_put_contents($file1, 'FILE1');
  367. file_put_contents($file2, 'FILE2');
  368. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  369. $this->filesystem->mirror($sourcePath, $targetPath);
  370. $this->assertTrue(is_dir($targetPath));
  371. $this->assertTrue(is_dir($targetPath.'directory'));
  372. $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
  373. $this->assertFileEquals($file2, $targetPath.'file2');
  374. }
  375. public function testMirrorCopiesLinks()
  376. {
  377. $this->markAsSkippeIfSymlinkIsMissing();
  378. $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
  379. mkdir($sourcePath);
  380. file_put_contents($sourcePath.'file1', 'FILE1');
  381. symlink($sourcePath.'file1', $sourcePath.'link1');
  382. $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
  383. $this->filesystem->mirror($sourcePath, $targetPath);
  384. $this->assertTrue(is_dir($targetPath));
  385. $this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
  386. $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
  387. }
  388. /**
  389. * @dataProvider providePathsForIsAbsolutePath
  390. */
  391. public function testIsAbsolutePath($path, $expectedResult)
  392. {
  393. $result = $this->filesystem->isAbsolutePath($path);
  394. $this->assertEquals($expectedResult, $result);
  395. }
  396. /**
  397. * @return array
  398. */
  399. public function providePathsForIsAbsolutePath()
  400. {
  401. return array(
  402. array('/var/lib', true),
  403. array('c:\\\\var\\lib', true),
  404. array('\\var\\lib', true),
  405. array('var/lib', false),
  406. array('../var/lib', false)
  407. );
  408. }
  409. /**
  410. * Returns file permissions as three digits (i.e. 755)
  411. *
  412. * @return integer
  413. */
  414. private function getFilePermisions($filePath)
  415. {
  416. return (int) substr(sprintf('%o', fileperms($filePath)), -3);
  417. }
  418. private function markAsSkippeIfSymlinkIsMissing()
  419. {
  420. if (!function_exists('symlink')) {
  421. $this->markTestSkipped('symlink is not supported');
  422. }
  423. }
  424. }