diff options
Diffstat (limited to 'tests/phpunit/structure')
-rw-r--r-- | tests/phpunit/structure/AutoLoaderTest.php | 56 | ||||
-rw-r--r-- | tests/phpunit/structure/ResourcesTest.php | 131 | ||||
-rw-r--r-- | tests/phpunit/structure/StructureTest.php | 63 |
3 files changed, 250 insertions, 0 deletions
diff --git a/tests/phpunit/structure/AutoLoaderTest.php b/tests/phpunit/structure/AutoLoaderTest.php new file mode 100644 index 00000000..205ea360 --- /dev/null +++ b/tests/phpunit/structure/AutoLoaderTest.php @@ -0,0 +1,56 @@ +<?php +class AutoLoaderTest extends MediaWikiTestCase { + + /** + * 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'] + ); + } + + protected static function checkAutoLoadConf() { + global $wgAutoloadLocalClasses, $wgAutoloadClasses, $IP; + $supportsParsekit = function_exists( 'parsekit_compile_file' ); + + // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php + $expected = $wgAutoloadLocalClasses + $wgAutoloadClasses; + $actual = array(); + + $files = array_unique( $expected ); + + foreach ( $files as $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 ( substr( $file, 0, 1 ) != '/' && substr( $file, 1, 1 ) != ':' ) { + $filePath = "$IP/$file"; + } else { + $filePath = $file; + } + if ( $supportsParsekit ) { + $parseInfo = parsekit_compile_file( "$filePath" ); + $classes = array_keys( $parseInfo['class_table'] ); + } else { + $contents = file_get_contents( "$filePath" ); + $m = array(); + preg_match_all( '/\n\s*(?:final)?\s*(?:abstract)?\s*(?:class|interface)\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER ); + $classes = $m[1]; + } + foreach ( $classes as $class ) { + $actual[$class] = $file; + } + } + + return array( + 'expected' => $expected, + 'actual' => $actual, + ); + } +} diff --git a/tests/phpunit/structure/ResourcesTest.php b/tests/phpunit/structure/ResourcesTest.php new file mode 100644 index 00000000..fe823fa4 --- /dev/null +++ b/tests/phpunit/structure/ResourcesTest.php @@ -0,0 +1,131 @@ +<?php +/** + * Sanity checks for making sure registered resources are sane. + * + * @file + * @author Antoine Musso + * @author Niklas Laxström + * @author Santhosh Thottingal + * @author Timo Tijhof + * @copyright © 2012, Antoine Musso + * @copyright © 2012, Niklas Laxström + * @copyright © 2012, Santhosh Thottingal + * @copyright © 2012, Timo Tijhof + * + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + */ +class ResourcesTest extends MediaWikiTestCase { + + /** + * @dataProvider provideResourceFiles + */ + public function testFileExistence( $filename, $module, $resource ) { + $this->assertFileExists( $filename, + "File '$resource' referenced by '$module' must exist." + ); + } + + /** + * This ask the ResouceLoader for all registered files from modules + * created by ResourceLoaderFileModule (or one of its descendants). + * + * + * Since the raw data is stored in protected properties, we have to + * overrride this through ReflectionObject methods. + */ + public static function provideResourceFiles() { + global $wgEnableJavaScriptTest; + + // Test existance of test suite files as well + // (can't use setUp or setMwGlobals because providers are static) + $live_wgEnableJavaScriptTest = $wgEnableJavaScriptTest; + $wgEnableJavaScriptTest = true; + + // Array with arguments for the test function + $cases = array(); + + // Initialize ResourceLoader + $rl = new ResourceLoader(); + + // See also ResourceLoaderFileModule::__construct + $filePathProps = array( + // Lists of file paths + 'lists' => array( + 'scripts', + 'debugScripts', + 'loaderScripts', + 'styles', + ), + + // Collated lists of file paths + 'nested-lists' => array( + 'languageScripts', + 'skinScripts', + 'skinStyles', + ), + ); + + foreach ( $rl->getModuleNames() as $moduleName ) { + $module = $rl->getModule( $moduleName ); + if ( !$module instanceof ResourceLoaderFileModule ) { + continue; + } + + $reflectedModule = new ReflectionObject( $module ); + + $files = array(); + + foreach ( $filePathProps['lists'] as $propName ) { + $property = $reflectedModule->getProperty( $propName ); + $property->setAccessible( true ); + $list = $property->getValue( $module ); + foreach ( $list as $key => $value ) { + // 'scripts' are numeral arrays. + // 'styles' can be numeral or associative. + // In case of associative the key is the file path + // and the value is the 'media' attribute. + if ( is_int( $key ) ) { + $files[] = $value; + } else { + $files[] = $key; + } + } + } + + foreach ( $filePathProps['nested-lists'] as $propName ) { + $property = $reflectedModule->getProperty( $propName ); + $property->setAccessible( true ); + $lists = $property->getValue( $module ); + foreach ( $lists as $list ) { + foreach ( $list as $key => $value ) { + // We need the same filter as for 'lists', + // due to 'skinStyles'. + if ( is_int( $key ) ) { + $files[] = $value; + } else { + $files[] = $key; + } + } + } + } + + // Get method for resolving the paths to full paths + $method = $reflectedModule->getMethod( 'getLocalPath' ); + $method->setAccessible( true ); + + // Populate cases + foreach ( $files as $file ) { + $cases[] = array( + $method->invoke( $module, $file ), + $module->getName(), + $file, + ); + } + } + + // Restore settings + $wgEnableJavaScriptTest = $live_wgEnableJavaScriptTest; + + return $cases; + } +} diff --git a/tests/phpunit/structure/StructureTest.php b/tests/phpunit/structure/StructureTest.php new file mode 100644 index 00000000..df00d4df --- /dev/null +++ b/tests/phpunit/structure/StructureTest.php @@ -0,0 +1,63 @@ +<?php +/** + * The tests here verify the structure of the code. This is for outright bugs, + * not just style issues. + */ + +class StructureTest extends MediaWikiTestCase { + /** + * Verify all files that appear to be tests have file names ending in + * Test. If the file names do not end in Test, they will not be run. + * @group medium + */ + public function testUnitTestFileNamesEndWithTest() { + if ( wfIsWindows() ) { + $this->markTestSkipped( 'This test does not work on Windows' ); + } + $rootPath = escapeshellarg( __DIR__ . '/..' ); + $testClassRegex = implode( '|', array( + 'ApiFormatTestBase', + 'ApiTestCase', + 'ApiQueryTestBase', + 'ApiQueryContinueTestBase', + 'MediaWikiLangTestCase', + 'MediaWikiTestCase', + 'PHPUnit_Framework_TestCase', + 'DumpTestCase', + ) ); + $testClassRegex = "^class .* extends ($testClassRegex)"; + $finder = "find $rootPath -name '*.php' '!' -name '*Test.php'" . + " | xargs grep -El '$testClassRegex|function suite\('"; + + $results = null; + $exitCode = null; + exec( $finder, $results, $exitCode ); + + $this->assertEquals( + 0, + $exitCode, + 'Verify find/grep command succeeds.' + ); + + $results = array_filter( + $results, + array( $this, 'filterSuites' ) + ); + $strip = strlen( $rootPath ) - 1; + foreach ( $results as $k => $v ) { + $results[$k] = substr( $v, $strip ); + } + $this->assertEquals( + array(), + $results, + "Unit test file in $rootPath must end with Test." + ); + } + + /** + * Filter to remove testUnitTestFileNamesEndWithTest false positives. + */ + public function filterSuites( $filename ) { + return strpos( $filename, __DIR__ . '/../suites/' ) !== 0; + } +} |