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.
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).
$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 ) {
/**
* 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 );
}
$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;
}
}
global $wgDBtype;
if ( !$this->databaseSetupDone ) {
+ $this->teardownGlobals();
return;
}
$this->teardownUploadDir( $this->uploadDir );
if ( $this->useTemporaryTables ) {
# Don't need to do anything
+ $this->teardownGlobals();
return;
}
if ( $wgDBtype == 'oracle' )
$db->query( 'BEGIN FILL_WIKI_INFO; END;' );
+
+ $this->teardownGlobals();
}
/**
* @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" );
}
/* 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;
}
}
// 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() );
}
<?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() {
<?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;
$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();
# 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() );
}
-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 ) {
function reportPercentage( $success, $total ) { }
}
-
<?php
-require_once dirname(__FILE__) . '/../../bootstrap.php';
+require_once dirname(dirname(dirname(__FILE__))). '/bootstrap.php';
/**
* @group Stub
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
- stopOnFailure="false">
+ stopOnFailure="false"
+ strict="true">
<testsuites>
<testsuite name="includes">
<directory>./includes</directory>
</testsuites>
<groups>
<exclude>
+ <group>Utility</group>
<group>Broken</group>
<group>Stub</group>
</exclude>
$this->lineNum = $this->index = 0;
}
- function setParser( ParserTest $parser ) {
+ function setParser( MediaWikiParserTest $parser ) {
$this->parser = $parser;
}
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;
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'];
}