NOTE THAT THIS COMMIT REVEALS FAILING PARSER TESTS WHEN THEY ARE RUN IN PHPUnit....
authorMark A. Hershberger <mah@users.mediawiki.org>
Mon, 11 Oct 2010 22:50:06 +0000 (22:50 +0000)
committerMark A. Hershberger <mah@users.mediawiki.org>
Mon, 11 Oct 2010 22:50:06 +0000 (22:50 +0000)
Committing this to get the parser tests running under PHPUnit on the whole.  I expect to find fixes for the PHPUnit harness shortly.

* 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
maintenance/tests/phpunit/bootstrap.php
maintenance/tests/phpunit/includes/ExtraParserTest.php
maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php
maintenance/tests/phpunit/includes/parser/ParserHelpers.php
maintenance/tests/phpunit/includes/search/SearchEngineTest.php
maintenance/tests/phpunit/suite.xml
maintenance/tests/testHelpers.inc

index faa4c72..5f43c47 100644 (file)
@@ -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" );
                }
 
index e348b2c..369cfe1 100644 (file)
@@ -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;
        }
 }
 
index 0f317ea..b95d793 100644 (file)
@@ -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( "<p>$longLine</p>",
                        $parser->parse( $longLine, $t, $options )->getText() );
        }
index 4b0c259..f441b98 100644 (file)
@@ -1,41 +1,34 @@
 <?php
 
 require_once( dirname( __FILE__ ) . '/ParserHelpers.php' );
+require_once( dirname(dirname(dirname( __FILE__ ))) . '/bootstrap.php' );
 
-class MediaWikiParserTest extends PHPUnit_Framework_TestSuite {
-       private $count;
+class MediaWikiParserTest extends MediaWikiTestSetup {
+       public $count;
        public $backend;
 
-       public static function suite() {
-               return new self;
-       }
-
        public function __construct() {
+               $suite = new PHPUnit_Framework_TestSuite('Parser Tests');
+               parent::__construct($suite);
                $this->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() {
index 165b93d..3fbd78b 100644 (file)
@@ -1,5 +1,21 @@
 <?php
 
+class PHPUnitParserTest extends ParserTest {
+       function showTesting( $desc ) {
+               /* Do nothing since we don't want to show info during PHPUnit testing. */
+       }
+
+       public function showSuccess( $desc ) {
+               PHPUnit_Framework_Assert::assertTrue( true, $desc );
+               return true;
+       }
+
+       public function showFailure( $desc, $expected, $got ) {
+               PHPUnit_Framework_Assert::assertEquals( $expected, $got, $desc );
+               return false;
+       }
+}
+
 class ParserUnitTest extends PHPUnit_Framework_TestCase {
        private $test = "";
        private $suite;
@@ -17,9 +33,9 @@ class ParserUnitTest extends PHPUnit_Framework_TestCase {
                        $result = new PHPUnit_Framework_TestResult;
                }
 
-               $backend = $this->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 ) { }
 }
-
index 58eaecf..5d534f5 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-require_once dirname(__FILE__) . '/../../bootstrap.php';
+require_once dirname(dirname(dirname(__FILE__))). '/bootstrap.php';
 
 /**
  * @group Stub
index 6ad6ec7..bc2c59b 100644 (file)
@@ -6,7 +6,8 @@
          convertErrorsToExceptions="true"
          convertNoticesToExceptions="true"
          convertWarningsToExceptions="true"
-                stopOnFailure="false">
+         stopOnFailure="false"
+         strict="true">
        <testsuites>
                <testsuite name="includes">
                        <directory>./includes</directory>
@@ -26,6 +27,7 @@
        </testsuites>
        <groups>
                <exclude>
+                       <group>Utility</group>
                        <group>Broken</group>
                        <group>Stub</group>
                </exclude>
index 6153ca3..5d6bdec 100644 (file)
@@ -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'];
                                        }