PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://github.com/symfony/symfony
PHP | 1734 lines | 1481 code | 210 blank | 43 comment | 13 complexity | a1ccfc0d08c5191f33f694596d9fde00 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
  24. }
  25. public function testCopyFails()
  26. {
  27. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  28. $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
  29. $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
  30. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  31. }
  32. public function testCopyUnreadableFileFails()
  33. {
  34. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  35. // skip test on Windows; PHP can't easily set file as unreadable on Windows
  36. if ('\\' === \DIRECTORY_SEPARATOR) {
  37. $this->markTestSkipped('This test cannot run on Windows.');
  38. }
  39. if (!getenv('USER') || 'root' === getenv('USER')) {
  40. $this->markTestSkipped('This test will fail if run under superuser');
  41. }
  42. $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
  43. $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
  44. file_put_contents($sourceFilePath, 'SOURCE FILE');
  45. // make sure target cannot be read
  46. $this->filesystem->chmod($sourceFilePath, 0222);
  47. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  48. }
  49. public function testCopyOverridesExistingFileIfModified()
  50. {
  51. $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
  52. $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
  53. file_put_contents($sourceFilePath, 'SOURCE FILE');
  54. file_put_contents($targetFilePath, 'TARGET FILE');
  55. touch($targetFilePath, time() - 1000);
  56. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  57. $this->assertFileExists($targetFilePath);
  58. $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
  59. }
  60. public function testCopyDoesNotOverrideExistingFileByDefault()
  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. // make sure both files have the same modification time
  67. $modificationTime = time() - 1000;
  68. touch($sourceFilePath, $modificationTime);
  69. touch($targetFilePath, $modificationTime);
  70. $this->filesystem->copy($sourceFilePath, $targetFilePath);
  71. $this->assertFileExists($targetFilePath);
  72. $this->assertStringEqualsFile($targetFilePath, 'TARGET FILE');
  73. }
  74. public function testCopyOverridesExistingFileIfForced()
  75. {
  76. $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file';
  77. $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
  78. file_put_contents($sourceFilePath, 'SOURCE FILE');
  79. file_put_contents($targetFilePath, 'TARGET FILE');
  80. // make sure both files have the same modification time
  81. $modificationTime = time() - 1000;
  82. touch($sourceFilePath, $modificationTime);
  83. touch($targetFilePath, $modificationTime);
  84. $this->filesystem->copy($sourceFilePath, $targetFilePath, true);
  85. $this->assertFileExists($targetFilePath);
  86. $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
  87. }
  88. public function testCopyWithOverrideWithReadOnlyTargetFails()
  89. {
  90. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  91. // skip test on Windows; PHP can't easily set file as unwritable on Windows
  92. if ('\\' === \DIRECTORY_SEPARATOR) {
  93. $this->markTestSkipped('This test cannot run on Windows.');
  94. }
  95. if (!getenv('USER') || 'root' === getenv('USER')) {
  96. $this->markTestSkipped('This test will fail if run under superuser');
  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->assertDirectoryExists($targetFileDirectory);
  118. $this->assertFileExists($targetFilePath);
  119. $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE');
  120. }
  121. /**
  122. * @group network
  123. */
  124. public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy()
  125. {
  126. if (!\in_array('https', stream_get_wrappers())) {
  127. $this->markTestSkipped('"https" stream wrapper is not enabled.');
  128. }
  129. $sourceFilePath = 'https://symfony.com/images/common/logo/logo_symfony_header.png';
  130. $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file';
  131. file_put_contents($targetFilePath, 'TARGET FILE');
  132. $this->filesystem->copy($sourceFilePath, $targetFilePath, false);
  133. $this->assertFileExists($targetFilePath);
  134. $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath));
  135. }
  136. public function testMkdirCreatesDirectoriesRecursively()
  137. {
  138. $directory = $this->workspace
  139. .\DIRECTORY_SEPARATOR.'directory'
  140. .\DIRECTORY_SEPARATOR.'sub_directory';
  141. $this->filesystem->mkdir($directory);
  142. $this->assertDirectoryExists($directory);
  143. }
  144. public function testMkdirCreatesDirectoriesFromArray()
  145. {
  146. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  147. $directories = [
  148. $basePath.'1', $basePath.'2', $basePath.'3',
  149. ];
  150. $this->filesystem->mkdir($directories);
  151. $this->assertDirectoryExists($basePath.'1');
  152. $this->assertDirectoryExists($basePath.'2');
  153. $this->assertDirectoryExists($basePath.'3');
  154. }
  155. public function testMkdirCreatesDirectoriesFromTraversableObject()
  156. {
  157. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  158. $directories = new \ArrayObject([
  159. $basePath.'1', $basePath.'2', $basePath.'3',
  160. ]);
  161. $this->filesystem->mkdir($directories);
  162. $this->assertDirectoryExists($basePath.'1');
  163. $this->assertDirectoryExists($basePath.'2');
  164. $this->assertDirectoryExists($basePath.'3');
  165. }
  166. public function testMkdirCreatesDirectoriesFails()
  167. {
  168. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  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. public function testTouchFails()
  181. {
  182. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  183. $file = $this->workspace.\DIRECTORY_SEPARATOR.'1'.\DIRECTORY_SEPARATOR.'2';
  184. $this->filesystem->touch($file);
  185. }
  186. public function testTouchCreatesEmptyFilesFromArray()
  187. {
  188. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  189. $files = [
  190. $basePath.'1', $basePath.'2', $basePath.'3',
  191. ];
  192. $this->filesystem->touch($files);
  193. $this->assertFileExists($basePath.'1');
  194. $this->assertFileExists($basePath.'2');
  195. $this->assertFileExists($basePath.'3');
  196. }
  197. public function testTouchCreatesEmptyFilesFromTraversableObject()
  198. {
  199. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  200. $files = new \ArrayObject([
  201. $basePath.'1', $basePath.'2', $basePath.'3',
  202. ]);
  203. $this->filesystem->touch($files);
  204. $this->assertFileExists($basePath.'1');
  205. $this->assertFileExists($basePath.'2');
  206. $this->assertFileExists($basePath.'3');
  207. }
  208. public function testRemoveCleansFilesAndDirectoriesIteratively()
  209. {
  210. $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
  211. mkdir($basePath);
  212. mkdir($basePath.'dir');
  213. touch($basePath.'file');
  214. $this->filesystem->remove($basePath);
  215. $this->assertFileNotExists($basePath);
  216. }
  217. public function testRemoveCleansArrayOfFilesAndDirectories()
  218. {
  219. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  220. mkdir($basePath.'dir');
  221. touch($basePath.'file');
  222. $files = [
  223. $basePath.'dir', $basePath.'file',
  224. ];
  225. $this->filesystem->remove($files);
  226. $this->assertFileNotExists($basePath.'dir');
  227. $this->assertFileNotExists($basePath.'file');
  228. }
  229. public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
  230. {
  231. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  232. mkdir($basePath.'dir');
  233. touch($basePath.'file');
  234. $files = new \ArrayObject([
  235. $basePath.'dir', $basePath.'file',
  236. ]);
  237. $this->filesystem->remove($files);
  238. $this->assertFileNotExists($basePath.'dir');
  239. $this->assertFileNotExists($basePath.'file');
  240. }
  241. public function testRemoveIgnoresNonExistingFiles()
  242. {
  243. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  244. mkdir($basePath.'dir');
  245. $files = [
  246. $basePath.'dir', $basePath.'file',
  247. ];
  248. $this->filesystem->remove($files);
  249. $this->assertFileNotExists($basePath.'dir');
  250. }
  251. public function testRemoveCleansInvalidLinks()
  252. {
  253. $this->markAsSkippedIfSymlinkIsMissing();
  254. $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
  255. mkdir($basePath);
  256. mkdir($basePath.'dir');
  257. // create symlink to nonexistent file
  258. @symlink($basePath.'file', $basePath.'file-link');
  259. // create symlink to dir using trailing forward slash
  260. $this->filesystem->symlink($basePath.'dir/', $basePath.'dir-link');
  261. $this->assertDirectoryExists($basePath.'dir-link');
  262. // create symlink to nonexistent dir
  263. rmdir($basePath.'dir');
  264. $this->assertFalse('\\' === \DIRECTORY_SEPARATOR ? @readlink($basePath.'dir-link') : is_dir($basePath.'dir-link'));
  265. $this->filesystem->remove($basePath);
  266. $this->assertFileNotExists($basePath);
  267. }
  268. public function testFilesExists()
  269. {
  270. $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
  271. mkdir($basePath);
  272. touch($basePath.'file1');
  273. mkdir($basePath.'folder');
  274. $this->assertTrue($this->filesystem->exists($basePath.'file1'));
  275. $this->assertTrue($this->filesystem->exists($basePath.'folder'));
  276. }
  277. public function testFilesExistsFails()
  278. {
  279. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  280. if ('\\' !== \DIRECTORY_SEPARATOR) {
  281. $this->markTestSkipped('Long file names are an issue on Windows');
  282. }
  283. $basePath = $this->workspace.'\\directory\\';
  284. $maxPathLength = PHP_MAXPATHLEN - 2;
  285. $oldPath = getcwd();
  286. mkdir($basePath);
  287. chdir($basePath);
  288. $file = str_repeat('T', $maxPathLength - \strlen($basePath) + 1);
  289. $path = $basePath.$file;
  290. exec('TYPE NUL >>'.$file); // equivalent of touch, we can not use the php touch() here because it suffers from the same limitation
  291. $this->longPathNamesWindows[] = $path; // save this so we can clean up later
  292. chdir($oldPath);
  293. $this->filesystem->exists($path);
  294. }
  295. public function testFilesExistsTraversableObjectOfFilesAndDirectories()
  296. {
  297. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  298. mkdir($basePath.'dir');
  299. touch($basePath.'file');
  300. $files = new \ArrayObject([
  301. $basePath.'dir', $basePath.'file',
  302. ]);
  303. $this->assertTrue($this->filesystem->exists($files));
  304. }
  305. public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
  306. {
  307. $basePath = $this->workspace.\DIRECTORY_SEPARATOR;
  308. mkdir($basePath.'dir');
  309. touch($basePath.'file');
  310. touch($basePath.'file2');
  311. $files = new \ArrayObject([
  312. $basePath.'dir', $basePath.'file', $basePath.'file2',
  313. ]);
  314. unlink($basePath.'file');
  315. $this->assertFalse($this->filesystem->exists($files));
  316. }
  317. public function testInvalidFileNotExists()
  318. {
  319. $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR;
  320. $this->assertFalse($this->filesystem->exists($basePath.time()));
  321. }
  322. public function testChmodChangesFileMode()
  323. {
  324. $this->markAsSkippedIfChmodIsMissing();
  325. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  326. mkdir($dir);
  327. $file = $dir.\DIRECTORY_SEPARATOR.'file';
  328. touch($file);
  329. $this->filesystem->chmod($file, 0400);
  330. $this->filesystem->chmod($dir, 0753);
  331. $this->assertFilePermissions(753, $dir);
  332. $this->assertFilePermissions(400, $file);
  333. }
  334. public function testChmodRecursive()
  335. {
  336. $this->markAsSkippedIfChmodIsMissing();
  337. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  338. mkdir($dir);
  339. $file = $dir.\DIRECTORY_SEPARATOR.'file';
  340. touch($file);
  341. $this->filesystem->chmod($file, 0400, 0000, true);
  342. $this->filesystem->chmod($dir, 0753, 0000, true);
  343. $this->assertFilePermissions(753, $dir);
  344. $this->assertFilePermissions(753, $file);
  345. }
  346. public function testChmodAppliesUmask()
  347. {
  348. $this->markAsSkippedIfChmodIsMissing();
  349. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  350. touch($file);
  351. $this->filesystem->chmod($file, 0770, 0022);
  352. $this->assertFilePermissions(750, $file);
  353. }
  354. public function testChmodChangesModeOfArrayOfFiles()
  355. {
  356. $this->markAsSkippedIfChmodIsMissing();
  357. $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
  358. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  359. $files = [$directory, $file];
  360. mkdir($directory);
  361. touch($file);
  362. $this->filesystem->chmod($files, 0753);
  363. $this->assertFilePermissions(753, $file);
  364. $this->assertFilePermissions(753, $directory);
  365. }
  366. public function testChmodChangesModeOfTraversableFileObject()
  367. {
  368. $this->markAsSkippedIfChmodIsMissing();
  369. $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
  370. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  371. $files = new \ArrayObject([$directory, $file]);
  372. mkdir($directory);
  373. touch($file);
  374. $this->filesystem->chmod($files, 0753);
  375. $this->assertFilePermissions(753, $file);
  376. $this->assertFilePermissions(753, $directory);
  377. }
  378. public function testChmodChangesZeroModeOnSubdirectoriesOnRecursive()
  379. {
  380. $this->markAsSkippedIfChmodIsMissing();
  381. $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory';
  382. $subdirectory = $directory.\DIRECTORY_SEPARATOR.'subdirectory';
  383. mkdir($directory);
  384. mkdir($subdirectory);
  385. chmod($subdirectory, 0000);
  386. $this->filesystem->chmod($directory, 0753, 0000, true);
  387. $this->assertFilePermissions(753, $subdirectory);
  388. }
  389. public function testChownByName()
  390. {
  391. $this->markAsSkippedIfPosixIsMissing();
  392. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  393. mkdir($dir);
  394. $owner = $this->getFileOwner($dir);
  395. $this->filesystem->chown($dir, $owner);
  396. $this->assertSame($owner, $this->getFileOwner($dir));
  397. }
  398. public function testChownById()
  399. {
  400. $this->markAsSkippedIfPosixIsMissing();
  401. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  402. mkdir($dir);
  403. $ownerId = $this->getFileOwnerId($dir);
  404. $this->filesystem->chown($dir, $ownerId);
  405. $this->assertSame($ownerId, $this->getFileOwnerId($dir));
  406. }
  407. public function testChownRecursiveByName()
  408. {
  409. $this->markAsSkippedIfPosixIsMissing();
  410. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  411. mkdir($dir);
  412. $file = $dir.\DIRECTORY_SEPARATOR.'file';
  413. touch($file);
  414. $owner = $this->getFileOwner($dir);
  415. $this->filesystem->chown($dir, $owner, true);
  416. $this->assertSame($owner, $this->getFileOwner($file));
  417. }
  418. public function testChownRecursiveById()
  419. {
  420. $this->markAsSkippedIfPosixIsMissing();
  421. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  422. mkdir($dir);
  423. $file = $dir.\DIRECTORY_SEPARATOR.'file';
  424. touch($file);
  425. $ownerId = $this->getFileOwnerId($dir);
  426. $this->filesystem->chown($dir, $ownerId, true);
  427. $this->assertSame($ownerId, $this->getFileOwnerId($file));
  428. }
  429. public function testChownSymlink()
  430. {
  431. $this->markAsSkippedIfSymlinkIsMissing();
  432. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  433. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  434. touch($file);
  435. $this->filesystem->symlink($file, $link);
  436. $owner = $this->getFileOwner($link);
  437. $this->filesystem->chown($link, $owner);
  438. $this->assertSame($owner, $this->getFileOwner($link));
  439. }
  440. public function testChownLink()
  441. {
  442. $this->markAsSkippedIfLinkIsMissing();
  443. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  444. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  445. touch($file);
  446. $this->filesystem->hardlink($file, $link);
  447. $owner = $this->getFileOwner($link);
  448. $this->filesystem->chown($link, $owner);
  449. $this->assertSame($owner, $this->getFileOwner($link));
  450. }
  451. public function testChownSymlinkFails()
  452. {
  453. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  454. $this->markAsSkippedIfSymlinkIsMissing();
  455. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  456. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  457. touch($file);
  458. $this->filesystem->symlink($file, $link);
  459. $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
  460. }
  461. public function testChownLinkFails()
  462. {
  463. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  464. $this->markAsSkippedIfLinkIsMissing();
  465. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  466. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  467. touch($file);
  468. $this->filesystem->hardlink($file, $link);
  469. $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
  470. }
  471. public function testChownFail()
  472. {
  473. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  474. $this->markAsSkippedIfPosixIsMissing();
  475. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  476. mkdir($dir);
  477. $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
  478. }
  479. public function testChgrpByName()
  480. {
  481. $this->markAsSkippedIfPosixIsMissing();
  482. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  483. mkdir($dir);
  484. $group = $this->getFileGroup($dir);
  485. $this->filesystem->chgrp($dir, $group);
  486. $this->assertSame($group, $this->getFileGroup($dir));
  487. }
  488. public function testChgrpById()
  489. {
  490. $this->markAsSkippedIfPosixIsMissing();
  491. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  492. mkdir($dir);
  493. $groupId = $this->getFileGroupId($dir);
  494. $this->filesystem->chgrp($dir, $groupId);
  495. $this->assertSame($groupId, $this->getFileGroupId($dir));
  496. }
  497. public function testChgrpRecursive()
  498. {
  499. $this->markAsSkippedIfPosixIsMissing();
  500. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  501. mkdir($dir);
  502. $file = $dir.\DIRECTORY_SEPARATOR.'file';
  503. touch($file);
  504. $group = $this->getFileGroup($dir);
  505. $this->filesystem->chgrp($dir, $group, true);
  506. $this->assertSame($group, $this->getFileGroup($file));
  507. }
  508. public function testChgrpSymlinkByName()
  509. {
  510. $this->markAsSkippedIfSymlinkIsMissing();
  511. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  512. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  513. touch($file);
  514. $this->filesystem->symlink($file, $link);
  515. $group = $this->getFileGroup($link);
  516. $this->filesystem->chgrp($link, $group);
  517. $this->assertSame($group, $this->getFileGroup($link));
  518. }
  519. public function testChgrpSymlinkById()
  520. {
  521. $this->markAsSkippedIfSymlinkIsMissing();
  522. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  523. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  524. touch($file);
  525. $this->filesystem->symlink($file, $link);
  526. $groupId = $this->getFileGroupId($link);
  527. $this->filesystem->chgrp($link, $groupId);
  528. $this->assertSame($groupId, $this->getFileGroupId($link));
  529. }
  530. public function testChgrpLink()
  531. {
  532. $this->markAsSkippedIfLinkIsMissing();
  533. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  534. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  535. touch($file);
  536. $this->filesystem->hardlink($file, $link);
  537. $group = $this->getFileGroup($link);
  538. $this->filesystem->chgrp($link, $group);
  539. $this->assertSame($group, $this->getFileGroup($link));
  540. }
  541. public function testChgrpSymlinkFails()
  542. {
  543. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  544. $this->markAsSkippedIfSymlinkIsMissing();
  545. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  546. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  547. touch($file);
  548. $this->filesystem->symlink($file, $link);
  549. $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
  550. }
  551. public function testChgrpLinkFails()
  552. {
  553. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  554. $this->markAsSkippedIfLinkIsMissing();
  555. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  556. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  557. touch($file);
  558. $this->filesystem->hardlink($file, $link);
  559. $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
  560. }
  561. public function testChgrpFail()
  562. {
  563. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  564. $this->markAsSkippedIfPosixIsMissing();
  565. $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir';
  566. mkdir($dir);
  567. $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
  568. }
  569. public function testRename()
  570. {
  571. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  572. $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
  573. touch($file);
  574. $this->filesystem->rename($file, $newPath);
  575. $this->assertFileNotExists($file);
  576. $this->assertFileExists($newPath);
  577. }
  578. public function testRenameThrowsExceptionIfTargetAlreadyExists()
  579. {
  580. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  581. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  582. $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
  583. touch($file);
  584. touch($newPath);
  585. $this->filesystem->rename($file, $newPath);
  586. }
  587. public function testRenameOverwritesTheTargetIfItAlreadyExists()
  588. {
  589. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  590. $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
  591. touch($file);
  592. touch($newPath);
  593. $this->filesystem->rename($file, $newPath, true);
  594. $this->assertFileNotExists($file);
  595. $this->assertFileExists($newPath);
  596. }
  597. public function testRenameThrowsExceptionOnError()
  598. {
  599. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  600. $file = $this->workspace.\DIRECTORY_SEPARATOR.uniqid('fs_test_', true);
  601. $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file';
  602. $this->filesystem->rename($file, $newPath);
  603. }
  604. public function testSymlink()
  605. {
  606. if ('\\' === \DIRECTORY_SEPARATOR) {
  607. $this->markTestSkipped('Windows does not support creating "broken" symlinks');
  608. }
  609. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  610. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  611. // $file does not exist right now: creating "broken" links is a wanted feature
  612. $this->filesystem->symlink($file, $link);
  613. $this->assertTrue(is_link($link));
  614. // Create the linked file AFTER creating the link
  615. touch($file);
  616. $this->assertEquals($file, readlink($link));
  617. }
  618. /**
  619. * @depends testSymlink
  620. */
  621. public function testRemoveSymlink()
  622. {
  623. $this->markAsSkippedIfSymlinkIsMissing();
  624. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  625. $this->filesystem->remove($link);
  626. $this->assertFalse(is_link($link));
  627. $this->assertFalse(is_file($link));
  628. $this->assertDirectoryNotExists($link);
  629. }
  630. public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
  631. {
  632. $this->markAsSkippedIfSymlinkIsMissing();
  633. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  634. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  635. touch($file);
  636. symlink($this->workspace, $link);
  637. $this->filesystem->symlink($file, $link);
  638. $this->assertTrue(is_link($link));
  639. $this->assertEquals($file, readlink($link));
  640. }
  641. public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
  642. {
  643. $this->markAsSkippedIfSymlinkIsMissing();
  644. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  645. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  646. touch($file);
  647. symlink($file, $link);
  648. $this->filesystem->symlink($file, $link);
  649. $this->assertTrue(is_link($link));
  650. $this->assertEquals($file, readlink($link));
  651. }
  652. public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
  653. {
  654. $this->markAsSkippedIfSymlinkIsMissing();
  655. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  656. $link1 = $this->workspace.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'link';
  657. $link2 = $this->workspace.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'subdir'.\DIRECTORY_SEPARATOR.'link';
  658. touch($file);
  659. $this->filesystem->symlink($file, $link1);
  660. $this->filesystem->symlink($file, $link2);
  661. $this->assertTrue(is_link($link1));
  662. $this->assertEquals($file, readlink($link1));
  663. $this->assertTrue(is_link($link2));
  664. $this->assertEquals($file, readlink($link2));
  665. }
  666. public function testLink()
  667. {
  668. $this->markAsSkippedIfLinkIsMissing();
  669. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  670. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  671. touch($file);
  672. $this->filesystem->hardlink($file, $link);
  673. $this->assertTrue(is_file($link));
  674. $this->assertEquals(fileinode($file), fileinode($link));
  675. }
  676. /**
  677. * @depends testLink
  678. */
  679. public function testRemoveLink()
  680. {
  681. $this->markAsSkippedIfLinkIsMissing();
  682. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  683. $this->filesystem->remove($link);
  684. $this->assertTrue(!is_file($link));
  685. }
  686. public function testLinkIsOverwrittenIfPointsToDifferentTarget()
  687. {
  688. $this->markAsSkippedIfLinkIsMissing();
  689. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  690. $file2 = $this->workspace.\DIRECTORY_SEPARATOR.'file2';
  691. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  692. touch($file);
  693. touch($file2);
  694. link($file2, $link);
  695. $this->filesystem->hardlink($file, $link);
  696. $this->assertTrue(is_file($link));
  697. $this->assertEquals(fileinode($file), fileinode($link));
  698. }
  699. public function testLinkIsNotOverwrittenIfAlreadyCreated()
  700. {
  701. $this->markAsSkippedIfLinkIsMissing();
  702. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  703. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  704. touch($file);
  705. link($file, $link);
  706. $this->filesystem->hardlink($file, $link);
  707. $this->assertTrue(is_file($link));
  708. $this->assertEquals(fileinode($file), fileinode($link));
  709. }
  710. public function testLinkWithSeveralTargets()
  711. {
  712. $this->markAsSkippedIfLinkIsMissing();
  713. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  714. $link1 = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  715. $link2 = $this->workspace.\DIRECTORY_SEPARATOR.'link2';
  716. touch($file);
  717. $this->filesystem->hardlink($file, [$link1, $link2]);
  718. $this->assertTrue(is_file($link1));
  719. $this->assertEquals(fileinode($file), fileinode($link1));
  720. $this->assertTrue(is_file($link2));
  721. $this->assertEquals(fileinode($file), fileinode($link2));
  722. }
  723. public function testLinkWithSameTarget()
  724. {
  725. $this->markAsSkippedIfLinkIsMissing();
  726. $file = $this->workspace.\DIRECTORY_SEPARATOR.'file';
  727. $link = $this->workspace.\DIRECTORY_SEPARATOR.'link';
  728. touch($file);
  729. // practically same as testLinkIsNotOverwrittenIfAlreadyCreated
  730. $this->filesystem->hardlink($file, [$link, $link]);
  731. $this->assertTrue(is_file($link));
  732. $this->assertEquals(fileinode($file), fileinode($link));
  733. }
  734. public function testReadRelativeLink()
  735. {
  736. $this->markAsSkippedIfSymlinkIsMissing();
  737. if ('\\' === \DIRECTORY_SEPARATOR) {
  738. $this->markTestSkipped('Relative symbolic links are not supported on Windows');
  739. }
  740. $file = $this->workspace.'/file';
  741. $link1 = $this->workspace.'/dir/link';
  742. $link2 = $this->workspace.'/dir/link2';
  743. touch($file);
  744. $this->filesystem->symlink('../file', $link1);
  745. $this->filesystem->symlink('link', $link2);
  746. $this->assertEquals($this->normalize('../file'), $this->filesystem->readlink($link1));
  747. $this->assertEquals('link', $this->filesystem->readlink($link2));
  748. $this->assertEquals($file, $this->filesystem->readlink($link1, true));
  749. $this->assertEquals($file, $this->filesystem->readlink($link2, true));
  750. $this->assertEquals($file, $this->filesystem->readlink($file, true));
  751. }
  752. public function testReadAbsoluteLink()
  753. {
  754. $this->markAsSkippedIfSymlinkIsMissing();
  755. $file = $this->normalize($this->workspace.'/file');
  756. $link1 = $this->normalize($this->workspace.'/dir/link');
  757. $link2 = $this->normalize($this->workspace.'/dir/link2');
  758. touch($file);
  759. $this->filesystem->symlink($file, $link1);
  760. $this->filesystem->symlink($link1, $link2);
  761. $this->assertEquals($file, $this->filesystem->readlink($link1));
  762. $this->assertEquals($link1, $this->filesystem->readlink($link2));
  763. $this->assertEquals($file, $this->filesystem->readlink($link1, true));
  764. $this->assertEquals($file, $this->filesystem->readlink($link2, true));
  765. $this->assertEquals($file, $this->filesystem->readlink($file, true));
  766. }
  767. public function testReadBrokenLink()
  768. {
  769. $this->markAsSkippedIfSymlinkIsMissing();
  770. if ('\\' === \DIRECTORY_SEPARATOR) {
  771. $this->markTestSkipped('Windows does not support creating "broken" symlinks');
  772. }
  773. $file = $this->workspace.'/file';
  774. $link = $this->workspace.'/link';
  775. $this->filesystem->symlink($file, $link);
  776. $this->assertEquals($file, $this->filesystem->readlink($link));
  777. $this->assertNull($this->filesystem->readlink($link, true));
  778. touch($file);
  779. $this->assertEquals($file, $this->filesystem->readlink($link, true));
  780. }
  781. public function testReadLinkDefaultPathDoesNotExist()
  782. {
  783. $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'/invalid')));
  784. }
  785. public function testReadLinkDefaultPathNotLink()
  786. {
  787. $file = $this->normalize($this->workspace.'/file');
  788. touch($file);
  789. $this->assertNull($this->filesystem->readlink($file));
  790. }
  791. public function testReadLinkCanonicalizePath()
  792. {
  793. $this->markAsSkippedIfSymlinkIsMissing();
  794. $file = $this->normalize($this->workspace.'/file');
  795. mkdir($this->normalize($this->workspace.'/dir'));
  796. touch($file);
  797. $this->assertEquals($file, $this->filesystem->readlink($this->normalize($this->workspace.'/dir/../file'), true));
  798. }
  799. public function testReadLinkCanonicalizedPathDoesNotExist()
  800. {
  801. $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'invalid'), true));
  802. }
  803. /**
  804. * @dataProvider providePathsForMakePathRelative
  805. */
  806. public function testMakePathRelative($endPath, $startPath, $expectedPath)
  807. {
  808. $path = $this->filesystem->makePathRelative($endPath, $startPath);
  809. $this->assertEquals($expectedPath, $path);
  810. }
  811. public function providePathsForMakePathRelative()
  812. {
  813. $paths = [
  814. ['/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'],
  815. ['/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'],
  816. ['/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'],
  817. ['/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'],
  818. ['/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'],
  819. ['/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'],
  820. ['/aa/bb', '/aa/bb', './'],
  821. ['/aa/bb', '/aa/bb/', './'],
  822. ['/aa/bb/', '/aa/bb', './'],
  823. ['/aa/bb/', '/aa/bb/', './'],
  824. ['/aa/bb/cc', '/aa/bb/cc/dd', '../'],
  825. ['/aa/bb/cc', '/aa/bb/cc/dd/', '../'],
  826. ['/aa/bb/cc/', '/aa/bb/cc/dd', '../'],
  827. ['/aa/bb/cc/', '/aa/bb/cc/dd/', '../'],
  828. ['/aa/bb/cc', '/aa', 'bb/cc/'],
  829. ['/aa/bb/cc', '/aa/', 'bb/cc/'],
  830. ['/aa/bb/cc/', '/aa', 'bb/cc/'],
  831. ['/aa/bb/cc/', '/aa/', 'bb/cc/'],
  832. ['/a/aab/bb', '/a/aa', '../aab/bb/'],
  833. ['/a/aab/bb', '/a/aa/', '../aab/bb/'],
  834. ['/a/aab/bb/', '/a/aa', '../aab/bb/'],
  835. ['/a/aab/bb/', '/a/aa/', '../aab/bb/'],
  836. ['/a/aab/bb/', '/', 'a/aab/bb/'],
  837. ['/a/aab/bb/', '/b/aab', '../../a/aab/bb/'],
  838. ['/aab/bb', '/aa', '../aab/bb/'],
  839. ['/aab', '/aa', '../aab/'],
  840. ['/aa/bb/cc', '/aa/dd/..', 'bb/cc/'],
  841. ['/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'],
  842. ['/aa/bb/../../cc', '/aa/../dd/..', 'cc/'],
  843. ['/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'],
  844. ['/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'],
  845. ['C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'],
  846. ['C:/aa/bb/cc', 'c:/aa/dd/..', 'bb/cc/'],
  847. ['c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'],
  848. ['C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'],
  849. ['C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'],
  850. ['C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'],
  851. ['D:/', 'C:/aa/../bb/cc', 'D:/'],
  852. ['D:/aa/bb', 'C:/aa', 'D:/aa/bb/'],
  853. ['D:/../../aa/../bb/cc', 'C:/aa/dd/..', 'D:/bb/cc/'],
  854. ];
  855. if ('\\' === \DIRECTORY_SEPARATOR) {
  856. $paths[] = ['c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/'];
  857. }
  858. return $paths;
  859. }
  860. public function testMakePathRelativeWithRelativeStartPath()
  861. {
  862. $this->expectException('Symfony\Component\Filesystem\Exception\InvalidArgumentException');
  863. $this->expectExceptionMessage('The start path "var/lib/symfony/src/Symfony/Component" is not absolute.');
  864. $this->assertSame('../../../', $this->filesystem->makePathRelative('/var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component'));
  865. }
  866. public function testMakePathRelativeWithRelativeEndPath()
  867. {
  868. $this->expectException('Symfony\Component\Filesystem\Exception\InvalidArgumentException');
  869. $this->expectExceptionMessage('The end path "var/lib/symfony/" is not absolute.');
  870. $this->assertSame('../../../', $this->filesystem->makePathRelative('var/lib/symfony/', '/var/lib/symfony/src/Symfony/Component'));
  871. }
  872. public function testMirrorCopiesFilesAndDirectoriesRecursively()
  873. {
  874. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  875. $directory = $sourcePath.'directory'.\DIRECTORY_SEPARATOR;
  876. $file1 = $directory.'file1';
  877. $file2 = $sourcePath.'file2';
  878. mkdir($sourcePath);
  879. mkdir($directory);
  880. file_put_contents($file1, 'FILE1');
  881. file_put_contents($file2, 'FILE2');
  882. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  883. $this->filesystem->mirror($sourcePath, $targetPath);
  884. $this->assertDirectoryExists($targetPath);
  885. $this->assertDirectoryExists($targetPath.'directory');
  886. $this->assertFileEquals($file1, $targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1');
  887. $this->assertFileEquals($file2, $targetPath.'file2');
  888. $this->filesystem->remove($file1);
  889. $this->filesystem->mirror($sourcePath, $targetPath, null, ['delete' => false]);
  890. $this->assertTrue($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
  891. $this->filesystem->mirror($sourcePath, $targetPath, null, ['delete' => true]);
  892. $this->assertFalse($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
  893. file_put_contents($file1, 'FILE1');
  894. $this->filesystem->mirror($sourcePath, $targetPath, null, ['delete' => true]);
  895. $this->assertTrue($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
  896. $this->filesystem->remove($directory);
  897. $this->filesystem->mirror($sourcePath, $targetPath, null, ['delete' => true]);
  898. $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
  899. $this->assertFalse($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'));
  900. }
  901. public function testMirrorCreatesEmptyDirectory()
  902. {
  903. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  904. mkdir($sourcePath);
  905. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  906. $this->filesystem->mirror($sourcePath, $targetPath);
  907. $this->assertDirectoryExists($targetPath);
  908. $this->filesystem->remove($sourcePath);
  909. }
  910. public function testMirrorCopiesLinks()
  911. {
  912. $this->markAsSkippedIfSymlinkIsMissing();
  913. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  914. mkdir($sourcePath);
  915. file_put_contents($sourcePath.'file1', 'FILE1');
  916. symlink($sourcePath.'file1', $sourcePath.'link1');
  917. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  918. $this->filesystem->mirror($sourcePath, $targetPath);
  919. $this->assertDirectoryExists($targetPath);
  920. $this->assertFileEquals($sourcePath.'file1', $targetPath.'link1');
  921. $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1'));
  922. }
  923. public function testMirrorCopiesLinkedDirectoryContents()
  924. {
  925. $this->markAsSkippedIfSymlinkIsMissing(true);
  926. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  927. mkdir($sourcePath.'nested/', 0777, true);
  928. file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
  929. // Note: We symlink directory, not file
  930. symlink($sourcePath.'nested', $sourcePath.'link1');
  931. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  932. $this->filesystem->mirror($sourcePath, $targetPath);
  933. $this->assertDirectoryExists($targetPath);
  934. $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
  935. $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1'));
  936. }
  937. public function testMirrorCopiesRelativeLinkedContents()
  938. {
  939. $this->markAsSkippedIfSymlinkIsMissing(true);
  940. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  941. $oldPath = getcwd();
  942. mkdir($sourcePath.'nested/', 0777, true);
  943. file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
  944. // Note: Create relative symlink
  945. chdir($sourcePath);
  946. symlink('nested', 'link1');
  947. chdir($oldPath);
  948. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  949. $this->filesystem->mirror($sourcePath, $targetPath);
  950. $this->assertDirectoryExists($targetPath);
  951. $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt');
  952. $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1'));
  953. $this->assertEquals('\\' === \DIRECTORY_SEPARATOR ? realpath($sourcePath.'\nested') : 'nested', readlink($targetPath.\DIRECTORY_SEPARATOR.'link1'));
  954. }
  955. public function testMirrorContentsWithSameNameAsSourceOrTargetWithoutDeleteOption()
  956. {
  957. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  958. mkdir($sourcePath);
  959. touch($sourcePath.'source');
  960. touch($sourcePath.'target');
  961. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  962. $oldPath = getcwd();
  963. chdir($this->workspace);
  964. $this->filesystem->mirror('source', $targetPath);
  965. chdir($oldPath);
  966. $this->assertDirectoryExists($targetPath);
  967. $this->assertFileExists($targetPath.'source');
  968. $this->assertFileExists($targetPath.'target');
  969. }
  970. public function testMirrorContentsWithSameNameAsSourceOrTargetWithDeleteOption()
  971. {
  972. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  973. mkdir($sourcePath);
  974. touch($sourcePath.'source');
  975. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR;
  976. mkdir($targetPath);
  977. touch($targetPath.'source');
  978. touch($targetPath.'target');
  979. $oldPath = getcwd();
  980. chdir($this->workspace);
  981. $this->filesystem->mirror('source', 'target', null, ['delete' => true]);
  982. chdir($oldPath);
  983. $this->assertDirectoryExists($targetPath);
  984. $this->assertFileExists($targetPath.'source');
  985. $this->assertFileNotExists($targetPath.'target');
  986. }
  987. public function testMirrorAvoidCopyingTargetDirectoryIfInSourceDirectory()
  988. {
  989. $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR;
  990. $directory = $sourcePath.'directory'.\DIRECTORY_SEPARATOR;
  991. $file1 = $directory.'file1';
  992. $file2 = $sourcePath.'file2';
  993. mkdir($sourcePath);
  994. mkdir($directory);
  995. file_put_contents($file1, 'FILE1');
  996. file_put_contents($file2, 'FILE2');
  997. $targetPath = $sourcePath.'target'.\DIRECTORY_SEPARATOR;
  998. if ('\\' !== \DIRECTORY_SEPARATOR) {
  999. $this->filesystem->symlink($targetPath, $sourcePath.'target_simlink');
  1000. }
  1001. $this->filesystem->mirror($sourcePath, $targetPath, null, ['delete' => true]);
  1002. $this->assertTrue($this->filesystem->exists($targetPath));
  1003. $this->assertTrue($this->filesystem->exists($targetPath.'directory'));
  1004. $this->assertFileEquals($file1, $targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1');
  1005. $this->assertFileEquals($file2, $targetPath.'file2');
  1006. $this->assertFalse($this->filesystem->exists($targetPath.'target_simlink'));
  1007. $this->assertFalse($this->filesystem->exists($targetPath.'target'));
  1008. }
  1009. public function testMirrorFromSubdirectoryInToParentDirectory()
  1010. {
  1011. $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR;
  1012. $sourcePath = $targetPath.'bar'.\DIRECTORY_SEPARATOR;
  1013. $file1 = $sourcePath.'file1';
  1014. $file2 = $sourcePath.'file2';
  1015. $this->filesystem->mkdir($sourcePath);
  1016. file_put_contents($file1, 'FILE1');
  1017. file_put_contents($file2, 'FILE2');
  1018. $this->filesystem->mirror($sourcePath, $targetPath);
  1019. $this->assertFileEquals($file1, $targetPath.'file1');
  1020. }
  1021. /**
  1022. * @dataProvider providePathsForIsAbsolutePath
  1023. */
  1024. public function testIsAbsolutePath($path, $expectedResult)
  1025. {
  1026. $result = $this->filesystem->isAbsolutePath($path);
  1027. $this->assertEquals($expectedResult, $result);
  1028. }
  1029. public function providePathsForIsAbsolutePath()
  1030. {
  1031. return [
  1032. ['/var/lib', true],
  1033. ['c:\\\\var\\lib', true],
  1034. ['\\var\\lib', true],
  1035. ['var/lib', false],
  1036. ['../var/lib', false],
  1037. ['', false],
  1038. ];
  1039. }
  1040. public function testTempnam()
  1041. {
  1042. $dirname = $this->workspace;
  1043. $filename = $this->filesystem->tempnam($dirname, 'foo');
  1044. $this->assertFileExists($filename);
  1045. }
  1046. public function testTempnamWithFileScheme()
  1047. {
  1048. $scheme = 'file://';
  1049. $dirname = $scheme.$this->workspace;
  1050. $filename = $this->filesystem->tempnam($dirname, 'foo');
  1051. $this->assertStringStartsWith($scheme, $filename);
  1052. $this->assertFileExists($filename);
  1053. }
  1054. public function testTempnamWithMockScheme()
  1055. {
  1056. stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream');
  1057. $scheme = 'mock://';
  1058. $dirname = $scheme.$this->workspace;
  1059. $filename = $this->filesystem->tempnam($dirname, 'foo');
  1060. $this->assertStringStartsWith($scheme, $filename);
  1061. $this->assertFileExists($filename);
  1062. }
  1063. public function testTempnamWithZlibSchemeFails()
  1064. {
  1065. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  1066. $scheme = 'compress.zlib://';
  1067. $dirname = $scheme.$this->workspace;
  1068. // The compress.zlib:// stream does not support mode x: creates the file, errors "failed to open stream: operation failed" and returns false
  1069. $this->filesystem->tempnam($dirname, 'bar');
  1070. }
  1071. public function testTempnamWithPHPTempSchemeFails()
  1072. {
  1073. $scheme = 'php://temp';
  1074. $dirname = $scheme;
  1075. $filename = $this->filesystem->tempnam($dirname, 'bar');
  1076. $this->assertStringStartsWith($scheme, $filename);
  1077. // The php://temp stream deletes the file after close
  1078. $this->assertFileNotExists($filename);
  1079. }
  1080. public function testTempnamWithPharSchemeFails()
  1081. {
  1082. $this->expectException('Symfony\Component\Filesystem\Exception\IOException');
  1083. // Skip test if Phar disabled phar.readonly must be 0 in php.ini
  1084. if (!\Phar::canWrite()) {
  1085. $this->markTestSkipped('This test cannot run when phar.readonly is 1.');
  1086. }
  1087. $scheme = 'phar://';
  1088. $dirname = $scheme.$this->workspace;
  1089. $pharname = 'foo.phar';
  1090. new \Phar($this->workspace.'/'.$pharname, 0, $pharname);
  1091. // The phar:// stream does not support mode x: fails to create file, errors "failed to open stream: phar error: "$filename" is not a file in phar "$pharname"" and returns false
  1092. $this->filesystem->tempnam($dirname, $pharname.'/bar');
  1093. }
  1094. public function testTempnamWithHTTPSchemeFails()
  1095. {
  1096. $this->expe

Large files files are truncated, but you can click here to view the full file