MediaWiki
REL1_23
|
00001 <?php 00002 00003 class AutoLoaderTest extends MediaWikiTestCase { 00004 protected function setUp() { 00005 global $wgAutoloadLocalClasses, $wgAutoloadClasses; 00006 00007 parent::setUp(); 00008 00009 // Fancy dance to trigger a rebuild of AutoLoader::$autoloadLocalClassesLower 00010 $this->testLocalClasses = array( 00011 'TestAutoloadedLocalClass' => __DIR__ . '/../data/autoloader/TestAutoloadedLocalClass.php', 00012 'TestAutoloadedCamlClass' => __DIR__ . '/../data/autoloader/TestAutoloadedCamlClass.php', 00013 'TestAutoloadedSerializedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedSerializedClass.php', 00014 ); 00015 $this->setMwGlobals( 'wgAutoloadLocalClasses', $this->testLocalClasses + $wgAutoloadLocalClasses ); 00016 AutoLoader::resetAutoloadLocalClassesLower(); 00017 00018 $this->testExtensionClasses = array( 00019 'TestAutoloadedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedClass.php', 00020 ); 00021 $this->setMwGlobals( 'wgAutoloadClasses', $this->testExtensionClasses + $wgAutoloadClasses ); 00022 } 00023 00030 public function testAutoLoadConfig() { 00031 $results = self::checkAutoLoadConf(); 00032 00033 $this->assertEquals( 00034 $results['expected'], 00035 $results['actual'] 00036 ); 00037 } 00038 00039 protected static function checkAutoLoadConf() { 00040 global $wgAutoloadLocalClasses, $wgAutoloadClasses, $IP; 00041 00042 // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php 00043 $expected = $wgAutoloadLocalClasses + $wgAutoloadClasses; 00044 $actual = array(); 00045 00046 $files = array_unique( $expected ); 00047 00048 foreach ( $files as $file ) { 00049 // Only prefix $IP if it doesn't have it already. 00050 // Generally local classes don't have it, and those from extensions and test suites do. 00051 if ( substr( $file, 0, 1 ) != '/' && substr( $file, 1, 1 ) != ':' ) { 00052 $filePath = "$IP/$file"; 00053 } else { 00054 $filePath = $file; 00055 } 00056 00057 $contents = file_get_contents( $filePath ); 00058 00059 // We could use token_get_all() here, but this is faster 00060 $matches = array(); 00061 preg_match_all( '/ 00062 ^ [\t ]* (?: 00063 (?:final\s+)? (?:abstract\s+)? (?:class|interface) \s+ 00064 (?P<class> [a-zA-Z0-9_]+) 00065 | 00066 class_alias \s* \( \s* 00067 ([\'"]) (?P<original> [^\'"]+) \g{-2} \s* , \s* 00068 ([\'"]) (?P<alias> [^\'"]+ ) \g{-2} \s* 00069 \) \s* ; 00070 ) 00071 /imx', $contents, $matches, PREG_SET_ORDER ); 00072 00073 $classesInFile = array(); 00074 $aliasesInFile = array(); 00075 00076 foreach ( $matches as $match ) { 00077 if ( !empty( $match['class'] ) ) { 00078 $actual[$match['class']] = $file; 00079 $classesInFile[$match['class']] = true; 00080 } else { 00081 $aliasesInFile[$match['alias']] = $match['original']; 00082 } 00083 } 00084 00085 // Only accept aliases for classes in the same file, because for correct 00086 // behavior, all aliases for a class must be set up when the class is loaded 00087 // (see <https://bugs.php.net/bug.php?id=61422>). 00088 foreach ( $aliasesInFile as $alias => $class ) { 00089 if ( isset( $classesInFile[$class] ) ) { 00090 $actual[$alias] = $file; 00091 } else { 00092 $actual[$alias] = "[original class not in $file]"; 00093 } 00094 } 00095 } 00096 00097 return array( 00098 'expected' => $expected, 00099 'actual' => $actual, 00100 ); 00101 } 00102 00103 function testCoreClass() { 00104 $this->assertTrue( class_exists( 'TestAutoloadedLocalClass' ) ); 00105 } 00106 00107 function testExtensionClass() { 00108 $this->assertTrue( class_exists( 'TestAutoloadedClass' ) ); 00109 } 00110 00111 function testWrongCaseClass() { 00112 $this->assertTrue( class_exists( 'testautoLoadedcamlCLASS' ) ); 00113 } 00114 00115 function testWrongCaseSerializedClass() { 00116 $dummyCereal = 'O:29:"testautoloadedserializedclass":0:{}'; 00117 $uncerealized = unserialize( $dummyCereal ); 00118 $this->assertFalse( $uncerealized instanceof __PHP_Incomplete_Class, 00119 "unserialize() can load classes case-insensitively." ); 00120 } 00121 }