From 20f2d03d2eee8f8cc94fbc576efb7d33cd5f40fb Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 15 Sep 2015 17:55:56 +0200 Subject: [PATCH 1/2] Improve the structure of the Finder testsuite Testing against different adapters is now handled by multiple subclasses of a common test case rather than using data providers. This allows tests to be marked as skipped for unsupported adapters instead of making them disappear from the testsuite. --- .../Component/Finder/Tests/BsdFinderTest.php | 28 ++ .../Component/Finder/Tests/FinderTest.php | 444 +++++++----------- .../Component/Finder/Tests/GnuFinderTest.php | 28 ++ .../Tests/Iterator/IteratorTestCase.php | 2 +- 4 files changed, 218 insertions(+), 284 deletions(-) create mode 100644 src/Symfony/Component/Finder/Tests/BsdFinderTest.php create mode 100644 src/Symfony/Component/Finder/Tests/GnuFinderTest.php diff --git a/src/Symfony/Component/Finder/Tests/BsdFinderTest.php b/src/Symfony/Component/Finder/Tests/BsdFinderTest.php new file mode 100644 index 0000000000..42691a4318 --- /dev/null +++ b/src/Symfony/Component/Finder/Tests/BsdFinderTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Tests; + +use Symfony\Component\Finder\Adapter\BsdFindAdapter; + +class BsdFinderTest extends FinderTest +{ + protected function getAdapter() + { + $adapter = new BsdFindAdapter(); + + if (!$adapter->isSupported()) { + $this->markTestSkipped(get_class($adapter).' is not supported.'); + } + + return $adapter; + } +} diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 92f38ab94c..337dd9911d 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -11,8 +11,10 @@ namespace Symfony\Component\Finder\Tests; +use Symfony\Component\Finder\Adapter\AdapterInterface; +use Symfony\Component\Finder\Adapter\GnuFindAdapter; +use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\Adapter; class FinderTest extends Iterator\RealIteratorTestCase { @@ -21,109 +23,94 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testDirectories($adapter) + public function testDirectories() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->directories()); $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->directories(); $finder->files(); $finder->directories(); $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testFiles($adapter) + public function testFiles() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->files()); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files(); $finder->directories(); $finder->files(); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testDepth($adapter) + public function testDepth() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->depth('< 1')); $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->depth('<= 0')); $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->depth('>= 1')); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->depth('< 1')->depth('>= 1'); $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testName($adapter) + public function testName() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->name('*.php')); $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.ph*'); $finder->name('test.py'); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('~^test~i'); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('~\\.php$~i'); $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.p{hp,y}'); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testNotName($adapter) + public function testNotName() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->notName('*.php')); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->notName('*.php'); $finder->notName('*.py'); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.ph*'); $finder->name('test.py'); $finder->notName('*.php'); $finder->notName('*.py'); $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name('test.ph*'); $finder->name('test.py'); $finder->notName('*.p{hp,y}'); @@ -133,217 +120,177 @@ class FinderTest extends Iterator\RealIteratorTestCase /** * @dataProvider getRegexNameTestData */ - public function testRegexName($adapter, $regex) + public function testRegexName($regex) { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->name($regex); $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSize($adapter) + public function testSize() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500')); $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testDate($adapter) + public function testDate() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->files()->date('until last month')); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testExclude($adapter) + public function testExclude() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->exclude('foo')); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testIgnoreVCS($adapter) + public function testIgnoreVCS() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false)); $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()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false); $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()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false)); $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()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testIgnoreDotFiles($adapter) + public function testIgnoreDotFiles() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false)); $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()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false); $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()); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false)); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByName($adapter) + public function testSortByName() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByName()); $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByType($adapter) + public function testSortByType() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByType()); $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByAccessedTime($adapter) + public function testSortByAccessedTime() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByAccessedTime()); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByChangedTime($adapter) + public function testSortByChangedTime() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByChangedTime()); $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSortByModifiedTime($adapter) + public function testSortByModifiedTime() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sortByModifiedTime()); $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testSort($adapter) + public function testSort() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealPath(), $b->getRealPath()); })); $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testFilter($adapter) + public function testFilter() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return false !== strpos($f, 'test'); })); $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testFollowLinks($adapter) + public function testFollowLinks() { if ('\\' == DIRECTORY_SEPARATOR) { - return; + $this->markTestSkipped('symlinks are not supported on Windows'); } - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertSame($finder, $finder->followLinks()); $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testIn($adapter) + public function testIn() { - $finder = $this->buildFinder($adapter); - try { - $finder->in('foobar'); - $this->fail('->in() throws a \InvalidArgumentException if the directory does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '->in() throws a \InvalidArgumentException if the directory does not exist'); - } - - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator(); - $this->assertIterator(array(self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php'), $iterator); + $expected = array( + self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', + __DIR__.DIRECTORY_SEPARATOR.'BsdFinderTest.php', + __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php', + __DIR__.DIRECTORY_SEPARATOR.'GnuFinderTest.php', + ); + + $this->assertIterator($expected, $iterator); } /** - * @dataProvider getAdaptersTestData + * @expectedException \InvalidArgumentException */ - public function testInWithGlob($adapter) + public function testInWithNonExistentDirectory() { - $finder = $this->buildFinder($adapter); + $finder = new Finder(); + $finder->in('foobar'); + } + + public function testInWithGlob() + { + $finder = $this->buildFinder(); $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator(); $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder); } /** - * @dataProvider getAdaptersTestData * @expectedException \InvalidArgumentException */ - public function testInWithNonDirectoryGlob($adapter) + public function testInWithNonDirectoryGlob() { - $finder = $this->buildFinder($adapter); + $finder = new Finder(); $finder->in(__DIR__.'/Fixtures/A/a*'); } /** - * @dataProvider getAdaptersTestData + * @expectedException \LogicException */ - public function testGetIterator($adapter) + public function testGetIteratorWithoutIn() { - $finder = $this->buildFinder($adapter); - try { - $finder->getIterator(); - $this->fail('->getIterator() throws a \LogicException if the in() method has not been called'); - } catch (\Exception $e) { - $this->assertInstanceOf('LogicException', $e, '->getIterator() throws a \LogicException if the in() method has not been called'); - } + $finder = Finder::create(); + $finder->getIterator(); + } - $finder = $this->buildFinder($adapter); + public function testGetIterator() + { + $finder = $this->buildFinder(); $dirs = array(); foreach ($finder->directories()->in(self::$tmpDir) as $dir) { $dirs[] = (string) $dir; @@ -356,22 +303,19 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface'); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface'); - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $a = iterator_to_array($finder->directories()->in(self::$tmpDir)); $a = array_values(array_map(function ($a) { return (string) $a; }, $a)); sort($a); $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface'); } - /** - * @dataProvider getAdaptersTestData - */ - public function testRelativePath($adapter) + public function testRelativePath() { - $finder = $this->buildFinder($adapter)->in(self::$tmpDir); + $finder = $this->buildFinder()->in(self::$tmpDir); $paths = array(); @@ -387,12 +331,9 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertEquals($ref, $paths); } - /** - * @dataProvider getAdaptersTestData - */ - public function testRelativePathname($adapter) + public function testRelativePathname() { - $finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName(); + $finder = $this->buildFinder()->in(self::$tmpDir)->sortByName(); $paths = array(); @@ -408,15 +349,12 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertEquals($ref, $paths); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendWithAFinder($adapter) + public function testAppendWithAFinder() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo'); - $finder1 = $this->buildFinder($adapter); + $finder1 = $this->buildFinder(); $finder1->directories()->in(self::$tmpDir); $finder = $finder->append($finder1); @@ -424,12 +362,9 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendWithAnArray($adapter) + public function testAppendWithAnArray() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo'); $finder->append($this->toAbsolute(array('foo', 'toto'))); @@ -437,20 +372,14 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator()); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendReturnsAFinder($adapter) + public function testAppendReturnsAFinder() { - $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', $this->buildFinder($adapter)->append(array())); + $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', Finder::create()->append(array())); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAppendDoesNotRequireIn($adapter) + public function testAppendDoesNotRequireIn() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo'); $finder1 = Finder::create()->append($finder); @@ -494,9 +423,9 @@ class FinderTest extends Iterator\RealIteratorTestCase /** * @dataProvider getContainsTestData */ - public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expected) + public function testContains($matchPatterns, $noMatchPatterns, $expected) { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures') ->name('*.txt')->sortByName() ->contains($matchPatterns) @@ -505,12 +434,9 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); } - /** - * @dataProvider getAdaptersTestData - */ - public function testContainsOnDirectory(Adapter\AdapterInterface $adapter) + public function testContainsOnDirectory() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__) ->directories() ->name('Fixtures') @@ -518,12 +444,9 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertIterator(array(), $finder); } - /** - * @dataProvider getAdaptersTestData - */ - public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter) + public function testNotContainsOnDirectory() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__) ->directories() ->name('Fixtures') @@ -536,10 +459,8 @@ class FinderTest extends Iterator\RealIteratorTestCase * with inner FilesystemIterator in an invalid state. * * @see https://bugs.php.net/bug.php?id=49104 - * - * @dataProvider getAdaptersTestData */ - public function testMultipleLocations(Adapter\AdapterInterface $adapter) + public function testMultipleLocations() { $locations = array( self::$tmpDir.'/', @@ -547,36 +468,57 @@ class FinderTest extends Iterator\RealIteratorTestCase ); // it is expected that there are test.py test.php in the tmpDir - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in($locations)->depth('< 1')->name('test.php'); $this->assertCount(1, $finder); } /** - * Iterator keys must be the file pathname. + * Searching in multiple locations with sub directories involves + * AppendIterator which does an unnecessary rewind which leaves + * FilterIterator with inner FilesystemIterator in an invalid state. * - * @dataProvider getAdaptersTestData + * @see https://bugs.php.net/bug.php?id=49104 */ - public function testIteratorKeys(Adapter\AdapterInterface $adapter) + public function testMultipleLocationsWithSubDirectories() { - $finder = $this->buildFinder($adapter)->in(self::$tmpDir); + $locations = array( + __DIR__.'/Fixtures/one', + self::$tmpDir.DIRECTORY_SEPARATOR.'toto', + ); + + $finder = $this->buildFinder(); + $finder->in($locations)->depth('< 10')->name('*.neon'); + + $expected = array( + __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon', + __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon', + ); + + $this->assertIterator($expected, $finder); + $this->assertIteratorInForeach($expected, $finder); + } + + /** + * Iterator keys must be the file pathname. + */ + public function testIteratorKeys() + { + $finder = $this->buildFinder()->in(self::$tmpDir); foreach ($finder as $key => $file) { $this->assertEquals($file->getPathname(), $key); } } - /** - * @dataProvider getAdaptersTestData - */ - public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag(Adapter\AdapterInterface $adapter) + public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag() { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'r+e.gex[c]a(r)s') ->path('/^dir/'); $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',); + 'r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'bar.dat',); $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); } @@ -592,7 +534,7 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertEquals( array('c', 'e', 'a', 'd', 'b'), - array_map(function (Adapter\AdapterInterface $adapter) { + array_map(function (AdapterInterface $adapter) { return $adapter->getName(); }, $finder->getAdapters()) ); @@ -615,17 +557,9 @@ class FinderTest extends Iterator\RealIteratorTestCase $this->assertIterator($filenames, $finder->in(sys_get_temp_dir())->getIterator()); } - public function getAdaptersTestData() - { - return array_map( - function ($adapter) { return array($adapter); }, - $this->getValidAdapters() - ); - } - public function getContainsTestData() { - $tests = array( + return array( array('', '', array()), array('foo', 'bar', array()), array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')), @@ -637,26 +571,22 @@ class FinderTest extends Iterator\RealIteratorTestCase array('', 'lorem', array('dolor.txt', 'ipsum.txt')), array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')), ); - - return $this->buildTestData($tests); } public function getRegexNameTestData() { - $tests = array( + return array( array('~.+\\.p.+~i'), array('~t.*s~i'), ); - - return $this->buildTestData($tests); } /** * @dataProvider getTestPathData */ - public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected) + public function testPath($matchPatterns, $noMatchPatterns, array $expected) { - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures') ->path($matchPatterns) ->notPath($noMatchPatterns); @@ -668,20 +598,20 @@ class FinderTest extends Iterator\RealIteratorTestCase { // test that by default, PhpAdapter is selected $adapters = Finder::create()->getAdapters(); - $this->assertTrue($adapters[0] instanceof Adapter\PhpAdapter); + $this->assertTrue($adapters[0] instanceof PhpAdapter); // test another adapter selection $adapters = Finder::create()->setAdapter('gnu_find')->getAdapters(); - $this->assertTrue($adapters[0] instanceof Adapter\GnuFindAdapter); + $this->assertTrue($adapters[0] instanceof GnuFindAdapter); // test that useBestAdapter method removes selection $adapters = Finder::create()->useBestAdapter()->getAdapters(); - $this->assertFalse($adapters[0] instanceof Adapter\PhpAdapter); + $this->assertFalse($adapters[0] instanceof PhpAdapter); } public function getTestPathData() { - $tests = array( + return array( array('', '', array()), array('/^A\/B\/C/', '/C$/', array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat'), @@ -722,20 +652,15 @@ class FinderTest extends Iterator\RealIteratorTestCase ), ), ); - - return $this->buildTestData($tests); } - /** - * @dataProvider getAdaptersTestData - */ - public function testAccessDeniedException(Adapter\AdapterInterface $adapter) + public function testAccessDeniedException() { if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('chmod is not supported on Windows'); } - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->in(self::$tmpDir); // make 'foo' directory non-readable @@ -765,16 +690,13 @@ class FinderTest extends Iterator\RealIteratorTestCase } } - /** - * @dataProvider getAdaptersTestData - */ - public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter) + public function testIgnoredAccessDeniedException() { if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('chmod is not supported on Windows'); } - $finder = $this->buildFinder($adapter); + $finder = $this->buildFinder(); $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir); // make 'foo' directory non-readable @@ -794,62 +716,18 @@ class FinderTest extends Iterator\RealIteratorTestCase } } - private function buildTestData(array $tests) + /** + * @return AdapterInterface + */ + protected function getAdapter() { - $data = array(); - foreach ($this->getValidAdapters() as $adapter) { - foreach ($tests as $test) { - $data[] = array_merge(array($adapter), $test); - } - } - - return $data; + return new PhpAdapter(); } - private function buildFinder(Adapter\AdapterInterface $adapter) + private function buildFinder() { return Finder::create() ->removeAdapters() - ->addAdapter($adapter); - } - - private function getValidAdapters() - { - return array_filter( - array( - new Adapter\BsdFindAdapter(), - new Adapter\GnuFindAdapter(), - new Adapter\PhpAdapter(), - ), - function (Adapter\AdapterInterface $adapter) { - return $adapter->isSupported(); - } - ); - } - - /** - * Searching in multiple locations with sub directories involves - * AppendIterator which does an unnecessary rewind which leaves - * FilterIterator with inner FilesystemIterator in an invalid state. - * - * @see https://bugs.php.net/bug.php?id=49104 - */ - public function testMultipleLocationsWithSubDirectories() - { - $locations = array( - __DIR__.'/Fixtures/one', - self::$tmpDir.DIRECTORY_SEPARATOR.'toto', - ); - - $finder = new Finder(); - $finder->in($locations)->depth('< 10')->name('*.neon'); - - $expected = array( - __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon', - __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon', - ); - - $this->assertIterator($expected, $finder); - $this->assertIteratorInForeach($expected, $finder); + ->addAdapter($this->getAdapter()); } } diff --git a/src/Symfony/Component/Finder/Tests/GnuFinderTest.php b/src/Symfony/Component/Finder/Tests/GnuFinderTest.php new file mode 100644 index 0000000000..5c66723c1b --- /dev/null +++ b/src/Symfony/Component/Finder/Tests/GnuFinderTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Tests; + +use Symfony\Component\Finder\Adapter\GnuFindAdapter; + +class GnuFinderTest extends FinderTest +{ + protected function getAdapter() + { + $adapter = new GnuFindAdapter(); + + if (!$adapter->isSupported()) { + $this->markTestSkipped(get_class($adapter).' is not supported.'); + } + + return $adapter; + } +} diff --git a/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php b/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php index 9d2cf5fe45..2d29efedf1 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php @@ -16,7 +16,7 @@ abstract class IteratorTestCase extends \PHPUnit_Framework_TestCase protected function assertIterator($expected, \Traversable $iterator) { // set iterator_to_array $use_key to false to avoid values merge - // this made FinderTest::testAppendWithAnArray() failed with GnuFinderAdapter + // this made FinderTest::testAppendWithAnArray() fail with GnuFinderAdapter $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false)); $expected = array_map(function ($path) { return str_replace('/', DIRECTORY_SEPARATOR, $path); }, $expected); From cf3019bc5a7b8e71880d8f8900c0af6ada9ffe05 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Sep 2015 09:52:41 +0200 Subject: [PATCH 2/2] [Finder] Fix recursive filter iterator --- .../Iterator/ExcludeDirectoryFilterIterator.php | 17 ++++++++++++++++- .../Finder/Iterator/FilterIterator.php | 12 +----------- .../Component/Finder/Tests/FinderTest.php | 8 ++++---- .../Iterator/DateRangeFilterIteratorTest.php | 3 +++ .../Iterator/DepthRangeFilterIteratorTest.php | 3 +++ .../ExcludeDirectoryFilterIteratorTest.php | 2 ++ .../Iterator/FileTypeFilterIteratorTest.php | 1 + .../Tests/Iterator/RealIteratorTestCase.php | 1 + .../Iterator/SizeRangeFilterIteratorTest.php | 1 + .../Tests/Iterator/SortableIteratorTest.php | 6 ++++++ 10 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index 66f8149446..836c426f0c 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -16,8 +16,9 @@ namespace Symfony\Component\Finder\Iterator; * * @author Fabien Potencier */ -class ExcludeDirectoryFilterIterator extends FilterIterator +class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator { + private $isRecursive; private $patterns; /** @@ -28,6 +29,7 @@ class ExcludeDirectoryFilterIterator extends FilterIterator */ public function __construct(\Iterator $iterator, array $directories) { + $this->isRecursive = $iterator instanceof \RecursiveIterator; $this->patterns = array(); foreach ($directories as $directory) { $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; @@ -53,4 +55,17 @@ class ExcludeDirectoryFilterIterator extends FilterIterator return true; } + + public function hasChildren() + { + return $this->isRecursive && $this->getInnerIterator()->hasChildren(); + } + + public function getChildren() + { + $children = new self($this->getInnerIterator()->getChildren(), array()); + $children->patterns = $this->patterns; + + return $children; + } } diff --git a/src/Symfony/Component/Finder/Iterator/FilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilterIterator.php index c5290cc80f..f4da44c4cd 100644 --- a/src/Symfony/Component/Finder/Iterator/FilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilterIterator.php @@ -18,18 +18,8 @@ namespace Symfony\Component\Finder\Iterator; * * @author Alex Bogomazov */ -abstract class FilterIterator extends \FilterIterator implements \RecursiveIterator +abstract class FilterIterator extends \FilterIterator { - public function hasChildren() - { - return $this->getInnerIterator() instanceof \RecursiveIterator && $this->getInnerIterator()->hasChildren(); - } - - public function getChildren() - { - return $this->getInnerIterator()->getChildren(); - } - /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 337dd9911d..cee8bd7530 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -152,11 +152,11 @@ class FinderTest extends Iterator\RealIteratorTestCase { $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false)); - $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()); + $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()); $finder = $this->buildFinder(); $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false); - $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()); + $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()); $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false)); @@ -167,11 +167,11 @@ class FinderTest extends Iterator\RealIteratorTestCase { $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false)); - $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()); + $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()); $finder = $this->buildFinder(); $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false); - $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()); + $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()); $finder = $this->buildFinder(); $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false)); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php index 18896d5528..8f61124131 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php @@ -37,6 +37,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', '.bar', '.foo', '.foo/.bar', @@ -49,6 +50,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase 'test.py', 'foo', 'toto', + 'toto/.git', '.bar', '.foo', '.foo/.bar', @@ -62,6 +64,7 @@ class DateRangeFilterIteratorTest extends RealIteratorTestCase 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', '.foo', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php index 5ec983247d..2e90140530 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php @@ -50,6 +50,7 @@ class DepthRangeFilterIteratorTest extends RealIteratorTestCase 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', '.foo', '.foo/.bar', '.bar', @@ -58,12 +59,14 @@ class DepthRangeFilterIteratorTest extends RealIteratorTestCase ); $graterThanOrEqualTo1 = array( + 'toto/.git', 'foo/bar.tmp', '.foo/.bar', '.foo/bar', ); $equalTo1 = array( + 'toto/.git', 'foo/bar.tmp', '.foo/.bar', '.foo/bar', diff --git a/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php index 693b73319a..c5f4ba495a 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php @@ -39,6 +39,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase 'test.py', 'test.php', 'toto', + 'toto/.git', 'foo bar', ); @@ -53,6 +54,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase 'foo/bar.tmp', 'test.php', 'toto', + 'toto/.git', 'foo bar', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php index cfa8684fdf..4350b00ca9 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php @@ -43,6 +43,7 @@ class FileTypeFilterIteratorTest extends RealIteratorTestCase '.git', 'foo', 'toto', + 'toto/.git', '.foo', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php b/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php index e22476dad2..94253c7ee7 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php @@ -31,6 +31,7 @@ abstract class RealIteratorTestCase extends IteratorTestCase 'foo/bar.tmp', 'test.php', 'toto/', + 'toto/.git/', 'foo bar', ); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php index 8780db4da1..6d75b0f2f0 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php @@ -36,6 +36,7 @@ class SizeRangeFilterIteratorTest extends RealIteratorTestCase 'foo', 'test.php', 'toto', + 'toto/.git', ); return array( diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php index ed24f3ea0d..6a3124d352 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php @@ -85,6 +85,7 @@ class SortableIteratorTest extends RealIteratorTestCase 'test.php', 'test.py', 'toto', + 'toto/.git', ); $sortByType = array( @@ -92,6 +93,7 @@ class SortableIteratorTest extends RealIteratorTestCase '.git', 'foo', 'toto', + 'toto/.git', '.bar', '.foo/.bar', '.foo/bar', @@ -113,6 +115,7 @@ class SortableIteratorTest extends RealIteratorTestCase 'test.php', 'test.py', 'toto', + 'toto/.git', ); $sortByAccessedTime = array( @@ -127,6 +130,7 @@ class SortableIteratorTest extends RealIteratorTestCase 'test.py', 'foo', 'toto', + 'toto/.git', 'foo bar', ), // This file was accessed after sleeping for 1 sec @@ -143,6 +147,7 @@ class SortableIteratorTest extends RealIteratorTestCase 'foo', 'foo/bar.tmp', 'toto', + 'toto/.git', 'foo bar', ), array('test.php'), @@ -159,6 +164,7 @@ class SortableIteratorTest extends RealIteratorTestCase 'foo', 'foo/bar.tmp', 'toto', + 'toto/.git', 'foo bar', ), array('test.php'),