X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=tests%2Fparser%2FParserTestRunner.php;h=f44b0d5e26bcc4e2df04fad85e50797ba9c1311f;hb=7916919c810a2385c1481423a999b972c349e388;hp=97e24b65f9f1d25f00955266140104443d39d7a8;hpb=68b30d922b1d76f6630323942e17f125bde4774a;p=lhc%2Fweb%2Fwiklou.git diff --git a/tests/parser/ParserTestRunner.php b/tests/parser/ParserTestRunner.php index 97e24b65f9..fff1eec78e 100644 --- a/tests/parser/ParserTestRunner.php +++ b/tests/parser/ParserTestRunner.php @@ -25,13 +25,27 @@ * @file * @ingroup Testing */ +use Wikimedia\Rdbms\IDatabase; use MediaWiki\MediaWikiServices; use Wikimedia\ScopedCallback; +use Wikimedia\TestingAccessWrapper; /** * @ingroup Testing */ class ParserTestRunner { + + /** + * MediaWiki core parser test files, paths + * will be prefixed with __DIR__ . '/' + * + * @var array + */ + private static $coreTestFiles = [ + 'parserTests.txt', + 'extraParserTests.txt', + ]; + /** * @var bool $useTemporaryTables Use temporary tables for the temporary database */ @@ -145,6 +159,43 @@ class ParserTestRunner { } } + /** + * Get list of filenames to extension and core parser tests + * + * @return array + */ + public static function getParserTestFiles() { + global $wgParserTestFiles; + + // Add core test files + $files = array_map( function( $item ) { + return __DIR__ . "/$item"; + }, self::$coreTestFiles ); + + // Plus legacy global files + $files = array_merge( $files, $wgParserTestFiles ); + + // Auto-discover extension parser tests + $registry = ExtensionRegistry::getInstance(); + foreach ( $registry->getAllThings() as $info ) { + $dir = dirname( $info['path'] ) . '/tests/parser'; + if ( !file_exists( $dir ) ) { + continue; + } + $dirIterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator( $dir ) + ); + foreach ( $dirIterator as $fileInfo ) { + /** @var SplFileInfo $fileInfo */ + if ( substr( $fileInfo->getFilename(), -4 ) === '.txt' ) { + $files[] = $fileInfo->getPathname(); + } + } + } + + return array_unique( $files ); + } + public function getRecorder() { return $this->recorder; } @@ -239,7 +290,7 @@ class ParserTestRunner { 'name' => 'nullLockManager', 'class' => 'NullLockManager', ] ]; - $reset = function() { + $reset = function () { LockManagerGroup::destroySingletons(); }; $setup[] = $reset; @@ -264,7 +315,10 @@ class ParserTestRunner { $setup['wgSVGConverters'] = [ 'null' => 'echo "1">$output' ]; // Fake constant timestamp - Hooks::register( 'ParserGetVariableValueTs', 'ParserTestRunner::getFakeTimestamp' ); + Hooks::register( 'ParserGetVariableValueTs', function ( &$parser, &$ts ) { + $ts = $this->getFakeTimestamp(); + return true; + } ); $teardown[] = function () { Hooks::clear( 'ParserGetVariableValueTs' ); }; @@ -287,7 +341,7 @@ class ParserTestRunner { MediaWikiServices::getInstance()->disableService( 'MediaHandlerFactory' ); MediaWikiServices::getInstance()->redefineService( 'MediaHandlerFactory', - function() { + function () { return new MockMediaHandlerFactory(); } ); @@ -295,7 +349,7 @@ class ParserTestRunner { MediaWikiServices::getInstance()->resetServiceForTesting( 'MediaHandlerFactory' ); }; - // SqlBagOStuff broke when using temporary tables on r40209 (bug 15892). + // SqlBagOStuff broke when using temporary tables on r40209 (T17892). // It seems to have been fixed since (r55079?), but regressed at some point before r85701. // This works around it for now... global $wgObjectCaches; @@ -316,7 +370,7 @@ class ParserTestRunner { private function appendNamespaceSetup( &$setup, &$teardown ) { // Add a namespace shadowing a interwiki link, to test - // proper precedence when resolving links. (bug 51680) + // proper precedence when resolving links. (T53680) $setup['wgExtraNamespaces'] = [ 100 => 'MemoryAlpha', 101 => 'MemoryAlpha_talk' @@ -427,7 +481,7 @@ class ParserTestRunner { * @return ScopedCallback */ protected function createTeardownObject( $teardown, $nextTeardown = null ) { - return new ScopedCallback( function() use ( $teardown, $nextTeardown ) { + return new ScopedCallback( function () use ( $teardown, $nextTeardown ) { // Schedule teardown snippets in reverse order $teardown = array_reverse( $teardown ); @@ -745,6 +799,11 @@ class ParserTestRunner { $context = RequestContext::getMain(); $user = $context->getUser(); $options = ParserOptions::newFromContext( $context ); + $options->setTimestamp( $this->getFakeTimestamp() ); + + if ( !isset( $opts['wrap'] ) ) { + $options->setWrapOutputClass( false ); + } if ( isset( $opts['tidy'] ) ) { if ( !$this->tidySupport->isEnabled() ) { @@ -768,6 +827,7 @@ class ParserTestRunner { if ( isset( $opts['pst'] ) ) { $out = $parser->preSaveTransform( $test['input'], $title, $user, $options ); + $output = $parser->getOutput(); } elseif ( isset( $opts['msg'] ) ) { $out = $parser->transformMsg( $test['input'], $options, $title ); } elseif ( isset( $opts['section'] ) ) { @@ -818,6 +878,12 @@ class ParserTestRunner { } } + if ( isset( $output ) && isset( $opts['showflags'] ) ) { + $actualFlags = array_keys( TestingAccessWrapper::newFromObject( $output )->mFlags ); + sort( $actualFlags ); + $out .= "\nflags=" . join( ', ', $actualFlags ); + } + ScopedCallback::consume( $teardownGuard ); $expected = $test['result']; @@ -970,14 +1036,16 @@ class ParserTestRunner { $linkHolderBatchSize = self::getOptionValue( 'wgLinkHolderBatchSize', $opts, 1000 ); + // Default to fallback skin, but allow it to be overridden + $skin = self::getOptionValue( 'skin', $opts, 'fallback' ); + $setup = [ 'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ), 'wgLanguageCode' => $langCode, 'wgRawHtml' => self::getOptionValue( 'wgRawHtml', $opts, false ), - 'wgNamespacesWithSubpages' => [ - 0 => isset( $opts['subpage'] ), - 2 => isset( $opts['subpage'] ), - ], + 'wgNamespacesWithSubpages' => array_fill_keys( + MWNamespace::getValidNamespaces(), isset( $opts['subpage'] ) + ), 'wgMaxTocLevel' => $maxtoclevel, 'wgAllowExternalImages' => self::getOptionValue( 'wgAllowExternalImages', $opts, true ), 'wgThumbLimits' => [ self::getOptionValue( 'thumbsize', $opts, 180 ) ], @@ -1040,10 +1108,23 @@ class ParserTestRunner { $context = RequestContext::getMain(); $context->setUser( $user ); $context->setLanguage( $lang ); - $teardown[] = function () use ( $context ) { + // And the skin! + $oldSkin = $context->getSkin(); + $skinFactory = MediaWikiServices::getInstance()->getSkinFactory(); + $context->setSkin( $skinFactory->makeSkin( $skin ) ); + $context->setOutput( new OutputPage( $context ) ); + $setup['wgOut'] = $context->getOutput(); + $teardown[] = function () use ( $context, $oldSkin ) { + // Clear language conversion tables + $wrapper = TestingAccessWrapper::newFromObject( + $context->getLanguage()->getConverter() + ); + $wrapper->reloadTables(); // Reset context to the restored globals $context->setUser( $GLOBALS['wgUser'] ); $context->setLanguage( $GLOBALS['wgContLang'] ); + $context->setSkin( $oldSkin ); + $context->setOutput( $GLOBALS['wgOut'] ); }; $teardown[] = $this->executeSetupSnippets( $setup ); @@ -1321,7 +1402,7 @@ class ParserTestRunner { if ( $this->useTemporaryTables ) { if ( $this->db->getType() == 'sqlite' ) { # Under SQLite the searchindex table is virtual and need - # to be explicitly destroyed. See bug 29912 + # to be explicitly destroyed. See T31912 # See also MediaWikiTestCase::destroyDB() wfDebug( __METHOD__ . " explicitly destroying sqlite virtual table parsertest_searchindex\n" ); $this->db->query( "DROP TABLE `parsertest_searchindex`" ); @@ -1588,11 +1669,14 @@ class ParserTestRunner { } /** - * The ParserGetVariableValueTs hook, used to make sure time-related parser + * Fake constant timestamp to make sure time-related parser * functions give a persistent value. + * + * - Parser::getVariableValue (via ParserGetVariableValueTs hook) + * - Parser::preSaveTransform (via ParserOptions) */ - static function getFakeTimestamp( &$parser, &$ts ) { - $ts = 123; // parsed as '1970-01-01T00:02:03Z' - return true; + private function getFakeTimestamp() { + // parsed as '1970-01-01T00:02:03Z' + return 123; } }