[BUGFIX] Improve test class detection in ClassLoadingInformationGenerator 31/43231/7
authorNicole Cordes <typo3@cordes.co>
Sat, 12 Sep 2015 09:50:34 +0000 (11:50 +0200)
committerNicole Cordes <typo3@cordes.co>
Sun, 13 Sep 2015 16:05:55 +0000 (18:05 +0200)
Currently class names ending with test or fixture suffix are excluded
from the autoload classmap generation. Unfortunately this skips valid
class names like Tx_RedirectTest_Domain_Model_Test as well. This patch
improves the decision if class name can be skipped by assuming there is
an alphabetic character in front of the suffix.

Furthermore generation of the class map is skipped if a valid psr-4
annotation is found in the package information.

Resolves: #69710
Releases: master
Change-Id: Id433294f982f39b438b10393fda2c468cd1518fd
Reviewed-on: http://review.typo3.org/43231
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Mathias Brodala <mbrodala@pagemachine.de>
Tested-by: Mathias Brodala <mbrodala@pagemachine.de>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
typo3/sysext/core/Classes/Core/ClassLoadingInformationGenerator.php
typo3/sysext/core/Tests/Unit/Core/ClassLoadingInformationGeneratorTest.php

index 8954adb..bb6430d 100644 (file)
@@ -44,36 +44,32 @@ class ClassLoadingInformationGenerator {
                $psr4 = array();
                $packagePath = $package->getPackagePath();
 
-               try {
-                       $manifest = self::getPackageManager()->getComposerManifest($package->getPackagePath());
-                       if (!empty($manifest->autoload->{'psr-4'})) {
-                               $psr4manifest = json_decode(json_encode($manifest->autoload->{'psr-4'}), TRUE);
-                               if (is_array($psr4manifest)) {
-                                       foreach ($psr4manifest as $namespacePrefix => $path) {
-                                               $namespacePath = $packagePath . $path;
-                                               if ($useRelativePaths) {
-                                                       $psr4[$namespacePrefix] = $this->makePathRelative($namespacePath, realpath($namespacePath));
-                                               } else {
-                                                       $psr4[$namespacePrefix] = $namespacePath;
-                                               }
+               $manifest = self::getPackageManager()->getComposerManifest($package->getPackagePath());
+               if (!empty($manifest->autoload->{'psr-4'})) {
+                       $psr4manifest = json_decode(json_encode($manifest->autoload->{'psr-4'}), TRUE);
+                       if (is_array($psr4manifest)) {
+                               foreach ($psr4manifest as $namespacePrefix => $path) {
+                                       $namespacePath = $packagePath . $path;
+                                       if ($useRelativePaths) {
+                                               $psr4[$namespacePrefix] = $this->makePathRelative($namespacePath, realpath($namespacePath));
+                                       } else {
+                                               $psr4[$namespacePrefix] = $namespacePath;
                                        }
                                }
                        }
-               } catch (MissingPackageManifestException $e) {
-                       // Ignore missing composer manifest
-               }
-
-               foreach (ClassMapGenerator::createMap($packagePath) as $class => $path) {
-                       if ($this->isIgnoredPath($packagePath, $path)) {
-                               continue;
-                       }
-                       if ($this->isIgnoredClassName($class)) {
-                               continue;
-                       }
-                       if ($useRelativePaths) {
-                               $classMap[$class] = self::makePathRelative($packagePath, $path);
-                       } else {
-                               $classMap[$class] = $path;
+               } else {
+                       foreach (ClassMapGenerator::createMap($packagePath) as $class => $path) {
+                               if ($this->isIgnoredPath($packagePath, $path)) {
+                                       continue;
+                               }
+                               if ($this->isIgnoredClassName($class)) {
+                                       continue;
+                               }
+                               if ($useRelativePaths) {
+                                       $classMap[$class] = self::makePathRelative($packagePath, $path);
+                               } else {
+                                       $classMap[$class] = $path;
+                               }
                        }
                }
 
@@ -104,8 +100,8 @@ class ClassLoadingInformationGenerator {
         * @return bool
         */
        protected function isIgnoredClassName($className) {
-               foreach (array('test', 'fixture') as $suffix) {
-                       if (strtolower(substr($className, 0 - strlen($suffix))) === $suffix) {
+               foreach (array('Test', 'Fixture') as $suffix) {
+                       if (preg_match('/(^|[a-z])' . $suffix . '$/', $className)) {
                                return TRUE;
                        }
                }
index c506c74..cb0536a 100644 (file)
@@ -26,25 +26,31 @@ class ClassLoadingInformationGeneratorTest extends UnitTestCase {
         */
        public function isIgnoredClassNameIgnoresTestClassesDataProvider() {
                return array(
-                       array('FoTest', TRUE),
-                       array('FoLowercasetest', TRUE),
-                       array('DifferentClassTes', FALSE),
-                       array('Test', TRUE),
-                       array('FoFixture', TRUE),
-                       array('FoLowercasefixture', TRUE),
-                       array('DifferentClassFixtur', FALSE),
-                       array('Fixture', TRUE),
+                       'FoTest' => array('FoTest', TRUE),
+                       'FoLowercasetest' => array('FoLowercasetest', FALSE),
+                       'DifferentClassTes' => array('DifferentClassTes', FALSE),
+                       'Test' => array('Test', TRUE),
+                       'FoFixture' => array('FoFixture', TRUE),
+                       'FoLowercasefixture' => array('FoLowercasefixture', FALSE),
+                       'DifferentClassFixtur' => array('DifferentClassFixtur', FALSE),
+                       'Fixture' => array('Fixture', TRUE),
+                       'Latest' => array('Latest', FALSE),
+                       'LaTest' => array('LaTest', TRUE),
+                       'Tx_RedirectTest_Domain_Model_Test' => array('Tx_RedirectTest_Domain_Model_Test', FALSE),
                );
        }
 
        /**
         * @test
         * @dataProvider isIgnoredClassNameIgnoresTestClassesDataProvider
+        *
+        * @param string $className
+        * @param bool $expectedResult
         */
-       public function isIgnoredClassNameIgnoresTestClasses($path, $expectedResult) {
+       public function isIgnoredClassNameIgnoresTestClasses($className, $expectedResult) {
                $generator = $this->getAccessibleMock(ClassLoadingInformationGenerator::class, ['dummy']);
 
-               $this->assertEquals($expectedResult, $generator->_call('isIgnoredClassName', $path));
+               $this->assertEquals($expectedResult, $generator->_call('isIgnoredClassName', $className));
        }
 
 }