wiki.techinc.nl/tests/phpunit/structure/AutoLoaderStructureTest.php

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

161 lines
4.6 KiB
PHP
Raw Normal View History

<?php
/**
* @coversNothing
*/
class AutoLoaderStructureTest extends MediaWikiIntegrationTestCase {
/**
* Assert that there were no classes loaded that are not registered with the AutoLoader.
*
* For example foo.php having class Foo and class Bar but only registering Foo.
* This is important because we should not be relying on Foo being used before Bar.
*/
public function testAutoLoadConfig() {
$results = self::checkAutoLoadConf();
$this->assertEquals(
$results['expected'],
$results['actual']
);
}
private static function parseFile( $contents ) {
// We could use token_get_all() here, but this is faster
// Note: Keep in sync with ClassCollector
$matches = [];
preg_match_all( '/
^ [\t ]* (?:
(?:final\s+)? (?:abstract\s+)? (?:class|interface|trait|enum) \s+
(?P<class> \w+)
|
class_alias \s* \( \s*
([\'"]) (?P<original> [^\'"]+) \g{-2} \s* , \s*
([\'"]) (?P<alias> [^\'"]+ ) \g{-2} \s*
\) \s* ;
|
class_alias \s* \( \s*
(?P<originalStatic> [\w\\\\]+)::class \s* , \s*
([\'"]) (?P<aliasString> [^\'"]+ ) \g{-2} \s*
\) \s* ;
)
/imx', $contents, $matches, PREG_SET_ORDER );
$namespaceMatch = [];
preg_match( '/
^ [\t ]*
namespace \s+
(\w+(\\\\\w+)*)
\s* ;
/imx', $contents, $namespaceMatch );
$fileNamespace = $namespaceMatch ? $namespaceMatch[1] . '\\' : '';
$classesInFile = [];
$aliasesInFile = [];
foreach ( $matches as $match ) {
if ( !empty( $match['class'] ) ) {
// 'class Foo {}'
$class = $fileNamespace . $match['class'];
$classesInFile[$class] = true;
} elseif ( !empty( $match['original'] ) ) {
// 'class_alias( "Foo", "Bar" );'
$aliasesInFile[self::removeSlashes( $match['alias'] )] = $match['original'];
} else {
// 'class_alias( Foo::class, "Bar" );'
$aliasesInFile[self::removeSlashes( $match['aliasString'] )] =
$fileNamespace . $match['originalStatic'];
}
}
return [ $classesInFile, $aliasesInFile ];
}
private static function removeSlashes( $str ) {
return str_replace( '\\\\', '\\', $str );
}
AutoLoaderStructureTest: Re-write slashes so test passes on Windows A difference between UNIX and Windows is the dir separator, which makes this test failing, because the file name does not match to filter out the psr4 loaded classes to just keep the alias, which must be part of the autoloader class list. 1) AutoLoaderStructureTest::testAutoLoadConfig Failed asserting that two arrays are equal. --- Expected +++ Actual @@ @@ 'ParserTestFileSuite' => '[...]...te.php' 'ParserTestTopLevelSuite' => '[...]...te.php' 'SuiteEventsTrait' => '[...]...it.php' + 'MediaWiki\Block\DatabaseBlock' => '[...]...ck.php' + 'MediaWiki\SpecialPage\SpecialPageFactory' => '[...]...ry.php' + 'MediaWiki\Revision\IncompleteRevisionException' => '[...]...on.php' + 'MediaWiki\Revision\MutableRevisionRecord' => '[...]...rd.php' + 'MediaWiki\Revision\MutableRevisionSlots' => '[...]...ts.php' + 'MediaWiki\Revision\RevisionAccessException' => '[...]...on.php' + 'MediaWiki\Revision\RevisionArchiveRecord' => '[...]...rd.php' + 'MediaWiki\Revision\RevisionFactory' => '[...]...ry.php' + 'MediaWiki\Revision\RevisionLookup' => '[...]...up.php' + 'MediaWiki\Revision\RevisionRecord' => '[...]...rd.php' + 'MediaWiki\Revision\RevisionSlots' => '[...]...ts.php' + 'MediaWiki\Revision\RevisionStore' => '[...]...re.php' + 'MediaWiki\Revision\RevisionStoreRecord' => '[...]...rd.php' + 'MediaWiki\Revision\SlotRecord' => '[...]...rd.php' + 'MediaWiki\Revision\SuppressedDataException' => '[...]...on.php' ) Change-Id: I1485cc7309c20d131f398473367d281a3ce78a25
2020-10-31 01:04:49 +00:00
private static function fixSlashes( $str ) {
return str_replace( '\\', '/', $str );
}
protected static function checkAutoLoadConf() {
$IP = MW_INSTALL_PATH;
// wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
$expected = AutoLoader::getClassFiles();
$actual = [];
foreach ( $expected as $class => $file ) {
// Only prefix $IP if it doesn't have it already.
// Generally local classes don't have it, and those from extensions and test suites do.
if ( $file[0] !== '/' && $file[1] !== ':' ) {
AutoLoaderStructureTest: Re-write slashes so test passes on Windows A difference between UNIX and Windows is the dir separator, which makes this test failing, because the file name does not match to filter out the psr4 loaded classes to just keep the alias, which must be part of the autoloader class list. 1) AutoLoaderStructureTest::testAutoLoadConfig Failed asserting that two arrays are equal. --- Expected +++ Actual @@ @@ 'ParserTestFileSuite' => '[...]...te.php' 'ParserTestTopLevelSuite' => '[...]...te.php' 'SuiteEventsTrait' => '[...]...it.php' + 'MediaWiki\Block\DatabaseBlock' => '[...]...ck.php' + 'MediaWiki\SpecialPage\SpecialPageFactory' => '[...]...ry.php' + 'MediaWiki\Revision\IncompleteRevisionException' => '[...]...on.php' + 'MediaWiki\Revision\MutableRevisionRecord' => '[...]...rd.php' + 'MediaWiki\Revision\MutableRevisionSlots' => '[...]...ts.php' + 'MediaWiki\Revision\RevisionAccessException' => '[...]...on.php' + 'MediaWiki\Revision\RevisionArchiveRecord' => '[...]...rd.php' + 'MediaWiki\Revision\RevisionFactory' => '[...]...ry.php' + 'MediaWiki\Revision\RevisionLookup' => '[...]...up.php' + 'MediaWiki\Revision\RevisionRecord' => '[...]...rd.php' + 'MediaWiki\Revision\RevisionSlots' => '[...]...ts.php' + 'MediaWiki\Revision\RevisionStore' => '[...]...re.php' + 'MediaWiki\Revision\RevisionStoreRecord' => '[...]...rd.php' + 'MediaWiki\Revision\SlotRecord' => '[...]...rd.php' + 'MediaWiki\Revision\SuppressedDataException' => '[...]...on.php' ) Change-Id: I1485cc7309c20d131f398473367d281a3ce78a25
2020-10-31 01:04:49 +00:00
$filePath = self::fixSlashes( "$IP/$file" );
} else {
AutoLoaderStructureTest: Re-write slashes so test passes on Windows A difference between UNIX and Windows is the dir separator, which makes this test failing, because the file name does not match to filter out the psr4 loaded classes to just keep the alias, which must be part of the autoloader class list. 1) AutoLoaderStructureTest::testAutoLoadConfig Failed asserting that two arrays are equal. --- Expected +++ Actual @@ @@ 'ParserTestFileSuite' => '[...]...te.php' 'ParserTestTopLevelSuite' => '[...]...te.php' 'SuiteEventsTrait' => '[...]...it.php' + 'MediaWiki\Block\DatabaseBlock' => '[...]...ck.php' + 'MediaWiki\SpecialPage\SpecialPageFactory' => '[...]...ry.php' + 'MediaWiki\Revision\IncompleteRevisionException' => '[...]...on.php' + 'MediaWiki\Revision\MutableRevisionRecord' => '[...]...rd.php' + 'MediaWiki\Revision\MutableRevisionSlots' => '[...]...ts.php' + 'MediaWiki\Revision\RevisionAccessException' => '[...]...on.php' + 'MediaWiki\Revision\RevisionArchiveRecord' => '[...]...rd.php' + 'MediaWiki\Revision\RevisionFactory' => '[...]...ry.php' + 'MediaWiki\Revision\RevisionLookup' => '[...]...up.php' + 'MediaWiki\Revision\RevisionRecord' => '[...]...rd.php' + 'MediaWiki\Revision\RevisionSlots' => '[...]...ts.php' + 'MediaWiki\Revision\RevisionStore' => '[...]...re.php' + 'MediaWiki\Revision\RevisionStoreRecord' => '[...]...rd.php' + 'MediaWiki\Revision\SlotRecord' => '[...]...rd.php' + 'MediaWiki\Revision\SuppressedDataException' => '[...]...on.php' ) Change-Id: I1485cc7309c20d131f398473367d281a3ce78a25
2020-10-31 01:04:49 +00:00
$filePath = self::fixSlashes( $file );
}
if ( !is_file( $filePath ) ) {
$actual[$class] = "[file '$filePath' does not exist]";
continue;
}
$contents = @file_get_contents( $filePath );
if ( $contents === false ) {
$actual[$class] = "[couldn't read file '$filePath']";
continue;
}
[ $classesInFile, $aliasesInFile ] = self::parseFile( $contents );
foreach ( $classesInFile as $className => $ignore ) {
$actual[$className] = $file;
}
// Only accept aliases for classes in the same file, because for correct
// behavior, all aliases for a class must be set up when the class is loaded
// (see <https://bugs.php.net/bug.php?id=61422>).
foreach ( $aliasesInFile as $alias => $class ) {
if ( isset( $classesInFile[$class] ) ) {
$actual[$alias] = $file;
} else {
$actual[$alias] = "[original class not in $file]";
}
}
}
return [
'expected' => $expected,
'actual' => $actual,
];
}
public function testAutoloadOrder() {
$path = __DIR__ . '/../../..';
$oldAutoload = file_get_contents( $path . '/autoload.php' );
$generator = new AutoloadGenerator( $path, 'local' );
$generator->setPsr4Namespaces( AutoLoader::CORE_NAMESPACES );
$generator->initMediaWikiDefault();
$newAutoload = $generator->getAutoload( 'maintenance/generateLocalAutoload.php' );
$this->assertEquals( $oldAutoload, $newAutoload, 'autoload.php does not match' .
' output of generateLocalAutoload.php script.' );
}
/**
* Verify that all the directories specified for PSR-4 autoloading
* actually exist, to prevent situations like T259448
*/
public function testAutoloadNamespaces() {
$missing = [];
$psr4Namespaces = AutoLoader::getNamespaceDirectories();
foreach ( $psr4Namespaces as $ns => $path ) {
if ( !is_dir( $path ) ) {
$missing[] = "Directory $path for namespace $ns does not exist";
}
}
$this->assertSame( [], $missing );
}
}