MediaWiki  REL1_23
AutoLoaderTest.php
Go to the documentation of this file.
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 }