No Description

FinderTest.php 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  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\Finder\Tests;
  11. use Symfony\Component\Finder\Finder;
  12. use Symfony\Component\Finder\Adapter;
  13. class FinderTest extends Iterator\RealIteratorTestCase
  14. {
  15. public function testCreate()
  16. {
  17. $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create());
  18. }
  19. /**
  20. * @dataProvider getAdaptersTestData
  21. */
  22. public function testDirectories($adapter)
  23. {
  24. $finder = $this->buildFinder($adapter);
  25. $this->assertSame($finder, $finder->directories());
  26. $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
  27. $finder = $this->buildFinder($adapter);
  28. $finder->directories();
  29. $finder->files();
  30. $finder->directories();
  31. $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
  32. }
  33. /**
  34. * @dataProvider getAdaptersTestData
  35. */
  36. public function testFiles($adapter)
  37. {
  38. $finder = $this->buildFinder($adapter);
  39. $this->assertSame($finder, $finder->files());
  40. $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  41. $finder = $this->buildFinder($adapter);
  42. $finder->files();
  43. $finder->directories();
  44. $finder->files();
  45. $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  46. }
  47. /**
  48. * @dataProvider getAdaptersTestData
  49. */
  50. public function testDepth($adapter)
  51. {
  52. $finder = $this->buildFinder($adapter);
  53. $this->assertSame($finder, $finder->depth('< 1'));
  54. $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  55. $finder = $this->buildFinder($adapter);
  56. $this->assertSame($finder, $finder->depth('<= 0'));
  57. $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  58. $finder = $this->buildFinder($adapter);
  59. $this->assertSame($finder, $finder->depth('>= 1'));
  60. $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator());
  61. $finder = $this->buildFinder($adapter);
  62. $finder->depth('< 1')->depth('>= 1');
  63. $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
  64. }
  65. /**
  66. * @dataProvider getAdaptersTestData
  67. */
  68. public function testName($adapter)
  69. {
  70. $finder = $this->buildFinder($adapter);
  71. $this->assertSame($finder, $finder->name('*.php'));
  72. $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
  73. $finder = $this->buildFinder($adapter);
  74. $finder->name('test.ph*');
  75. $finder->name('test.py');
  76. $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
  77. $finder = $this->buildFinder($adapter);
  78. $finder->name('~^test~i');
  79. $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
  80. $finder = $this->buildFinder($adapter);
  81. $finder->name('~\\.php$~i');
  82. $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
  83. $finder = $this->buildFinder($adapter);
  84. $finder->name('test.p{hp,y}');
  85. $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
  86. }
  87. /**
  88. * @dataProvider getAdaptersTestData
  89. */
  90. public function testNotName($adapter)
  91. {
  92. $finder = $this->buildFinder($adapter);
  93. $this->assertSame($finder, $finder->notName('*.php'));
  94. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  95. $finder = $this->buildFinder($adapter);
  96. $finder->notName('*.php');
  97. $finder->notName('*.py');
  98. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  99. $finder = $this->buildFinder($adapter);
  100. $finder->name('test.ph*');
  101. $finder->name('test.py');
  102. $finder->notName('*.php');
  103. $finder->notName('*.py');
  104. $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
  105. $finder = $this->buildFinder($adapter);
  106. $finder->name('test.ph*');
  107. $finder->name('test.py');
  108. $finder->notName('*.p{hp,y}');
  109. $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
  110. }
  111. /**
  112. * @dataProvider getRegexNameTestData
  113. *
  114. * @group regexName
  115. */
  116. public function testRegexName($adapter, $regex)
  117. {
  118. $finder = $this->buildFinder($adapter);
  119. $finder->name($regex);
  120. $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
  121. }
  122. /**
  123. * @dataProvider getAdaptersTestData
  124. */
  125. public function testSize($adapter)
  126. {
  127. $finder = $this->buildFinder($adapter);
  128. $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500'));
  129. $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
  130. }
  131. /**
  132. * @dataProvider getAdaptersTestData
  133. */
  134. public function testDate($adapter)
  135. {
  136. $finder = $this->buildFinder($adapter);
  137. $this->assertSame($finder, $finder->files()->date('until last month'));
  138. $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
  139. }
  140. /**
  141. * @dataProvider getAdaptersTestData
  142. */
  143. public function testExclude($adapter)
  144. {
  145. $finder = $this->buildFinder($adapter);
  146. $this->assertSame($finder, $finder->exclude('foo'));
  147. $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  148. }
  149. /**
  150. * @dataProvider getAdaptersTestData
  151. */
  152. public function testIgnoreVCS($adapter)
  153. {
  154. $finder = $this->buildFinder($adapter);
  155. $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
  156. $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  157. $finder = $this->buildFinder($adapter);
  158. $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
  159. $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  160. $finder = $this->buildFinder($adapter);
  161. $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
  162. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  163. }
  164. /**
  165. * @dataProvider getAdaptersTestData
  166. */
  167. public function testIgnoreDotFiles($adapter)
  168. {
  169. $finder = $this->buildFinder($adapter);
  170. $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
  171. $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  172. $finder = $this->buildFinder($adapter);
  173. $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
  174. $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  175. $finder = $this->buildFinder($adapter);
  176. $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
  177. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  178. }
  179. /**
  180. * @dataProvider getAdaptersTestData
  181. */
  182. public function testSortByName($adapter)
  183. {
  184. $finder = $this->buildFinder($adapter);
  185. $this->assertSame($finder, $finder->sortByName());
  186. $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
  187. }
  188. /**
  189. * @dataProvider getAdaptersTestData
  190. */
  191. public function testSortByType($adapter)
  192. {
  193. $finder = $this->buildFinder($adapter);
  194. $this->assertSame($finder, $finder->sortByType());
  195. $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
  196. }
  197. /**
  198. * @dataProvider getAdaptersTestData
  199. */
  200. public function testSortByAccessedTime($adapter)
  201. {
  202. $finder = $this->buildFinder($adapter);
  203. $this->assertSame($finder, $finder->sortByAccessedTime());
  204. $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  205. }
  206. /**
  207. * @dataProvider getAdaptersTestData
  208. */
  209. public function testSortByChangedTime($adapter)
  210. {
  211. $finder = $this->buildFinder($adapter);
  212. $this->assertSame($finder, $finder->sortByChangedTime());
  213. $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  214. }
  215. /**
  216. * @dataProvider getAdaptersTestData
  217. */
  218. public function testSortByModifiedTime($adapter)
  219. {
  220. $finder = $this->buildFinder($adapter);
  221. $this->assertSame($finder, $finder->sortByModifiedTime());
  222. $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  223. }
  224. /**
  225. * @dataProvider getAdaptersTestData
  226. */
  227. public function testSort($adapter)
  228. {
  229. $finder = $this->buildFinder($adapter);
  230. $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }));
  231. $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
  232. }
  233. /**
  234. * @dataProvider getAdaptersTestData
  235. */
  236. public function testFilter($adapter)
  237. {
  238. $finder = $this->buildFinder($adapter);
  239. $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return preg_match('/test/', $f) > 0; }));
  240. $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
  241. }
  242. /**
  243. * @dataProvider getAdaptersTestData
  244. */
  245. public function testFollowLinks($adapter)
  246. {
  247. if ('\\' == DIRECTORY_SEPARATOR) {
  248. return;
  249. }
  250. $finder = $this->buildFinder($adapter);
  251. $this->assertSame($finder, $finder->followLinks());
  252. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
  253. }
  254. /**
  255. * @dataProvider getAdaptersTestData
  256. */
  257. public function testIn($adapter)
  258. {
  259. $finder = $this->buildFinder($adapter);
  260. try {
  261. $finder->in('foobar');
  262. $this->fail('->in() throws a \InvalidArgumentException if the directory does not exist');
  263. } catch (\Exception $e) {
  264. $this->assertInstanceOf('InvalidArgumentException', $e, '->in() throws a \InvalidArgumentException if the directory does not exist');
  265. }
  266. $finder = $this->buildFinder($adapter);
  267. $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator();
  268. $this->assertIterator(array(self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php'), $iterator);
  269. }
  270. /**
  271. * @dataProvider getAdaptersTestData
  272. */
  273. public function testInWithGlob($adapter)
  274. {
  275. $finder = $this->buildFinder($adapter);
  276. $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator();
  277. $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
  278. }
  279. /**
  280. * @dataProvider getAdaptersTestData
  281. * @expectedException \InvalidArgumentException
  282. */
  283. public function testInWithNonDirectoryGlob($adapter)
  284. {
  285. $finder = $this->buildFinder($adapter);
  286. $finder->in(__DIR__.'/Fixtures/A/a*');
  287. }
  288. /**
  289. * @dataProvider getAdaptersTestData
  290. */
  291. public function testInWithGlobBrace($adapter)
  292. {
  293. $finder = $this->buildFinder($adapter);
  294. $finder->in(array(__DIR__.'/Fixtures/{A,copy/A}/B/C'))->getIterator();
  295. $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
  296. }
  297. /**
  298. * @dataProvider getAdaptersTestData
  299. */
  300. public function testGetIterator($adapter)
  301. {
  302. $finder = $this->buildFinder($adapter);
  303. try {
  304. $finder->getIterator();
  305. $this->fail('->getIterator() throws a \LogicException if the in() method has not been called');
  306. } catch (\Exception $e) {
  307. $this->assertInstanceOf('LogicException', $e, '->getIterator() throws a \LogicException if the in() method has not been called');
  308. }
  309. $finder = $this->buildFinder($adapter);
  310. $dirs = array();
  311. foreach ($finder->directories()->in(self::$tmpDir) as $dir) {
  312. $dirs[] = (string) $dir;
  313. }
  314. $expected = $this->toAbsolute(array('foo', 'toto'));
  315. sort($dirs);
  316. sort($expected);
  317. $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface');
  318. $finder = $this->buildFinder($adapter);
  319. $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');
  320. $finder = $this->buildFinder($adapter);
  321. $a = iterator_to_array($finder->directories()->in(self::$tmpDir));
  322. $a = array_values(array_map(function ($a) { return (string) $a; }, $a));
  323. sort($a);
  324. $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface');
  325. }
  326. /**
  327. * @dataProvider getAdaptersTestData
  328. */
  329. public function testRelativePath($adapter)
  330. {
  331. $finder = $this->buildFinder($adapter)->in(self::$tmpDir);
  332. $paths = array();
  333. foreach ($finder as $file) {
  334. $paths[] = $file->getRelativePath();
  335. }
  336. $ref = array("", "", "", "", "foo", "");
  337. sort($ref);
  338. sort($paths);
  339. $this->assertEquals($ref, $paths);
  340. }
  341. /**
  342. * @dataProvider getAdaptersTestData
  343. */
  344. public function testRelativePathname($adapter)
  345. {
  346. $finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName();
  347. $paths = array();
  348. foreach ($finder as $file) {
  349. $paths[] = $file->getRelativePathname();
  350. }
  351. $ref = array("test.php", "toto", "test.py", "foo", "foo".DIRECTORY_SEPARATOR."bar.tmp", "foo bar");
  352. sort($paths);
  353. sort($ref);
  354. $this->assertEquals($ref, $paths);
  355. }
  356. /**
  357. * @dataProvider getAdaptersTestData
  358. */
  359. public function testAppendWithAFinder($adapter)
  360. {
  361. $finder = $this->buildFinder($adapter);
  362. $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
  363. $finder1 = $this->buildFinder($adapter);
  364. $finder1->directories()->in(self::$tmpDir);
  365. $finder = $finder->append($finder1);
  366. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
  367. }
  368. /**
  369. * @dataProvider getAdaptersTestData
  370. */
  371. public function testAppendWithAnArray($adapter)
  372. {
  373. $finder = $this->buildFinder($adapter);
  374. $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
  375. $finder->append($this->toAbsolute(array('foo', 'toto')));
  376. $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
  377. }
  378. /**
  379. * @dataProvider getAdaptersTestData
  380. */
  381. public function testAppendReturnsAFinder($adapter)
  382. {
  383. $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', $this->buildFinder($adapter)->append(array()));
  384. }
  385. /**
  386. * @dataProvider getAdaptersTestData
  387. */
  388. public function testAppendDoesNotRequireIn($adapter)
  389. {
  390. $finder = $this->buildFinder($adapter);
  391. $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
  392. $finder1 = Finder::create()->append($finder);
  393. $this->assertIterator(iterator_to_array($finder->getIterator()), $finder1->getIterator());
  394. }
  395. public function testCountDirectories()
  396. {
  397. $directory = Finder::create()->directories()->in(self::$tmpDir);
  398. $i = 0;
  399. foreach ($directory as $dir) {
  400. $i++;
  401. }
  402. $this->assertCount($i, $directory);
  403. }
  404. public function testCountFiles()
  405. {
  406. $files = Finder::create()->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
  407. $i = 0;
  408. foreach ($files as $file) {
  409. $i++;
  410. }
  411. $this->assertCount($i, $files);
  412. }
  413. /**
  414. * @expectedException \LogicException
  415. */
  416. public function testCountWithoutIn()
  417. {
  418. $finder = Finder::create()->files();
  419. count($finder);
  420. }
  421. /**
  422. * @dataProvider getContainsTestData
  423. * @group grep
  424. */
  425. public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expected)
  426. {
  427. $finder = $this->buildFinder($adapter);
  428. $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
  429. ->name('*.txt')->sortByName()
  430. ->contains($matchPatterns)
  431. ->notContains($noMatchPatterns);
  432. $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
  433. }
  434. /**
  435. * @dataProvider getAdaptersTestData
  436. */
  437. public function testContainsOnDirectory(Adapter\AdapterInterface $adapter)
  438. {
  439. $finder = $this->buildFinder($adapter);
  440. $finder->in(__DIR__)
  441. ->directories()
  442. ->name('Fixtures')
  443. ->contains('abc');
  444. $this->assertIterator(array(), $finder);
  445. }
  446. /**
  447. * @dataProvider getAdaptersTestData
  448. */
  449. public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter)
  450. {
  451. $finder = $this->buildFinder($adapter);
  452. $finder->in(__DIR__)
  453. ->directories()
  454. ->name('Fixtures')
  455. ->notContains('abc');
  456. $this->assertIterator(array(), $finder);
  457. }
  458. /**
  459. * Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
  460. * with inner FilesystemIterator in an invalid state.
  461. *
  462. * @see https://bugs.php.net/bug.php?id=49104
  463. *
  464. * @dataProvider getAdaptersTestData
  465. */
  466. public function testMultipleLocations(Adapter\AdapterInterface $adapter)
  467. {
  468. $locations = array(
  469. self::$tmpDir.'/',
  470. self::$tmpDir.'/toto/',
  471. );
  472. // it is expected that there are test.py test.php in the tmpDir
  473. $finder = $this->buildFinder($adapter);
  474. $finder->in($locations)->depth('< 1')->name('test.php');
  475. $this->assertCount(1, $finder);
  476. }
  477. /**
  478. * Iterator keys must be the file pathname.
  479. *
  480. * @dataProvider getAdaptersTestData
  481. */
  482. public function testIteratorKeys(Adapter\AdapterInterface $adapter)
  483. {
  484. $finder = $this->buildFinder($adapter)->in(self::$tmpDir);
  485. foreach ($finder as $key => $file) {
  486. $this->assertEquals($file->getPathname(), $key);
  487. }
  488. }
  489. /**
  490. * @dataProvider getAdaptersTestData
  491. */
  492. public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag(Adapter\AdapterInterface $adapter)
  493. {
  494. $finder = $this->buildFinder($adapter);
  495. $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'r+e.gex[c]a(r)s')
  496. ->path('/^dir/');
  497. $expected = array('r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir',
  498. 'r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'bar.dat',);
  499. $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
  500. }
  501. public function testAdaptersOrdering()
  502. {
  503. $finder = Finder::create()
  504. ->removeAdapters()
  505. ->addAdapter(new FakeAdapter\NamedAdapter('a'), 0)
  506. ->addAdapter(new FakeAdapter\NamedAdapter('b'), -50)
  507. ->addAdapter(new FakeAdapter\NamedAdapter('c'), 50)
  508. ->addAdapter(new FakeAdapter\NamedAdapter('d'), -25)
  509. ->addAdapter(new FakeAdapter\NamedAdapter('e'), 25);
  510. $this->assertEquals(
  511. array('c', 'e', 'a', 'd', 'b'),
  512. array_map(function (Adapter\AdapterInterface $adapter) {
  513. return $adapter->getName();
  514. }, $finder->getAdapters())
  515. );
  516. }
  517. public function testAdaptersChaining()
  518. {
  519. $iterator = new \ArrayIterator(array());
  520. $filenames = $this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto'));
  521. foreach ($filenames as $file) {
  522. $iterator->append(new \Symfony\Component\Finder\SplFileInfo($file, null, null));
  523. }
  524. $finder = Finder::create()
  525. ->removeAdapters()
  526. ->addAdapter(new FakeAdapter\UnsupportedAdapter(), 3)
  527. ->addAdapter(new FakeAdapter\FailingAdapter(), 2)
  528. ->addAdapter(new FakeAdapter\DummyAdapter($iterator), 1);
  529. $this->assertIterator($filenames, $finder->in(sys_get_temp_dir())->getIterator());
  530. }
  531. public function getAdaptersTestData()
  532. {
  533. return array_map(
  534. function ($adapter) { return array($adapter); },
  535. $this->getValidAdapters()
  536. );
  537. }
  538. public function getContainsTestData()
  539. {
  540. $tests = array(
  541. array('', '', array()),
  542. array('foo', 'bar', array()),
  543. array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
  544. array('lorem ipsum dolor sit amet', 'foobar', array('lorem.txt')),
  545. array('sit', 'bar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
  546. array('dolor sit amet', '@^L@m', array('dolor.txt', 'ipsum.txt')),
  547. array('/^lorem ipsum dolor sit amet$/m', 'foobar', array('lorem.txt')),
  548. array('lorem', 'foobar', array('lorem.txt')),
  549. array('', 'lorem', array('dolor.txt', 'ipsum.txt')),
  550. array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')),
  551. );
  552. return $this->buildTestData($tests);
  553. }
  554. public function getRegexNameTestData()
  555. {
  556. $tests = array(
  557. array('~.+\\.p.+~i'),
  558. array('~t.*s~i'),
  559. );
  560. return $this->buildTestData($tests);
  561. }
  562. /**
  563. * @dataProvider getTestPathData
  564. */
  565. public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected)
  566. {
  567. $finder = $this->buildFinder($adapter);
  568. $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
  569. ->path($matchPatterns)
  570. ->notPath($noMatchPatterns);
  571. $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
  572. }
  573. public function testAdapterSelection()
  574. {
  575. // test that by default, PhpAdapter is selected
  576. $adapters = Finder::create()->getAdapters();
  577. $this->assertTrue($adapters[0] instanceof Adapter\PhpAdapter);
  578. // test another adapter selection
  579. $adapters = Finder::create()->setAdapter('gnu_find')->getAdapters();
  580. $this->assertTrue($adapters[0] instanceof Adapter\GnuFindAdapter);
  581. // test that useBestAdapter method removes selection
  582. $adapters = Finder::create()->useBestAdapter()->getAdapters();
  583. $this->assertFalse($adapters[0] instanceof Adapter\PhpAdapter);
  584. }
  585. public function getTestPathData()
  586. {
  587. $tests = array(
  588. array('', '', array()),
  589. array('/^A\/B\/C/', '/C$/',
  590. array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat'),
  591. ),
  592. array('/^A\/B/', 'foobar',
  593. array(
  594. 'A'.DIRECTORY_SEPARATOR.'B',
  595. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
  596. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
  597. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
  598. ),
  599. ),
  600. array('A/B/C', 'foobar',
  601. array(
  602. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
  603. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
  604. 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
  605. 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
  606. ),
  607. ),
  608. array('A/B', 'foobar',
  609. array(
  610. //dirs
  611. 'A'.DIRECTORY_SEPARATOR.'B',
  612. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
  613. 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B',
  614. 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
  615. //files
  616. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
  617. 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
  618. 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat.copy',
  619. 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
  620. ),
  621. ),
  622. array('/^with space\//', 'foobar',
  623. array(
  624. 'with space'.DIRECTORY_SEPARATOR.'foo.txt',
  625. ),
  626. ),
  627. );
  628. return $this->buildTestData($tests);
  629. }
  630. /**
  631. * @dataProvider getAdaptersTestData
  632. */
  633. public function testAccessDeniedException(Adapter\AdapterInterface $adapter)
  634. {
  635. if ('\\' === DIRECTORY_SEPARATOR) {
  636. $this->markTestSkipped('chmod is not supported on Windows');
  637. }
  638. $finder = $this->buildFinder($adapter);
  639. $finder->files()->in(self::$tmpDir);
  640. // make 'foo' directory non-readable
  641. $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
  642. chmod($testDir, 0333);
  643. if (false === $couldRead = is_readable($testDir)) {
  644. try {
  645. $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
  646. $this->fail('Finder should throw an exception when opening a non-readable directory.');
  647. } catch (\Exception $e) {
  648. $expectedExceptionClass = 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException';
  649. if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) {
  650. $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, 'PHPUnit_Framework_ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString()));
  651. }
  652. $this->assertInstanceOf($expectedExceptionClass, $e);
  653. }
  654. }
  655. // restore original permissions
  656. chmod($testDir, 0777);
  657. clearstatcache($testDir);
  658. if ($couldRead) {
  659. $this->markTestSkipped('could read test files while test requires unreadable');
  660. }
  661. }
  662. /**
  663. * @dataProvider getAdaptersTestData
  664. */
  665. public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter)
  666. {
  667. if ('\\' === DIRECTORY_SEPARATOR) {
  668. $this->markTestSkipped('chmod is not supported on Windows');
  669. }
  670. $finder = $this->buildFinder($adapter);
  671. $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);
  672. // make 'foo' directory non-readable
  673. $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
  674. chmod($testDir, 0333);
  675. if (false === ($couldRead = is_readable($testDir))) {
  676. $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
  677. }
  678. // restore original permissions
  679. chmod($testDir, 0777);
  680. clearstatcache($testDir);
  681. if ($couldRead) {
  682. $this->markTestSkipped('could read test files while test requires unreadable');
  683. }
  684. }
  685. private function buildTestData(array $tests)
  686. {
  687. $data = array();
  688. foreach ($this->getValidAdapters() as $adapter) {
  689. foreach ($tests as $test) {
  690. $data[] = array_merge(array($adapter), $test);
  691. }
  692. }
  693. return $data;
  694. }
  695. private function buildFinder(Adapter\AdapterInterface $adapter)
  696. {
  697. return Finder::create()
  698. ->removeAdapters()
  699. ->addAdapter($adapter);
  700. }
  701. private function getValidAdapters()
  702. {
  703. return array_filter(
  704. array(
  705. new Adapter\BsdFindAdapter(),
  706. new Adapter\GnuFindAdapter(),
  707. new Adapter\PhpAdapter(),
  708. ),
  709. function (Adapter\AdapterInterface $adapter) {
  710. return $adapter->isSupported();
  711. }
  712. );
  713. }
  714. /**
  715. * Searching in multiple locations with sub directories involves
  716. * AppendIterator which does an unnecessary rewind which leaves
  717. * FilterIterator with inner FilesystemIterator in an invalid state.
  718. *
  719. * @see https://bugs.php.net/bug.php?id=49104
  720. */
  721. public function testMultipleLocationsWithSubDirectories()
  722. {
  723. $locations = array(
  724. __DIR__.'/Fixtures/one',
  725. self::$tmpDir.DIRECTORY_SEPARATOR.'toto',
  726. );
  727. $finder = new Finder();
  728. $finder->in($locations)->depth('< 10')->name('*.neon');
  729. $expected = array(
  730. __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon',
  731. __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon',
  732. );
  733. $this->assertIterator($expected, $finder);
  734. $this->assertIteratorInForeach($expected, $finder);
  735. }
  736. }