Merge "RCFilters: Fix highlight circle misalignment"
[lhc/web/wiklou.git] / tests / parser / ParserTestRunner.php
index a373142..97c3c05 100644 (file)
@@ -34,6 +34,18 @@ 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
         */
@@ -147,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;
        }
@@ -266,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' );
                };
@@ -289,8 +341,9 @@ class ParserTestRunner {
                MediaWikiServices::getInstance()->disableService( 'MediaHandlerFactory' );
                MediaWikiServices::getInstance()->redefineService(
                        'MediaHandlerFactory',
-                       function () {
-                               return new MockMediaHandlerFactory();
+                       function ( MediaWikiServices $services ) {
+                               $handlers = $services->getMainConfig()->get( 'ParserTestMediaHandlers' );
+                               return new MediaHandlerFactory( $handlers );
                        }
                );
                $teardown[] = function () {
@@ -425,7 +478,7 @@ class ParserTestRunner {
         * @see staticSetup
         *
         * @param array $teardown The snippet array
-        * @param ScopedCallback|null A ScopedCallback to consume
+        * @param ScopedCallback|null $nextTeardown A ScopedCallback to consume
         * @return ScopedCallback
         */
        protected function createTeardownObject( $teardown, $nextTeardown = null ) {
@@ -474,7 +527,7 @@ class ParserTestRunner {
         * Determine whether a particular setup function has been run
         *
         * @param string $funcName
-        * @return boolean
+        * @return bool
         */
        public function isSetupDone( $funcName ) {
                return isset( $this->setupDone[$funcName] ) ? $this->setupDone[$funcName] : false;
@@ -747,6 +800,7 @@ class ParserTestRunner {
                $context = RequestContext::getMain();
                $user = $context->getUser();
                $options = ParserOptions::newFromContext( $context );
+               $options->setTimestamp( $this->getFakeTimestamp() );
 
                if ( !isset( $opts['wrap'] ) ) {
                        $options->setWrapOutputClass( false );
@@ -774,6 +828,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'] ) ) {
@@ -824,6 +879,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'];
@@ -976,6 +1037,9 @@ 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,
@@ -992,6 +1056,8 @@ class ParserTestRunner {
                        // wgEnableMagicLinks={"ISBN":false, "PMID":false, "RFC":false}
                        'wgEnableMagicLinks' => self::getOptionValue( 'wgEnableMagicLinks', $opts, [] )
                                + [ 'ISBN' => true, 'PMID' => true, 'RFC' => true ],
+                       // Test with legacy encoding by default until HTML5 is very stable and default
+                       'wgFragmentMode' => [ 'legacy' ],
                ];
 
                if ( $config ) {
@@ -1045,7 +1111,13 @@ 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()
@@ -1054,6 +1126,8 @@ class ParserTestRunner {
                        // 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 );
@@ -1456,7 +1530,7 @@ class ParserTestRunner {
        /**
         * Add articles to the test DB.
         *
-        * @param $articles Article info array from TestFileReader
+        * @param array $articles Article info array from TestFileReader
         */
        public function addArticles( $articles ) {
                global $wgContLang;
@@ -1598,11 +1672,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;
        }
 }