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