From d42e3ed23bd553458ef19b4b3c254f46abb87c11 Mon Sep 17 00:00:00 2001 From: "Mark A. Hershberger" Date: Mon, 11 Oct 2010 22:50:06 +0000 Subject: [PATCH] =?utf8?q?NOTE=20THAT=20THIS=20COMMIT=20REVEALS=20FAILING?= =?utf8?q?=20PARSER=20TESTS=20WHEN=20THEY=20ARE=20RUN=20IN=20PHPUnit.=20TH?= =?utf8?q?E=20PHPUnit=20HARNESS=20NEEDS=20TO=20BE=20FIXED=20IN=20THIS=20CA?= =?utf8?q?SE.=20Running=20parser=20tests=20by=20the=20traditional=20?= =?utf8?q?=E2=80=9Cphp=20parserTests.php=E2=80=9D=20verified=20to=20work?= =?utf8?q?=20without=20failures.=20Committing=20this=20to=20get=20the=20pa?= =?utf8?q?rser=20tests=20running=20under=20PHPUnit=20on=20the=20whole.=20?= =?utf8?q?=20I=20expect=20to=20find=20fixes=20for=20the=20PHPUnit=20harnes?= =?utf8?q?s=20shortly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * Construct ParserOptions with a user in ExtraParserTest and set up wgLang if it gets set to null — which *was* happening PHPUnit. Note that this probably shows a bug that I wasn't able to track down. * Adjust phpunit tests so that they execute and report Parser test failures properly. Attempt to make parser test titles the test titles PHPUnit sees. * Add E_STRICT reporting to PHPUnit testing. * Provide PHPUnitParserTest as an exension of ParserTest to handle necessary PHPUnit calls for running parser tests under PHPUnit. * Use dirname() instead of relative paths (i.e. “..”) where SearchEngineTest.php looks for bootstrap.php. * Sprinkle teardownGlobals() in exit points for teardownDatabase() * Make ParserTest::chomp() static. --- maintenance/tests/parser/parserTest.inc | 87 +++++++++++++++++-- maintenance/tests/phpunit/bootstrap.php | 35 +++----- .../phpunit/includes/ExtraParserTest.php | 5 +- .../includes/parser/MediaWikiParserTest.php | 35 +++----- .../phpunit/includes/parser/ParserHelpers.php | 55 ++++++++---- .../includes/search/SearchEngineTest.php | 2 +- maintenance/tests/phpunit/suite.xml | 4 +- maintenance/tests/testHelpers.inc | 21 +++-- 8 files changed, 162 insertions(+), 82 deletions(-) diff --git a/maintenance/tests/parser/parserTest.inc b/maintenance/tests/parser/parserTest.inc index faa4c72fe7..5f43c4708c 100644 --- a/maintenance/tests/parser/parserTest.inc +++ b/maintenance/tests/parser/parserTest.inc @@ -57,6 +57,8 @@ class ParserTest { private $fuzzSeed = 0; private $memoryLimit = 50; + public $regex = ""; + private $savedGlobals = array(); /** * Sets terminal colorization and diff/quick modes depending on OS and * command-line options (--color and --quick). @@ -113,6 +115,57 @@ class ParserTest { $this->hooks = array(); $this->functionHooks = array(); + self::setUp(); + } + + static function setUp() { + global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, $wgDeferredUpdateList, + $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache, + $wgMessageCache, $wgUseDatabaseMessages, $wgMsgCacheExpiry, $parserMemc, + $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo, + $wgThumbnailScriptPath, $wgScriptPath, + $wgArticlePath, $wgStyleSheetPath, $wgScript, $wgStylePath; + + $wgScript = '/index.php'; + $wgScriptPath = '/'; + $wgArticlePath = '/wiki/$1'; + $wgStyleSheetPath = '/skins'; + $wgStylePath = '/skins'; + $wgThumbnailScriptPath = false; + $wgLocalFileRepo = array( + 'class' => 'LocalRepo', + 'name' => 'local', + 'directory' => wfTempDir() . '/test-repo', + 'url' => 'http://example.com/images', + 'deletedDir' => wfTempDir() . '/test-repo/delete', + 'hashLevels' => 2, + 'transformVia404' => false, + ); + $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface'; + $wgNamespaceAliases['Image'] = NS_FILE; + $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK; + + + $wgEnableParserCache = false; + $wgDeferredUpdateList = array(); + $wgMemc =& wfGetMainCache(); + $messageMemc =& wfGetMessageCacheStorage(); + $parserMemc =& wfGetParserCacheStorage(); + + // $wgContLang = new StubContLang; + $wgUser = new User; + $wgLang = new StubUserLang; + $wgOut = new StubObject( 'wgOut', 'OutputPage' ); + $wgParser = new StubObject( 'wgParser', $wgParserConf['class'], array( $wgParserConf ) ); + $wgRequest = new WebRequest; + + $wgMessageCache = new StubObject( 'wgMessageCache', 'MessageCache', + array( $messageMemc, $wgUseDatabaseMessages, + $wgMsgCacheExpiry ) ); + if ( $wgStyleDirectory === false ) { + $wgStyleDirectory = "$IP/skins"; + } + } public function setupRecorder ( $options ) { @@ -131,8 +184,9 @@ class ParserTest { /** * Remove last character if it is a newline + * @group utility */ - public function chomp( $s ) { + static public function chomp( $s ) { if ( substr( $s, -1 ) === "\n" ) { return substr( $s, 0, -1 ); } @@ -421,13 +475,20 @@ class ParserTest { $result = $this->tidy( $result ); } - $this->teardownGlobals(); + return $this->showTestResult( $desc, $result, $out ); + } - if ( $result === $out && ( $noxml === true || $this->wellFormed( $out ) ) ) { - return $this->showSuccess( $desc ); + /** + * + */ + function showTestResult( $desc, $result, $out ) { + if ( $result === $out ) { + $this->showSuccess( $desc ); + return true; } else { - return $this->showFailure( $desc, $result, $out ); + $this->showFailure( $desc, $result, $out ); + return false; } } @@ -820,6 +881,7 @@ class ParserTest { global $wgDBtype; if ( !$this->databaseSetupDone ) { + $this->teardownGlobals(); return; } $this->teardownUploadDir( $this->uploadDir ); @@ -829,6 +891,7 @@ class ParserTest { if ( $this->useTemporaryTables ) { # Don't need to do anything + $this->teardownGlobals(); return; } @@ -842,6 +905,8 @@ class ParserTest { if ( $wgDBtype == 'oracle' ) $db->query( 'BEGIN FILL_WIKI_INFO; END;' ); + + $this->teardownGlobals(); } /** @@ -1085,20 +1150,26 @@ class ParserTest { * @param $text String: the article text * @param $line Integer: the input line number, for reporting errors */ - public function addArticle( $name, $text, $line ) { + static public function addArticle( $name, $text, $line ) { global $wgCapitalLinks; + + $text = self::chomp($text); + $oldCapitalLinks = $wgCapitalLinks; $wgCapitalLinks = true; // We only need this from SetupGlobals() See r70917#c8637 - $title = Title::newFromText( $name ); + $title = Title::newFromText( self::chomp($name) ); if ( is_null( $title ) ) { - wfDie( "invalid title at line $line\n" ); + wfDie( "invalid title ('$name' => '$title') at line $line\n" ); } $aid = $title->getArticleID( Title::GAID_FOR_UPDATE ); if ( $aid != 0 ) { + foreach(debug_backtrace() as $bt) { + echo "{$bt['file']}::{$bt['line']}\n"; + } wfDie( "duplicate article '$name' at line $line\n" ); } diff --git a/maintenance/tests/phpunit/bootstrap.php b/maintenance/tests/phpunit/bootstrap.php index e348b2c13f..369cfe1120 100644 --- a/maintenance/tests/phpunit/bootstrap.php +++ b/maintenance/tests/phpunit/bootstrap.php @@ -31,34 +31,25 @@ EOF; /* Classes */ abstract class MediaWikiTestSetup extends PHPUnit_Framework_TestCase { + protected $suite; + public $regex = ''; + public $runDisabled = false; - protected function buildTestDatabase( $tables ) { - global $wgDBprefix; - $db = wfGetDB( DB_MASTER ); - $oldTableNames = array(); - foreach ( $tables as $table ) - $oldTableNames[$table] = $db->tableName( $table ); - if ( $db->getType() == 'oracle' ) { - $wgDBprefix = 'pt_'; - } else { - $wgDBprefix = 'parsertest_'; + function __construct( PHPUnit_Framework_TestSuite $suite = null ) { + if ( null !== $suite ) { + $this->suite = $suite; } - - $db->tablePrefix( $wgDBprefix ); - - if ( $db->isOpen() ) { - foreach ( $tables as $tbl ) { - $newTableName = $db->tableName( $tbl ); - $tableName = $oldTableNames[$tbl]; - $db->query( "DROP TABLE IF EXISTS $newTableName", __METHOD__ ); - $db->duplicateTableStructure( $tableName, $newTableName, __METHOD__ ); } - return $db; + + function __call( $func, $args ) { + if ( method_exists( $this->suite, $func ) ) { + return call_user_func_array( array( $tohis->suite, $func ), $args); } else { - // Something amiss - return null; + throw new MWException( "Called non-existant $func method on " + . get_class( $this ) ); } + return false; } } diff --git a/maintenance/tests/phpunit/includes/ExtraParserTest.php b/maintenance/tests/phpunit/includes/ExtraParserTest.php index 0f317ea37d..b95d79349a 100644 --- a/maintenance/tests/phpunit/includes/ExtraParserTest.php +++ b/maintenance/tests/phpunit/includes/ExtraParserTest.php @@ -23,11 +23,14 @@ class ExtraParserTest extends PHPUnit_Framework_TestCase { // Bug 8689 - Long numeric lines kill the parser function testBug8689() { + global $wgLang; + global $wgUser; $longLine = '1.' . str_repeat( '1234567890', 100000 ) . "\n"; + if ( $wgLang === null ) $wgLang = new Language; $parser = new Parser(); $t = Title::newFromText( 'Unit test' ); - $options = new ParserOptions(); + $options = ParserOptions::newFromUser( $wgUser ); $this->assertEquals( "

$longLine

", $parser->parse( $longLine, $t, $options )->getText() ); } diff --git a/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php b/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php index 4b0c259e8a..f441b98731 100644 --- a/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php +++ b/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php @@ -1,41 +1,34 @@ backend = new ParserTestSuiteBackend; - parent::__construct(); $this->setName( 'Parser tests' ); } - public function run( PHPUnit_Framework_TestResult $result = null, $filter = false, - array $groups = array(), array $excludeGroups = array(), $processIsolation = false - ) { - global $IP, $wgContLang, $wgMemc; - $wgContLang = Language::factory( 'en' ); - $wgMemc = new FakeMemCachedClient; - $this->backend->setupDatabase(); + public static function suite() { + global $IP; + + $tester = new self; $iter = new TestFileIterator( "$IP/maintenance/tests/parser/parserTests.txt" ); - $iter->setParser( $this->backend ); - $this->count = 0; + $iter->setParser( $tester ); + $tester->count = 0; foreach ( $iter as $test ) { - $this->addTest( new ParserUnitTest( $this, $test ) ); - $this->count++; + $tester->suite->addTest( new ParserUnitTest( $tester, $test ) ); + $tester->count++; } - parent::run( $result, $filter, $groups, $excludeGroups, $processIsolation ); - - $this->backend->teardownDatabase(); + return $tester->suite; } public function count() { diff --git a/maintenance/tests/phpunit/includes/parser/ParserHelpers.php b/maintenance/tests/phpunit/includes/parser/ParserHelpers.php index 165b93d9b2..3fbd78b684 100644 --- a/maintenance/tests/phpunit/includes/parser/ParserHelpers.php +++ b/maintenance/tests/phpunit/includes/parser/ParserHelpers.php @@ -1,5 +1,21 @@ suite->getBackend(); + $backend = new ParserTestSuiteBackend; $result->startTest( $this ); - + // Support the transition to PHPUnit 3.5 where PHPUnit_Util_Timer is replaced with PHP_Timer if ( class_exists( 'PHP_Timer' ) ) { PHP_Timer::start(); @@ -32,16 +48,13 @@ class ParserUnitTest extends PHPUnit_Framework_TestCase { # Run the test. # On failure, the subclassed backend will throw an exception with # the details. - $r = $backend->runTest( - $this->test['test'], - $this->test['input'], - $this->test['result'], - $this->test['options'], - $this->test['config'] + $pt = new PHPUnitParserTest; + $r = $pt->runTest( $this->test['test'], $this->test['input'], + $this->test['result'], $this->test['options'], $this->test['config'] ); } catch ( PHPUnit_Framework_AssertionFailedError $e ) { - + // PHPUnit_Util_Timer -> PHP_Timer support (see above) if ( class_exists( 'PHP_Timer' ) ) { $result->addFailure( $this, $e, PHP_Timer::stop() ); @@ -77,20 +90,29 @@ class ParserUnitTest extends PHPUnit_Framework_TestCase { } -class ParserTestSuiteBackend extends ParserTest { +class ParserTestSuiteBackend extends PHPUnit_FrameWork_TestSuite { + public $recorder; + public $term; + static $usePHPUnit = false; + + function __construct() { + parent::__construct(); + $this->setupRecorder(null); + self::$usePHPUnit = method_exists('PHPUnit_Framework_Assert', 'assertEquals'); + } + function showTesting( $desc ) { } function showRunFile( $path ) { } - function showSuccess( $desc ) { - PHPUnit_Framework_Assert::assertTrue( true, $desc ); - return true; + function showTestResult( $desc, $result, $out ) { + if ( $result === $out ) { + return self::showSuccess( $desc, $result, $out ); + } else { + return self::showFailure( $desc, $result, $out ); } - - function showFailure( $desc, $expected, $got ) { - PHPUnit_Framework_Assert::assertEquals( $expected, $got, $desc ); } public function setupRecorder( $options ) { @@ -107,4 +129,3 @@ class PHPUnitTestRecorder extends TestRecorder { function reportPercentage( $success, $total ) { } } - diff --git a/maintenance/tests/phpunit/includes/search/SearchEngineTest.php b/maintenance/tests/phpunit/includes/search/SearchEngineTest.php index 58eaecfed2..5d534f52fd 100644 --- a/maintenance/tests/phpunit/includes/search/SearchEngineTest.php +++ b/maintenance/tests/phpunit/includes/search/SearchEngineTest.php @@ -1,6 +1,6 @@ + stopOnFailure="false" + strict="true"> ./includes @@ -26,6 +27,7 @@ + Utility Broken Stub diff --git a/maintenance/tests/testHelpers.inc b/maintenance/tests/testHelpers.inc index 6153ca31b7..5d6bdec234 100644 --- a/maintenance/tests/testHelpers.inc +++ b/maintenance/tests/testHelpers.inc @@ -478,7 +478,7 @@ class TestFileIterator implements Iterator { $this->lineNum = $this->index = 0; } - function setParser( ParserTest $parser ) { + function setParser( MediaWikiParserTest $parser ) { $this->parser = $parser; } @@ -536,11 +536,10 @@ class TestFileIterator implements Iterator { wfDie( "'endarticle' without 'article' at line {$this->lineNum} of $this->file\n" ); } - if ( $this->parser ) { - $this->parser->addArticle( $this->parser->chomp( $data['article'] ), $this->parser->chomp( $data['text'] ), - $this->lineNum ); - } - + $title = Title::newFromText( ParserTest::chomp( $data['article'] ) ); + $aid = $title->getArticleID( Title::GAID_FOR_UPDATE ); + if ( $aid == 0 ) + ParserTest::addArticle( $data['article'], $data['text'], $this->lineNum ); $data = array(); $section = null; @@ -632,11 +631,11 @@ class TestFileIterator implements Iterator { if ( $this->parser ) { $this->test = array( - 'test' => $this->parser->chomp( $data['test'] ), - 'input' => $this->parser->chomp( $data['input'] ), - 'result' => $this->parser->chomp( $data['result'] ), - 'options' => $this->parser->chomp( $data['options'] ), - 'config' => $this->parser->chomp( $data['config'] ) ); + 'test' => ParserTest::chomp( $data['test'] ), + 'input' => ParserTest::chomp( $data['input'] ), + 'result' => ParserTest::chomp( $data['result'] ), + 'options' => ParserTest::chomp( $data['options'] ), + 'config' => ParserTest::chomp( $data['config'] ) ); } else { $this->test['test'] = $data['test']; } -- 2.20.1