FilesystemTest.php 30 KB

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