From 2e33fb3ff667d1b774fd3551b6dc4380665adb49 Mon Sep 17 00:00:00 2001 From: Platonides Date: Sat, 26 Feb 2011 21:49:42 +0000 Subject: [PATCH] Finally commit the testing stuff I have been with this week. Could be considered a continuation of r79411. Mixture of the NewParserTests.php with old code present in MediaWikiParserTest.php, reverting r79184 (revert of a revert...) and even eval(). Using the iterator as dataProvider, but defering the insertion of articles, as the dataprovider is processed on load, before switching dbs. Each parser test appear now as a phpunit test. This means that by adding 683 tests (partly from extensions) we now surpass two thousand tests. The downside of that is that they become painfully slow. Initialise $wgHooks to $wgHooks, not to array() (r82499) as otherwise we lose ParserFirstCallInit registrations. There's no attempt to support extensions registering to $wgParser instead of using ParserFirstCallInit properly (Cite falls in this category). --- tests/phpunit/MediaWikiTestCase.php | 8 +- .../includes/parser/MediaWikiParserTest.php | 71 ++--- .../includes/parser/NewParserHelpers.php | 10 +- .../phpunit/includes/parser/NewParserTest.php | 278 ++++++++---------- 4 files changed, 156 insertions(+), 211 deletions(-) diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index 37c7b5921f..c030c4d6cf 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -30,7 +30,13 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { } function run( PHPUnit_Framework_TestResult $result = NULL ) { - + global $wgCaches; + /* Some functions require some kind of caching, and will end up using the db, + * which we can't allow, as that would open a new connection for mysql. + * Replace with a HashBag. They would not be going to persist anyway. + */ + $wgCaches[CACHE_DB] = new HashBagOStuff; + if( $this->needsDB() ) { global $wgDBprefix; diff --git a/tests/phpunit/includes/parser/MediaWikiParserTest.php b/tests/phpunit/includes/parser/MediaWikiParserTest.php index 3ff2b18252..634c666192 100644 --- a/tests/phpunit/includes/parser/MediaWikiParserTest.php +++ b/tests/phpunit/includes/parser/MediaWikiParserTest.php @@ -1,66 +1,35 @@ pt = new PHPUnitParserTest; - $this->pt->setupDatabase(); - - } - - function tearDown() { - if( is_object( $this->pt ) && $this->pt instanceof PHPUnitParserTest ) { - $this->pt->teardownDatabase(); - $this->pt = null; - } - } +class MediaWikiParserTest { - - public function testParserTests() { - //global $IP; - //$wgParserTestFiles = array( "$IP/tests/parser/testparserTests.txt" ); - - global $wgParserTestFiles; - - foreach( $wgParserTestFiles as $file ) { - - $iter = new TestFileIterator( $file, $this->pt ); - - try { - foreach( $iter as $test ) { - $r = $this->pt->runTest( $test['test'], $test['input'], - $test['result'], $test['options'], $test['config'] - ); - - $this->assertTrue( $r, 'Parser test ' . $test['test'] ); - - } - } - catch( DBQueryError $e ) { - $this->assertTrue( false, 'Parser test ' . $test['test'] . ' (error: "' . $e->getMessage() . '")' ); - //This is annoying... it always stops on error and doesn't go to the next one. - continue; - } + public static function suite() { + global $IP, $wgParserTestFiles; + + $suite = new PHPUnit_Framework_TestSuite; + + foreach ( $wgParserTestFiles as $filename ) { + $testsName = basename( $filename, '.txt' ); + $className = /*ucfirst( basename( dirname( $filename ) ) ) .*/ ucfirst( basename( $filename, '.txt' ) ); + eval( "/** @group Database\n@group Parser\n*/ class $className extends NewParserTest { protected \$file = \"" . addslashes( $filename ) . "\"; } " ); + + $parserTester = new $className( $testsName ); + $suite->addTestSuite( new ReflectionClass ( $parserTester ) ); } - } + return $suite; + } } - diff --git a/tests/phpunit/includes/parser/NewParserHelpers.php b/tests/phpunit/includes/parser/NewParserHelpers.php index 744dfd975d..a3762779b5 100644 --- a/tests/phpunit/includes/parser/NewParserHelpers.php +++ b/tests/phpunit/includes/parser/NewParserHelpers.php @@ -169,11 +169,11 @@ class ParserTestFileIterator implements Iterator { } $this->test = array( - 'test' => $this->parserTest->removeEndingNewline( $data['test'] ), - 'input' => $this->parserTest->removeEndingNewline( $data['input'] ), - 'result' => $this->parserTest->removeEndingNewline( $data['result'] ), - 'options' => $this->parserTest->removeEndingNewline( $data['options'] ), - 'config' => $this->parserTest->removeEndingNewline( $data['config'] ) ); + $this->parserTest->removeEndingNewline( $data['test'] ), + $this->parserTest->removeEndingNewline( $data['input'] ), + $this->parserTest->removeEndingNewline( $data['result'] ), + $this->parserTest->removeEndingNewline( $data['options'] ), + $this->parserTest->removeEndingNewline( $data['config'] ) ); return true; } diff --git a/tests/phpunit/includes/parser/NewParserTest.php b/tests/phpunit/includes/parser/NewParserTest.php index b337beeaeb..fe19341a49 100644 --- a/tests/phpunit/includes/parser/NewParserTest.php +++ b/tests/phpunit/includes/parser/NewParserTest.php @@ -2,9 +2,16 @@ /** * @group Database + * @group Parser + * @group Stub (can also work independently) */ class NewParserTest extends MediaWikiTestCase { + static protected $articles = array(); // Array of test articles defined by the tests + /* The dataProvider is run on a different instance than the test, so it must be static + * When running tests from several files, all tests will see all articles. + */ + public $uploadDir; public $keepUploads = false; public $runDisabled = false; @@ -21,10 +28,15 @@ class NewParserTest extends MediaWikiTestCase { public $fuzzSeed = 0; public $memoryLimit = 50; - //PHPUnit + MediaWikiTestCase functions - + protected $file = false; + + /*function __construct($a = null,$b = array(),$c = null ) { + parent::__construct($a,$b,$c); + }*/ + function setUp() { - global $wgContLang, $wgNamespaceProtection, $wgNamespaceAliases, $IP; + global $wgContLang, $wgNamespaceProtection, $wgNamespaceAliases; + global $wgHooks, $IP; $wgContLang = Language::factory( 'en' ); //Setup CLI arguments @@ -56,7 +68,7 @@ class NewParserTest extends MediaWikiTestCase { ); $tmpGlobals['wgEnableParserCache'] = false; - $tmpGlobals['wgHooks'] = array(); + $tmpGlobals['wgHooks'] = $wgHooks; $tmpGlobals['wgDeferredUpdateList'] = array(); $tmpGlobals['wgMemc'] = &wfGetMainCache(); $tmpGlobals['messageMemc'] = &wfGetMessageCacheStorage(); @@ -152,8 +164,9 @@ class NewParserTest extends MediaWikiTestCase { MessageCache::singleton()->clear(); $this->uploadDir = $this->setupUploadDir(); - + $user = User::newFromId( 0 ); + LinkCache::singleton()->clear(); # Avoids the odd failure at creating the nullRevision $image = wfLocalFile( Title::makeTitle( NS_FILE, 'Foobar.jpg' ) ); $image->recordUpload2( '', 'Upload of some lame file', 'Some lame file', array( @@ -258,7 +271,8 @@ class NewParserTest extends MediaWikiTestCase { 'wgHtml5' => true, 'wgWellFormedXml' => true, 'wgAllowMicrodataAttributes' => true, - 'wgAdaptiveMessageCache' => true + 'wgAdaptiveMessageCache' => true, + 'wgUseDatabaseMessages' => true, ); if ( $config ) { @@ -295,6 +309,13 @@ class NewParserTest extends MediaWikiTestCase { MagicWord::clearCache(); + # Publish the articles after we have the final language set + $this->publishTestArticles(); + + # The entries saved into RepoGroup cache with previous globals will be wrong. + RepoGroup::destroySingleton(); + MessageCache::singleton()->destroyInstance(); + global $wgUser; $wgUser = new User(); } @@ -345,115 +366,93 @@ class NewParserTest extends MediaWikiTestCase { return $dir; } + public function parserTestProvider() { + if ( $this->file === false ) { + global $wgParserTestFiles; + $this->file = $wgParserTestFiles[0]; + } + return new ParserTestFileIterator( $this->file, $this ); + } + /** + * Set the file from whose tests will be run by this instance + */ + public function setParserTestFile( $filename ) { + $this->file = $filename; + } - - - //Actual test suites + /** @dataProvider parserTestProvider */ + public function testParserTest( $desc, $input, $result, $opts, $config ) { + if ( !preg_match( '/' . $this->regex . '/', $desc ) ) return; //$this->markTestSkipped( 'Filtered out by the user' ); + $opts = $this->parseOptions( $opts ); + $this->setupGlobals( $opts, $config ); - public function testParserTests() { - - global $wgParserTestFiles; - - $files = $wgParserTestFiles; - - if( $this->getCliArg( 'file=' ) ) { - $files = array( $this->getCliArg( 'file=' ) ); + $user = new User(); + $options = ParserOptions::newFromUser( $user ); + + if ( isset( $opts['title'] ) ) { + $titleText = $opts['title']; } + else { + $titleText = 'Parser test'; + } + + $local = isset( $opts['local'] ); + $preprocessor = isset( $opts['preprocessor'] ) ? $opts['preprocessor'] : null; + $parser = $this->getParser( $preprocessor ); - foreach( $files as $file ) { - - $iter = new ParserTestFileIterator( $file, $this ); - - foreach ( $iter as $t ) { - - try { - - $desc = $t['test']; - $input = $t['input']; - $result = $t['result']; - $opts = $t['options']; - $config = $t['config']; - - - $opts = $this->parseOptions( $opts ); - $this->setupGlobals( $opts, $config ); - - $user = new User(); - $options = ParserOptions::newFromUser( $user ); - - if ( isset( $opts['title'] ) ) { - $titleText = $opts['title']; - } - else { - $titleText = 'Parser test'; - } - - $local = isset( $opts['local'] ); - $preprocessor = isset( $opts['preprocessor'] ) ? $opts['preprocessor'] : null; - $parser = $this->getParser( $preprocessor ); - $title = Title::newFromText( $titleText ); - - if ( isset( $opts['pst'] ) ) { - $out = $parser->preSaveTransform( $input, $title, $user, $options ); - } elseif ( isset( $opts['msg'] ) ) { - $out = $parser->transformMsg( $input, $options ); - } elseif ( isset( $opts['section'] ) ) { - $section = $opts['section']; - $out = $parser->getSection( $input, $section ); - } elseif ( isset( $opts['replace'] ) ) { - $section = $opts['replace'][0]; - $replace = $opts['replace'][1]; - $out = $parser->replaceSection( $input, $section, $replace ); - } elseif ( isset( $opts['comment'] ) ) { - $linker = $user->getSkin(); - $out = $linker->formatComment( $input, $title, $local ); - } elseif ( isset( $opts['preload'] ) ) { - $out = $parser->getpreloadText( $input, $title, $options ); - } else { - $output = $parser->parse( $input, $title, $options, true, true, 1337 ); - $out = $output->getText(); - - if ( isset( $opts['showtitle'] ) ) { - if ( $output->getTitleText() ) { - $title = $output->getTitleText(); - } - - $out = "$title\n$out"; - } - - if ( isset( $opts['ill'] ) ) { - $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) ); - } elseif ( isset( $opts['cat'] ) ) { - global $wgOut; - - $wgOut->addCategoryLinks( $output->getCategories() ); - $cats = $wgOut->getCategoryLinks(); - - if ( isset( $cats['normal'] ) ) { - $out = $this->tidy( implode( ' ', $cats['normal'] ) ); - } else { - $out = ''; - } - } - $parser->mPreprocessor = null; - - $result = $this->tidy( $result ); - } - - $this->teardownGlobals(); - - $this->assertEquals( $result, $out, $desc ); - + $title = Title::newFromText( $titleText ); + + if ( isset( $opts['pst'] ) ) { + $out = $parser->preSaveTransform( $input, $title, $user, $options ); + } elseif ( isset( $opts['msg'] ) ) { + $out = $parser->transformMsg( $input, $options ); + } elseif ( isset( $opts['section'] ) ) { + $section = $opts['section']; + $out = $parser->getSection( $input, $section ); + } elseif ( isset( $opts['replace'] ) ) { + $section = $opts['replace'][0]; + $replace = $opts['replace'][1]; + $out = $parser->replaceSection( $input, $section, $replace ); + } elseif ( isset( $opts['comment'] ) ) { + $linker = $user->getSkin(); + $out = $linker->formatComment( $input, $title, $local ); + } elseif ( isset( $opts['preload'] ) ) { + $out = $parser->getpreloadText( $input, $title, $options ); + } else { + $output = $parser->parse( $input, $title, $options, true, true, 1337 ); + $out = $output->getText(); + + if ( isset( $opts['showtitle'] ) ) { + if ( $output->getTitleText() ) { + $title = $output->getTitleText(); } - catch( Exception $e ) { - $this->assertTrue( false, $t['test'] . ' (failed: ' . $e->getMessage() . ')' ); + + $out = "$title\n$out"; + } + + if ( isset( $opts['ill'] ) ) { + $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) ); + } elseif ( isset( $opts['cat'] ) ) { + global $wgOut; + + $wgOut->addCategoryLinks( $output->getCategories() ); + $cats = $wgOut->getCategoryLinks(); + + if ( isset( $cats['normal'] ) ) { + $out = $this->tidy( implode( ' ', $cats['normal'] ) ); + } else { + $out = ''; } - } - + $parser->mPreprocessor = null; + + $result = $this->tidy( $result ); } - + + $this->teardownGlobals(); + + $this->assertEquals( $result, $out, $desc ); } /** @@ -593,59 +592,34 @@ class NewParserTest extends MediaWikiTestCase { * Get a Parser object */ function getParser( $preprocessor = null ) { - global $wgParserConf; + global $wgParserConf, $wgHooks; $class = $wgParserConf['class']; $parser = new $class( array( 'preprocessorClass' => $preprocessor ) + $wgParserConf ); - foreach ( $this->hooks as $tag => $callback ) { - $parser->setHook( $tag, $callback ); - } - - foreach ( $this->functionHooks as $tag => $bits ) { - list( $callback, $flags ) = $bits; - $parser->setFunctionHook( $tag, $callback, $flags ); - } - wfRunHooks( 'ParserTestParser', array( &$parser ) ); return $parser; } //Various action functions - - /** - * Insert a temporary test article - * @param $name String: the title, including any prefix - * @param $text String: the article text - * @param $line Integer: the input line number, for reporting errors - */ - public function addArticle( $name, $text, $line = 'unknown' ) { - global $wgCapitalLinks; - $text = $this->removeEndingNewline($text); - - $oldCapitalLinks = $wgCapitalLinks; - $wgCapitalLinks = true; // We only need this from SetupGlobals() See r70917#c8637 - - $name = $this->removeEndingNewline( $name ); - $title = Title::newFromText( $name ); - - if ( is_null( $title ) ) { - throw new MWException( "invalid title ('$name' => '$title') at line $line\n" ); + public function addArticle( $name, $text, $line ) { + self::$articles[$name] = $text; + } + + public function publishTestArticles() { + if ( empty( self::$articles ) ) { + return; } - $aid = $title->getArticleID( Title::GAID_FOR_UPDATE ); + foreach ( self::$articles as $name => $text ) { + $title = Title::newFromText( $name ); - if ( $aid != 0 ) { - debug_print_backtrace(); - throw new MWException( "duplicate article '$name' at line $line\n" ); + if ( $title->getArticleID( Title::GAID_FOR_UPDATE ) == 0 ) { + ParserTest::addArticle( $name, $text ); + } } - - $art = new Article( $title ); - $art->doEdit( $text, '', EDIT_NEW ); - - $wgCapitalLinks = $oldCapitalLinks; } /** @@ -658,19 +632,15 @@ class NewParserTest extends MediaWikiTestCase { */ public function requireHook( $name ) { global $wgParser; - $wgParser->firstCallInit( ); // make sure hooks are loaded. - - if ( isset( $wgParser->mTagHooks[$name] ) ) { - $this->hooks[$name] = $wgParser->mTagHooks[$name]; - } else { - echo " This test suite requires the '$name' hook extension, skipping.\n"; - return false; - } - - return true; + return isset( $wgParser->mTagHooks[$name] ); } + public function requireFunctionHook( $name ) { + global $wgParser; + $wgParser->firstCallInit( ); // make sure hooks are loaded. + return isset( $wgParser->mFunctionHooks[$name] ); + } //Various "cleanup" functions /* -- 2.20.1