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; +	} +} | 
