From: Chad Horohoe Date: Tue, 28 Sep 2010 12:24:56 +0000 (+0000) Subject: Move parser test related stuff to tests directory X-Git-Tag: 1.31.0-rc.0~34763 X-Git-Url: http://git.cyclocoop.org/%7B%24admin_url%7Dcompta/comptes/journal.php?a=commitdiff_plain;h=002cdd47e1a951e9da6c1566ea82aeab08a40a40;p=lhc%2Fweb%2Fwiklou.git Move parser test related stuff to tests directory * Moved test record stuff to testHelpers.inc, could be useful for non-parser test stuff? * Everything else in tests/parser * parserTestsParserTime from r12533 doesn't seem used? --- diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 1805d7de12..07b4fff8fb 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -678,26 +678,26 @@ $wgAutoloadLocalClasses = array( 'LanguageConverter' => 'languages/LanguageConverter.php', # maintenance - 'AnsiTermColorer' => 'maintenance/parserTests.inc', + 'AnsiTermColorer' => 'maintenance/tests/testHelpers.inc', 'ConvertLinks' => 'maintenance/convertLinks.php', - 'DbTestPreviewer' => 'maintenance/parserTests.inc', - 'DbTestRecorder' => 'maintenance/parserTests.inc', + 'DbTestPreviewer' => 'maintenance/tests/testHelpers.inc', + 'DbTestRecorder' => 'maintenance/tests/testHelpers.inc', 'DeleteArchivedFilesImplementation' => 'maintenance/deleteArchivedFiles.inc', 'DeleteArchivedRevisionsImplementation' => 'maintenance/deleteArchivedRevisions.inc', 'DeleteDefaultMessages' => 'maintenance/deleteDefaultMessages.php', - 'DummyTermColorer' => 'maintenance/parserTests.inc', - 'ParserTest' => 'maintenance/parserTests.inc', - 'ParserTestParserHook' => 'maintenance/parserTestsParserHook.php', - 'ParserTestStaticParserHook' => 'maintenance/parserTestsStaticParserHook.php', + 'DummyTermColorer' => 'maintenance/tests/testHelpers.inc', + 'ParserTest' => 'maintenance/tests/parser/parserTest.inc', + 'ParserTestParserHook' => 'maintenance/tests/parser/parserTestsParserHook.php', + 'ParserTestStaticParserHook' => 'maintenance/tests/parser/parserTestsStaticParserHook.php', 'PopulateCategory' => 'maintenance/populateCategory.php', 'PopulateLogSearch' => 'maintenance/populateLogSearch.php', 'PopulateParentId' => 'maintenance/populateParentId.php', 'PopulateRevisionLength' => 'maintenance/populateRevisionLength.php', - 'RemoteTestRecorder' => 'maintenance/parserTests.inc', + 'RemoteTestRecorder' => 'maintenance/tests/testHelpers.inc', 'SevenZipStream' => 'maintenance/7zip.inc', 'Sqlite' => 'maintenance/sqlite.inc', - 'TestFileIterator' => 'maintenance/parserTests.inc', - 'TestRecorder' => 'maintenance/parserTests.inc', + 'TestFileIterator' => 'maintenance/tests/testHelpers.inc', + 'TestRecorder' => 'maintenance/tests/testHelpers.inc', 'UpdateCollation' => 'maintenance/updateCollation.php', 'UpdateRestrictions' => 'maintenance/updateRestrictions.php', 'UserDupes' => 'maintenance/userDupes.inc', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 4b395f2589..60bc8918dc 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -3736,8 +3736,8 @@ $wgUseTrackbacks = false; * Use full paths. */ $wgParserTestFiles = array( - "$IP/maintenance/parserTests.txt", - "$IP/maintenance/ExtraParserTests.txt" + "$IP/maintenance/tests/parser/parserTests.txt", + "$IP/maintenance/tests/parser/ExtraParserTests.txt" ); /** diff --git a/maintenance/ExtraParserTests.txt b/maintenance/ExtraParserTests.txt deleted file mode 100644 index 66b8032d18..0000000000 Binary files a/maintenance/ExtraParserTests.txt and /dev/null differ diff --git a/maintenance/Makefile b/maintenance/Makefile index 82476139f4..a92751c93d 100644 --- a/maintenance/Makefile +++ b/maintenance/Makefile @@ -3,7 +3,7 @@ help: @echo "Run 'make doc' to run the doxygen generation." test: - php parserTests.php --quiet + php tests/parserTests.php --quiet doc: php mwdocgen.php --all diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc deleted file mode 100644 index 896d631f66..0000000000 --- a/maintenance/parserTests.inc +++ /dev/null @@ -1,1884 +0,0 @@ - -# http://www.mediawiki.org/ -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# http://www.gnu.org/copyleft/gpl.html - -/** - * @todo Make this more independent of the configuration (and if possible the database) - * @todo document - * @file - * @ingroup Maintenance - */ - -/** - * @ingroup Maintenance - */ -class ParserTest { - /** - * boolean $color whereas output should be colorized - */ - private $color; - - /** - * boolean $showOutput Show test output - */ - private $showOutput; - - /** - * boolean $useTemporaryTables Use temporary tables for the temporary database - */ - private $useTemporaryTables = true; - - /** - * boolean $databaseSetupDone True if the database has been set up - */ - private $databaseSetupDone = false; - - /** - * string $oldTablePrefix Original table prefix - */ - private $oldTablePrefix; - - private $maxFuzzTestLength = 300; - private $fuzzSeed = 0; - private $memoryLimit = 50; - - /** - * Sets terminal colorization and diff/quick modes depending on OS and - * command-line options (--color and --quick). - */ - public function ParserTest( $options = array() ) { - # Only colorize output if stdout is a terminal. - $this->color = !wfIsWindows() && posix_isatty( 1 ); - - if ( isset( $options['color'] ) ) { - switch( $options['color'] ) { - case 'no': - $this->color = false; - break; - case 'yes': - default: - $this->color = true; - break; - } - } - - $this->term = $this->color - ? new AnsiTermColorer() - : new DummyTermColorer(); - - $this->showDiffs = !isset( $options['quick'] ); - $this->showProgress = !isset( $options['quiet'] ); - $this->showFailure = !( - isset( $options['quiet'] ) - && ( isset( $options['record'] ) - || isset( $options['compare'] ) ) ); // redundant output - - $this->showOutput = isset( $options['show-output'] ); - - - if ( isset( $options['regex'] ) ) { - if ( isset( $options['record'] ) ) { - echo "Warning: --record cannot be used with --regex, disabling --record\n"; - unset( $options['record'] ); - } - $this->regex = $options['regex']; - } else { - # Matches anything - $this->regex = ''; - } - - $this->setupRecorder( $options ); - $this->keepUploads = isset( $options['keep-uploads'] ); - - if ( isset( $options['seed'] ) ) { - $this->fuzzSeed = intval( $options['seed'] ) - 1; - } - - $this->runDisabled = isset( $options['run-disabled'] ); - - $this->hooks = array(); - $this->functionHooks = array(); - } - - public function setupRecorder ( $options ) { - if ( isset( $options['record'] ) ) { - $this->recorder = new DbTestRecorder( $this ); - $this->recorder->version = isset( $options['setversion'] ) ? - $options['setversion'] : SpecialVersion::getVersion(); - } elseif ( isset( $options['compare'] ) ) { - $this->recorder = new DbTestPreviewer( $this ); - } elseif ( isset( $options['upload'] ) ) { - $this->recorder = new RemoteTestRecorder( $this ); - } else { - $this->recorder = new TestRecorder( $this ); - } - } - - /** - * Remove last character if it is a newline - */ - public function chomp( $s ) { - if ( substr( $s, -1 ) === "\n" ) { - return substr( $s, 0, -1 ); - } - else { - return $s; - } - } - - /** - * Run a fuzz test series - * Draw input from a set of test files - */ - function fuzzTest( $filenames ) { - $GLOBALS['wgContLang'] = Language::factory( 'en' ); - $dict = $this->getFuzzInput( $filenames ); - $dictSize = strlen( $dict ); - $logMaxLength = log( $this->maxFuzzTestLength ); - $this->setupDatabase(); - ini_set( 'memory_limit', $this->memoryLimit * 1048576 ); - - $numTotal = 0; - $numSuccess = 0; - $user = new User; - $opts = ParserOptions::newFromUser( $user ); - $title = Title::makeTitle( NS_MAIN, 'Parser_test' ); - - while ( true ) { - // Generate test input - mt_srand( ++$this->fuzzSeed ); - $totalLength = mt_rand( 1, $this->maxFuzzTestLength ); - $input = ''; - - while ( strlen( $input ) < $totalLength ) { - $logHairLength = mt_rand( 0, 1000000 ) / 1000000 * $logMaxLength; - $hairLength = min( intval( exp( $logHairLength ) ), $dictSize ); - $offset = mt_rand( 0, $dictSize - $hairLength ); - $input .= substr( $dict, $offset, $hairLength ); - } - - $this->setupGlobals(); - $parser = $this->getParser(); - - // Run the test - try { - $parser->parse( $input, $title, $opts ); - $fail = false; - } catch ( Exception $exception ) { - $fail = true; - } - - if ( $fail ) { - echo "Test failed with seed {$this->fuzzSeed}\n"; - echo "Input:\n"; - var_dump( $input ); - echo "\n\n"; - echo "$exception\n"; - } else { - $numSuccess++; - } - - $numTotal++; - $this->teardownGlobals(); - $parser->__destruct(); - - if ( $numTotal % 100 == 0 ) { - $usage = intval( memory_get_usage( true ) / $this->memoryLimit / 1048576 * 100 ); - echo "{$this->fuzzSeed}: $numSuccess/$numTotal (mem: $usage%)\n"; - if ( $usage > 90 ) { - echo "Out of memory:\n"; - $memStats = $this->getMemoryBreakdown(); - - foreach ( $memStats as $name => $usage ) { - echo "$name: $usage\n"; - } - $this->abort(); - } - } - } - } - - /** - * Get an input dictionary from a set of parser test files - */ - function getFuzzInput( $filenames ) { - $dict = ''; - - foreach ( $filenames as $filename ) { - $contents = file_get_contents( $filename ); - preg_match_all( '/!!\s*input\n(.*?)\n!!\s*result/s', $contents, $matches ); - - foreach ( $matches[1] as $match ) { - $dict .= $match . "\n"; - } - } - - return $dict; - } - - /** - * Get a memory usage breakdown - */ - function getMemoryBreakdown() { - $memStats = array(); - - foreach ( $GLOBALS as $name => $value ) { - $memStats['$' . $name] = strlen( serialize( $value ) ); - } - - $classes = get_declared_classes(); - - foreach ( $classes as $class ) { - $rc = new ReflectionClass( $class ); - $props = $rc->getStaticProperties(); - $memStats[$class] = strlen( serialize( $props ) ); - $methods = $rc->getMethods(); - - foreach ( $methods as $method ) { - $memStats[$class] += strlen( serialize( $method->getStaticVariables() ) ); - } - } - - $functions = get_defined_functions(); - - foreach ( $functions['user'] as $function ) { - $rf = new ReflectionFunction( $function ); - $memStats["$function()"] = strlen( serialize( $rf->getStaticVariables() ) ); - } - - asort( $memStats ); - - return $memStats; - } - - function abort() { - $this->abort(); - } - - /** - * Run a series of tests listed in the given text files. - * Each test consists of a brief description, wikitext input, - * and the expected HTML output. - * - * Prints status updates on stdout and counts up the total - * number and percentage of passed tests. - * - * @param $filenames Array of strings - * @return Boolean: true if passed all tests, false if any tests failed. - */ - public function runTestsFromFiles( $filenames ) { - $GLOBALS['wgContLang'] = Language::factory( 'en' ); - $this->recorder->start(); - $this->setupDatabase(); - $ok = true; - - foreach ( $filenames as $filename ) { - $tests = new TestFileIterator( $filename, $this ); - $ok = $this->runTests( $tests ) && $ok; - } - - $this->teardownDatabase(); - $this->recorder->report(); - $this->recorder->end(); - - return $ok; - } - - function runTests( $tests ) { - $ok = true; - - foreach ( $tests as $i => $t ) { - $result = - $this->runTest( $t['test'], $t['input'], $t['result'], $t['options'], $t['config'] ); - $ok = $ok && $result; - $this->recorder->record( $t['test'], $result ); - } - - if ( $this->showProgress ) { - print "\n"; - } - - return $ok; - } - - /** - * Get a Parser object - */ - function getParser( $preprocessor = null ) { - global $wgParserConf; - - $class = $wgParserConf['class']; - $parser = new $class( array( 'preprocessorClass' => $preprocessor ) + $wgParserConf ); - - foreach ( $this->hooks as $tag => $callback ) { - $parser->setHook( $tag, $callback ); - } - - foreach ( $this->functionHooks as $tag => $bits ) { - list( $callback, $flags ) = $bits; - $parser->setFunctionHook( $tag, $callback, $flags ); - } - - wfRunHooks( 'ParserTestParser', array( &$parser ) ); - - return $parser; - } - - /** - * Run a given wikitext input through a freshly-constructed wiki parser, - * and compare the output against the expected results. - * Prints status and explanatory messages to stdout. - * - * @param $desc String: test's description - * @param $input String: wikitext to try rendering - * @param $result String: result to output - * @param $opts Array: test's options - * @param $config String: overrides for global variables, one per line - * @return Boolean - */ - public function runTest( $desc, $input, $result, $opts, $config ) { - if ( $this->showProgress ) { - $this->showTesting( $desc ); - } - - $opts = $this->parseOptions( $opts ); - $this->setupGlobals( $opts, $config ); - - $user = new User(); - $options = ParserOptions::newFromUser( $user ); - - if ( isset( $opts['title'] ) ) { - $titleText = $opts['title']; - } - else { - $titleText = 'Parser test'; - } - - $noxml = isset( $opts['noxml'] ); - $local = isset( $opts['local'] ); - $preprocessor = isset( $opts['preprocessor'] ) ? $opts['preprocessor'] : null; - $parser = $this->getParser( $preprocessor ); - $title = Title::newFromText( $titleText ); - - if ( isset( $opts['pst'] ) ) { - $out = $parser->preSaveTransform( $input, $title, $user, $options ); - } elseif ( isset( $opts['msg'] ) ) { - $out = $parser->transformMsg( $input, $options ); - } elseif ( isset( $opts['section'] ) ) { - $section = $opts['section']; - $out = $parser->getSection( $input, $section ); - } elseif ( isset( $opts['replace'] ) ) { - $section = $opts['replace'][0]; - $replace = $opts['replace'][1]; - $out = $parser->replaceSection( $input, $section, $replace ); - } elseif ( isset( $opts['comment'] ) ) { - $linker = $user->getSkin(); - $out = $linker->formatComment( $input, $title, $local ); - } elseif ( isset( $opts['preload'] ) ) { - $out = $parser->getpreloadText( $input, $title, $options ); - } else { - $output = $parser->parse( $input, $title, $options, true, true, 1337 ); - $out = $output->getText(); - - if ( isset( $opts['showtitle'] ) ) { - if ( $output->getTitleText() ) { - $title = $output->getTitleText(); - } - - $out = "$title\n$out"; - } - - if ( isset( $opts['ill'] ) ) { - $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) ); - } elseif ( isset( $opts['cat'] ) ) { - global $wgOut; - - $wgOut->addCategoryLinks( $output->getCategories() ); - $cats = $wgOut->getCategoryLinks(); - - if ( isset( $cats['normal'] ) ) { - $out = $this->tidy( implode( ' ', $cats['normal'] ) ); - } else { - $out = ''; - } - } - - $result = $this->tidy( $result ); - } - - - $this->teardownGlobals(); - - if ( $result === $out && ( $noxml === true || $this->wellFormed( $out ) ) ) { - return $this->showSuccess( $desc ); - } else { - return $this->showFailure( $desc, $result, $out ); - } - } - - /** - * Use a regex to find out the value of an option - * @param $key String: name of option val to retrieve - * @param $opts Options array to look in - * @param $default Mixed: default value returned if not found - */ - private static function getOptionValue( $key, $opts, $default ) { - $key = strtolower( $key ); - - if ( isset( $opts[$key] ) ) { - return $opts[$key]; - } else { - return $default; - } - } - - private function parseOptions( $instring ) { - $opts = array(); - $lines = explode( "\n", $instring ); - // foo - // foo=bar - // foo="bar baz" - // foo=[[bar baz]] - // foo=bar,"baz quux" - $regex = '/\b - ([\w-]+) # Key - \b - (?:\s* - = # First sub-value - \s* - ( - " - [^"]* # Quoted val - " - | - \[\[ - [^]]* # Link target - \]\] - | - [\w-]+ # Plain word - ) - (?:\s* - , # Sub-vals 1..N - \s* - ( - "[^"]*" # Quoted val - | - \[\[[^]]*\]\] # Link target - | - [\w-]+ # Plain word - ) - )* - )? - /x'; - - if ( preg_match_all( $regex, $instring, $matches, PREG_SET_ORDER ) ) { - foreach ( $matches as $bits ) { - $match = array_shift( $bits ); - $key = strtolower( array_shift( $bits ) ); - if ( count( $bits ) == 0 ) { - $opts[$key] = true; - } elseif ( count( $bits ) == 1 ) { - $opts[$key] = $this->cleanupOption( array_shift( $bits ) ); - } else { - // Array! - $opts[$key] = array_map( array( $this, 'cleanupOption' ), $bits ); - } - } - } - return $opts; - } - - private function cleanupOption( $opt ) { - if ( substr( $opt, 0, 1 ) == '"' ) { - return substr( $opt, 1, -1 ); - } - - if ( substr( $opt, 0, 2 ) == '[[' ) { - return substr( $opt, 2, -2 ); - } - return $opt; - } - - /** - * Set up the global variables for a consistent environment for each test. - * Ideally this should replace the global configuration entirely. - */ - private function setupGlobals( $opts = '', $config = '' ) { - global $wgDBtype; - - # Find out values for some special options. - $lang = - self::getOptionValue( 'language', $opts, 'en' ); - $variant = - self::getOptionValue( 'variant', $opts, false ); - $maxtoclevel = - self::getOptionValue( 'wgMaxTocLevel', $opts, 999 ); - $linkHolderBatchSize = - self::getOptionValue( 'wgLinkHolderBatchSize', $opts, 1000 ); - - $settings = array( - 'wgServer' => 'http://localhost', - 'wgScript' => '/index.php', - 'wgScriptPath' => '/', - 'wgArticlePath' => '/wiki/$1', - 'wgActionPaths' => array(), - 'wgLocalFileRepo' => array( - 'class' => 'LocalRepo', - 'name' => 'local', - 'directory' => $this->uploadDir, - 'url' => 'http://example.com/images', - 'hashLevels' => 2, - 'transformVia404' => false, - ), - 'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ), - 'wgStyleSheetPath' => '/skins', - 'wgSitename' => 'MediaWiki', - 'wgServerName' => 'Britney-Spears', - 'wgLanguageCode' => $lang, - 'wgDBprefix' => $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_', - 'wgRawHtml' => isset( $opts['rawhtml'] ), - 'wgLang' => null, - 'wgContLang' => null, - 'wgNamespacesWithSubpages' => array( 0 => isset( $opts['subpage'] ) ), - 'wgMaxTocLevel' => $maxtoclevel, - 'wgCapitalLinks' => true, - 'wgNoFollowLinks' => true, - 'wgNoFollowDomainExceptions' => array(), - 'wgThumbnailScriptPath' => false, - 'wgUseImageResize' => false, - 'wgUseTeX' => isset( $opts['math'] ), - 'wgMathDirectory' => $this->uploadDir . '/math', - 'wgLocaltimezone' => 'UTC', - 'wgAllowExternalImages' => true, - 'wgUseTidy' => false, - 'wgDefaultLanguageVariant' => $variant, - 'wgVariantArticlePath' => false, - 'wgGroupPermissions' => array( '*' => array( - 'createaccount' => true, - 'read' => true, - 'edit' => true, - 'createpage' => true, - 'createtalk' => true, - ) ), - 'wgNamespaceProtection' => array( NS_MEDIAWIKI => 'editinterface' ), - 'wgDefaultExternalStore' => array(), - 'wgForeignFileRepos' => array(), - 'wgLinkHolderBatchSize' => $linkHolderBatchSize, - 'wgExperimentalHtmlIds' => false, - 'wgExternalLinkTarget' => false, - 'wgAlwaysUseTidy' => false, - 'wgHtml5' => true, - 'wgWellFormedXml' => true, - 'wgAllowMicrodataAttributes' => true, - ); - - if ( $config ) { - $configLines = explode( "\n", $config ); - - foreach ( $configLines as $line ) { - list( $var, $value ) = explode( '=', $line, 2 ); - - $settings[$var] = eval( "return $value;" ); - } - } - - $this->savedGlobals = array(); - - foreach ( $settings as $var => $val ) { - if ( array_key_exists( $var, $GLOBALS ) ) { - $this->savedGlobals[$var] = $GLOBALS[$var]; - } - - $GLOBALS[$var] = $val; - } - - $langObj = Language::factory( $lang ); - $GLOBALS['wgLang'] = $langObj; - $GLOBALS['wgContLang'] = $langObj; - $GLOBALS['wgMemc'] = new FakeMemCachedClient; - $GLOBALS['wgOut'] = new OutputPage; - - global $wgHooks; - - $wgHooks['ParserTestParser'][] = 'ParserTestParserHook::setup'; - $wgHooks['ParserTestParser'][] = 'ParserTestStaticParserHook::setup'; - $wgHooks['ParserGetVariableValueTs'][] = 'ParserTest::getFakeTimestamp'; - - MagicWord::clearCache(); - - global $wgUser; - $wgUser = new User(); - } - - /** - * List of temporary tables to create, without prefix. - * Some of these probably aren't necessary. - */ - private function listTables() { - global $wgDBtype; - - $tables = array( 'user', 'user_properties', 'page', 'page_restrictions', - 'protected_titles', 'revision', 'text', 'pagelinks', 'imagelinks', - 'categorylinks', 'templatelinks', 'externallinks', 'langlinks', 'iwlinks', - 'site_stats', 'hitcounter', 'ipblocks', 'image', 'oldimage', - 'recentchanges', 'watchlist', 'math', 'interwiki', 'logging', - 'querycache', 'objectcache', 'job', 'l10n_cache', 'redirect', 'querycachetwo', - 'archive', 'user_groups', 'page_props', 'category', 'msg_resource', 'msg_resource_links' - ); - - if ( in_array( $wgDBtype, array( 'mysql', 'sqlite' ) ) ) - array_push( $tables, 'searchindex' ); - - // Allow extensions to add to the list of tables to duplicate; - // may be necessary if they hook into page save or other code - // which will require them while running tests. - wfRunHooks( 'ParserTestTables', array( &$tables ) ); - - return $tables; - } - - /** - * Set up a temporary set of wiki tables to work with for the tests. - * Currently this will only be done once per run, and any changes to - * the db will be visible to later tests in the run. - */ - public function setupDatabase() { - global $wgDBprefix, $wgDBtype; - - if ( $this->databaseSetupDone ) { - return; - } - - if ( $wgDBprefix === 'parsertest_' || ( $wgDBtype == 'oracle' && $wgDBprefix === 'pt_' ) ) { - throw new MWException( 'setupDatabase should be called before setupGlobals' ); - } - - $this->databaseSetupDone = true; - $this->oldTablePrefix = $wgDBprefix; - - # SqlBagOStuff broke when using temporary tables on r40209 (bug 15892). - # It seems to have been fixed since (r55079?). - # If it fails, $wgCaches[CACHE_DB] = new HashBagOStuff(); should work around it. - - # CREATE TEMPORARY TABLE breaks if there is more than one server - if ( wfGetLB()->getServerCount() != 1 ) { - $this->useTemporaryTables = false; - } - - $temporary = $this->useTemporaryTables || $wgDBtype == 'postgres'; - - $db = wfGetDB( DB_MASTER ); - $tables = $this->listTables(); - - foreach ( $tables as $tbl ) { - # Clean up from previous aborted run. So that table escaping - # works correctly across DB engines, we need to change the pre- - # fix back and forth so tableName() works right. - $this->changePrefix( $this->oldTablePrefix ); - $oldTableName = $db->tableName( $tbl ); - $this->changePrefix( $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_' ); - $newTableName = $db->tableName( $tbl ); - - if ( $wgDBtype == 'mysql' ) { - $db->query( "DROP TABLE IF EXISTS $newTableName" ); - } elseif ( in_array( $wgDBtype, array( 'postgres', 'oracle' ) ) ) { - /* DROPs wouldn't work due to Foreign Key Constraints (bug 14990, r58669) - * Use "DROP TABLE IF EXISTS $newTableName CASCADE" for postgres? That - * syntax would also work for mysql. - */ - } elseif ( $db->tableExists( $tbl ) ) { - $db->query( "DROP TABLE $newTableName" ); - } - - # Create new table - $db->duplicateTableStructure( $oldTableName, $newTableName, $temporary ); - } - - if ( $wgDBtype == 'oracle' ) - $db->query( 'BEGIN FILL_WIKI_INFO; END;' ); - - $this->changePrefix( $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_' ); - - # Hack: insert a few Wikipedia in-project interwiki prefixes, - # for testing inter-language links - $db->insert( 'interwiki', array( - array( 'iw_prefix' => 'wikipedia', - 'iw_url' => 'http://en.wikipedia.org/wiki/$1', - 'iw_api' => '', - 'iw_wikiid' => '', - 'iw_local' => 0 ), - array( 'iw_prefix' => 'meatball', - 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1', - 'iw_api' => '', - 'iw_wikiid' => '', - 'iw_local' => 0 ), - array( 'iw_prefix' => 'zh', - 'iw_url' => 'http://zh.wikipedia.org/wiki/$1', - 'iw_api' => '', - 'iw_wikiid' => '', - 'iw_local' => 1 ), - array( 'iw_prefix' => 'es', - 'iw_url' => 'http://es.wikipedia.org/wiki/$1', - 'iw_api' => '', - 'iw_wikiid' => '', - 'iw_local' => 1 ), - array( 'iw_prefix' => 'fr', - 'iw_url' => 'http://fr.wikipedia.org/wiki/$1', - 'iw_api' => '', - 'iw_wikiid' => '', - 'iw_local' => 1 ), - array( 'iw_prefix' => 'ru', - 'iw_url' => 'http://ru.wikipedia.org/wiki/$1', - 'iw_api' => '', - 'iw_wikiid' => '', - 'iw_local' => 1 ), - ) ); - - - if ( $wgDBtype == 'oracle' ) { - # Insert 0 user to prevent FK violations - - # Anonymous user - $db->insert( 'user', array( - 'user_id' => 0, - 'user_name' => 'Anonymous' ) ); - } - - # Update certain things in site_stats - $db->insert( 'site_stats', array( 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ) ); - - # Reinitialise the LocalisationCache to match the database state - Language::getLocalisationCache()->unloadAll(); - - # Make a new message cache - global $wgMessageCache, $wgMemc; - $wgMessageCache = new MessageCache( $wgMemc, true, 3600 ); - - $this->uploadDir = $this->setupUploadDir(); - $user = User::createNew( 'WikiSysop' ); - $image = wfLocalFile( Title::makeTitle( NS_FILE, 'Foobar.jpg' ) ); - $image->recordUpload2( '', 'Upload of some lame file', 'Some lame file', array( - 'size' => 12345, - 'width' => 1941, - 'height' => 220, - 'bits' => 24, - 'media_type' => MEDIATYPE_BITMAP, - 'mime' => 'image/jpeg', - 'metadata' => serialize( array() ), - 'sha1' => sha1( '' ), - 'fileExists' => true - ), $db->timestamp( '20010115123500' ), $user ); - - # This image will be blacklisted in [[MediaWiki:Bad image list]] - $image = wfLocalFile( Title::makeTitle( NS_FILE, 'Bad.jpg' ) ); - $image->recordUpload2( '', 'zomgnotcensored', 'Borderline image', array( - 'size' => 12345, - 'width' => 320, - 'height' => 240, - 'bits' => 24, - 'media_type' => MEDIATYPE_BITMAP, - 'mime' => 'image/jpeg', - 'metadata' => serialize( array() ), - 'sha1' => sha1( '' ), - 'fileExists' => true - ), $db->timestamp( '20010115123500' ), $user ); - } - - /** - * Change the table prefix on all open DB connections/ - */ - protected function changePrefix( $prefix ) { - global $wgDBprefix; - wfGetLBFactory()->forEachLB( array( $this, 'changeLBPrefix' ), array( $prefix ) ); - $wgDBprefix = $prefix; - } - - public function changeLBPrefix( $lb, $prefix ) { - $lb->forEachOpenConnection( array( $this, 'changeDBPrefix' ), array( $prefix ) ); - } - - public function changeDBPrefix( $db, $prefix ) { - $db->tablePrefix( $prefix ); - } - - public function teardownDatabase() { - global $wgDBtype; - - if ( !$this->databaseSetupDone ) { - return; - } - $this->teardownUploadDir( $this->uploadDir ); - - $this->changePrefix( $this->oldTablePrefix ); - $this->databaseSetupDone = false; - - if ( $this->useTemporaryTables ) { - # Don't need to do anything - return; - } - - $tables = $this->listTables(); - $db = wfGetDB( DB_MASTER ); - - foreach ( $tables as $table ) { - $sql = $wgDBtype == 'oracle' ? "DROP TABLE pt_$table DROP CONSTRAINTS" : "DROP TABLE `parsertest_$table`"; - $db->query( $sql ); - } - - if ( $wgDBtype == 'oracle' ) - $db->query( 'BEGIN FILL_WIKI_INFO; END;' ); - } - - /** - * Create a dummy uploads directory which will contain a couple - * of files in order to pass existence tests. - * - * @return String: the directory - */ - private function setupUploadDir() { - global $IP; - - if ( $this->keepUploads ) { - $dir = wfTempDir() . '/mwParser-images'; - - if ( is_dir( $dir ) ) { - return $dir; - } - } else { - $dir = wfTempDir() . "/mwParser-" . mt_rand() . "-images"; - } - - // wfDebug( "Creating upload directory $dir\n" ); - if ( file_exists( $dir ) ) { - wfDebug( "Already exists!\n" ); - return $dir; - } - - wfMkdirParents( $dir . '/3/3a' ); - copy( "$IP/skins/monobook/headbg.jpg", "$dir/3/3a/Foobar.jpg" ); - wfMkdirParents( $dir . '/0/09' ); - copy( "$IP/skins/monobook/headbg.jpg", "$dir/0/09/Bad.jpg" ); - - return $dir; - } - - /** - * Restore default values and perform any necessary clean-up - * after each test runs. - */ - private function teardownGlobals() { - RepoGroup::destroySingleton(); - LinkCache::singleton()->clear(); - - foreach ( $this->savedGlobals as $var => $val ) { - $GLOBALS[$var] = $val; - } - } - - /** - * Remove the dummy uploads directory - */ - private function teardownUploadDir( $dir ) { - if ( $this->keepUploads ) { - return; - } - - // delete the files first, then the dirs. - self::deleteFiles( - array ( - "$dir/3/3a/Foobar.jpg", - "$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg", - "$dir/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg", - "$dir/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg", - "$dir/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg", - - "$dir/0/09/Bad.jpg", - - "$dir/math/f/a/5/fa50b8b616463173474302ca3e63586b.png", - ) - ); - - self::deleteDirs( - array ( - "$dir/3/3a", - "$dir/3", - "$dir/thumb/6/65", - "$dir/thumb/6", - "$dir/thumb/3/3a/Foobar.jpg", - "$dir/thumb/3/3a", - "$dir/thumb/3", - - "$dir/0/09/", - "$dir/0/", - "$dir/thumb", - "$dir/math/f/a/5", - "$dir/math/f/a", - "$dir/math/f", - "$dir/math", - "$dir", - ) - ); - } - - /** - * Delete the specified files, if they exist. - * @param $files Array: full paths to files to delete. - */ - private static function deleteFiles( $files ) { - foreach ( $files as $file ) { - if ( file_exists( $file ) ) { - unlink( $file ); - } - } - } - - /** - * Delete the specified directories, if they exist. Must be empty. - * @param $dirs Array: full paths to directories to delete. - */ - private static function deleteDirs( $dirs ) { - foreach ( $dirs as $dir ) { - if ( is_dir( $dir ) ) { - rmdir( $dir ); - } - } - } - - /** - * "Running test $desc..." - */ - protected function showTesting( $desc ) { - print "Running test $desc... "; - } - - /** - * Print a happy success message. - * - * @param $desc String: the test name - * @return Boolean - */ - protected function showSuccess( $desc ) { - if ( $this->showProgress ) { - print $this->term->color( '1;32' ) . 'PASSED' . $this->term->reset() . "\n"; - } - - return true; - } - - /** - * Print a failure message and provide some explanatory output - * about what went wrong if so configured. - * - * @param $desc String: the test name - * @param $result String: expected HTML output - * @param $html String: actual HTML output - * @return Boolean - */ - protected function showFailure( $desc, $result, $html ) { - if ( $this->showFailure ) { - if ( !$this->showProgress ) { - # In quiet mode we didn't show the 'Testing' message before the - # test, in case it succeeded. Show it now: - $this->showTesting( $desc ); - } - - print $this->term->color( '31' ) . 'FAILED!' . $this->term->reset() . "\n"; - - if ( $this->showOutput ) { - print "--- Expected ---\n$result\n--- Actual ---\n$html\n"; - } - - if ( $this->showDiffs ) { - print $this->quickDiff( $result, $html ); - if ( !$this->wellFormed( $html ) ) { - print "XML error: $this->mXmlError\n"; - } - } - } - - return false; - } - - /** - * Run given strings through a diff and return the (colorized) output. - * Requires writable /tmp directory and a 'diff' command in the PATH. - * - * @param $input String - * @param $output String - * @param $inFileTail String: tailing for the input file name - * @param $outFileTail String: tailing for the output file name - * @return String - */ - protected function quickDiff( $input, $output, $inFileTail = 'expected', $outFileTail = 'actual' ) { - $prefix = wfTempDir() . "/mwParser-" . mt_rand(); - - $infile = "$prefix-$inFileTail"; - $this->dumpToFile( $input, $infile ); - - $outfile = "$prefix-$outFileTail"; - $this->dumpToFile( $output, $outfile ); - - $diff = `diff -au $infile $outfile`; - unlink( $infile ); - unlink( $outfile ); - - return $this->colorDiff( $diff ); - } - - /** - * Write the given string to a file, adding a final newline. - * - * @param $data String - * @param $filename String - */ - private function dumpToFile( $data, $filename ) { - $file = fopen( $filename, "wt" ); - fwrite( $file, $data . "\n" ); - fclose( $file ); - } - - /** - * Colorize unified diff output if set for ANSI color output. - * Subtractions are colored blue, additions red. - * - * @param $text String - * @return String - */ - protected function colorDiff( $text ) { - return preg_replace( - array( '/^(-.*)$/m', '/^(\+.*)$/m' ), - array( $this->term->color( 34 ) . '$1' . $this->term->reset(), - $this->term->color( 31 ) . '$1' . $this->term->reset() ), - $text ); - } - - /** - * Show "Reading tests from ..." - * - * @param $path String - */ - public function showRunFile( $path ) { - print $this->term->color( 1 ) . - "Reading tests from \"$path\"..." . - $this->term->reset() . - "\n"; - } - - /** - * Insert a temporary test article - * @param $name String: the title, including any prefix - * @param $text String: the article text - * @param $line Integer: the input line number, for reporting errors - */ - public function addArticle( $name, $text, $line ) { - global $wgCapitalLinks; - $oldCapitalLinks = $wgCapitalLinks; - $wgCapitalLinks = true; // We only need this from SetupGlobals() See r70917#c8637 - - $title = Title::newFromText( $name ); - - if ( is_null( $title ) ) { - wfDie( "invalid title at line $line\n" ); - } - - $aid = $title->getArticleID( GAID_FOR_UPDATE ); - - if ( $aid != 0 ) { - wfDie( "duplicate article '$name' at line $line\n" ); - } - - $art = new Article( $title ); - $art->insertNewArticle( $text, '', false, false ); - - $wgCapitalLinks = $oldCapitalLinks; - } - - /** - * Steal a callback function from the primary parser, save it for - * application to our scary parser. If the hook is not installed, - * abort processing of this file. - * - * @param $name String - * @return Bool true if tag hook is present - */ - public function requireHook( $name ) { - global $wgParser; - - $wgParser->firstCallInit( ); // make sure hooks are loaded. - - if ( isset( $wgParser->mTagHooks[$name] ) ) { - $this->hooks[$name] = $wgParser->mTagHooks[$name]; - } else { - echo " This test suite requires the '$name' hook extension, skipping.\n"; - return false; - } - - return true; - } - - /** - * Steal a callback function from the primary parser, save it for - * application to our scary parser. If the hook is not installed, - * abort processing of this file. - * - * @param $name String - * @return Bool true if function hook is present - */ - public function requireFunctionHook( $name ) { - global $wgParser; - - $wgParser->firstCallInit( ); // make sure hooks are loaded. - - if ( isset( $wgParser->mFunctionHooks[$name] ) ) { - $this->functionHooks[$name] = $wgParser->mFunctionHooks[$name]; - } else { - echo " This test suite requires the '$name' function hook extension, skipping.\n"; - return false; - } - - return true; - } - - /* - * Run the "tidy" command on text if the $wgUseTidy - * global is true - * - * @param $text String: the text to tidy - * @return String - * @static - */ - private function tidy( $text ) { - global $wgUseTidy; - - if ( $wgUseTidy ) { - $text = MWTidy::tidy( $text ); - } - - return $text; - } - - private function wellFormed( $text ) { - $html = - Sanitizer::hackDocType() . - '' . - $text . - ''; - - $parser = xml_parser_create( "UTF-8" ); - - # case folding violates XML standard, turn it off - xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false ); - - if ( !xml_parse( $parser, $html, true ) ) { - $err = xml_error_string( xml_get_error_code( $parser ) ); - $position = xml_get_current_byte_index( $parser ); - $fragment = $this->extractFragment( $html, $position ); - $this->mXmlError = "$err at byte $position:\n$fragment"; - xml_parser_free( $parser ); - - return false; - } - - xml_parser_free( $parser ); - - return true; - } - - private function extractFragment( $text, $position ) { - $start = max( 0, $position - 10 ); - $before = $position - $start; - $fragment = '...' . - $this->term->color( 34 ) . - substr( $text, $start, $before ) . - $this->term->color( 0 ) . - $this->term->color( 31 ) . - $this->term->color( 1 ) . - substr( $text, $position, 1 ) . - $this->term->color( 0 ) . - $this->term->color( 34 ) . - substr( $text, $position + 1, 9 ) . - $this->term->color( 0 ) . - '...'; - $display = str_replace( "\n", ' ', $fragment ); - $caret = ' ' . - str_repeat( ' ', $before ) . - $this->term->color( 31 ) . - '^' . - $this->term->color( 0 ); - - return "$display\n$caret"; - } - - static function getFakeTimestamp( &$parser, &$ts ) { - $ts = 123; - return true; - } -} - -class AnsiTermColorer { - function __construct() { - } - - /** - * Return ANSI terminal escape code for changing text attribs/color - * - * @param $color String: semicolon-separated list of attribute/color codes - * @return String - */ - public function color( $color ) { - global $wgCommandLineDarkBg; - - $light = $wgCommandLineDarkBg ? "1;" : "0;"; - - return "\x1b[{$light}{$color}m"; - } - - /** - * Return ANSI terminal escape code for restoring default text attributes - * - * @return String - */ - public function reset() { - return $this->color( 0 ); - } -} - -/* A colour-less terminal */ -class DummyTermColorer { - public function color( $color ) { - return ''; - } - - public function reset() { - return ''; - } -} - -class TestRecorder { - var $parent; - var $term; - - function __construct( $parent ) { - $this->parent = $parent; - $this->term = $parent->term; - } - - function start() { - $this->total = 0; - $this->success = 0; - } - - function record( $test, $result ) { - $this->total++; - $this->success += ( $result ? 1 : 0 ); - } - - function end() { - // dummy - } - - function report() { - if ( $this->total > 0 ) { - $this->reportPercentage( $this->success, $this->total ); - } else { - wfDie( "No tests found.\n" ); - } - } - - function reportPercentage( $success, $total ) { - $ratio = wfPercent( 100 * $success / $total ); - print $this->term->color( 1 ) . "Passed $success of $total tests ($ratio)... "; - - if ( $success == $total ) { - print $this->term->color( 32 ) . "ALL TESTS PASSED!"; - } else { - $failed = $total - $success ; - print $this->term->color( 31 ) . "$failed tests failed!"; - } - - print $this->term->reset() . "\n"; - - return ( $success == $total ); - } -} - -class DbTestPreviewer extends TestRecorder { - protected $lb; // /< Database load balancer - protected $db; // /< Database connection to the main DB - protected $curRun; // /< run ID number for the current run - protected $prevRun; // /< run ID number for the previous run, if any - protected $results; // /< Result array - - /** - * This should be called before the table prefix is changed - */ - function __construct( $parent ) { - parent::__construct( $parent ); - - $this->lb = wfGetLBFactory()->newMainLB(); - // This connection will have the wiki's table prefix, not parsertest_ - $this->db = $this->lb->getConnection( DB_MASTER ); - } - - /** - * Set up result recording; insert a record for the run with the date - * and all that fun stuff - */ - function start() { - parent::start(); - - if ( ! $this->db->tableExists( 'testrun' ) - or ! $this->db->tableExists( 'testitem' ) ) - { - print "WARNING> `testrun` table not found in database.\n"; - $this->prevRun = false; - } else { - // We'll make comparisons against the previous run later... - $this->prevRun = $this->db->selectField( 'testrun', 'MAX(tr_id)' ); - } - - $this->results = array(); - } - - function record( $test, $result ) { - parent::record( $test, $result ); - $this->results[$test] = $result; - } - - function report() { - if ( $this->prevRun ) { - // f = fail, p = pass, n = nonexistent - // codes show before then after - $table = array( - 'fp' => 'previously failing test(s) now PASSING! :)', - 'pn' => 'previously PASSING test(s) removed o_O', - 'np' => 'new PASSING test(s) :)', - - 'pf' => 'previously passing test(s) now FAILING! :(', - 'fn' => 'previously FAILING test(s) removed O_o', - 'nf' => 'new FAILING test(s) :(', - 'ff' => 'still FAILING test(s) :(', - ); - - $prevResults = array(); - - $res = $this->db->select( 'testitem', array( 'ti_name', 'ti_success' ), - array( 'ti_run' => $this->prevRun ), __METHOD__ ); - - foreach ( $res as $row ) { - if ( !$this->parent->regex - || preg_match( "/{$this->parent->regex}/i", $row->ti_name ) ) - { - $prevResults[$row->ti_name] = $row->ti_success; - } - } - - $combined = array_keys( $this->results + $prevResults ); - - # Determine breakdown by change type - $breakdown = array(); - foreach ( $combined as $test ) { - if ( !isset( $prevResults[$test] ) ) { - $before = 'n'; - } elseif ( $prevResults[$test] == 1 ) { - $before = 'p'; - } else /* if ( $prevResults[$test] == 0 )*/ { - $before = 'f'; - } - - if ( !isset( $this->results[$test] ) ) { - $after = 'n'; - } elseif ( $this->results[$test] == 1 ) { - $after = 'p'; - } else /*if ( $this->results[$test] == 0 ) */ { - $after = 'f'; - } - - $code = $before . $after; - - if ( isset( $table[$code] ) ) { - $breakdown[$code][$test] = $this->getTestStatusInfo( $test, $after ); - } - } - - # Write out results - foreach ( $table as $code => $label ) { - if ( !empty( $breakdown[$code] ) ) { - $count = count( $breakdown[$code] ); - printf( "\n%4d %s\n", $count, $label ); - - foreach ( $breakdown[$code] as $differing_test_name => $statusInfo ) { - print " * $differing_test_name [$statusInfo]\n"; - } - } - } - } else { - print "No previous test runs to compare against.\n"; - } - - print "\n"; - parent::report(); - } - - /** - * Returns a string giving information about when a test last had a status change. - * Could help to track down when regressions were introduced, as distinct from tests - * which have never passed (which are more change requests than regressions). - */ - private function getTestStatusInfo( $testname, $after ) { - // If we're looking at a test that has just been removed, then say when it first appeared. - if ( $after == 'n' ) { - $changedRun = $this->db->selectField ( 'testitem', - 'MIN(ti_run)', - array( 'ti_name' => $testname ), - __METHOD__ ); - $appear = $this->db->selectRow ( 'testrun', - array( 'tr_date', 'tr_mw_version' ), - array( 'tr_id' => $changedRun ), - __METHOD__ ); - - return "First recorded appearance: " - . date( "d-M-Y H:i:s", strtotime ( $appear->tr_date ) ) - . ", " . $appear->tr_mw_version; - } - - // Otherwise, this test has previous recorded results. - // See when this test last had a different result to what we're seeing now. - $conds = array( - 'ti_name' => $testname, - 'ti_success' => ( $after == 'f' ? "1" : "0" ) ); - - if ( $this->curRun ) { - $conds[] = "ti_run != " . $this->db->addQuotes ( $this->curRun ); - } - - $changedRun = $this->db->selectField ( 'testitem', 'MAX(ti_run)', $conds, __METHOD__ ); - - // If no record of ever having had a different result. - if ( is_null ( $changedRun ) ) { - if ( $after == "f" ) { - return "Has never passed"; - } else { - return "Has never failed"; - } - } - - // Otherwise, we're looking at a test whose status has changed. - // (i.e. it used to work, but now doesn't; or used to fail, but is now fixed.) - // In this situation, give as much info as we can as to when it changed status. - $pre = $this->db->selectRow ( 'testrun', - array( 'tr_date', 'tr_mw_version' ), - array( 'tr_id' => $changedRun ), - __METHOD__ ); - $post = $this->db->selectRow ( 'testrun', - array( 'tr_date', 'tr_mw_version' ), - array( "tr_id > " . $this->db->addQuotes ( $changedRun ) ), - __METHOD__, - array( "LIMIT" => 1, "ORDER BY" => 'tr_id' ) - ); - - if ( $post ) { - $postDate = date( "d-M-Y H:i:s", strtotime ( $post->tr_date ) ) . ", {$post->tr_mw_version}"; - } else { - $postDate = 'now'; - } - - return ( $after == "f" ? "Introduced" : "Fixed" ) . " between " - . date( "d-M-Y H:i:s", strtotime ( $pre->tr_date ) ) . ", " . $pre->tr_mw_version - . " and $postDate"; - - } - - /** - * Commit transaction and clean up for result recording - */ - function end() { - $this->lb->commitMasterChanges(); - $this->lb->closeAll(); - parent::end(); - } - -} - -class DbTestRecorder extends DbTestPreviewer { - var $version; - - /** - * Set up result recording; insert a record for the run with the date - * and all that fun stuff - */ - function start() { - global $wgDBtype; - $this->db->begin(); - - if ( ! $this->db->tableExists( 'testrun' ) - or ! $this->db->tableExists( 'testitem' ) ) - { - print "WARNING> `testrun` table not found in database. Trying to create table.\n"; - if ( $wgDBtype === 'postgres' ) { - $this->db->sourceFile( dirname( __FILE__ ) . '/testRunner.postgres.sql' ); - } elseif ( $wgDBtype === 'oracle' ) { - $this->db->sourceFile( dirname( __FILE__ ) . '/testRunner.ora.sql' ); - } else { - $this->db->sourceFile( dirname( __FILE__ ) . '/testRunner.sql' ); - } - - echo "OK, resuming.\n"; - } - - parent::start(); - - $this->db->insert( 'testrun', - array( - 'tr_date' => $this->db->timestamp(), - 'tr_mw_version' => $this->version, - 'tr_php_version' => phpversion(), - 'tr_db_version' => $this->db->getServerVersion(), - 'tr_uname' => php_uname() - ), - __METHOD__ ); - if ( $wgDBtype === 'postgres' ) { - $this->curRun = $this->db->currentSequenceValue( 'testrun_id_seq' ); - } else { - $this->curRun = $this->db->insertId(); - } - } - - /** - * Record an individual test item's success or failure to the db - * - * @param $test String - * @param $result Boolean - */ - function record( $test, $result ) { - parent::record( $test, $result ); - - $this->db->insert( 'testitem', - array( - 'ti_run' => $this->curRun, - 'ti_name' => $test, - 'ti_success' => $result ? 1 : 0, - ), - __METHOD__ ); - } -} - -class RemoteTestRecorder extends TestRecorder { - function start() { - parent::start(); - - $this->results = array(); - $this->ping( 'running' ); - } - - function record( $test, $result ) { - parent::record( $test, $result ); - $this->results[$test] = (bool)$result; - } - - function end() { - $this->ping( 'complete', $this->results ); - parent::end(); - } - - /** - * Inform a CodeReview instance that we've started or completed a test run... - * - * @param $status string: "running" - tell it we've started - * "complete" - provide test results array - * "abort" - something went horribly awry - * @param $results array of test name => true/false - */ - function ping( $status, $results = false ) { - global $wgParserTestRemote, $IP; - - $remote = $wgParserTestRemote; - $revId = SpecialVersion::getSvnRevision( $IP ); - $jsonResults = FormatJson::encode( $results ); - - if ( !$remote ) { - print "Can't do remote upload without configuring \$wgParserTestRemote!\n"; - exit( 1 ); - } - - // Generate a hash MAC to validate our credentials - $message = array( - $remote['repo'], - $remote['suite'], - $revId, - $status, - ); - - if ( $status == "complete" ) { - $message[] = $jsonResults; - } - $hmac = hash_hmac( "sha1", implode( "|", $message ), $remote['secret'] ); - - $postData = array( - 'action' => 'codetestupload', - 'format' => 'json', - 'repo' => $remote['repo'], - 'suite' => $remote['suite'], - 'rev' => $revId, - 'status' => $status, - 'hmac' => $hmac, - ); - - if ( $status == "complete" ) { - $postData['results'] = $jsonResults; - } - - $response = $this->post( $remote['api-url'], $postData ); - - if ( $response === false ) { - print "CodeReview info upload failed to reach server.\n"; - exit( 1 ); - } - - $responseData = FormatJson::decode( $response, true ); - - if ( !is_array( $responseData ) ) { - print "CodeReview API response not recognized...\n"; - wfDebug( "Unrecognized CodeReview API response: $response\n" ); - exit( 1 ); - } - - if ( isset( $responseData['error'] ) ) { - $code = $responseData['error']['code']; - $info = $responseData['error']['info']; - print "CodeReview info upload failed: $code $info\n"; - exit( 1 ); - } - } - - function post( $url, $data ) { - return Http::post( $url, array( 'postData' => $data ) ); - } -} - -class TestFileIterator implements Iterator { - private $file; - private $fh; - private $parser; - private $index = 0; - private $test; - private $lineNum; - private $eof; - - function __construct( $file, $parser = null ) { - global $IP; - - $this->file = $file; - $this->fh = fopen( $this->file, "rt" ); - - if ( !$this->fh ) { - wfDie( "Couldn't open file '$file'\n" ); - } - - $this->parser = $parser; - - if ( $this->parser ) { - $this->parser->showRunFile( wfRelativePath( $this->file, $IP ) ); - } - - $this->lineNum = $this->index = 0; - } - - function setParser( ParserTest $parser ) { - $this->parser = $parser; - } - - function rewind() { - if ( fseek( $this->fh, 0 ) ) { - wfDie( "Couldn't fseek to the start of '$this->file'\n" ); - } - - $this->index = -1; - $this->lineNum = 0; - $this->eof = false; - $this->next(); - - return true; - } - - function current() { - return $this->test; - } - - function key() { - return $this->index; - } - - function next() { - if ( $this->readNextTest() ) { - $this->index++; - return true; - } else { - $this->eof = true; - } - } - - function valid() { - return $this->eof != true; - } - - function readNextTest() { - $data = array(); - $section = null; - - while ( false !== ( $line = fgets( $this->fh ) ) ) { - $this->lineNum++; - $matches = array(); - - if ( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) { - $section = strtolower( $matches[1] ); - - if ( $section == 'endarticle' ) { - if ( !isset( $data['text'] ) ) { - wfDie( "'endarticle' without 'text' at line {$this->lineNum} of $this->file\n" ); - } - - if ( !isset( $data['article'] ) ) { - 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 ); - } - - $data = array(); - $section = null; - - continue; - } - - if ( $section == 'endhooks' ) { - if ( !isset( $data['hooks'] ) ) { - wfDie( "'endhooks' without 'hooks' at line {$this->lineNum} of $this->file\n" ); - } - - foreach ( explode( "\n", $data['hooks'] ) as $line ) { - $line = trim( $line ); - - if ( $line ) { - if ( $this->parser && !$this->parser->requireHook( $line ) ) { - return false; - } - } - } - - $data = array(); - $section = null; - - continue; - } - - if ( $section == 'endfunctionhooks' ) { - if ( !isset( $data['functionhooks'] ) ) { - wfDie( "'endfunctionhooks' without 'functionhooks' at line {$this->lineNum} of $this->file\n" ); - } - - foreach ( explode( "\n", $data['functionhooks'] ) as $line ) { - $line = trim( $line ); - - if ( $line ) { - if ( $this->parser && !$this->parser->requireFunctionHook( $line ) ) { - return false; - } - } - } - - $data = array(); - $section = null; - - continue; - } - - if ( $section == 'end' ) { - if ( !isset( $data['test'] ) ) { - wfDie( "'end' without 'test' at line {$this->lineNum} of $this->file\n" ); - } - - if ( !isset( $data['input'] ) ) { - wfDie( "'end' without 'input' at line {$this->lineNum} of $this->file\n" ); - } - - if ( !isset( $data['result'] ) ) { - wfDie( "'end' without 'result' at line {$this->lineNum} of $this->file\n" ); - } - - if ( !isset( $data['options'] ) ) { - $data['options'] = ''; - } - - if ( !isset( $data['config'] ) ) - $data['config'] = ''; - - if ( $this->parser - && ( ( preg_match( '/\\bdisabled\\b/i', $data['options'] ) && !$this->parser->runDisabled ) - || !preg_match( "/" . $this->parser->regex . "/i", $data['test'] ) ) ) { - # disabled test - $data = array(); - $section = null; - - continue; - } - - global $wgUseTeX; - - if ( $this->parser && - preg_match( '/\\bmath\\b/i', $data['options'] ) && !$wgUseTeX ) { - # don't run math tests if $wgUseTeX is set to false in LocalSettings - $data = array(); - $section = null; - - continue; - } - - 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'] ) ); - } else { - $this->test['test'] = $data['test']; - } - - return true; - } - - if ( isset ( $data[$section] ) ) { - wfDie( "duplicate section '$section' at line {$this->lineNum} of $this->file\n" ); - } - - $data[$section] = ''; - - continue; - } - - if ( $section ) { - $data[$section] .= $line; - } - } - - return false; - } -} diff --git a/maintenance/parserTests.php b/maintenance/parserTests.php deleted file mode 100644 index 5a3710349d..0000000000 --- a/maintenance/parserTests.php +++ /dev/null @@ -1,91 +0,0 @@ - -# http://www.mediawiki.org/ -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# http://www.gnu.org/copyleft/gpl.html - -/** - * @file - * @ingroup Maintenance - */ - -$options = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record', 'run-disabled' ); -$optionsWithArgs = array( 'regex', 'seed', 'setversion' ); - -require_once( dirname( __FILE__ ) . '/commandLine.inc' ); -require_once( dirname( __FILE__ ) . '/parserTests.inc' ); - -if ( isset( $options['help'] ) ) { - echo << Run test cases from a custom file instead of parserTests.txt - --record Record tests in database - --compare Compare with recorded results, without updating the database. - --setversion When using --record, set the version string to use (useful - with git-svn so that you can get the exact revision) - --keep-uploads Re-use the same upload directory for each test, don't delete it - --fuzz Do a fuzz test instead of a normal test - --seed Start the fuzz test from the specified seed - --help Show this help message - --run-disabled run disabled tests - --upload Upload test results to remote wiki (per \$wgParserTestRemote) - -ENDS; - exit( 0 ); -} - -# Cases of weird db corruption were encountered when running tests on earlyish -# versions of SQLite -if ( $wgDBtype == 'sqlite' ) { - $db = wfGetDB( DB_MASTER ); - $version = $db->getServerVersion(); - if ( version_compare( $version, '3.6' ) < 0 ) { - die( "Parser tests require SQLite version 3.6 or later, you have $version\n" ); - } -} - -# There is a convention that the parser should never -# refer to $wgTitle directly, but instead use the title -# passed to it. -$wgTitle = Title::newFromText( 'Parser test script do not use' ); -$tester = new ParserTest($options); - -if ( isset( $options['file'] ) ) { - $files = array( $options['file'] ); -} else { - // Default parser tests and any set from extensions or local config - $files = $wgParserTestFiles; -} - -# Print out software version to assist with locating regressions -$version = SpecialVersion::getVersion(); -echo( "This is MediaWiki version {$version}.\n\n" ); - -if ( isset( $options['fuzz'] ) ) { - $tester->fuzzTest( $files ); -} else { - $ok = $tester->runTestsFromFiles( $files ); - exit ( $ok ? 0 : 1 ); -} diff --git a/maintenance/parserTests.txt b/maintenance/parserTests.txt deleted file mode 100644 index 43ac4bfc8d..0000000000 --- a/maintenance/parserTests.txt +++ /dev/null @@ -1,8224 +0,0 @@ -# MediaWiki Parser test cases -# Some taken from http://meta.wikimedia.org/wiki/Parser_testing -# All (C) their respective authors and released under the GPL -# -# The syntax should be fairly self-explanatory. -# -# Currently supported test options: -# One of the following three: -# -# (default) generate HTML output -# pst apply pre-save transform -# msg apply message transform -# -# Plus any combination of these: -# -# cat add category links -# ill add inter-language links -# subpage enable subpages (disabled by default) -# noxml don't check for XML well formdness -# title=[[XXX]] run test using article title XXX -# language=XXX set content language to XXX for this test -# variant=XXX set the variant of language for this test (eg zh-tw) -# disabled do not run test -# showtitle make the first line the title -# comment run through Linker::formatComment() instead of main parser -# local format section links in edit comment text as local links -# -# For testing purposes, temporary articles can created: -# !!article / NAMESPACE:TITLE / !!text / ARTICLE TEXT / !!endarticle -# where '/' denotes a newline. - -# This is the standard article assumed to exist. -!! article -Main Page -!! text -blah blah -!! endarticle - -!!article -Template:Foo -!!text -FOO -!!endarticle - -!! article -Template:Blank -!! text -!! endarticle - -!! article -Template:! -!! text -| -!! endarticle - -!!article -MediaWiki:bad image list -!!text -* [[File:Bad.jpg]] except [[Nasty page]] -!!endarticle - -### -### Basic tests -### -!! test -Blank input -!! input -!! result -!! end - - -!! test -Simple paragraph -!! input -This is a simple paragraph. -!! result -

This is a simple paragraph. -

-!! end - -!! test -Simple list -!! input -* Item 1 -* Item 2 -!! result -
  • Item 1 -
  • Item 2 -
- -!! end - -!! test -Italics and bold -!! input -* plain -* plain''italic''plain -* plain''italic''plain''italic''plain -* plain'''bold'''plain -* plain'''bold'''plain'''bold'''plain -* plain''italic''plain'''bold'''plain -* plain'''bold'''plain''italic''plain -* plain''italic'''bold-italic'''italic''plain -* plain'''bold''bold-italic''bold'''plain -* plain'''''bold-italic'''italic''plain -* plain'''''bold-italic''bold'''plain -* plain''italic'''bold-italic'''''plain -* plain'''bold''bold-italic'''''plain -* plain l'''italic''plain -* plain l''''bold''' plain -!! result -
  • plain -
  • plainitalicplain -
  • plainitalicplainitalicplain -
  • plainboldplain -
  • plainboldplainboldplain -
  • plainitalicplainboldplain -
  • plainboldplainitalicplain -
  • plainitalicbold-italicitalicplain -
  • plainboldbold-italicboldplain -
  • plainbold-italicitalicplain -
  • plainbold-italicboldplain -
  • plainitalicbold-italicplain -
  • plainboldbold-italicplain -
  • plain l'italicplain -
  • plain l'bold plain -
- -!! end - -### -### test cases -### - -!! test - unordered list -!! input -* This is not an unordered list item. -!! result -

* This is not an unordered list item. -

-!! end - -!! test - spacing -!! input -Lorem ipsum dolor - -sed abit. - sed nullum. - -:and a colon - -!! result -

Lorem ipsum dolor - -sed abit. - sed nullum. - -:and a colon - -

-!! end - -!! test -nowiki 3 -!! input -:There is not nowiki. -:There is nowiki. - -#There is not nowiki. -#There is nowiki. - -*There is not nowiki. -*There is nowiki. -!! result -
There is not nowiki. -
There is nowiki. -
-
  1. There is not nowiki. -
  2. There is nowiki. -
-
  • There is not nowiki. -
  • There is nowiki. -
- -!! end - - -### -### Comments -### -!! test -Comment test 1 -!! input - asdf - -!! result -
asdf
-
- -!! end - -!! test -Comment test 2 -!! input -asdf - -jkl -!! result -

asdf -jkl -

-!! end - -!! test -Comment test 3 -!! input -asdf - - -jkl -!! result -

asdf -jkl -

-!! end - -!! test -Comment test 4 -!! input -asdfjkl -!! result -

asdfjkl -

-!! end - -!! test -Comment spacing -!! input -a - b -c -!! result -

a -

-
 b 
-
-

c -

-!! end - -!! test -Comment whitespace -!! input - -!! result - -!! end - -!! test -Comment semantics and delimiters -!! input - -!! result - -!! end - -!! test -Comment semantics and delimiters, redux -!! input - -!! result - -!! end - -!! test -Comment semantics and delimiters: directors cut -!! input ---> -!! result -

--> -

-!! end - -!! test -Comment semantics: nesting -!! input ---> -!! result -

--> -

-!! end - -!! test -Comment semantics: unclosed comment at end -!! input -oo}} -!! result -

FOO -

-!! end - -!! test -Comment on its own line post-expand -!! input -a -{{blank}} -b -!! result -

a -

b -

-!! end - -### -### Preformatted text -### -!! test -Preformatted text -!! input - This is some - Preformatted text - With ''italic'' - And '''bold''' - And a [[Main Page|link]] -!! result -
This is some
-Preformatted text
-With italic
-And bold
-And a link
-
-!! end - -!! test -
 with  inside (compatibility with 1.6 and earlier)
-!! input
-

-
-
-
-
-!! result -
-<b>
-<cite>
-<em>
-
- -!! end - -!! test -Regression with preformatted in
-!! input -
- Blah -
-!! result -
-
Blah
-
-
- -!! end - -# Expected output in the following test is not really expected (there should be -#
 in the output) -- it's only testing for well-formedness.
-!! test
-Bug 6200: Preformatted in 
-!! input -
- Blah -
-!! result -
- Blah -
- -!! end - -!! test -
 with attributes (bug 3202)
-!! input
-
Bluescreen of WikiDeath
-!! result -
Bluescreen of WikiDeath
- -!! end - -!! test -
 with width attribute (bug 3202)
-!! input
-
Narrow screen goodies
-!! result -
Narrow screen goodies
- -!! end - -!! test -
 with forbidden attribute (bug 3202)
-!! input
-
Narrow screen goodies
-!! result -
Narrow screen goodies
- -!! end - -!! test -
 with forbidden attribute values (bug 3202)
-!! input
-
Narrow screen goodies
-!! result -
Narrow screen goodies
- -!! end - -### -### Definition lists -### -!! test -Simple definition -!! input -; name : Definition -!! result -
name 
Definition -
- -!! end - -!! test -Definition list for indentation only -!! input -: Indented text -!! result -
Indented text -
- -!! end - -!! test -Definition list with no space -!! input -;name:Definition -!! result -
name
Definition -
- -!!end - -!! test -Definition list with URL link -!! input -; http://example.com/ : definition -!! result -
http://example.com/ 
definition -
- -!! end - -!! test -Definition list with bracketed URL link -!! input -;[http://www.example.com/ Example]:Something about it -!! result -
Example
Something about it -
- -!! end - -!! test -Definition list with wikilink containing colon -!! input -; [[Help:FAQ]]: The least-read page on Wikipedia -!! result -
Help:FAQ
The least-read page on Wikipedia -
- -!! end - -# At Brion's and JeLuF's insistence... :) -!! test -Definition list with news link containing colon -!! input -; news:alt.wikipedia.rox: This isn't even a real newsgroup! -!! result -
news:alt.wikipedia.rox
This isn't even a real newsgroup! -
- -!! end - -!! test -Malformed definition list with colon -!! input -; news:alt.wikipedia.rox -- don't crash or enter an infinite loop -!! result -
news:alt.wikipedia.rox -- don't crash or enter an infinite loop -
- -!! end - -!! test -Definition lists: colon in external link text -!! input -; [http://www.wikipedia2.org/ Wikipedia : The Next Generation]: OK, I made that up -!! result -
Wikipedia : The Next Generation
OK, I made that up -
- -!! end - -!! test -Definition lists: colon in HTML attribute -!! input -;bold -!! result -
bold -
- -!! end - - -!! test -Definition lists: self-closed tag -!! input -;one
two : two-line fun -!! result -
one
two 
two-line fun -
- -!! end - - -### -### External links -### -!! test -External links: non-bracketed -!! input -Non-bracketed: http://example.com -!! result -

Non-bracketed: http://example.com -

-!! end - -!! test -External links: numbered -!! input -Numbered: [http://example.com] -Numbered: [http://example.net] -Numbered: [http://example.com] -!! result -

Numbered: [1] -Numbered: [2] -Numbered: [3] -

-!!end - -!! test -External links: specified text -!! input -Specified text: [http://example.com link] -!! result -

Specified text: link -

-!!end - -!! test -External links: trail -!! input -Linktrails should not work for external links: [http://example.com link]s -!! result -

Linktrails should not work for external links: links -

-!! end - -!! test -External links: dollar sign in URL -!! input -http://example.com/1$2345 -!! result -

http://example.com/1$2345 -

-!! end - -!! test -External links: dollar sign in URL (named) -!! input -[http://example.com/1$2345] -!! result -

[1] -

-!!end - -!! test -External links: open square bracket forbidden in URL (bug 4377) -!! input -http://example.com/1[2345 -!! result -

http://example.com/1[2345 -

-!! end - -!! test -External links: open square bracket forbidden in URL (named) (bug 4377) -!! input -[http://example.com/1[2345] -!! result -

[2345 -

-!!end - -!! test -External links: nowiki in URL link text (bug 6230) -!!input -[http://example.com/ ''example site''] -!! result -

''example site'' -

-!! end - -!! test -External links: newline forbidden in text (bug 6230 regression check) -!! input -[http://example.com/ first -second] -!! result -

[http://example.com/ first -second] -

-!!end - -!! test -External image -!! input -External image: http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png -!! result -

External image: Ncwikicol.png -

-!! end - -!! test -External image from https -!! input -External image from https: https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png -!! result -

External image from https: Ncwikicol.png -

-!! end - -!! test -Link to non-http image, no img tag -!! input -Link to non-http image, no img tag: ftp://example.com/test.jpg -!! result -

Link to non-http image, no img tag: ftp://example.com/test.jpg -

-!! end - -!! test -External links: terminating separator -!! input -Terminating separator: http://example.com/thing, -!! result -

Terminating separator: http://example.com/thing, -

-!! end - -!! test -External links: intervening separator -!! input -Intervening separator: http://example.com/1,2,3 -!! result -

Intervening separator: http://example.com/1,2,3 -

-!! end - -!! test -External links: old bug with URL in query -!! input -Old bug with URL in query: [http://example.com/thing?url=http://example.com link] -!! result -

Old bug with URL in query: link -

-!! end - -!! test -External links: old URL-in-URL bug, mixed protocols -!! input -And again with mixed protocols: [ftp://example.com?url=http://example.com link] -!! result -

And again with mixed protocols: link -

-!!end - -!! test -External links: URL in text -!! input -URL in text: [http://example.com http://example.com] -!! result -

URL in text: http://example.com -

-!! end - -!! test -External links: Clickable images -!! input -ja-style clickable images: [http://example.com http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png] -!! result -

ja-style clickable images: Ncwikicol.png -

-!!end - -!! test -External links: raw ampersand -!! input -Old & use: http://x&y -!! result -

Old & use: http://x&y -

-!! end - -!! test -External links: encoded ampersand -!! input -Old & use: http://x&y -!! result -

Old & use: http://x&y -

-!! end - -!! test -External links: encoded equals (bug 6102) -!! input -http://example.com/?foo=bar -!! result -

http://example.com/?foo=bar -

-!! end - -!! test -External links: [raw ampersand] -!! input -Old & use: [http://x&y] -!! result -

Old & use: [1] -

-!! end - -!! test -External links: [encoded ampersand] -!! input -Old & use: [http://x&y] -!! result -

Old & use: [1] -

-!! end - -!! test -External links: [encoded equals] (bug 6102) -!! input -[http://example.com/?foo=bar] -!! result -

[1] -

-!! end - -!! test -External links: [IDN ignored character reference in hostname; strip it right off] -!! input -[http://e‌xample.com/] -!! result -

[1] -

-!! end - -!! test -External links: IDN ignored character reference in hostname; strip it right off -!! input -http://e‌xample.com/ -!! result -

http://example.com/ -

-!! end - -!! test -External links: www.jpeg.org (bug 554) -!! input -http://www.jpeg.org -!!result -

http://www.jpeg.org -

-!! end - -!! test -External links: URL within URL (original bug 2) -!! input -[http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp] -!! result -

[1] -

-!! end - -!! test -BUG 361: URL inside bracketed URL -!! input -[http://www.example.com/foo http://www.example.com/bar] -!! result -

http://www.example.com/bar -

-!! end - -!! test -BUG 361: URL within URL, not bracketed -!! input -http://www.example.com/foo?=http://www.example.com/bar -!! result -

http://www.example.com/foo?=http://www.example.com/bar -

-!! end - -!! test -BUG 289: ">"-token in URL-tail -!! input -http://www.example.com/ -!! result -

http://www.example.com/<hello> -

-!!end - -!! test -BUG 289: literal ">"-token in URL-tail -!! input -http://www.example.com/html -!! result -

http://www.example.com/html -

-!!end - -!! test -BUG 289: ">"-token in bracketed URL -!! input -[http://www.example.com/ stuff] -!! result -

<hello> stuff -

-!!end - -!! test -BUG 289: literal ">"-token in bracketed URL -!! input -[http://www.example.com/html stuff] -!! result -

html stuff -

-!!end - -!! test -BUG 289: literal double quote at end of URL -!! input -http://www.example.com/"hello" -!! result -

http://www.example.com/"hello" -

-!!end - -!! test -BUG 289: literal double quote in bracketed URL -!! input -[http://www.example.com/"hello" stuff] -!! result -

"hello" stuff -

-!!end - -!! test -External links: multiple legal whitespace is fine, Magnus. Don't break it please. (bug 5081) -!! input -[http://www.example.com test] -!! result -

test -

-!! end - -!! test -External links: wiki links within external link (Bug 3695) -!! input -[http://example.com [[wikilink]] embedded in ext link] -!! result -

wikilink embedded in ext link -

-!! end - -!! test -BUG 787: Links with one slash after the url protocol are invalid -!! input -http:/example.com - -[http:/example.com title] -!! result -

http:/example.com -

[http:/example.com title] -

-!! end - -!! test -Bug 2702: Mismatched , and tags are invalid -!! input -''[http://example.com text''] -[http://example.com '''text]''' -''Something [http://example.com in italic''] -''Something [http://example.com mixed''''', even bold]''' -'''''Now [http://example.com both'''''] -!! result -

text -text -Something in italic -Something mixed, even bold -Now both -

-!! end - - -!! test -Bug 4781: %26 in URL -!! input -http://www.example.com/?title=AT%26T -!! result -

http://www.example.com/?title=AT%26T -

-!! end - -!! test -Bug 4781, 5267: %26 in URL -!! input -http://www.example.com/?title=100%25_Bran -!! result -

http://www.example.com/?title=100%25_Bran -

-!! end - -!! test -Bug 4781, 5267: %28, %29 in URL -!! input -http://www.example.com/?title=Ben-Hur_%281959_film%29 -!! result -

http://www.example.com/?title=Ben-Hur_%281959_film%29 -

-!! end - - -!! test -Bug 4781: %26 in autonumber URL -!! input -[http://www.example.com/?title=AT%26T] -!! result -

[1] -

-!! end - -!! test -Bug 4781, 5267: %26 in autonumber URL -!! input -[http://www.example.com/?title=100%25_Bran] -!! result -

[1] -

-!! end - -!! test -Bug 4781, 5267: %28, %29 in autonumber URL -!! input -[http://www.example.com/?title=Ben-Hur_%281959_film%29] -!! result -

[1] -

-!! end - - -!! test -Bug 4781: %26 in bracketed URL -!! input -[http://www.example.com/?title=AT%26T link] -!! result -

link -

-!! end - -!! test -Bug 4781, 5267: %26 in bracketed URL -!! input -[http://www.example.com/?title=100%25_Bran link] -!! result -

link -

-!! end - -!! test -Bug 4781, 5267: %28, %29 in bracketed URL -!! input -[http://www.example.com/?title=Ben-Hur_%281959_film%29 link] -!! result -

link -

-!! end - -!! test -External link containing double-single-quotes in text '' (bug 4598 sanity check) -!! input -Some [http://example.com/ pretty ''italics'' and stuff]! -!! result -

Some pretty italics and stuff! -

-!! end - -!! test -External link containing double-single-quotes in text embedded in italics (bug 4598 sanity check) -!! input -''Some [http://example.com/ pretty ''italics'' and stuff]!'' -!! result -

Some pretty italics and stuff! -

-!! end - -!! test -External link containing double-single-quotes with no space separating the url from text in italics -!! input -[http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm''La muerte de Casagemas'' (1901) en el sitio de [[Museo Picasso (París)|Museo Picasso]].] -!! result -

La muerte de Casagemas (1901) en el sitio de Museo Picasso. -

-!! end - -!! test -URL-encoding in URL functions (single parameter) -!! input -{{localurl:Some page|amp=&}} -!! result -

/index.php?title=Some_page&amp=& -

-!! end - -!! test -URL-encoding in URL functions (multiple parameters) -!! input -{{localurl:Some page|q=?&=&}} -!! result -

/index.php?title=Some_page&q=?&amp=& -

-!! end - -### -### Quotes -### - -!! test -Quotes -!! input -Normal text. '''Bold text.''' Normal text. ''Italic text.'' - -Normal text. '''''Bold italic text.''''' Normal text. -!!result -

Normal text. Bold text. Normal text. Italic text. -

Normal text. Bold italic text. Normal text. -

-!! end - - -!! test -Unclosed and unmatched quotes -!! input -'''''Bold italic text '''with bold deactivated''' in between.''''' - -'''''Bold italic text ''with italic deactivated'' in between.''''' - -'''Bold text.. - -..spanning two paragraphs (should not work).''' - -'''Bold tag left open - -''Italic tag left open - -Normal text. - - -'''This year''''s election ''should'' beat '''last year''''s. - -''Tom'''s car is bigger than ''Susan'''s. -!! result -

Bold italic text with bold deactivated in between. -

Bold italic text with italic deactivated in between. -

Bold text.. -

..spanning two paragraphs (should not work). -

Bold tag left open -

Italic tag left open -

Normal text. -

This year's election should beat last year's. -

Toms car is bigger than Susans. -

-!! end - -### -### Tables -### -### some content taken from http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide:_Using_tables -### - -# This should not produce
as
-# is the bare minimun required by the spec, see: -# http://www.w3.org/TR/xhtml-modularization/dtd_module_defs.html#a_module_Basic_Tables -!! test -A table with no data. -!! input -{||} -!! result -!! end - -# A table with nothing but a caption is invalid XHTML, we might want to render -# this as

caption

-!! test -A table with nothing but a caption -!! input -{| -|+ caption -|} -!! result - -
caption -
- -!! end - -!! test -Simple table -!! input -{| -| 1 || 2 -|- -| 3 || 4 -|} -!! result - - - - - - -
1 2 -
3 4 -
- -!! end - -!! test -Multiplication table -!! input -{| border="1" cellpadding="2" -|+Multiplication table -|- -! × !! 1 !! 2 !! 3 -|- -! 1 -| 1 || 2 || 3 -|- -! 2 -| 2 || 4 || 6 -|- -! 3 -| 3 || 6 || 9 -|- -! 4 -| 4 || 8 || 12 -|- -! 5 -| 5 || 10 || 15 -|} -!! result - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Multiplication table -
× 1 2 3 -
1 - 1 2 3 -
2 - 2 4 6 -
3 - 3 6 9 -
4 - 4 8 12 -
5 - 5 10 15 -
- -!! end - -!! test -Table rowspan -!! input -{| align=right border=1 -| Cell 1, row 1 -|rowspan=2| Cell 2, row 1 (and 2) -| Cell 3, row 1 -|- -| Cell 1, row 2 -| Cell 3, row 2 -|} -!! result - - - - - - - -
Cell 1, row 1 - Cell 2, row 1 (and 2) - Cell 3, row 1 -
Cell 1, row 2 - Cell 3, row 2 -
- -!! end - -!! test -Nested table -!! input -{| border=1 -| α -| -{| bgcolor=#ABCDEF border=2 -|nested -|- -|table -|} -|the original table again -|} -!! result - - - - -
α - - - - - -
nested -
table -
-
the original table again -
- -!! end - -!! test -Invalid attributes in table cell (bug 1830) -!! input -{| -|Cell:|broken -|} -!! result - - -
broken -
- -!! end - - -!! test -Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitech-l/2006-April/022293.html) -!! input -{| -| |[ftp://|x||]" onmouseover="alert(document.cookie)">test -!! result - - - - - -
[ftp://%7Cx]" onmouseover="alert(document.cookie)">test -
- -!! end - - -### -### Internal links -### -!! test -Plain link, capitalized -!! input -[[Main Page]] -!! result -

Main Page -

-!! end - -!! test -Plain link, uncapitalized -!! input -[[main Page]] -!! result -

main Page -

-!! end - -!! test -Piped link -!! input -[[Main Page|The Main Page]] -!! result -

The Main Page -

-!! end - -!! test -Broken link -!! input -[[Zigzagzogzagzig]] -!! result -

Zigzagzogzagzig -

-!! end - -!! test -Broken link with fragment -!! input -[[Zigzagzogzagzig#zug]] -!! result -

Zigzagzogzagzig#zug -

-!! end - -!! test -Special page link with fragment -!! input -[[Special:Version#anchor]] -!! result -

Special:Version#anchor -

-!! end - -!! test -Nonexistent special page link with fragment -!! input -[[Special:ThisNameWillHopefullyNeverBeUsed#anchor]] -!! result -

Special:ThisNameWillHopefullyNeverBeUsed#anchor -

-!! end - -!! test -Link with prefix -!! input -xxx[[main Page]], xxx[[Main Page]], Xxx[[main Page]] XXX[[main Page]], XXX[[Main Page]] -!! result -

xxxmain Page, xxxMain Page, Xxxmain Page XXXmain Page, XXXMain Page -

-!! end - -!! test -Link with suffix -!! input -[[Main Page]]xxx, [[Main Page]]XXX, [[Main Page]]!!! -!! result -

Main Pagexxx, Main PageXXX, Main Page!!! -

-!! end - -!! test -Link with 3 brackets -!! input -[[[main page]]] -!! result -

[[[main page]]] -

-!! end - -!! test -Piped link with 3 brackets -!! input -[[[main page|the main page]]] -!! result -

[[[main page|the main page]]] -

-!! end - -!! test -Link with multiple pipes -!! input -[[Main Page|The|Main|Page]] -!! result -

The|Main|Page -

-!! end - -!! test -Link to namespaces -!! input -[[Talk:Parser testing]], [[Meta:Disclaimers]] -!! result -

Talk:Parser testing, Meta:Disclaimers -

-!! end - -!! test -Piped link to namespace -!! input -[[Meta:Disclaimers|The disclaimers]] -!! result -

The disclaimers -

-!! end - -!! test -Link containing } -!! input -[[Usually caused by a typo (oops}]] -!! result -

[[Usually caused by a typo (oops}]] -

-!! end - -!! test -Link containing % (not as a hex sequence) -!! input -[[7% Solution]] -!! result -

7% Solution -

-!! end - -!! test -Link containing % as a single hex sequence interpreted to char -!! input -[[7%25 Solution]] -!! result -

7% Solution -

-!!end - -!! test -Link containing % as a double hex sequence interpreted to hex sequence -!! input -[[7%2525 Solution]] -!! result -

[[7%2525 Solution]] -

-!!end - -!! test -Link containing "#<" and "#>" % as a hex sequences- these are valid section anchors -Example for such a section: == < == -!! input -[[%23%3c]][[%23%3e]] -!! result -

#<#> -

-!! end - -!! test -Link containing "<#" and ">#" as a hex sequences -!! input -[[%3c%23]][[%3e%23]] -!! result -

[[%3c%23]][[%3e%23]] -

-!! end - -!! test -Link containing double-single-quotes '' (bug 4598) -!! input -[[Lista d''e paise d''o munno]] -!! result -

Lista d''e paise d''o munno -

-!! end - -!! test -Link containing double-single-quotes '' in text (bug 4598 sanity check) -!! input -Some [[Link|pretty ''italics'' and stuff]]! -!! result -

Some pretty italics and stuff! -

-!! end - -!! test -Link containing double-single-quotes '' in text embedded in italics (bug 4598 sanity check) -!! input -''Some [[Link|pretty ''italics'' and stuff]]! -!! result -

Some pretty italics and stuff! -

-!! end - -!! test -Link with double quotes in title part (literal) and alternate part (interpreted) -!! input -[[File:Denys Savchenko ''Pentecoste''.jpg]] - -[[''Pentecoste'']] - -[[''Pentecoste''|Pentecoste]] - -[[''Pentecoste''|''Pentecoste'']] -!! result -

File:Denys Savchenko Pentecoste.jpg -

''Pentecoste'' -

Pentecoste -

Pentecoste -

-!! end - -!! test -Plain link to URL -!! input -[[http://www.example.com]] -!! result -

[[1]] -

-!! end - -# I'm fairly sure the expected result here is wrong. -# We want these to be URL links, not pseudo-pages with URLs for titles.... -# However the current output is also pretty screwy. -# -# ---- -# I'm changing it to match the current output--it arguably makes more -# sense in the light of the test above. Old expected result was: -#

Piped link to URL: an example URL -#

-# But I think this test is bordering on "garbage in, garbage out" anyway. -# -- wtm -!! test -Piped link to URL -!! input -Piped link to URL: [[http://www.example.com|an example URL]] -!! result -

Piped link to URL: [example URL] -

-!! end - -!! test -BUG 2: [[page|http://url/]] should link to page, not http://url/ -!! input -[[Main Page|http://url/]] -!! result -

http://url/ -

-!! end - -!! test -BUG 337: Escaped self-links should be bold -!! options -title=[[Bug462]] -!! input -[[Bug462]] [[Bug462]] -!! result -

Bug462 Bug462 -

-!! end - -!! test -Self-link to section should not be bold -!! options -title=[[Main Page]] -!! input -[[Main Page#section]] -!! result -

Main Page#section -

-!! end - -!! article -00 -!! text -This is 00. -!! endarticle - -!!test -Self-link to numeric title -!!options -title=[[0]] -!!input -[[0]] -!!result -

0 -

-!!end - -!!test -Link to numeric-equivalent title -!!options -title=[[0]] -!!input -[[00]] -!!result -

00 -

-!!end - -!! test - inside a link -!! input -[[Main Page]] [[Main Page|the main page [it's not very good]]] -!! result -

[[Main Page]] the main page [it's not very good] -

-!! end - -!! test -Non-breaking spaces in title -!! input -[[  Main   Page  ]] -!! result -

  Main   Page   -

-!!end - - -### -### Interwiki links (see maintenance/interwiki.sql) -### - -!! test -Inline interwiki link -!! input -[[MeatBall:SoftSecurity]] -!! result -

MeatBall:SoftSecurity -

-!! end - -!! test -Inline interwiki link with empty title (bug 2372) -!! input -[[MeatBall:]] -!! result -

MeatBall: -

-!! end - -!! test -Interwiki link encoding conversion (bug 1636) -!! input -*[[Wikipedia:ro:Olteniţa]] -*[[Wikipedia:ro:Olteniţa]] -!! result - - -!! end - -!! test -Interwiki link with fragment (bug 2130) -!! input -[[MeatBall:SoftSecurity#foo]] -!! result -

MeatBall:SoftSecurity#foo -

-!! end - -!! test -Interlanguage link -!! input -Blah blah blah -[[zh:Chinese]] -!!result -

Blah blah blah -

-!! end - -!! test -Double interlanguage link -!! input -Blah blah blah -[[es:Spanish]] -[[zh:Chinese]] -!!result -

Blah blah blah -

-!! end - -!! test -Interlanguage link, with prefix links -!! options -language=ln -!! input -Blah blah blah -[[zh:Chinese]] -!!result -

Blah blah blah -

-!! end - -!! test -Double interlanguage link, with prefix links (bug 8897) -!! options -language=ln -!! input -Blah blah blah -[[es:Spanish]] -[[zh:Chinese]] -!!result -

Blah blah blah -

-!! end - - -## -## XHTML tidiness -### - -!! test -
to
-!! input -1
2
3 -!! result -

1
2
3 -

-!! end - -!! test -Incorrecly removing closing slashes from correctly formed XHTML -!! input -
-!! result -


-

-!! end - -!! test -Failing to transform badly formed HTML into correct XHTML -!! input -
-
-
-!! result -


-
-
-

-!!end - -!! test -Horizontal ruler (should it add that extra space?) -!! input -
-
-foo
bar -!! result -
-
-foo
bar - -!! end - -### -### Block-level elements -### -!! test -Common list -!! input -*Common list -* item 2 -*item 3 -!! result -
  • Common list -
  • item 2 -
  • item 3 -
- -!! end - -!! test -Numbered list -!! input -#Numbered list -#item 2 -# item 3 -!! result -
  1. Numbered list -
  2. item 2 -
  3. item 3 -
- -!! end - -!! test -Mixed list -!! input -*Mixed list -*# with numbers -** and bullets -*# and numbers -*bullets again -**bullet level 2 -***bullet level 3 -***#Number on level 4 -**bullet level 2 -**#Number on level 3 -**#Number on level 3 -*#number level 2 -*Level 1 -!! result -
  • Mixed list -
    1. with numbers -
    -
    • and bullets -
    -
    1. and numbers -
    -
  • bullets again -
    • bullet level 2 -
      • bullet level 3 -
        1. Number on level 4 -
        -
      -
    • bullet level 2 -
      1. Number on level 3 -
      2. Number on level 3 -
      -
    -
    1. number level 2 -
    -
  • Level 1 -
- -!! end - -!! test -List items are not parsed correctly following a
 block (bug 785)
-!! input
-* 
foo
-*
bar
-* zar -!! result -
  • foo
    -
  • bar
    -
  • zar -
- -!! end - -### -### Magic Words -### - -!! test -Magic Word: {{CURRENTDAY}} -!! input -{{CURRENTDAY}} -!! result -

1 -

-!! end - -!! test -Magic Word: {{CURRENTDAY2}} -!! input -{{CURRENTDAY2}} -!! result -

01 -

-!! end - -!! test -Magic Word: {{CURRENTDAYNAME}} -!! input -{{CURRENTDAYNAME}} -!! result -

Thursday -

-!! end - -!! test -Magic Word: {{CURRENTDOW}} -!! input -{{CURRENTDOW}} -!! result -

4 -

-!! end - -!! test -Magic Word: {{CURRENTMONTH}} -!! input -{{CURRENTMONTH}} -!! result -

01 -

-!! end - -!! test -Magic Word: {{CURRENTMONTHABBREV}} -!! input -{{CURRENTMONTHABBREV}} -!! result -

Jan -

-!! end - -!! test -Magic Word: {{CURRENTMONTHNAME}} -!! input -{{CURRENTMONTHNAME}} -!! result -

January -

-!! end - -!! test -Magic Word: {{CURRENTMONTHNAMEGEN}} -!! input -{{CURRENTMONTHNAMEGEN}} -!! result -

January -

-!! end - -!! test -Magic Word: {{CURRENTTIME}} -!! input -{{CURRENTTIME}} -!! result -

00:02 -

-!! end - -!! test -Magic Word: {{CURRENTWEEK}} (@bug 4594) -!! input -{{CURRENTWEEK}} -!! result -

1 -

-!! end - -!! test -Magic Word: {{CURRENTYEAR}} -!! input -{{CURRENTYEAR}} -!! result -

1970 -

-!! end - -!! test -Magic Word: {{FULLPAGENAME}} -!! options -title=[[User:Ævar Arnfjörð Bjarmason]] -!! input -{{FULLPAGENAME}} -!! result -

User:Ævar Arnfjörð Bjarmason -

-!! end - -!! test -Magic Word: {{FULLPAGENAMEE}} -!! options -title=[[User:Ævar Arnfjörð Bjarmason]] -!! input -{{FULLPAGENAMEE}} -!! result -

User:%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason -

-!! end - -!! test -Magic Word: {{NAMESPACE}} -!! options -title=[[User:Ævar Arnfjörð Bjarmason]] -!! input -{{NAMESPACE}} -!! result -

User -

-!! end - -!! test -Magic Word: {{NAMESPACEE}} -!! options -title=[[User:Ævar Arnfjörð Bjarmason]] -!! input -{{NAMESPACEE}} -!! result -

User -

-!! end - -!! test -Magic Word: {{NUMBEROFFILES}} -!! input -{{NUMBEROFFILES}} -!! result -

2 -

-!! end - -!! test -Magic Word: {{PAGENAME}} -!! options -title=[[User:Ævar Arnfjörð Bjarmason]] -!! input -{{PAGENAME}} -!! result -

Ævar Arnfjörð Bjarmason -

-!! end - -!! test -Magic Word: {{PAGENAMEE}} -!! options -title=[[User:Ævar Arnfjörð Bjarmason]] -!! input -{{PAGENAMEE}} -!! result -

%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason -

-!! end - -!! test -Magic Word: {{REVISIONID}} -!! input -{{REVISIONID}} -!! result -

1337 -

-!! end - -!! test -Magic Word: {{SCRIPTPATH}} -!! input -{{SCRIPTPATH}} -!! result -

/ -

-!! end - -!! test -Magic Word: {{SERVER}} -!! input -{{SERVER}} -!! result -

http://localhost -

-!! end - -!! test -Magic Word: {{SERVERNAME}} -!! input -{{SERVERNAME}} -!! result -

Britney-Spears -

-!! end - -!! test -Magic Word: {{SITENAME}} -!! input -{{SITENAME}} -!! result -

MediaWiki -

-!! end - -!! test -Namespace 1 {{ns:1}} -!! input -{{ns:1}} -!! result -

Talk -

-!! end - -!! test -Namespace 1 {{ns:01}} -!! input -{{ns:01}} -!! result -

Talk -

-!! end - -!! test -Namespace 0 {{ns:0}} (bug 4783) -!! input -{{ns:0}} -!! result - -!! end - -!! test -Namespace 0 {{ns:00}} (bug 4783) -!! input -{{ns:00}} -!! result - -!! end - -!! test -Namespace -1 {{ns:-1}} -!! input -{{ns:-1}} -!! result -

Special -

-!! end - -!! test -Namespace User {{ns:User}} -!! input -{{ns:User}} -!! result -

User -

-!! end - -!! test -Namespace User talk {{ns:User_talk}} -!! input -{{ns:User_talk}} -!! result -

User talk -

-!! end - -!! test -Namespace User talk {{ns:uSeR tAlK}} -!! input -{{ns:uSeR tAlK}} -!! result -

User talk -

-!! end - -!! test -Namespace File {{ns:File}} -!! input -{{ns:File}} -!! result -

File -

-!! end - -!! test -Namespace File {{ns:Image}} -!! input -{{ns:Image}} -!! result -

File -

-!! end - -!! test -Namespace (lang=de) Benutzer {{ns:User}} -!! options -language=de -!! input -{{ns:User}} -!! result -

Benutzer -

-!! end - -!! test -Namespace (lang=de) Benutzer Diskussion {{ns:3}} -!! options -language=de -!! input -{{ns:3}} -!! result -

Benutzer Diskussion -

-!! end - - -!! test -Urlencode -!! input -{{urlencode:hi world?!}} -{{urlencode:hi world?!|WIKI}} -{{urlencode:hi world?!|PATH}} -{{urlencode:hi world?!|QUERY}} -!! result -

hi+world%3F%21 -hi_world%3F! -hi%20world%3F%21 -hi+world%3F%21 -

-!! end - -### -### Magic links -### -!! test -Magic links: internal link to RFC (bug 479) -!! input -[[RFC 123]] -!! result -

RFC 123 -

-!! end - -!! test -Magic links: RFC (bug 479) -!! input -RFC 822 -!! result -

RFC 822 -

-!! end - -!! test -Magic links: ISBN (bug 1937) -!! input -ISBN 0-306-40615-2 -!! result -

ISBN 0-306-40615-2 -

-!! end - -!! test -Magic links: PMID incorrectly converts space to underscore -!! input -PMID 1234 -!! result -

PMID 1234 -

-!! end - -### -### Templates -#### - -!! test -Nonexistent template -!! input -{{thistemplatedoesnotexist}} -!! result -

Template:Thistemplatedoesnotexist -

-!! end - -!! article -Template:test -!! text -This is a test template -!! endarticle - -!! test -Simple template -!! input -{{test}} -!! result -

This is a test template -

-!! end - -!! test -Template with explicit namespace -!! input -{{Template:test}} -!! result -

This is a test template -

-!! end - - -!! article -Template:paramtest -!! text -This is a test template with parameter {{{param}}} -!! endarticle - -!! test -Template parameter -!! input -{{paramtest|param=foo}} -!! result -

This is a test template with parameter foo -

-!! end - -!! article -Template:paramtestnum -!! text -[[{{{1}}}|{{{2}}}]] -!! endarticle - -!! test -Template unnamed parameter -!! input -{{paramtestnum|Main Page|the main page}} -!! result -

the main page -

-!! end - -!! article -Template:templatesimple -!! text -(test) -!! endarticle - -!! article -Template:templateredirect -!! text -#redirect [[Template:templatesimple]] -!! endarticle - -!! article -Template:templateasargtestnum -!! text -{{{{{1}}}}} -!! endarticle - -!! article -Template:templateasargtest -!! text -{{template{{{templ}}}}} -!! endarticle - -!! article -Template:templateasargtest2 -!! text -{{{{{templ}}}}} -!! endarticle - -!! test -Template with template name as unnamed argument -!! input -{{templateasargtestnum|templatesimple}} -!! result -

(test) -

-!! end - -!! test -Template with template name as argument -!! input -{{templateasargtest|templ=simple}} -!! result -

(test) -

-!! end - -!! test -Template with template name as argument (2) -!! input -{{templateasargtest2|templ=templatesimple}} -!! result -

(test) -

-!! end - -!! article -Template:templateasargtestdefault -!! text -{{{{{templ|templatesimple}}}}} -!! endarticle - -!! article -Template:templa -!! text -'''templ''' -!! endarticle - -!! test -Template with default value -!! input -{{templateasargtestdefault}} -!! result -

(test) -

-!! end - -!! test -Template with default value (value set) -!! input -{{templateasargtestdefault|templ=templa}} -!! result -

templ -

-!! end - -!! test -Template redirect -!! input -{{templateredirect}} -!! result -

(test) -

-!! end - -!! test -Template with argument in separate line -!! input -{{ templateasargtest | - templ = simple }} -!! result -

(test) -

-!! end - -!! test -Template with complex template as argument -!! input -{{paramtest| - param ={{ templateasargtest | - templ = simple }}}} -!! result -

This is a test template with parameter (test) -

-!! end - -!! test -Template with thumb image (with link in description) -!! input -{{paramtest| - param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}} -!! result -This is a test template with parameter - -!! end - -!! article -Template:complextemplate -!! text -{{{1}}} {{paramtest| - param ={{{param}}}}} -!! endarticle - -!! test -Template with complex arguments -!! input -{{complextemplate| - param ={{ templateasargtest | - templ = simple }}|[[Template:complextemplate|link]]}} -!! result -

link This is a test template with parameter (test) -

-!! end - -!! test -BUG 553: link with two variables in a piped link -!! input -{| -|[[{{{1}}}|{{{2}}}]] -|} -!! result - - -
[[{{{1}}}|{{{2}}}]] -
- -!! end - -!! test -Magic variable as template parameter -!! input -{{paramtest|param={{SITENAME}}}} -!! result -

This is a test template with parameter MediaWiki -

-!! end - -!! article -Template:linktest -!! text -[[{{{param}}}|link]] -!! endarticle - -!! test -Template parameter as link source -!! input -{{linktest|param=Main Page}} -!! result -

link -

-!! end - - -!!article -Template:paramtest2 -!! text -including another template, {{paramtest|param={{{arg}}}}} -!! endarticle - -!! test -Template passing argument to another template -!! input -{{paramtest2|arg='hmm'}} -!! result -

including another template, This is a test template with parameter 'hmm' -

-!! end - -!! article -Template:Linktest2 -!! text -Main Page -!! endarticle - -!! test -Template as link source -!! input -[[{{linktest2}}]] -!! result -

Main Page -

-!! end - - -!! article -Template:loop1 -!! text -{{loop2}} -!! endarticle - -!! article -Template:loop2 -!! text -{{loop1}} -!! endarticle - -!! test -Template infinite loop -!! input -{{loop1}} -!! result -

Template loop detected: Template:Loop1 -

-!! end - -!! test -Template from main namespace -!! input -{{:Main Page}} -!! result -

blah blah -

-!! end - -!! article -Template:table -!! text -{| -| 1 || 2 -|- -| 3 || 4 -|} -!! endarticle - -!! test -BUG 529: Template with table, not included at beginning of line -!! input -foo {{table}} -!! result -

foo -

- - - - - - -
1 2 -
3 4 -
- -!! end - -!! test -BUG 523: Template shouldn't eat newline (or add an extra one before table) -!! input -foo -{{table}} -!! result -

foo -

- - - - - - -
1 2 -
3 4 -
- -!! end - -!! test -BUG 41: Template parameters shown as broken links -!! input -{{{parameter}}} -!! result -

{{{parameter}}} -

-!! end - - -!! article -Template:MSGNW test -!! text -''None'' of '''this''' should be -* interpreted - but rather passed unmodified -{{test}} -!! endarticle - -# hmm, fix this or just deprecate msgnw and document its behavior? -!! test -msgnw keyword -!! options -disabled -!! input -{{msgnw:MSGNW test}} -!! result -

''None'' of '''this''' should be -* interpreted - but rather passed unmodified -{{test}} -

-!! end - -!! test -int keyword -!! input -{{int:youhavenewmessages|lots of money|not!}} -!! result -

You have lots of money (not!). -

-!! end - -!! article -Template:Includes -!! text -Foozarbar -!! endarticle - -!! test - and being included -!! input -{{Includes}} -!! result -

Foobar -

-!! end - -!! article -Template:Includes2 -!! text -Foobar -!! endarticle - -!! test - being included -!! input -{{Includes2}} -!! result -

Foo -

-!! end - - -!! article -Template:Includes3 -!! text -Foobarzar -!! endarticle - -!! test - and being included -!! input -{{Includes3}} -!! result -

Foo -

-!! end - -!! test - and on a page -!! input -Foozarbar -!! result -

Foozar -

-!! end - -!! test - on a page -!! input -Foobar -!! result -

Foobar -

-!! end - -!! article -Template:Includeonly section -!! text - -==Includeonly section== - -==Section T-1== -!!endarticle - -!! test -Bug 6563: Edit link generation for section shown by -!! input -{{includeonly section}} -!! result -

[edit] Includeonly section

-

[edit] Section T-1

- -!! end - -# Uses same input as the contents of [[Template:Includeonly section]] -!! test -Bug 6563: Section extraction for section shown by -!! options -section=T-2 -!! input - -==Includeonly section== - -==Section T-2== -!! result -==Section T-2== -!! end - -!! test -Bug 6563: Edit link generation for section suppressed by -!! input - -==Includeonly section== - -==Section 1== -!! result -

[edit] Section 1

- -!! end - -!! test -Bug 6563: Section extraction for section suppressed by -!! options -section=1 -!! input - -==Includeonly section== - -==Section 1== -!! result -==Section 1== -!! end - -### -### Pre-save transform tests -### -!! test -pre-save transform: subst: -!! options -PST -!! input -{{subst:test}} -!! result -This is a test template -!! end - -!! test -pre-save transform: normal template -!! options -PST -!! input -{{test}} -!! result -{{test}} -!! end - -!! test -pre-save transform: nonexistent template -!! options -PST -!! input -{{thistemplatedoesnotexist}} -!! result -{{thistemplatedoesnotexist}} -!! end - - -!! test -pre-save transform: subst magic variables -!! options -PST -!! input -{{subst:SITENAME}} -!! result -MediaWiki -!! end - -# This is bug 89, which I fixed. -- wtm -!! test -pre-save transform: subst: templates with parameters -!! options -pst -!! input -{{subst:paramtest|param="something else"}} -!! result -This is a test template with parameter "something else" -!! end - -!! article -Template:nowikitest -!! text -'''not wiki''' -!! endarticle - -!! test -pre-save transform: nowiki in subst (bug 1188) -!! options -pst -!! input -{{subst:nowikitest}} -!! result -'''not wiki''' -!! end - - -!! article -Template:commenttest -!! text -This template has in it. -!! endarticle - -!! test -pre-save transform: comment in subst (bug 1936) -!! options -pst -!! input -{{subst:commenttest}} -!! result -This template has in it. -!! end - -!! test -pre-save transform: unclosed tag -!! options -pst noxml -!! input -'''not wiki''' -!! result -'''not wiki''' -!! end - -!! test -pre-save transform: mixed tag case -!! options -pst noxml -!! input -'''not wiki''' -!! result -'''not wiki''' -!! end - -!! test -pre-save transform: unclosed comment in -!! options -pst noxml -!! input -wikinowiki -!!result - -!!end - -!! test -pre-save transform: comment containing extension -!! options -pst -!! input - -!!result - -!!end - -!! test -pre-save transform: comment containing nowiki -!! options -pst -!! input - -!!result - -!!end - -!! test -pre-save transform: comment containing math -!! options -pst -!! input - -!!result - -!!end - -!! test -pre-save transform: in subst (bug 3298) -!! options -pst -!! input -{{subst:Includes}} -!! result -Foobar -!! end - -!! test -pre-save transform: in subst (bug 3298) -!! options -pst -!! input -{{subst:Includes2}} -!! result -Foo -!! end - -!! article -Template:SubstTest -!!text -{{subst:Includes}} -!! endarticle - -!! article -Template:SafeSubstTest -!! text -{{safesubst:Includes}} -!! endarticle - -!! test -bug 22297: safesubst: works during PST -!! options -pst -!! input -{{subst:SafeSubstTest}}{{safesubst:SubstTest}} -!! result -FoobarFoobar -!! end - -!! test -bug 22297: safesubst: works during normal parse -!! input -{{SafeSubstTest}} -!! result -

Foobar -

-!! end - -!! test: -subst: does not work during normal parse -!! input -{{SubstTest}} -!! result -

{{subst:Includes}} -

-!! end - -!! test -pre-save transform: context links ("pipe trick") -!! options -pst -!! input -[[Article (context)|]] -[[Bar:Article|]] -[[:Bar:Article|]] -[[Bar:Article (context)|]] -[[:Bar:Article (context)|]] -[[|Article]] -[[|Article (context)]] -[[Bar:X (Y) Z|]] -[[:Bar:X (Y) Z|]] -!! result -[[Article (context)|Article]] -[[Bar:Article|Article]] -[[:Bar:Article|Article]] -[[Bar:Article (context)|Article]] -[[:Bar:Article (context)|Article]] -[[Article]] -[[Article (context)]] -[[Bar:X (Y) Z|X (Y) Z]] -[[:Bar:X (Y) Z|X (Y) Z]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with interwiki prefix -!! options -pst -!! input -[[interwiki:Article|]] -[[:interwiki:Article|]] -[[interwiki:Bar:Article|]] -[[:interwiki:Bar:Article|]] -!! result -[[interwiki:Article|Article]] -[[:interwiki:Article|Article]] -[[interwiki:Bar:Article|Bar:Article]] -[[:interwiki:Bar:Article|Bar:Article]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with parens in title -!! options -pst title=[[Somearticle (context)]] -!! input -[[|Article]] -!! result -[[Article (context)|Article]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with comma in title -!! options -pst title=[[Someplace, Somewhere]] -!! input -[[|Otherplace]] -[[Otherplace, Elsewhere|]] -[[Otherplace, Elsewhere, Anywhere|]] -!! result -[[Otherplace, Somewhere|Otherplace]] -[[Otherplace, Elsewhere|Otherplace]] -[[Otherplace, Elsewhere, Anywhere|Otherplace]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with parens and comma -!! options -pst title=[[Someplace (IGNORED), Somewhere]] -!! input -[[|Otherplace]] -[[Otherplace (place), Elsewhere|]] -!! result -[[Otherplace, Somewhere|Otherplace]] -[[Otherplace (place), Elsewhere|Otherplace]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with comma and parens -!! options -pst title=[[Who, me? (context)]] -!! input -[[|Yes, you.]] -[[Me, Myself, and I (1937 song)|]] -!! result -[[Yes, you. (context)|Yes, you.]] -[[Me, Myself, and I (1937 song)|Me, Myself, and I]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with namespace -!! options -pst title=[[Ns:Somearticle]] -!! input -[[|Article]] -!! result -[[Ns:Article|Article]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with namespace and parens -!! options -pst title=[[Ns:Somearticle (context)]] -!! input -[[|Article]] -!! result -[[Ns:Article (context)|Article]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with namespace and comma -!! options -pst title=[[Ns:Somearticle, Context, Whatever]] -!! input -[[|Article]] -!! result -[[Ns:Article, Context, Whatever|Article]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with namespace, comma and parens -!! options -pst title=[[Ns:Somearticle, Context (context)]] -!! input -[[|Article]] -!! result -[[Ns:Article (context)|Article]] -!! end - -!! test -pre-save transform: context links ("pipe trick") with namespace, parens and comma -!! options -pst title=[[Ns:Somearticle (IGNORED), Context]] -!! input -[[|Article]] -!! result -[[Ns:Article, Context|Article]] -!! end - - -### -### Message transform tests -### -!! test -message transform: magic variables -!! options -msg -!! input -{{SITENAME}} -!! result -MediaWiki -!! end - -!! test -message transform: should not transform wiki markup -!! options -msg -!! input -''test'' -!! result -''test'' -!! end - -!! test -message transform: in transcluded template (bug 4926) -!! options -msg -!! input -{{Includes}} -!! result -Foobar -!! end - -!! test -message transform: in transcluded template (bug 4926) -!! options -msg -!! input -{{Includes2}} -!! result -Foo -!! end - -!! test -{{#special:}} page name, known -!! options -msg -!! input -{{#special:Recentchanges}} -!! result -Special:RecentChanges -!! end - -!! test -{{#special:}} page name with subpage, known -!! options -msg -!! input -{{#special:Recentchanges/param}} -!! result -Special:RecentChanges/param -!! end - -!! test -{{#special:}} page name, unknown -!! options -msg -!! input -{{#special:foobarnonexistent}} -!! result -No such special page -!! end - -### -### Images -### -!! test -Simple image -!! input -[[Image:foobar.jpg]] -!! result -

Foobar.jpg -

-!! end - -!! test -Right-aligned image -!! input -[[Image:foobar.jpg|right]] -!! result -
Foobar.jpg
- -!! end - -!! test -Simple image (using File: namespace, now canonical) -!! input -[[File:foobar.jpg]] -!! result -

Foobar.jpg -

-!! end - -!! test -Image with caption -!! input -[[Image:foobar.jpg|right|Caption text]] -!! result -
Caption text
- -!! end - -!! test -Image with link parameter, wiki target -!! input -[[Image:foobar.jpg|link=Target page]] -!! result -

Foobar.jpg -

-!! end - -!! test -Image with link parameter, URL target -!! input -[[Image:foobar.jpg|link=http://example.com/]] -!! result -

Foobar.jpg -

-!! end - -!! test -Image with empty link parameter -!! input -[[Image:foobar.jpg|link=]] -!! result -

Foobar.jpg -

-!! end - -!! test -Image with link parameter (wiki target) and unnamed parameter -!! input -[[Image:foobar.jpg|link=Target page|Title]] -!! result -

Title -

-!! end - -!! test -Image with link parameter (URL target) and unnamed parameter -!! input -[[Image:foobar.jpg|link=http://example.com/|Title]] -!! result -

Title -

-!! end - -!! test -Thumbnail image with link parameter -!! input -[[Image:foobar.jpg|thumb|link=http://example.com/|Title]] -!! result -
Title
- -!! end - -!! test -Image with frame and link -!! input -[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]]] -!! result -
This is a test image Main Page
- -!! end - -!! test -Image with frame and link and explicit alt -!! input -[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]|alt=Altitude]] -!! result -
Altitude
This is a test image Main Page
- -!! end - -!! test -Image with wiki markup in implicit alt -!! input -[[Image:Foobar.jpg|testing '''bold''' in alt]] -!! result -

testing bold in alt -

-!! end - -!! test -Image with wiki markup in explicit alt -!! input -[[Image:Foobar.jpg|alt=testing '''bold''' in alt]] -!! result -

testing bold in alt -

-!! end - -!! test -Link to image page- image page normally doesn't exists, hence edit link -Add test with existing image page -#

Image:test -!! input -[[:Image:test]] -!! result -

Image:test -

-!! end - -!! test -bug 18784 Link to non-existent image page with caption should use caption as link text -!! input -[[:Image:test|caption]] -!! result -

caption -

-!! end - -!! test -Frameless image caption with a free URL -!! input -[[Image:foobar.jpg|http://example.com]] -!! result -

http://example.com -

-!! end - -!! test -Thumbnail image caption with a free URL -!! input -[[Image:foobar.jpg|thumb|http://example.com]] -!! result - - -!! end - -!! test -Thumbnail image caption with a free URL and explicit alt -!! input -[[Image:foobar.jpg|thumb|http://example.com|alt=Alteration]] -!! result - - -!! end - -!! test -BUG 1887: A ISBN with a thumbnail -!! input -[[Image:foobar.jpg|thumb|ISBN 1235467890]] -!! result - - -!! end - -!! test -BUG 1887: A RFC with a thumbnail -!! input -[[Image:foobar.jpg|thumb|This is RFC 12354]] -!! result -
This is RFC 12354
- -!! end - -!! test -BUG 1887: A mailto link with a thumbnail -!! input -[[Image:foobar.jpg|thumb|Please mailto:nobody@example.com]] -!! result - - -!! end - -!! test -BUG 1887: A with a thumbnail- we don't render math in the parsertests by default, -so math is not stripped and turns up as escaped <math> tags. -!! input -[[Image:foobar.jpg|thumb|2+2]] -!! result -
<math>2+2</math>
- -!! end - -!! test -BUG 1887, part 2: A with a thumbnail- math enabled -!! options -math -!! input -[[Image:foobar.jpg|thumb|2+2]] -!! result -
2 + 2
- -!! end - -# Pending resolution to bug 368 -!! test -BUG 648: Frameless image caption with a link -!! input -[[Image:foobar.jpg|text with a [[link]] in it]] -!! result -

text with a link in it -

-!! end - -!! test -BUG 648: Frameless image caption with a link (suffix) -!! input -[[Image:foobar.jpg|text with a [[link]]foo in it]] -!! result -

text with a linkfoo in it -

-!! end - -!! test -BUG 648: Frameless image caption with an interwiki link -!! input -[[Image:foobar.jpg|text with a [[MeatBall:Link]] in it]] -!! result -

text with a MeatBall:Link in it -

-!! end - -!! test -BUG 648: Frameless image caption with a piped interwiki link -!! input -[[Image:foobar.jpg|text with a [[MeatBall:Link|link]] in it]] -!! result -

text with a link in it -

-!! end - -!! test -Escape HTML special chars in image alt text -!! input -[[Image:foobar.jpg|& < > "]] -!! result -

& < > " -

-!! end - -!! test -BUG 499: Alt text should have Ӓ, not &1234; -!! input -[[Image:foobar.jpg|♀]] -!! result -

♀ -

-!! end - -!! test -Broken image caption with link -!! input -[[Image:Foobar.jpg|thumb|This is a broken caption. But [[Main Page|this]] is just an ordinary link. -!! result -

[[Image:Foobar.jpg|thumb|This is a broken caption. But this is just an ordinary link. -

-!! end - -!! test -Image caption containing another image -!! input -[[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]] -!! result -
This is a caption with another image inside it!
- -!! end - -!! test -Image caption containing a newline -!! input -[[Image:Foobar.jpg|This -*is some text]] -!! result -

This *is some text -

-!!end - - -!! test -Bug 3090: External links other than http: in image captions -!! input -[[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]] -!! result -
This caption has irc and Secure ext links in it.
- -!! end - -!! article -File:Barfoo.jpg -!! text -#REDIRECT [[File:Barfoo.jpg]] -!! endarticle - -!! test -Redirected image -!! input -[[Image:Barfoo.jpg]] -!! result -

File:Barfoo.jpg -

-!! end - -!! test -Missing image with uploads disabled -!! options -wgEnableUploads=0 -!! input -[[Image:Foobaz.jpg]] -!! result -

File:Foobaz.jpg -

-!! end - - -### -### Subpages -### -!! article -Subpage test/subpage -!! text -foo -!! endarticle - -!! test -Subpage link -!! options -subpage title=[[Subpage test]] -!! input -[[/subpage]] -!! result -

/subpage -

-!! end - -!! test -Subpage noslash link -!! options -subpage title=[[Subpage test]] -!!input -[[/subpage/]] -!! result -

subpage -

-!! end - -!! test -Disabled subpages -!! input -[[/subpage]] -!! result -

/subpage -

-!! end - -!! test -BUG 561: {{/Subpage}} -!! options -subpage title=[[Page]] -!! input -{{/Subpage}} -!! result -

Page/Subpage -

-!! end - -### -### Categories -### -!! article -Category:MediaWiki User's Guide -!! text -blah -!! endarticle - -!! test -Link to category -!! input -[[:Category:MediaWiki User's Guide]] -!! result -

Category:MediaWiki User's Guide -

-!! end - -!! test -Simple category -!! options -cat -!! input -[[Category:MediaWiki User's Guide]] -!! result -MediaWiki User's Guide -!! end - -!! test -PAGESINCATEGORY invalid title fatal (r33546 fix) -!! input -{{PAGESINCATEGORY:}} -!! result -

0 -

-!! end - -### -### Inter-language links -### -!! test -Inter-language links -!! options -ill -!! input -[[es:Alimento]] -[[fr:Nourriture]] -[[zh:食品]] -!! result -es:Alimento fr:Nourriture zh:食品 -!! end - -### -### Sections -### -!! test -Basic section headings -!! input -== Headline 1 == -Some text - -==Headline 2== -More -===Smaller headline=== -Blah blah -!! result -

[edit] Headline 1

-

Some text -

-

[edit] Headline 2

-

More -

-

[edit] Smaller headline

-

Blah blah -

-!! end - -!! test -Section headings with TOC -!! input -== Headline 1 == -=== Subheadline 1 === -===== Skipping a level ===== -====== Skipping a level ====== - -== Headline 2 == -Some text -===Another headline=== -!! result -

Contents

- -
-

[edit] Headline 1

-

[edit] Subheadline 1

-
[edit] Skipping a level
-
[edit] Skipping a level
-

[edit] Headline 2

-

Some text -

-

[edit] Another headline

- -!! end - -# perl -e 'print "="x$_," Level $_ heading","="x$_,"\n" for 1..10' -!! test -Handling of sections up to level 6 and beyond -!! input -= Level 1 Heading= -== Level 2 Heading== -=== Level 3 Heading=== -==== Level 4 Heading==== -===== Level 5 Heading===== -====== Level 6 Heading====== -======= Level 7 Heading======= -======== Level 8 Heading======== -========= Level 9 Heading========= -========== Level 10 Heading========== -!! result -

Contents

- -
-

[edit] Level 1 Heading

-

[edit] Level 2 Heading

-

[edit] Level 3 Heading

-

[edit] Level 4 Heading

-
[edit] Level 5 Heading
-
[edit] Level 6 Heading
-
[edit] = Level 7 Heading=
-
[edit] == Level 8 Heading==
-
[edit] === Level 9 Heading===
-
[edit] ==== Level 10 Heading====
- -!! end - -!! test -TOC regression (bug 9764) -!! input -== title 1 == -=== title 1.1 === -==== title 1.1.1 ==== -=== title 1.2 === -== title 2 == -=== title 2.1 === -!! result -

Contents

- -
-

[edit] title 1

-

[edit] title 1.1

-

[edit] title 1.1.1

-

[edit] title 1.2

-

[edit] title 2

-

[edit] title 2.1

- -!! end - -!! test -TOC with wgMaxTocLevel=3 (bug 6204) -!! options -wgMaxTocLevel=3 -!! input -== title 1 == -=== title 1.1 === -==== title 1.1.1 ==== -=== title 1.2 === -== title 2 == -=== title 2.1 === -!! result -

Contents

- -
-

[edit] title 1

-

[edit] title 1.1

-

[edit] title 1.1.1

-

[edit] title 1.2

-

[edit] title 2

-

[edit] title 2.1

- -!! end - -!! test -TOC with wgMaxTocLevel=3 and two level four headings (bug 6204) -!! options -wgMaxTocLevel=3 -!! input -==Section 1== -===Section 1.1=== -====Section 1.1.1==== -====Section 1.1.1.1==== -==Section 2== -!! result -

Contents

- -
-

[edit] Section 1

-

[edit] Section 1.1

-

[edit] Section 1.1.1

-

[edit] Section 1.1.1.1

-

[edit] Section 2

- -!! end - - -!! test -Resolving duplicate section names -!! input -== Foo bar == -== Foo bar == -!! result -

[edit] Foo bar

-

[edit] Foo bar

- -!! end - -!! test -Resolving duplicate section names with differing case (bug 10721) -!! input -== Foo bar == -== Foo Bar == -!! result -

[edit] Foo bar

-

[edit] Foo Bar

- -!! end - -!! article -Template:sections -!! text -===Section 1=== -==Section 2== -!! endarticle - -!! test -Template with sections, __NOTOC__ -!! input -__NOTOC__ -==Section 0== -{{sections}} -==Section 4== -!! result -

[edit] Section 0

-

[edit] Section 1

-

[edit] Section 2

-

[edit] Section 4

- -!! end - -!! test -__NOEDITSECTION__ keyword -!! input -__NOEDITSECTION__ -==Section 1== -==Section 2== -!! result -

Section 1

-

Section 2

- -!! end - -!! test -Link inside a section heading -!! input -==Section with a [[Main Page|link]] in it== -!! result -

[edit] Section with a link in it

- -!! end - -!! test -TOC regression (bug 12077) -!! input -__TOC__ -== title 1 == -=== title 1.1 === -== title 2 == -!! result -

Contents

- -
-

[edit] title 1

-

[edit] title 1.1

-

[edit] title 2

- -!! end - -!! test -BUG 1219 URL next to image (good) -!! input -http://example.com [[Image:foobar.jpg]] -!! result -

http://example.com Foobar.jpg -

-!!end - -!! test -Short headings with trailing space should match behaviour of Parser::doHeadings (bug 19910) -!! input -=== -The line above must have a trailing space! -=== -But just in case it doesn't... -!! result -

[edit] =

-

The line above must have a trailing space! -

-

[edit] =

-

But just in case it doesn't... -

-!! end - -!! test -BUG 1219 URL next to image (broken) -!! input -http://example.com[[Image:foobar.jpg]] -!! result -

http://example.comFoobar.jpg -

-!!end - -!! test -Bug 1186 news: in the middle of text -!! input -http://en.wikinews.org/wiki/Wikinews:Workplace -!! result -

http://en.wikinews.org/wiki/Wikinews:Workplace -

-!!end - - -!! test -Namespaced link must have a title -!! input -[[Project:]] -!! result -

[[Project:]] -

-!!end - -!! test -Namespaced link must have a title (bad fragment version) -!! input -[[Project:#fragment]] -!! result -

[[Project:#fragment]] -

-!!end - - -!! test -div with no attributes -!! input -
HTML rocks
-!! result -
HTML rocks
- -!! end - -!! test -div with double-quoted attribute -!! input -
HTML rocks
-!! result -
HTML rocks
- -!! end - -!! test -div with single-quoted attribute -!! input -
HTML rocks
-!! result -
HTML rocks
- -!! end - -!! test -div with unquoted attribute -!! input -
HTML rocks
-!! result -
HTML rocks
- -!! end - -!! test -div with illegal double attributes -!! input -
HTML rocks
-!! result -
HTML rocks
- -!!end - -!! test -HTML multiple attributes correction -!! input -

Awesome!

-!! result -

Awesome!

- -!!end - -!! test -Table multiple attributes correction -!! input -{| -!+ class="error" class="awesome"| status -|} -!! result - - -
status -
- -!!end - -!! test -DIV IN UPPERCASE -!! input -
HTML ROCKS
-!! result -
HTML ROCKS
- -!!end - - -!! test -text with amp in the middle of nowhere -!! input -Remember AT&T? -!!result -

Remember AT&T? -

-!! end - -!! test -text with character entity: eacute -!! input -I always thought é was a cute letter. -!! result -

I always thought é was a cute letter. -

-!! end - -!! test -text with undefined character entity: xacute -!! input -I always thought &xacute; was a cute letter. -!! result -

I always thought &xacute; was a cute letter. -

-!! end - - -### -### Media links -### - -!! test -Media link -!! input -[[Media:Foobar.jpg]] -!! result -

Media:Foobar.jpg -

-!! end - -!! test -Media link with text -!! input -[[Media:Foobar.jpg|A neat file to look at]] -!! result -

A neat file to look at -

-!! end - -# FIXME: this is still bad HTML tag nesting -!! test -Media link with nasty text -fixme: doBlockLevels won't wrap this in a paragraph because it contains a div -!! input -[[Media:Foobar.jpg|Safe Link
" onmouseover="alert(document.cookie)" onfoo="
]] -!! result -Safe Link<div style="display:none">" onmouseover="alert(document.cookie)" onfoo="</div> - -!! end - -!! test -Media link to nonexistent file (bug 1702) -!! input -[[Media:No such.jpg]] -!! result -

Media:No such.jpg -

-!! end - -!! test -Image link to nonexistent file (bug 1850 - good) -!! input -[[Image:No such.jpg]] -!! result -

File:No such.jpg -

-!! end - -!! test -:Image link to nonexistent file (bug 1850 - bad) -!! input -[[:Image:No such.jpg]] -!! result -

Image:No such.jpg -

-!! end - - - -!! test -Character reference normalization in link text (bug 1938) -!! input -[[Main Page|this&that]] -!! result -

this&that -

-!!end - -!! article -אַ -!! text -Test for unicode normalization - -The page's name is U+05d0 U+05b7, with non-canonical form U+FB2E -!! endarticle - -!! test -(bug 19451) Links should refer to the normalized form. -!! input -[[אַ]] -[[אַ]] -[[אÖ·]] -[[אַ]] -[[אַ]] -!! result -

-אַ -אÖ· -אַ -אַ -

-!! end - -!! test -Empty attribute crash test (bug 2067) -!! input -foo -!! result -

foo -

-!! end - -!! test -Empty attribute crash test single-quotes (bug 2067) -!! input -foo -!! result -

foo -

-!! end - -!! test -Attribute test: equals, then nothing -!! input -foo -!! result -

foo -

-!! end - -!! test -Attribute test: unquoted value -!! input -foo -!! result -

foo -

-!! end - -!! test -Attribute test: unquoted but illegal value (hash) -!! input -foo -!! result -

foo -

-!! end - -!! test -Attribute test: no value -!! input -foo -!! result -

foo -

-!! end - -!! test -Bug 2095: link with three closing brackets -!! input -[[Main Page]]] -!! result -

Main Page] -

-!! end - -!! test -Bug 2095: link with pipe and three closing brackets -!! input -[[Main Page|link]]] -!! result -

link] -

-!! end - -!! test -Bug 2095: link with pipe and three closing brackets, version 2 -!! input -[[Main Page|[http://example.com/]]] -!! result -

[http://example.com/] -

-!! end - - -### -### Safety -### - -!! article -Template:Dangerous attribute -!! text -" onmouseover="alert(document.cookie) -!! endarticle - -!! article -Template:Dangerous style attribute -!! text -border-size: expression(alert(document.cookie)) -!! endarticle - -!! article -Template:Div style -!! text -
Magic div
-!! endarticle - -!! test -Bug 2304: HTML attribute safety (safe template; regression bug 2309) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (dangerous template; 2309) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (dangerous style template; 2309) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (safe parameter; 2309) -!! input -{{div style|width: 200px}} -!! result -
Magic div
- -!! end - -!! test -Bug 2304: HTML attribute safety (unsafe parameter; 2309) -!! input -{{div style|width: expression(alert(document.cookie))}} -!! result -
Magic div
- -!! end - -!! test -Bug 2304: HTML attribute safety (unsafe breakout parameter; 2309) -!! input -{{div style|">}} -!! result -
<script>alert(document.cookie)</script>">Magic div
- -!! end - -!! test -Bug 2304: HTML attribute safety (unsafe breakout parameter 2; 2309) -!! input -{{div style|" >}} -!! result -
<script>alert(document.cookie)</script>">Magic div
- -!! end - -!! test -Bug 2304: HTML attribute safety (link) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (italics) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (bold) -!! input -
-!! result -
- -!! end - - -!! test -Bug 2304: HTML attribute safety (ISBN) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (RFC) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (PMID) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (web link) -!! input -
-!! result -
- -!! end - -!! test -Bug 2304: HTML attribute safety (named web link) -!! input -
-!! result -
- -!! end - -!! test -Bug 3244: HTML attribute safety (extension; safe) -!! input -
-!! result -
- -!! end - -!! test -Bug 3244: HTML attribute safety (extension; unsafe) -!! input -
-!! result -
- -!! end - -!! test -Math section safety when disabled -!! input - -!! result -

<math><script>alert(document.cookies);</script></math> -

-!! end - -# More MSIE fun discovered by Tom Gilder - -!! test -MSIE CSS safety test: spurious slash -!! input -
evil
-!! result -
evil
- -!! end - -!! test -MSIE CSS safety test: hex code -!! input -
evil
-!! result -
evil
- -!! end - -!! test -MSIE CSS safety test: comment in url -!! input -
evil
-!! result -
evil
- -!! end - -!! test -MSIE CSS safety test: comment in expression -!! input -
evil4
-!! result -
evil4
- -!! end - - -!! test -Table attribute legitimate extension -!! input -{| -!+ style="color:blue"| status -|} -!! result - - -
status -
- -!!end - -!! test -Table attribute safety -!! input -{| -!+ style="border-width:expression(0+alert(document.cookie))"| status -|} -!! result - - -
status -
- -!! end - -!! test -CSS line continuation 1 -!! input -
-!! result -
- -!! end - -!! test -CSS line continuation 2 -!! input -
-!! result -
- -!! end - -!! article -Template:Identity -!! text -{{{1}}} -!! endarticle - -!! test -Expansion of multi-line templates in attribute values (bug 6255) -!! input -
-
-!! result -
-
- -!! end - - -!! test -Expansion of multi-line templates in attribute values (bug 6255 sanity check) -!! input -
-
-!! result -
-
- -!! end - -!! test -Expansion of multi-line templates in attribute values (bug 6255 sanity check 2) -!! input -
-
-!! result -
-
- -!! end - -### -### Parser hooks (see maintenance/parserTestsParserHook.php for the extension) -### -!! test -Parser hook: empty input -!! input - -!! result -
-string(0) ""
-array(0) {
-}
-
- -!! end - -!! test -Parser hook: empty input using terminated empty elements -!! input - -!! result -
-NULL
-array(0) {
-}
-
- -!! end - -!! test -Parser hook: empty input using terminated empty elements (space before) -!! input - -!! result -
-NULL
-array(0) {
-}
-
- -!! end - -!! test -Parser hook: basic input -!! input -input -!! result -
-string(5) "input"
-array(0) {
-}
-
- -!! end - - -!! test -Parser hook: case insensitive -!! input -input -!! result -
-string(5) "input"
-array(0) {
-}
-
- -!! end - - -!! test -Parser hook: case insensitive, redux -!! input -input -!! result -
-string(5) "input"
-array(0) {
-}
-
- -!! end - -!! test -Parser hook: nested tags -!! options -noxml -!! input - -!! result -
-string(5) ""
-array(0) {
-}
-
</tag> - -!! end - -!! test -Parser hook: basic arguments -!! input - -!! result -
-string(0) ""
-array(4) {
-  ["width"]=>
-  string(3) "200"
-  ["height"]=>
-  string(3) "100"
-  ["depth"]=>
-  string(2) "50"
-  ["square"]=>
-  string(6) "square"
-}
-
- -!! end - -!! test -Parser hook: argument containing a forward slash (bug 5344) -!! input - -!! result -
-string(0) ""
-array(1) {
-  ["filename"]=>
-  string(8) "/tmp/bla"
-}
-
- -!! end - -!! test -Parser hook: empty input using terminated empty elements (bug 2374) -!! input -text -!! result -
-NULL
-array(1) {
-  ["foo"]=>
-  string(3) "bar"
-}
-
text - -!! end - -#
should be output literally since there is no matching tag that begins it -!! test -Parser hook: basic arguments using terminated empty elements (bug 2374) -!! input - -other stuff - -!! result -
-NULL
-array(4) {
-  ["width"]=>
-  string(3) "200"
-  ["height"]=>
-  string(3) "100"
-  ["depth"]=>
-  string(2) "50"
-  ["square"]=>
-  string(6) "square"
-}
-
-

other stuff -</tag> -

-!! end - -### -### (see maintenance/parserTestsStaticParserHook.php for the extension) -### - -!! test -Parser hook: static parser hook not inside a comment -!! input -hello, world - -!! result -

hello, world -

-!! end - - -!! test -Parser hook: static parser hook inside a comment -!! input - - -!! result -


-

-!! end - -# Nested template calls; this case was broken by Parser.php rev 1.506, -# since reverted. - -!! article -Template:One-parameter -!! text -(My parameter is: {{{1}}}) -!! endarticle - -!! article -Template:Map-one-parameter -!! text -{{{{{1}}}|{{{2}}}}} -!! endarticle - -!! test -Nested template calls -!! input -{{Map-one-parameter|One-parameter|param}} -!! result -

(My parameter is: param) -

-!! end - - -### -### Sanitizer -### -!! test -Sanitizer: Closing of open tags -!! input -
-!! result -
- -!! end - -!! test -Sanitizer: Closing of open but not closed tags -!! input -foo -!! result -

foo -

-!! end - -!! test -Sanitizer: Closing of closed but not open tags -!! input -
-!! result -

</s> -

-!! end - -!! test -Sanitizer: Closing of closed but not open table tags -!! input -Table not started -!! result -

Table not started</td></tr></table> -

-!! end - -!! test -Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id="" -!! input -byte[[#æ: v|backlink]] -!! result -

bytebacklink -

-!! end - -!! test -Sanitizer: Validating the contents of the id attribute (bug 4515) -!! options -disabled -!! input -
-!! result -Something, but definitely not
... -!! end - -!! test -Sanitizer: Validating id attribute uniqueness (bug 4515, bug 6301) -!! options -disabled -!! input -

-!! result -Something need to be done. foo-2 ? -!! end - -!! test -Language converter: output gets cut off unexpectedly (bug 5757) -!! options -language=zh -!! input -this bit is safe: }- - -but if we add a conversion instance: -{zh-cn:xxx;zh-tw:yyy}- - -then we get cut off here: }- - -all additional text is vanished -!! result -

this bit is safe: }- -

but if we add a conversion instance: xxx -

then we get cut off here: }- -

all additional text is vanished -

-!! end - -!! test -Self closed html pairs (bug 5487) -!! options -!! input -
Centered text
-
In div text
-!! result -
<font id="bug" />Centered text
-
<font id="bug2" />In div text
- -!! end - -# -# -# - -!! test -Punctuation: nbsp before exclamation -!! input -C'est grave ! -!! result -

C'est grave ! -

-!! end - -!! test -Punctuation: CSS !important (bug 11874) -!! input -
important
-!! result -
important
- -!!end - -!! test -Punctuation: CSS ! important (bug 11874; with space after) -!! input -
important
-!! result -
important
- -!!end - - -!! test -HTML bullet list, closed tags (bug 5497) -!! input -
    -
  • One
  • -
  • Two
  • -
-!! result -
    -
  • One
  • -
  • Two
  • -
- -!! end - -!! test -HTML bullet list, unclosed tags (bug 5497) -!! options -disabled -!! input -
    -
  • One -
  • Two -
-!! result -
    -
  • One -
  • Two -
- -!! end - -!! test -HTML ordered list, closed tags (bug 5497) -!! input -
    -
  1. One
  2. -
  3. Two
  4. -
-!! result -
    -
  1. One
  2. -
  3. Two
  4. -
- -!! end - -!! test -HTML ordered list, unclosed tags (bug 5497) -!! options -disabled -!! input -
    -
  1. One -
  2. Two -
-!! result -
    -
  1. One -
  2. Two -
- -!! end - -!! test -HTML nested bullet list, closed tags (bug 5497) -!! input -
    -
  • One
  • -
  • Two: -
      -
    • Sub-one
    • -
    • Sub-two
    • -
    -
  • -
-!! result -
    -
  • One
  • -
  • Two: -
      -
    • Sub-one
    • -
    • Sub-two
    • -
    -
  • -
- -!! end - -!! test -HTML nested bullet list, open tags (bug 5497) -!! options -disabled -!! input -
    -
  • One -
  • Two: -
      -
    • Sub-one -
    • Sub-two -
    -
-!! result -
    -
  • One -
  • Two: -
      -
    • Sub-one -
    • Sub-two -
    -
- -!! end - -!! test -HTML nested ordered list, closed tags (bug 5497) -!! input -
    -
  1. One
  2. -
  3. Two: -
      -
    1. Sub-one
    2. -
    3. Sub-two
    4. -
    -
  4. -
-!! result -
    -
  1. One
  2. -
  3. Two: -
      -
    1. Sub-one
    2. -
    3. Sub-two
    4. -
    -
  4. -
- -!! end - -!! test -HTML nested ordered list, open tags (bug 5497) -!! options -disabled -!! input -
    -
  1. One -
  2. Two: -
      -
    1. Sub-one -
    2. Sub-two -
    -
-!! result -
    -
  1. One -
  2. Two: -
      -
    1. Sub-one -
    2. Sub-two -
    -
- -!! end - -!! test -HTML ordered list item with parameters oddity -!! input -
  1. One
-!! result -
  1. One
- -!! end - -!!test -bug 5918: autonumbering -!! input -[http://first/] [http://second] [ftp://ftp] - -ftp://inlineftp - -[mailto:enclosed@mail.tld With target] - -[mailto:enclosed@mail.tld] - -mailto:inline@mail.tld -!! result -

[1] [2] [3] -

ftp://inlineftp -

With target -

[4] -

mailto:inline@mail.tld -

-!! end - - -# -# Security and HTML correctness -# From Nick Jenkins' fuzz testing -# - -!! test -Fuzz testing: Parser13 -!! input -{| -| http://a| -!! result - - - - -
-
- -!! end - -!! test -Fuzz testing: Parser14 -!! input -== onmouseover= == -http://__TOC__ -!! result -

[edit] onmouseover=

-http://

Contents

- -
- -!! end - -!! test -Fuzz testing: Parser14-table -!! input -==a== -{| STYLE=__TOC__ -!! result -

[edit] a

- - -
- -!! end - -# Known to produce bogus xml (extra ) -!! test -Fuzz testing: Parser16 -!! options -noxml -!! input -{| -!https://|||||| -!! result - - - - - - -
https:// - -
- -!! end - -!! test -Fuzz testing: Parser21 -!! input -{| -! irc://{{ftp://a" onmouseover="alert('hello world');" -| -!! result - - - - - -
irc://{{ftp://a" onmouseover="alert('hello world');" - -
- -!! end - -!! test -Fuzz testing: Parser22 -!! input -http://===r:::https://b - -{| -!!result -

http://===r:::https://b -

- - -
- -!! end - -# Known to produce bad XML for now -!! test -Fuzz testing: Parser24 -!! options -noxml -!! input -{| -{{{| -}}}} > -
- -MOVE YOUR MOUSE CURSOR OVER THIS TEXT -| -!! result - -{{{| -}}}} > -
- -MOVE YOUR MOUSE CURSOR OVER THIS TEXT -
- - -
-
- -!! end - -# Note: the current result listed for this is not what the original one was, -# but the original bug was JavaScript injection, which is fixed in any case. -# It's not clear that the original result listed was any more correct than the -# current one. Original result: -#

{{{| -#

-#
  • -# }}}blah" onmouseover="alert('hello world');" align="left"MOVE MOUSE CURSOR OVER HERE -!!test -Fuzz testing: Parser25 (bug 6055) -!! input -{{{ -| -
  • -}}}blah" onmouseover="alert('hello world');" align="left"'''MOVE MOUSE CURSOR OVER HERE -!! result -

    <LI CLASS=blah" onmouseover="alert('hello world');" align="left"MOVE MOUSE CURSOR OVER HERE -

    -!! end - -!!test -Fuzz testing: URL adjacent extension (with space, clean) -!! options -!! input -http://example.com junk -!! result -

    http://example.com junk -

    -!!end - -!!test -Fuzz testing: URL adjacent extension (no space, dirty; nowiki) -!! options -!! input -http://example.comjunk -!! result -

    http://example.comjunk -

    -!!end - -!!test -Fuzz testing: URL adjacent extension (no space, dirty; pre) -!! options -!! input -http://example.com
    junk
    -!! result -http://example.com
    junk
    - -!!end - -!!test -Fuzz testing: image with bogus manual thumbnail -!!input -[[Image:foobar.jpg|thumbnail= ]] -!!result -
    Error creating thumbnail:
    - -!!end - -!! test -Fuzz testing: encoded newline in generated HTML replacements (bug 6577) -!! input -
    
    -!! result
    -
    
    -
    -!! end
    -
    -!! test
    -Parsing optional HTML elements (Bug 6171)
    -!! options
    -!! input
    -
    -  
    -    
    -    
    -  
    -
    Some tabular data More tabular data ... - And yet som tabular data
    -!! result - - - - - -
    Some tabular data More tabular data ... - And yet som tabular data
    - -!! end - -!! test -Correct handling of , (Bug 6171) -!! options -!! input - - - - - - -
    Some tabular data More tabular data ... And yet som tabular data
    -!! result - - - - - - -
    Some tabular data More tabular data ... And yet som tabular data
    - -!! end - - -!! test -Parsing crashing regression (fr:JavaScript) -!! input - -!! result -

    </body></x> -

    -!! end - -!! test -Inline wiki vs wiki block nesting -!! input -'''Bold paragraph - -New wiki paragraph -!! result -

    Bold paragraph -

    New wiki paragraph -

    -!! end - -!! test -Inline HTML vs wiki block nesting -!! options -disabled -!! input -Bold paragraph - -New wiki paragraph -!! result -

    Bold paragraph -

    New wiki paragraph -

    -!! end - -# Original result was this: -#

    boldboldbolditalics -#

    -# While that might be marginally more intuitive, maybe, the six-apostrophe -# construct is clearly pathological and the result stated here (which is what -# the parser actually does) is about as reasonable as anything. -!!test -Mixing markup for italics and bold -!! options -!! input -'''bold''''''bold''bolditalics''''' -!! result -

    'bold'boldbolditalics -

    -!! end - - -!! article -Xyzzyx -!! text -Article for special page transclusion test -!! endarticle - -!! test -Special page transclusion -!! options -!! input -{{Special:Prefixindex/Xyzzyx}} -!! result -


    -

    -
    Xyzzyx
    - -!! end - -!! test -Special page transclusion twice (bug 5021) -!! options -!! input -{{Special:Prefixindex/Xyzzyx}} -{{Special:Prefixindex/Xyzzyx}} -!! result -


    -

    -
    Xyzzyx
    -


    -

    -
    Xyzzyx
    - -!! end - -!! test -Transclusion of default MediaWiki message -!! input -{{MediaWiki:Mainpage}} -!!result -

    Main Page -

    -!! end - -!! test -Transclusion of nonexistent MediaWiki message -!! input -{{MediaWiki:Mainpagexxx}} -!!result -

    MediaWiki:Mainpagexxx -

    -!! end - -!! test -Transclusion of MediaWiki message with underscore -!! input -{{MediaWiki:history_short}} -!! result -

    History -

    -!! end - -!! test -Transclusion of MediaWiki message with space -!! input -{{MediaWiki:history short}} -!! result -

    History -

    -!! end - -!! test -Invalid header with following text -!! input -= x = y -!! result -

    = x = y -

    -!! end - - -!! test -Section extraction test (section 0) -!! options -section=0 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -!! end - -!! test -Section extraction test (section 1) -!! options -section=1 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -==a== -===aa=== -====aaa==== -!! end - -!! test -Section extraction test (section 2) -!! options -section=2 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -===aa=== -====aaa==== -!! end - -!! test -Section extraction test (section 3) -!! options -section=3 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -====aaa==== -!! end - -!! test -Section extraction test (section 4) -!! options -section=4 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -==b== -===ba=== -===bb=== -====bba==== -===bc=== -!! end - -!! test -Section extraction test (section 5) -!! options -section=5 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -===ba=== -!! end - -!! test -Section extraction test (section 6) -!! options -section=6 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -===bb=== -====bba==== -!! end - -!! test -Section extraction test (section 7) -!! options -section=7 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -====bba==== -!! end - -!! test -Section extraction test (section 8) -!! options -section=8 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -===bc=== -!! end - -!! test -Section extraction test (section 9) -!! options -section=9 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -==c== -===ca=== -!! end - -!! test -Section extraction test (section 10) -!! options -section=10 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -===ca=== -!! end - -!! test -Section extraction test (nonexistent section 11) -!! options -section=11 -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -!! end - -!! test -Section extraction test with bogus heading (section 1) -!! options -section=1 -!! input -==a== -==bogus== not a legal section -==b== -!! result -==a== -==bogus== not a legal section -!! end - -!! test -Section extraction test with bogus heading (section 2) -!! options -section=2 -!! input -==a== -==bogus== not a legal section -==b== -!! result -==b== -!! end - -!! test -Section extraction test with comment after heading (section 1) -!! options -section=1 -!! input -==a== -==b== -==c== -!! result -==a== -!! end - -!! test -Section extraction test with comment after heading (section 2) -!! options -section=2 -!! input -==a== -==b== -==c== -!! result -==b== -!! end - -!! test -Section extraction test with bogus heading (section 1) -!! options -section=1 -!! input -==a== -==bogus== not a legal section -==b== -!! result -==a== -==bogus== not a legal section -!! end - -!! test -Section extraction test with bogus heading (section 2) -!! options -section=2 -!! input -==a== -==bogus== not a legal section -==b== -!! result -==b== -!! end - - -# Formerly testing for bug 2587, now resolved by the use of unmarked sections -# instead of respecting commented sections -!! test -Section extraction prefixed by comment (section 1) -!! options -section=1 -!! input -==sec1== -==sec2== -!!result -==sec2== -!!end - -!! test -Section extraction prefixed by comment (section 2) -!! options -section=2 -!! input -==sec1== -==sec2== -!!result - -!!end - - -# Formerly testing for bug 2607, now resolved by the use of unmarked sections -# instead of respecting HTML-style headings -!! test -Section extraction, mixed wiki and html (section 1) -!! options -section=1 -!! input -

    unmarked

    -unmarked -==1== -one -==2== -two -!! result -==1== -one -!! end - -!! test -Section extraction, mixed wiki and html (section 2) -!! options -section=2 -!! input -

    unmarked

    -unmarked -==1== -one -==2== -two -!! result -==2== -two -!! end - - -# Formerly testing for bug 3342 -!! test -Section extraction, heading surrounded by -!! options -section=1 -!! input -==unmarked== -==marked== -!! result -==marked== -!!end - -# Test behaviour of bug 19910 -!! test -Sectiion with all-equals -!! options -section=2 -!! input -=== -The line above must have a trailing space -=== -But just in case it doesn't... -!! result -=== -But just in case it doesn't... -!! end - -!! test -Section replacement test (section 0) -!! options -replace=0,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -xxx - -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 1) -!! options -replace=1,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -xxx - -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 2) -!! options -replace=2,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -xxx - -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 3) -!! options -replace=3,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -xxx - -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 4) -!! options -replace=4,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -xxx - -==c== -===ca=== -!! end - -!! test -Section replacement test (section 5) -!! options -replace=5,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -==b== -xxx - -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 6) -!! options -replace=6,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -xxx - -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 7) -!! options -replace=7,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -xxx - -===bc=== -==c== -===ca=== -!! end - -!! test -Section replacement test (section 8) -!! options -replace=8,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -xxx - -==c== -===ca=== -!!end - -!! test -Section replacement test (section 9) -!! options -replace=9,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -xxx -!! end - -!! test -Section replacement test (section 10) -!! options -replace=10,"xxx" -!! input -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -===ca=== -!! result -start -==a== -===aa=== -====aaa==== -==b== -===ba=== -===bb=== -====bba==== -===bc=== -==c== -xxx -!! end - -!! test -Section replacement test with initial whitespace (bug 13728) -!! options -replace=2,"xxx" -!! input - Preformatted initial line -==a== -===a=== -!! result - Preformatted initial line -==a== -xxx -!! end - - -!! test -Section extraction, heading followed by pre with 20 spaces (bug 6398) -!! options -section=1 -!! input -==a== - a -!! result -==a== - a -!! end - -!! test -Section extraction, heading followed by pre with 19 spaces (bug 6398 sanity check) -!! options -section=1 -!! input -==a== - a -!! result -==a== - a -!! end - - -!! test -Section extraction,
     around bogus header (bug 10309)
    -!! options
    -noxml section=2
    -!! input
    -== Section One ==
    -
    -=======
    -
    - -== Section Two == -stuff -!! result -== Section Two == -stuff -!! end - -!! test -Section replacement,
     around bogus header (bug 10309)
    -!! options
    -noxml replace=2,"xxx"
    -!! input
    -== Section One ==
    -
    -=======
    -
    - -== Section Two == -stuff -!! result -== Section One == -
    -=======
    -
    - -xxx -!! end - - - -!! test -Handling of in URLs -!! input -**irc:// a -!! result - - -!!end - -!! test -5 quotes, code coverage +1 line -!! input -''''' -!! result -!! end - -!! test -Special:Search page linking. -!! input -{{Special:search}} -!! result -

    Special:Search -

    -!! end - -!! test -Say the magic word -!! input -* {{PAGENAME}} -* {{BASEPAGENAME}} -* {{SUBPAGENAME}} -* {{SUBPAGENAMEE}} -* {{BASEPAGENAME}} -* {{BASEPAGENAMEE}} -* {{TALKPAGENAME}} -* {{TALKPAGENAMEE}} -* {{SUBJECTPAGENAME}} -* {{SUBJECTPAGENAMEE}} -* {{NAMESPACEE}} -* {{NAMESPACE}} -* {{TALKSPACE}} -* {{TALKSPACEE}} -* {{SUBJECTSPACE}} -* {{SUBJECTSPACEE}} -* {{Dynamic|{{NUMBEROFUSERS}}|{{NUMBEROFPAGES}}|{{CURRENTVERSION}}|{{CONTENTLANGUAGE}}|{{DIRECTIONMARK}}|{{CURRENTTIMESTAMP}}|{{NUMBEROFARTICLES}}}} -!! result -
    • Parser test -
    • Parser test -
    • Parser test -
    • Parser_test -
    • Parser test -
    • Parser_test -
    • Talk:Parser test -
    • Talk:Parser_test -
    • Parser test -
    • Parser_test -
    • -
    • -
    • Talk -
    • Talk -
    • -
    • -
    • Template:Dynamic -
    - -!! end -### Note: Above tests excludes the "{{NUMBEROFADMINS}}" magic word because it generates a MySQL error when included. - -!! test -Gallery -!! input - -image1.png | -image2.gif||||| - -image3| -image4 |300px| centre - image5.svg| http:///////// -[[x|xx]]]] -* image6 - -!! result - - - - - - - - - - - - - -!! end - -!! test -Gallery (with options) -!! input - -File:Nonexistant.jpg|caption -File:Nonexistant.jpg -image:foobar.jpg|some '''caption''' [[Main Page]] -image:foobar.jpg - -!! result - - - - - - - - - - - - -!! end - -!! test -gallery (with showfilename option) -!! input - -File:Nonexistant.jpg|caption -File:Nonexistant.jpg -image:foobar.jpg|some '''caption''' [[Main Page]] -File:Foobar.jpg - -!! result - - - - - - - - - -!! end - -!! test -HTML Hex character encoding (spells the word "JavaScript") -!! input -JavaScript -!! result -

    JavaScript -

    -!! end - -!! test -__FORCETOC__ override -!! input -__NEWSECTIONLINK__ -__FORCETOC__ -!! result -


    -

    -!! end - -!! test -ISBN code coverage -!! input -ISBN 978-0-1234-56 789 -!! result -

    ISBN 978-0-1234-56 789 -

    -!! end - -!! test -ISBN followed by 5 spaces -!! input -ISBN -!! result -

    ISBN -

    -!! end - -!! test -Double ISBN -!! input -ISBN ISBN 1234567890 -!! result -

    ISBN ISBN 1234567890 -

    -!! end - -!! test -Bug 22905: followed by ISBN followed by -!! input -(fr) ISBN 2753300917 [http://www.example.com example.com] -!! result -

    (fr) ISBN 2753300917 example.com -

    -!! end - -!! test -Double RFC -!! input -RFC RFC 1234 -!! result -

    RFC RFC 1234 -

    -!! end - -!! test -Double RFC with a wiki link -!! input -RFC [[RFC 1234]] -!! result -

    RFC RFC 1234 -

    -!! end - -!! test -RFC code coverage -!! input -RFC 983 987 -!! result -

    RFC 983 987 -

    -!! end - -!! test -Centre-aligned image -!! input -[[Image:foobar.jpg|centre]] -!! result -
    Foobar.jpg
    - -!!end - -!! test -None-aligned image -!! input -[[Image:foobar.jpg|none]] -!! result -
    Foobar.jpg
    - -!!end - -!! test -Width + Height sized image (using px) (height is ignored) -!! input -[[Image:foobar.jpg|640x480px]] -!! result -

    Foobar.jpg -

    -!!end - -!! test -Width-sized image (using px, no following whitespace) -!! input -[[Image:foobar.jpg|640px]] -!! result -

    Foobar.jpg -

    -!!end - -!! test -Width-sized image (using px, with following whitespace - test regression from r39467) -!! input -[[Image:foobar.jpg|640px ]] -!! result -

    Foobar.jpg -

    -!!end - -!! test -Width-sized image (using px, with preceding whitespace - test regression from r39467) -!! input -[[Image:foobar.jpg| 640px]] -!! result -

    Foobar.jpg -

    -!!end - -!! test -Another italics / bold test -!! input - ''' ''x' -!! result -
    ' x'
    -
    -!!end - -# Note the results may be incorrect, as parserTest output included this: -# XML error: Mismatched tag at byte 6120: -# ...
    -
    -
    -
    -
    -
    -
    - -!!end - - -# Images with the "|" character in external URLs in comment tags; Eats half the comment, leaves unmatched "" tag. -!! test -Images with the "|" character in the comment -!! input -[[image:Foobar.jpg|thumb|An [http://test/?param1=|left|¶m2=|x external] URL]] -!! result -
    An external URL
    - -!!end - -!! test -[Before] HTML without raw HTML enabled ($wgRawHtml==false) -!! input - -!! result -

    <html><script>alert(1);</script></html> -

    -!! end - -!! test -HTML with raw HTML ($wgRawHtml==true) -!! options -rawhtml -!! input - -!! result -

    -

    -!! end - -!! test -Parents of subpages, one level up -!! options -subpage title=[[Subpage test/L1/L2/L3]] -!! input -[[../|L2]] -!! result -

    L2 -

    -!! end - - -!! test -Parents of subpages, one level up, not named -!! options -subpage title=[[Subpage test/L1/L2/L3]] -!! input -[[../]] -!! result -

    Subpage test/L1/L2 -

    -!! end - - - -!! test -Parents of subpages, two levels up -!! options -subpage title=[[Subpage test/L1/L2/L3]] -!! input -[[../../|L1]]2 - -[[../../|L1]]l -!! result -

    L12 -

    L1l -

    -!! end - -!! test -Parents of subpages, two levels up, without trailing slash or name. -!! options -subpage title=[[Subpage test/L1/L2/L3]] -!! input -[[../..]] -!! result -

    [[../..]] -

    -!! end - -!! test -Parents of subpages, two levels up, with lots of extra trailing slashes. -!! options -subpage title=[[Subpage test/L1/L2/L3]] -!! input -[[../../////]] -!! result -

    /// -

    -!! end - -!! test -Definition list code coverage -!! input -; title : def -; title : def -;title: def -!! result -
    title  
    def -
    title 
    def -
    title
    def -
    - -!! end - -!! test -Don't fall for the self-closing div -!! input -
    hello world
    -!! result -
    hello world
    - -!! end - -!! test -MSGNW magic word -!! input -{{MSGNW:msg}} -!! result -

    [[:Template:Msg]] -

    -!! end - -!! test -RAW magic word -!! input -{{RAW:QUERTY}} -!! result -

    Template:QUERTY -

    -!! end - -# This isn't needed for XHTML conformance, but would be handy as a fallback security measure -!! test -Always escape literal '>' in output, not just after '<' -!! input -><> -!! result -

    ><> -

    -!! end - -!! test -Template caching -!! input -{{Test}} -{{Test}} -!! result -

    This is a test template -This is a test template -

    -!! end - - -!! article -MediaWiki:Fake -!! text -==header== -!! endarticle - -!! test -Inclusion of !userCanEdit() content -!! input -{{MediaWiki:Fake}} -!! result -

    [edit] header

    - -!! end - - -!! test -Out-of-order TOC heading levels -!! input -==2== -======6====== -===3=== -=1= -=====5===== -==2== -!! result -

    Contents

    - -
    -

    [edit] 2

    -
    [edit] 6
    -

    [edit] 3

    -

    [edit] 1

    -
    [edit] 5
    -

    [edit] 2

    - -!! end - - -!! test -ISBN with a dummy number -!! input -ISBN --- -!! result -

    ISBN --- -

    -!! end - - -!! test -ISBN with space-delimited number -!! input -ISBN 92 9017 032 8 -!! result -

    ISBN 92 9017 032 8 -

    -!! end - - -!! test -ISBN with multiple spaces, no number -!! input -ISBN foo -!! result -

    ISBN foo -

    -!! end - - -!! test -ISBN length -!! input -ISBN 123456789 - -ISBN 1234567890 - -ISBN 12345678901 -!! result -

    ISBN 123456789 -

    ISBN 1234567890 -

    ISBN 12345678901 -

    -!! end - - -!! test -ISBN with trailing year (bug 8110) -!! input -ISBN 1-234-56789-0 - 2006 - -ISBN 1 234 56789 0 - 2006 -!! result -

    ISBN 1-234-56789-0 - 2006 -

    ISBN 1 234 56789 0 - 2006 -

    -!! end - - -!! test -anchorencode -!! input -{{anchorencode:foo bar©#%n}} -!! result -

    foo_bar.C2.A9.23.25n -

    -!! end - -!! test -anchorencode trims spaces -!! input -{{anchorencode: __pretty__please__}} -!! result -

    pretty_please -

    -!! end - -!! test -anchorencode deals with links -!! input -{{anchorencode: [[hello|world]] [[hi]]}} -!! result -

    world_hi -

    -!! end - -!! test -anchorencode deals with templates -!! input -{{anchorencode: {{Foo}} }} -!! result -

    FOO -

    -!! end - -!! test -anchorencode encodes like the TOC generator: (bug 18431) -!! input -=== _ +:.3A%3A&&]] === -{{anchorencode: _ +:.3A%3A&&]] }} -__NOEDITSECTION__ -!! result -

    _ +:.3A%3A&&]]

    -

    .2B:.3A.253A.26.26.5D.5D -

    -!! end - -# Expected output in the following test is not necessarily expected (there -# should probably be

    tags inside the

    in the output) -- it's -# only testing for well-formedness. -!! test -Bug 6200: blockquotes and paragraph formatting -!! input -
    -foo -
    - -bar - - baz -!! result -
    -foo -
    -

    bar -

    -
    baz
    -
    -!! end - -!! test -Bug 8293: Use of center tag ruins paragraph formatting -!! input -
    -foo -
    - -bar - - baz -!! result -
    -

    foo -

    -
    -

    bar -

    -
    baz
    -
    -!! end - - -### -### Language variants related tests -### -!! test -Self-link in language variants -!! options -title=[[Dunav]] language=sr -!! input -Both [[Dunav]] and [[Дунав]] are names for this river. -!! result -

    Both Dunav and Дунав are names for this river. -

    -!!end - - -!! test -Link to pages in language variants -!! options -language=sr -!! input -Main Page can be written as [[Маин Паге]] -!! result -

    Main Page can be written as Маин Паге -

    -!!end - - -!! test -Multiple links to pages in language variants -!! options -language=sr -!! input -[[Main Page]] can be written as [[Маин Паге]] same as [[Маин Паге]]. -!! result -

    Main Page can be written as Маин Паге same as Маин Паге. -

    -!!end - - -!! test -Simple template in language variants -!! options -language=sr -!! input -{{тест}} -!! result -

    This is a test template -

    -!! end - - -!! test -Template with explicit namespace in language variants -!! options -language=sr -!! input -{{Template:тест}} -!! result -

    This is a test template -

    -!! end - - -!! test -Basic test for template parameter in language variants -!! options -language=sr -!! input -{{парамтест|param=foo}} -!! result -

    This is a test template with parameter foo -

    -!! end - - -!! test -Simple category in language variants -!! options -language=sr cat -!! input -[[Category:МедиаWики Усер'с Гуиде]] -!! result -MediaWiki User's Guide -!! end - - -!! test -Stripping -{}- tags (language variants) -!! options -language=sr -!! input -Latin proverb: -{Ne nuntium necare}- -!! result -

    Latin proverb: Ne nuntium necare -

    -!! end - - -!! test -Prevent conversion with -{}- tags (language variants) -!! options -language=sr variant=sr-ec -!! input -Latinski: -{Ne nuntium necare}- -!! result -

    Латински: Ne nuntium necare -

    -!! end - - -!! test -Prevent conversion of text with -{}- tags (language variants) -!! options -language=sr variant=sr-ec -!! input -Latinski: -{Ne nuntium necare}- -!! result -

    Латински: Ne nuntium necare -

    -!! end - - -!! test -Prevent conversion of links with -{}- tags (language variants) -!! options -language=sr variant=sr-ec -!! input --{[[Main Page]]}- -!! result -

    Main Page -

    -!! end - - -!! test --{}- tags within headlines (within html for parserConvert()) -!! options -language=sr variant=sr-ec -!! input -== -{Naslov}- == -!! result -

    [уреди] Naslov

    - -!! end - - -!! test -Explicit definition of language variant alternatives -!! options -language=zh variant=zh-tw -!! input --{zh:China;zh-tw:Taiwan}-, not China -!! result -

    Taiwan, not China -

    -!! end - - -!! test -Explicit session-wise language variant mapping (A flag and - flag) -!! options -language=zh variant=zh-tw -!! input -Taiwan is not China. -But -{A|zh:China;zh-tw:Taiwan}- is China, -(This-{-|zh:China;zh-tw:Taiwan}- should be stripped!) -and -{China}- is China. -!! result -

    Taiwan is not China. -But Taiwan is Taiwan, -(This should be stripped!) -and China is China. -

    -!! end - -!! test -Explicit session-wise language variant mapping (H flag for hide) -!! options -language=zh variant=zh-tw -!! input -(This-{H|zh:China;zh-tw:Taiwan}- should be stripped!) -Taiwan is China. -!! result -

    (This should be stripped!) -Taiwan is Taiwan. -

    -!! end - -!! test -Adding explicit conversion rule for title (T flag) -!! options -language=zh variant=zh-tw showtitle -!! input -Should be stripped-{T|zh:China;zh-tw:Taiwan}-! -!! result -Taiwan -

    Should be stripped! -

    -!! end - -!! test -Testing that changing the language variant here in the tests actually works -!! options -language=zh variant=zh showtitle -!! input -Should be stripped-{T|zh:China;zh-tw:Taiwan}-! -!! result -China -

    Should be stripped! -

    -!! end - -!! test -Bug 24072: more test on conversion rule for title -!! options -language=zh variant=zh-tw showtitle -!! input -This should be stripped-{T|zh:China;zh-tw:Taiwan}-! -This won't take interferes with the title rule-{H|zh:Beijing;zh-tw:Taipei}-. -!! result -Taiwan -

    This should be stripped! -This won't take interferes with the title rule. -

    -!! end - -!! test -Raw output of variant escape tags (R flag) -!! options -language=zh variant=zh-tw -!! input -Raw: -{R|zh:China;zh-tw:Taiwan}- -!! result -

    Raw: zh:China;zh-tw:Taiwan -

    -!! end - -!! test -Nested using of manual convert syntax -!! options -language=zh variant=zh-hk -!! input -Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiwan;zh-hk:H-{ong}- K-{}-ong;}-;}-! -!! result -

    Nested: Hello Hong Kong! -

    -!! end - -!! test -Do not convert roman numbers to language variants -!! options -language=sr variant=sr-ec -!! input -Fridrih IV je car. -!! result -

    Фридрих IV је цар. -

    -!! end - -!! test -Unclosed language converter markup "-{" -!! options -language=sr -!! input --{T|hello -!! result -

    -{T|hello -

    -!! end - -!! test -Don't convert raw rule "-{R|=>}-" to "=>" -!! options -language=sr -!! input --{R|=>}- -!! result -

    => -

    -!!end - -!!article -Template:Bullet -!!text -* Bar -!!endarticle - -!! test -Bug 529: Uncovered bullet -!! input -* Foo {{bullet}} -!! result -
    • Foo -
    • Bar -
    - -!! end - -!! test -Bug 529: Uncovered table already at line-start -!! input -x - -{{table}} -y -!! result -

    x -

    - - - - - - -
    1 2 -
    3 4 -
    -

    y -

    -!! end - -!! test -Bug 529: Uncovered bullet in parser function result -!! input -* Foo {{lc:{{bullet}} }} -!! result -
    • Foo -
    • bar -
    - -!! end - -!! test -Bug 5678: Double-parsed template argument -!! input -{{lc:{{{1}}}|hello}} -!! result -

    {{{1}}} -

    -!! end - -!! test -Bug 5678: Double-parsed template invocation -!! input -{{lc:{{paramtest {{!}} param = hello }} }} -!! result -

    {{paramtest | param = hello }} -

    -!! end - -!! test -Case insensitivity of parser functions for non-ASCII characters (bug 8143) -!! options -language=cs -title=[[Main Page]] -!! input -{{PRVNÍVELKÉ:ěščř}} -{{prvnívelké:ěščř}} -{{PRVNÍMALÉ:ěščř}} -{{prvnímalé:ěščř}} -{{MALÁ:ěščř}} -{{malá:ěščř}} -{{VELKÁ:ěščř}} -{{velká:ěščř}} -!! result -

    Ěščř -Ěščř -ěščř -ěščř -ěščř -ěščř -ĚŠČŘ -ĚŠČŘ -

    -!! end - -!! test -Morwen/13: Unclosed link followed by heading -!! input -[[link -==heading== -!! result -

    [[link -

    -

    [edit] heading

    - -!! end - -!! test -HHP2.1: Heuristics for headings in preprocessor parenthetical structures -!! input -{{foo| -=heading= -!! result -

    {{foo| -

    -

    heading

    - -!! end - -!! test -HHP2.2: Heuristics for headings in preprocessor parenthetical structures -!! input -{{foo| -==heading== -!! result -

    {{foo| -

    -

    [edit] heading

    - -!! end - -!! test -Tildes in comments -!! options -pst -!! input - -!! result - -!! end - -!! test -Paragraphs inside divs (no extra line breaks) -!! input -
    Line one - -Line two
    -!! result -
    Line one -Line two
    - -!! end - -!! test -Paragraphs inside divs (extra line break on open) -!! input -
    -Line one - -Line two
    -!! result -
    -

    Line one -

    -Line two
    - -!! end - -!! test -Paragraphs inside divs (extra line break on close) -!! input -
    Line one - -Line two -
    -!! result -
    Line one -

    Line two -

    -
    - -!! end - -!! test -Paragraphs inside divs (extra line break on open and close) -!! input -
    -Line one - -Line two -
    -!! result -
    -

    Line one -

    Line two -

    -
    - -!! end - -!! test -Nesting tags, paragraphs on lines which begin with
    -!! options -disabled -!! input -
    A -B -!! result -
    -

    A -B -

    -!! end - -# Bug 6200:
    should behave like
    with respect to line breaks -!! test -Bug 6200: paragraphs inside blockquotes (no extra line breaks) -!! options -disabled -!! input -
    Line one - -Line two
    -!! result -
    Line one -Line two
    - -!! end - -!! test -Bug 6200: paragraphs inside blockquotes (extra line break on open) -!! options -disabled -!! input -
    -Line one - -Line two
    -!! result -
    -

    Line one -

    -Line two
    - -!! end - -!! test -Bug 6200: paragraphs inside blockquotes (extra line break on close) -!! options -disabled -!! input -
    Line one - -Line two -
    -!! result -
    Line one -

    Line two -

    -
    - -!! end - -!! test -Bug 6200: paragraphs inside blockquotes (extra line break on open and close) -!! options -disabled -!! input -
    -Line one - -Line two -
    -!! result -
    -

    Line one -

    Line two -

    -
    - -!! end - -!! test -Paragraphs inside blockquotes/divs (no extra line breaks) -!! input -
    Line one - -Line two
    -!! result -
    Line one -Line two
    - -!! end - -!! test -Paragraphs inside blockquotes/divs (extra line break on open) -!! input -
    -Line one - -Line two
    -!! result -
    -

    Line one -

    -Line two
    - -!! end - -!! test -Paragraphs inside blockquotes/divs (extra line break on close) -!! input -
    Line one - -Line two -
    -!! result -
    Line one -

    Line two -

    -
    - -!! end - -!! test -Paragraphs inside blockquotes/divs (extra line break on open and close) -!! input -
    -Line one - -Line two -
    -!! result -
    -

    Line one -

    Line two -

    -
    - -!! end - -!! test -Interwiki links trounced by replaceExternalLinks after early LinkHolderArray expansion -!! options -wgLinkHolderBatchSize=0 -!! input -[[meatball:1]] -[[meatball:2]] -[[meatball:3]] -!! result -

    meatball:1 -meatball:2 -meatball:3 -

    -!! end - -!! test -Free external link invading image caption -!! input -[[Image:Foobar.jpg|thumb|http://x|hello]] -!! result -
    hello
    - -!! end - -!! test -Bug 15196: localised external link numbers -!! options -language=fa -!! input -[http://en.wikipedia.org/] -!! result -

    [Û±] -

    -!! end - -!! test -Multibyte character in padleft -!! input -{{padleft:-Hello|7|Æ}} -!! result -

    Æ-Hello -

    -!! end - -!! test -Multibyte character in padright -!! input -{{padright:Hello-|7|Æ}} -!! result -

    Hello-Æ -

    -!! end - -!! test -Formatted date -!! config -wgUseDynamicDates=1 -!! input -[[2009-03-24]] -!! result -

    2009-03-24 -

    -!!end - -!!test -formatdate parser function -!!input -{{#formatdate:2009-03-24}} -!! result -

    2009-03-24 -

    -!! end - -!!test -formatdate parser function, with default format -!!input -{{#formatdate:2009-03-24|mdy}} -!! result -

    March 24, 2009 -

    -!! end - -!! test -Linked date with autoformatting disabled -!! config -wgUseDynamicDates=false -!! input -[[2009-03-24]] -!! result -

    2009-03-24 -

    -!! end - -!! test -Spacing of numbers in formatted dates -!! input -{{#formatdate:January 15}} -!! result -

    January 15 -

    -!! end - -!! test -Spacing of numbers in formatted dates (linked) -!! config -wgUseDynamicDates=true -!! input -[[January 15]] -!! result -

    January 15 -

    -!! end - -# -# -# - -# -# Edit comments -# - -!! test -Edit comment with link -!! options -comment -!! input -I like the [[Main Page]] a lot -!! result -I like the Main Page a lot -!!end - -!! test -Edit comment with link and link text -!! options -comment -!! input -I like the [[Main Page|best pages]] a lot -!! result -I like the best pages a lot -!!end - -!! test -Edit comment with link and link text with suffix -!! options -comment -!! input -I like the [[Main Page|best page]]s a lot -!! result -I like the best pages a lot -!!end - -!! test -Edit comment with section link (non-local, eg in history list) -!! options -comment title=[[Main Page]] -!! input -/* External links */ removed bogus entries -!! result -→External links: removed bogus entries -!!end - -!! test -Edit comment with section link (local, eg in diff view) -!! options -comment local title=[[Main Page]] -!! input -/* External links */ removed bogus entries -!! result -→External links: removed bogus entries -!!end - -!! test -Edit comment with subpage link (bug 14080) -!! options -comment -subpage -title=[[Subpage test]] -!! input -Poked at a [[/subpage]] here... -!! result -Poked at a /subpage here... -!!end - -!! test -Edit comment with subpage link and link text (bug 14080) -!! options -comment -subpage -title=[[Subpage test]] -!! input -Poked at a [[/subpage|neat little page]] here... -!! result -Poked at a neat little page here... -!!end - -!! test -Edit comment with bogus subpage link in non-subpage NS (bug 14080) -!! options -comment -title=[[Subpage test]] -!! input -Poked at a [[/subpage]] here... -!! result -Poked at a /subpage here... -!!end - -!! test -Edit comment with bare anchor link (local, as on diff) -!! options -comment -local -title=[[Main Page]] -!!input -[[#section]] -!! result -#section -!! end - -!! test -Edit comment with bare anchor link (non-local, as on history) -!! options -comment -title=[[Main Page]] -!!input -[[#section]] -!! result -#section -!! end - -!! test -Space normalisation on autocomment (bug 22784) -!! options -comment -title=[[Main Page]] -!!input -/* __hello__world__ */ -!! result -→__hello__world__ -!! end - -!! test -Bad images - basic functionality -!! input -[[File:Bad.jpg]] -!! result -!! end - -!! test -Bad images - bug 16039: text after bad image disappears -!! input -Foo bar -[[File:Bad.jpg]] -Bar foo -!! result -

    Foo bar -

    Bar foo -

    -!! end - -!! test -Verify that displaytitle works (bug #22501) no displaytitle -!! options -showtitle -!! config -wgAllowDisplayTitle=true -wgRestrictDisplayTitle=false -!! input -this is not the the title -!! result -Parser test -

    this is not the the title -

    -!! end - -!! test -Verify that displaytitle works (bug #22501) RestrictDisplayTitle=false -!! options -showtitle -title=[[Screen]] -!! config -wgAllowDisplayTitle=true -wgRestrictDisplayTitle=false -!! input -this is not the the title -{{DISPLAYTITLE:whatever}} -!! result -whatever -

    this is not the the title -

    -!! end - -!! test -Verify that displaytitle works (bug #22501) RestrictDisplayTitle=true mismatch -!! options -showtitle -title=[[Screen]] -!! config -wgAllowDisplayTitle=true -wgRestrictDisplayTitle=true -!! input -this is not the the title -{{DISPLAYTITLE:whatever}} -!! result -Screen -

    this is not the the title -

    -!! end - -!! test -Verify that displaytitle works (bug #22501) RestrictDisplayTitle=true matching -!! options -showtitle -title=[[Screen]] -!! config -wgAllowDisplayTitle=true -wgRestrictDisplayTitle=true -!! input -this is not the the title -{{DISPLAYTITLE:screen}} -!! result -screen -

    this is not the the title -

    -!! end - -!! test -Verify that displaytitle works (bug #22501) AllowDisplayTitle=false -!! options -showtitle -title=[[Screen]] -!! config -wgAllowDisplayTitle=false -!! input -this is not the the title -{{DISPLAYTITLE:screen}} -!! result -Screen -

    this is not the the title -Template:DISPLAYTITLE:screen -

    -!! end - -!! test -Verify that displaytitle works (bug #22501) AllowDisplayTitle=false no DISPLAYTITLE -!! options -showtitle -title=[[Screen]] -!! config -wgAllowDisplayTitle=false -!! input -this is not the the title -!! result -Screen -

    this is not the the title -

    -!! end - -!! test -preload: check and -!! options -preload -!! input -Hello cruelkind world. -!! result -Hello kind world. -!! end - -!! test -preload: check -!! options -preload -!! input -Goodbye Hello world -!! result -Hello world -!! end - -!! test -preload: can pass tags through if we want to -!! options -preload -!! input -<includeonly>Hello world</includeonly> -!! result -Hello world -!! end - -!! test -preload: check that it doesn't try to do tricks -!! options -preload -!! input -* ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}} -!! result -* ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}} -!! end - -!! test -Play a bit with r67090 and bug 3158 -!! options -disabled -!! input -
     
    -
     
    -
     
    -
     
    -!! result -
     
    -
     
    -
     
    -
     
    - -!! end - -!! test -HTML5 data attributes -!! input -Baz -

    Quuz

    -!! result -

    Baz -

    -

    Quuz

    - -!! end - - -TODO: -more images -more tables -math -character entities -and much more -Try for 100% code coverage diff --git a/maintenance/parserTestsParserHook.php b/maintenance/parserTestsParserHook.php deleted file mode 100644 index 6387208af3..0000000000 --- a/maintenance/parserTestsParserHook.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ - -class ParserTestParserHook { - - static function setup( &$parser ) { - $parser->setHook( 'tag', array( __CLASS__, 'hook' ) ); - - return true; - } - - static function hook( $in, $argv ) { - ob_start(); - var_dump( - $in, - $argv - ); - $ret = ob_get_clean(); - - return "
    \n$ret
    "; - } -} diff --git a/maintenance/parserTestsStaticParserHook.php b/maintenance/parserTestsStaticParserHook.php deleted file mode 100644 index 72f82276c8..0000000000 --- a/maintenance/parserTestsStaticParserHook.php +++ /dev/null @@ -1,58 +0,0 @@ - - */ - -class ParserTestStaticParserHook { - static function setup( &$parser ) { - $parser->setHook( 'statictag', array( __CLASS__, 'hook' ) ); - - return true; - } - - static function hook( $in, $argv, $parser ) { - if ( ! count( $argv ) ) { - $parser->static_tag_buf = $in; - return ''; - } else if ( count( $argv ) === 1 && isset( $argv['action'] ) - && $argv['action'] === 'flush' && $in === null ) - { - // Clear the buffer, we probably don't need to - if ( isset( $parser->static_tag_buf ) ) { - $tmp = $parser->static_tag_buf; - } else { - $tmp = ''; - } - $parser->static_tag_buf = null; - return $tmp; - } else - // wtf? - return - "\nCall this extension as string or as" . - " , not in any other way.\n" . - "text: " . var_export( $in, true ) . "\n" . - "argv: " . var_export( $argv, true ) . "\n"; - } -} diff --git a/maintenance/tests/parser/ExtraParserTests.txt b/maintenance/tests/parser/ExtraParserTests.txt new file mode 100644 index 0000000000..66b8032d18 Binary files /dev/null and b/maintenance/tests/parser/ExtraParserTests.txt differ diff --git a/maintenance/tests/parser/parserTest.inc b/maintenance/tests/parser/parserTest.inc new file mode 100644 index 0000000000..86ba03f8c5 --- /dev/null +++ b/maintenance/tests/parser/parserTest.inc @@ -0,0 +1,1231 @@ + +# http://www.mediawiki.org/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.gnu.org/copyleft/gpl.html + +/** + * @todo Make this more independent of the configuration (and if possible the database) + * @todo document + * @file + * @ingroup Maintenance + */ + +/** + * @ingroup Maintenance + */ +class ParserTest { + /** + * boolean $color whereas output should be colorized + */ + private $color; + + /** + * boolean $showOutput Show test output + */ + private $showOutput; + + /** + * boolean $useTemporaryTables Use temporary tables for the temporary database + */ + private $useTemporaryTables = true; + + /** + * boolean $databaseSetupDone True if the database has been set up + */ + private $databaseSetupDone = false; + + /** + * string $oldTablePrefix Original table prefix + */ + private $oldTablePrefix; + + private $maxFuzzTestLength = 300; + private $fuzzSeed = 0; + private $memoryLimit = 50; + + /** + * Sets terminal colorization and diff/quick modes depending on OS and + * command-line options (--color and --quick). + */ + public function ParserTest( $options = array() ) { + # Only colorize output if stdout is a terminal. + $this->color = !wfIsWindows() && posix_isatty( 1 ); + + if ( isset( $options['color'] ) ) { + switch( $options['color'] ) { + case 'no': + $this->color = false; + break; + case 'yes': + default: + $this->color = true; + break; + } + } + + $this->term = $this->color + ? new AnsiTermColorer() + : new DummyTermColorer(); + + $this->showDiffs = !isset( $options['quick'] ); + $this->showProgress = !isset( $options['quiet'] ); + $this->showFailure = !( + isset( $options['quiet'] ) + && ( isset( $options['record'] ) + || isset( $options['compare'] ) ) ); // redundant output + + $this->showOutput = isset( $options['show-output'] ); + + + if ( isset( $options['regex'] ) ) { + if ( isset( $options['record'] ) ) { + echo "Warning: --record cannot be used with --regex, disabling --record\n"; + unset( $options['record'] ); + } + $this->regex = $options['regex']; + } else { + # Matches anything + $this->regex = ''; + } + + $this->setupRecorder( $options ); + $this->keepUploads = isset( $options['keep-uploads'] ); + + if ( isset( $options['seed'] ) ) { + $this->fuzzSeed = intval( $options['seed'] ) - 1; + } + + $this->runDisabled = isset( $options['run-disabled'] ); + + $this->hooks = array(); + $this->functionHooks = array(); + } + + public function setupRecorder ( $options ) { + if ( isset( $options['record'] ) ) { + $this->recorder = new DbTestRecorder( $this ); + $this->recorder->version = isset( $options['setversion'] ) ? + $options['setversion'] : SpecialVersion::getVersion(); + } elseif ( isset( $options['compare'] ) ) { + $this->recorder = new DbTestPreviewer( $this ); + } elseif ( isset( $options['upload'] ) ) { + $this->recorder = new RemoteTestRecorder( $this ); + } else { + $this->recorder = new TestRecorder( $this ); + } + } + + /** + * Remove last character if it is a newline + */ + public function chomp( $s ) { + if ( substr( $s, -1 ) === "\n" ) { + return substr( $s, 0, -1 ); + } + else { + return $s; + } + } + + /** + * Run a fuzz test series + * Draw input from a set of test files + */ + function fuzzTest( $filenames ) { + $GLOBALS['wgContLang'] = Language::factory( 'en' ); + $dict = $this->getFuzzInput( $filenames ); + $dictSize = strlen( $dict ); + $logMaxLength = log( $this->maxFuzzTestLength ); + $this->setupDatabase(); + ini_set( 'memory_limit', $this->memoryLimit * 1048576 ); + + $numTotal = 0; + $numSuccess = 0; + $user = new User; + $opts = ParserOptions::newFromUser( $user ); + $title = Title::makeTitle( NS_MAIN, 'Parser_test' ); + + while ( true ) { + // Generate test input + mt_srand( ++$this->fuzzSeed ); + $totalLength = mt_rand( 1, $this->maxFuzzTestLength ); + $input = ''; + + while ( strlen( $input ) < $totalLength ) { + $logHairLength = mt_rand( 0, 1000000 ) / 1000000 * $logMaxLength; + $hairLength = min( intval( exp( $logHairLength ) ), $dictSize ); + $offset = mt_rand( 0, $dictSize - $hairLength ); + $input .= substr( $dict, $offset, $hairLength ); + } + + $this->setupGlobals(); + $parser = $this->getParser(); + + // Run the test + try { + $parser->parse( $input, $title, $opts ); + $fail = false; + } catch ( Exception $exception ) { + $fail = true; + } + + if ( $fail ) { + echo "Test failed with seed {$this->fuzzSeed}\n"; + echo "Input:\n"; + var_dump( $input ); + echo "\n\n"; + echo "$exception\n"; + } else { + $numSuccess++; + } + + $numTotal++; + $this->teardownGlobals(); + $parser->__destruct(); + + if ( $numTotal % 100 == 0 ) { + $usage = intval( memory_get_usage( true ) / $this->memoryLimit / 1048576 * 100 ); + echo "{$this->fuzzSeed}: $numSuccess/$numTotal (mem: $usage%)\n"; + if ( $usage > 90 ) { + echo "Out of memory:\n"; + $memStats = $this->getMemoryBreakdown(); + + foreach ( $memStats as $name => $usage ) { + echo "$name: $usage\n"; + } + $this->abort(); + } + } + } + } + + /** + * Get an input dictionary from a set of parser test files + */ + function getFuzzInput( $filenames ) { + $dict = ''; + + foreach ( $filenames as $filename ) { + $contents = file_get_contents( $filename ); + preg_match_all( '/!!\s*input\n(.*?)\n!!\s*result/s', $contents, $matches ); + + foreach ( $matches[1] as $match ) { + $dict .= $match . "\n"; + } + } + + return $dict; + } + + /** + * Get a memory usage breakdown + */ + function getMemoryBreakdown() { + $memStats = array(); + + foreach ( $GLOBALS as $name => $value ) { + $memStats['$' . $name] = strlen( serialize( $value ) ); + } + + $classes = get_declared_classes(); + + foreach ( $classes as $class ) { + $rc = new ReflectionClass( $class ); + $props = $rc->getStaticProperties(); + $memStats[$class] = strlen( serialize( $props ) ); + $methods = $rc->getMethods(); + + foreach ( $methods as $method ) { + $memStats[$class] += strlen( serialize( $method->getStaticVariables() ) ); + } + } + + $functions = get_defined_functions(); + + foreach ( $functions['user'] as $function ) { + $rf = new ReflectionFunction( $function ); + $memStats["$function()"] = strlen( serialize( $rf->getStaticVariables() ) ); + } + + asort( $memStats ); + + return $memStats; + } + + function abort() { + $this->abort(); + } + + /** + * Run a series of tests listed in the given text files. + * Each test consists of a brief description, wikitext input, + * and the expected HTML output. + * + * Prints status updates on stdout and counts up the total + * number and percentage of passed tests. + * + * @param $filenames Array of strings + * @return Boolean: true if passed all tests, false if any tests failed. + */ + public function runTestsFromFiles( $filenames ) { + $GLOBALS['wgContLang'] = Language::factory( 'en' ); + $this->recorder->start(); + $this->setupDatabase(); + $ok = true; + + foreach ( $filenames as $filename ) { + $tests = new TestFileIterator( $filename, $this ); + $ok = $this->runTests( $tests ) && $ok; + } + + $this->teardownDatabase(); + $this->recorder->report(); + $this->recorder->end(); + + return $ok; + } + + function runTests( $tests ) { + $ok = true; + + foreach ( $tests as $i => $t ) { + $result = + $this->runTest( $t['test'], $t['input'], $t['result'], $t['options'], $t['config'] ); + $ok = $ok && $result; + $this->recorder->record( $t['test'], $result ); + } + + if ( $this->showProgress ) { + print "\n"; + } + + return $ok; + } + + /** + * Get a Parser object + */ + function getParser( $preprocessor = null ) { + global $wgParserConf; + + $class = $wgParserConf['class']; + $parser = new $class( array( 'preprocessorClass' => $preprocessor ) + $wgParserConf ); + + foreach ( $this->hooks as $tag => $callback ) { + $parser->setHook( $tag, $callback ); + } + + foreach ( $this->functionHooks as $tag => $bits ) { + list( $callback, $flags ) = $bits; + $parser->setFunctionHook( $tag, $callback, $flags ); + } + + wfRunHooks( 'ParserTestParser', array( &$parser ) ); + + return $parser; + } + + /** + * Run a given wikitext input through a freshly-constructed wiki parser, + * and compare the output against the expected results. + * Prints status and explanatory messages to stdout. + * + * @param $desc String: test's description + * @param $input String: wikitext to try rendering + * @param $result String: result to output + * @param $opts Array: test's options + * @param $config String: overrides for global variables, one per line + * @return Boolean + */ + public function runTest( $desc, $input, $result, $opts, $config ) { + if ( $this->showProgress ) { + $this->showTesting( $desc ); + } + + $opts = $this->parseOptions( $opts ); + $this->setupGlobals( $opts, $config ); + + $user = new User(); + $options = ParserOptions::newFromUser( $user ); + + if ( isset( $opts['title'] ) ) { + $titleText = $opts['title']; + } + else { + $titleText = 'Parser test'; + } + + $noxml = isset( $opts['noxml'] ); + $local = isset( $opts['local'] ); + $preprocessor = isset( $opts['preprocessor'] ) ? $opts['preprocessor'] : null; + $parser = $this->getParser( $preprocessor ); + $title = Title::newFromText( $titleText ); + + if ( isset( $opts['pst'] ) ) { + $out = $parser->preSaveTransform( $input, $title, $user, $options ); + } elseif ( isset( $opts['msg'] ) ) { + $out = $parser->transformMsg( $input, $options ); + } elseif ( isset( $opts['section'] ) ) { + $section = $opts['section']; + $out = $parser->getSection( $input, $section ); + } elseif ( isset( $opts['replace'] ) ) { + $section = $opts['replace'][0]; + $replace = $opts['replace'][1]; + $out = $parser->replaceSection( $input, $section, $replace ); + } elseif ( isset( $opts['comment'] ) ) { + $linker = $user->getSkin(); + $out = $linker->formatComment( $input, $title, $local ); + } elseif ( isset( $opts['preload'] ) ) { + $out = $parser->getpreloadText( $input, $title, $options ); + } else { + $output = $parser->parse( $input, $title, $options, true, true, 1337 ); + $out = $output->getText(); + + if ( isset( $opts['showtitle'] ) ) { + if ( $output->getTitleText() ) { + $title = $output->getTitleText(); + } + + $out = "$title\n$out"; + } + + if ( isset( $opts['ill'] ) ) { + $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) ); + } elseif ( isset( $opts['cat'] ) ) { + global $wgOut; + + $wgOut->addCategoryLinks( $output->getCategories() ); + $cats = $wgOut->getCategoryLinks(); + + if ( isset( $cats['normal'] ) ) { + $out = $this->tidy( implode( ' ', $cats['normal'] ) ); + } else { + $out = ''; + } + } + + $result = $this->tidy( $result ); + } + + + $this->teardownGlobals(); + + if ( $result === $out && ( $noxml === true || $this->wellFormed( $out ) ) ) { + return $this->showSuccess( $desc ); + } else { + return $this->showFailure( $desc, $result, $out ); + } + } + + /** + * Use a regex to find out the value of an option + * @param $key String: name of option val to retrieve + * @param $opts Options array to look in + * @param $default Mixed: default value returned if not found + */ + private static function getOptionValue( $key, $opts, $default ) { + $key = strtolower( $key ); + + if ( isset( $opts[$key] ) ) { + return $opts[$key]; + } else { + return $default; + } + } + + private function parseOptions( $instring ) { + $opts = array(); + $lines = explode( "\n", $instring ); + // foo + // foo=bar + // foo="bar baz" + // foo=[[bar baz]] + // foo=bar,"baz quux" + $regex = '/\b + ([\w-]+) # Key + \b + (?:\s* + = # First sub-value + \s* + ( + " + [^"]* # Quoted val + " + | + \[\[ + [^]]* # Link target + \]\] + | + [\w-]+ # Plain word + ) + (?:\s* + , # Sub-vals 1..N + \s* + ( + "[^"]*" # Quoted val + | + \[\[[^]]*\]\] # Link target + | + [\w-]+ # Plain word + ) + )* + )? + /x'; + + if ( preg_match_all( $regex, $instring, $matches, PREG_SET_ORDER ) ) { + foreach ( $matches as $bits ) { + $match = array_shift( $bits ); + $key = strtolower( array_shift( $bits ) ); + if ( count( $bits ) == 0 ) { + $opts[$key] = true; + } elseif ( count( $bits ) == 1 ) { + $opts[$key] = $this->cleanupOption( array_shift( $bits ) ); + } else { + // Array! + $opts[$key] = array_map( array( $this, 'cleanupOption' ), $bits ); + } + } + } + return $opts; + } + + private function cleanupOption( $opt ) { + if ( substr( $opt, 0, 1 ) == '"' ) { + return substr( $opt, 1, -1 ); + } + + if ( substr( $opt, 0, 2 ) == '[[' ) { + return substr( $opt, 2, -2 ); + } + return $opt; + } + + /** + * Set up the global variables for a consistent environment for each test. + * Ideally this should replace the global configuration entirely. + */ + private function setupGlobals( $opts = '', $config = '' ) { + global $wgDBtype; + + # Find out values for some special options. + $lang = + self::getOptionValue( 'language', $opts, 'en' ); + $variant = + self::getOptionValue( 'variant', $opts, false ); + $maxtoclevel = + self::getOptionValue( 'wgMaxTocLevel', $opts, 999 ); + $linkHolderBatchSize = + self::getOptionValue( 'wgLinkHolderBatchSize', $opts, 1000 ); + + $settings = array( + 'wgServer' => 'http://localhost', + 'wgScript' => '/index.php', + 'wgScriptPath' => '/', + 'wgArticlePath' => '/wiki/$1', + 'wgActionPaths' => array(), + 'wgLocalFileRepo' => array( + 'class' => 'LocalRepo', + 'name' => 'local', + 'directory' => $this->uploadDir, + 'url' => 'http://example.com/images', + 'hashLevels' => 2, + 'transformVia404' => false, + ), + 'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ), + 'wgStyleSheetPath' => '/skins', + 'wgSitename' => 'MediaWiki', + 'wgServerName' => 'Britney-Spears', + 'wgLanguageCode' => $lang, + 'wgDBprefix' => $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_', + 'wgRawHtml' => isset( $opts['rawhtml'] ), + 'wgLang' => null, + 'wgContLang' => null, + 'wgNamespacesWithSubpages' => array( 0 => isset( $opts['subpage'] ) ), + 'wgMaxTocLevel' => $maxtoclevel, + 'wgCapitalLinks' => true, + 'wgNoFollowLinks' => true, + 'wgNoFollowDomainExceptions' => array(), + 'wgThumbnailScriptPath' => false, + 'wgUseImageResize' => false, + 'wgUseTeX' => isset( $opts['math'] ), + 'wgMathDirectory' => $this->uploadDir . '/math', + 'wgLocaltimezone' => 'UTC', + 'wgAllowExternalImages' => true, + 'wgUseTidy' => false, + 'wgDefaultLanguageVariant' => $variant, + 'wgVariantArticlePath' => false, + 'wgGroupPermissions' => array( '*' => array( + 'createaccount' => true, + 'read' => true, + 'edit' => true, + 'createpage' => true, + 'createtalk' => true, + ) ), + 'wgNamespaceProtection' => array( NS_MEDIAWIKI => 'editinterface' ), + 'wgDefaultExternalStore' => array(), + 'wgForeignFileRepos' => array(), + 'wgLinkHolderBatchSize' => $linkHolderBatchSize, + 'wgExperimentalHtmlIds' => false, + 'wgExternalLinkTarget' => false, + 'wgAlwaysUseTidy' => false, + 'wgHtml5' => true, + 'wgWellFormedXml' => true, + 'wgAllowMicrodataAttributes' => true, + ); + + if ( $config ) { + $configLines = explode( "\n", $config ); + + foreach ( $configLines as $line ) { + list( $var, $value ) = explode( '=', $line, 2 ); + + $settings[$var] = eval( "return $value;" ); + } + } + + $this->savedGlobals = array(); + + foreach ( $settings as $var => $val ) { + if ( array_key_exists( $var, $GLOBALS ) ) { + $this->savedGlobals[$var] = $GLOBALS[$var]; + } + + $GLOBALS[$var] = $val; + } + + $langObj = Language::factory( $lang ); + $GLOBALS['wgLang'] = $langObj; + $GLOBALS['wgContLang'] = $langObj; + $GLOBALS['wgMemc'] = new FakeMemCachedClient; + $GLOBALS['wgOut'] = new OutputPage; + + global $wgHooks; + + $wgHooks['ParserTestParser'][] = 'ParserTestParserHook::setup'; + $wgHooks['ParserTestParser'][] = 'ParserTestStaticParserHook::setup'; + $wgHooks['ParserGetVariableValueTs'][] = 'ParserTest::getFakeTimestamp'; + + MagicWord::clearCache(); + + global $wgUser; + $wgUser = new User(); + } + + /** + * List of temporary tables to create, without prefix. + * Some of these probably aren't necessary. + */ + private function listTables() { + global $wgDBtype; + + $tables = array( 'user', 'user_properties', 'page', 'page_restrictions', + 'protected_titles', 'revision', 'text', 'pagelinks', 'imagelinks', + 'categorylinks', 'templatelinks', 'externallinks', 'langlinks', 'iwlinks', + 'site_stats', 'hitcounter', 'ipblocks', 'image', 'oldimage', + 'recentchanges', 'watchlist', 'math', 'interwiki', 'logging', + 'querycache', 'objectcache', 'job', 'l10n_cache', 'redirect', 'querycachetwo', + 'archive', 'user_groups', 'page_props', 'category', 'msg_resource', 'msg_resource_links' + ); + + if ( in_array( $wgDBtype, array( 'mysql', 'sqlite' ) ) ) + array_push( $tables, 'searchindex' ); + + // Allow extensions to add to the list of tables to duplicate; + // may be necessary if they hook into page save or other code + // which will require them while running tests. + wfRunHooks( 'ParserTestTables', array( &$tables ) ); + + return $tables; + } + + /** + * Set up a temporary set of wiki tables to work with for the tests. + * Currently this will only be done once per run, and any changes to + * the db will be visible to later tests in the run. + */ + public function setupDatabase() { + global $wgDBprefix, $wgDBtype; + + if ( $this->databaseSetupDone ) { + return; + } + + if ( $wgDBprefix === 'parsertest_' || ( $wgDBtype == 'oracle' && $wgDBprefix === 'pt_' ) ) { + throw new MWException( 'setupDatabase should be called before setupGlobals' ); + } + + $this->databaseSetupDone = true; + $this->oldTablePrefix = $wgDBprefix; + + # SqlBagOStuff broke when using temporary tables on r40209 (bug 15892). + # It seems to have been fixed since (r55079?). + # If it fails, $wgCaches[CACHE_DB] = new HashBagOStuff(); should work around it. + + # CREATE TEMPORARY TABLE breaks if there is more than one server + if ( wfGetLB()->getServerCount() != 1 ) { + $this->useTemporaryTables = false; + } + + $temporary = $this->useTemporaryTables || $wgDBtype == 'postgres'; + + $db = wfGetDB( DB_MASTER ); + $tables = $this->listTables(); + + foreach ( $tables as $tbl ) { + # Clean up from previous aborted run. So that table escaping + # works correctly across DB engines, we need to change the pre- + # fix back and forth so tableName() works right. + $this->changePrefix( $this->oldTablePrefix ); + $oldTableName = $db->tableName( $tbl ); + $this->changePrefix( $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_' ); + $newTableName = $db->tableName( $tbl ); + + if ( $wgDBtype == 'mysql' ) { + $db->query( "DROP TABLE IF EXISTS $newTableName" ); + } elseif ( in_array( $wgDBtype, array( 'postgres', 'oracle' ) ) ) { + /* DROPs wouldn't work due to Foreign Key Constraints (bug 14990, r58669) + * Use "DROP TABLE IF EXISTS $newTableName CASCADE" for postgres? That + * syntax would also work for mysql. + */ + } elseif ( $db->tableExists( $tbl ) ) { + $db->query( "DROP TABLE $newTableName" ); + } + + # Create new table + $db->duplicateTableStructure( $oldTableName, $newTableName, $temporary ); + } + + if ( $wgDBtype == 'oracle' ) + $db->query( 'BEGIN FILL_WIKI_INFO; END;' ); + + $this->changePrefix( $wgDBtype != 'oracle' ? 'parsertest_' : 'pt_' ); + + # Hack: insert a few Wikipedia in-project interwiki prefixes, + # for testing inter-language links + $db->insert( 'interwiki', array( + array( 'iw_prefix' => 'wikipedia', + 'iw_url' => 'http://en.wikipedia.org/wiki/$1', + 'iw_api' => '', + 'iw_wikiid' => '', + 'iw_local' => 0 ), + array( 'iw_prefix' => 'meatball', + 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1', + 'iw_api' => '', + 'iw_wikiid' => '', + 'iw_local' => 0 ), + array( 'iw_prefix' => 'zh', + 'iw_url' => 'http://zh.wikipedia.org/wiki/$1', + 'iw_api' => '', + 'iw_wikiid' => '', + 'iw_local' => 1 ), + array( 'iw_prefix' => 'es', + 'iw_url' => 'http://es.wikipedia.org/wiki/$1', + 'iw_api' => '', + 'iw_wikiid' => '', + 'iw_local' => 1 ), + array( 'iw_prefix' => 'fr', + 'iw_url' => 'http://fr.wikipedia.org/wiki/$1', + 'iw_api' => '', + 'iw_wikiid' => '', + 'iw_local' => 1 ), + array( 'iw_prefix' => 'ru', + 'iw_url' => 'http://ru.wikipedia.org/wiki/$1', + 'iw_api' => '', + 'iw_wikiid' => '', + 'iw_local' => 1 ), + ) ); + + + if ( $wgDBtype == 'oracle' ) { + # Insert 0 user to prevent FK violations + + # Anonymous user + $db->insert( 'user', array( + 'user_id' => 0, + 'user_name' => 'Anonymous' ) ); + } + + # Update certain things in site_stats + $db->insert( 'site_stats', array( 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ) ); + + # Reinitialise the LocalisationCache to match the database state + Language::getLocalisationCache()->unloadAll(); + + # Make a new message cache + global $wgMessageCache, $wgMemc; + $wgMessageCache = new MessageCache( $wgMemc, true, 3600 ); + + $this->uploadDir = $this->setupUploadDir(); + $user = User::createNew( 'WikiSysop' ); + $image = wfLocalFile( Title::makeTitle( NS_FILE, 'Foobar.jpg' ) ); + $image->recordUpload2( '', 'Upload of some lame file', 'Some lame file', array( + 'size' => 12345, + 'width' => 1941, + 'height' => 220, + 'bits' => 24, + 'media_type' => MEDIATYPE_BITMAP, + 'mime' => 'image/jpeg', + 'metadata' => serialize( array() ), + 'sha1' => sha1( '' ), + 'fileExists' => true + ), $db->timestamp( '20010115123500' ), $user ); + + # This image will be blacklisted in [[MediaWiki:Bad image list]] + $image = wfLocalFile( Title::makeTitle( NS_FILE, 'Bad.jpg' ) ); + $image->recordUpload2( '', 'zomgnotcensored', 'Borderline image', array( + 'size' => 12345, + 'width' => 320, + 'height' => 240, + 'bits' => 24, + 'media_type' => MEDIATYPE_BITMAP, + 'mime' => 'image/jpeg', + 'metadata' => serialize( array() ), + 'sha1' => sha1( '' ), + 'fileExists' => true + ), $db->timestamp( '20010115123500' ), $user ); + } + + /** + * Change the table prefix on all open DB connections/ + */ + protected function changePrefix( $prefix ) { + global $wgDBprefix; + wfGetLBFactory()->forEachLB( array( $this, 'changeLBPrefix' ), array( $prefix ) ); + $wgDBprefix = $prefix; + } + + public function changeLBPrefix( $lb, $prefix ) { + $lb->forEachOpenConnection( array( $this, 'changeDBPrefix' ), array( $prefix ) ); + } + + public function changeDBPrefix( $db, $prefix ) { + $db->tablePrefix( $prefix ); + } + + public function teardownDatabase() { + global $wgDBtype; + + if ( !$this->databaseSetupDone ) { + return; + } + $this->teardownUploadDir( $this->uploadDir ); + + $this->changePrefix( $this->oldTablePrefix ); + $this->databaseSetupDone = false; + + if ( $this->useTemporaryTables ) { + # Don't need to do anything + return; + } + + $tables = $this->listTables(); + $db = wfGetDB( DB_MASTER ); + + foreach ( $tables as $table ) { + $sql = $wgDBtype == 'oracle' ? "DROP TABLE pt_$table DROP CONSTRAINTS" : "DROP TABLE `parsertest_$table`"; + $db->query( $sql ); + } + + if ( $wgDBtype == 'oracle' ) + $db->query( 'BEGIN FILL_WIKI_INFO; END;' ); + } + + /** + * Create a dummy uploads directory which will contain a couple + * of files in order to pass existence tests. + * + * @return String: the directory + */ + private function setupUploadDir() { + global $IP; + + if ( $this->keepUploads ) { + $dir = wfTempDir() . '/mwParser-images'; + + if ( is_dir( $dir ) ) { + return $dir; + } + } else { + $dir = wfTempDir() . "/mwParser-" . mt_rand() . "-images"; + } + + // wfDebug( "Creating upload directory $dir\n" ); + if ( file_exists( $dir ) ) { + wfDebug( "Already exists!\n" ); + return $dir; + } + + wfMkdirParents( $dir . '/3/3a' ); + copy( "$IP/skins/monobook/headbg.jpg", "$dir/3/3a/Foobar.jpg" ); + wfMkdirParents( $dir . '/0/09' ); + copy( "$IP/skins/monobook/headbg.jpg", "$dir/0/09/Bad.jpg" ); + + return $dir; + } + + /** + * Restore default values and perform any necessary clean-up + * after each test runs. + */ + private function teardownGlobals() { + RepoGroup::destroySingleton(); + LinkCache::singleton()->clear(); + + foreach ( $this->savedGlobals as $var => $val ) { + $GLOBALS[$var] = $val; + } + } + + /** + * Remove the dummy uploads directory + */ + private function teardownUploadDir( $dir ) { + if ( $this->keepUploads ) { + return; + } + + // delete the files first, then the dirs. + self::deleteFiles( + array ( + "$dir/3/3a/Foobar.jpg", + "$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg", + "$dir/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg", + "$dir/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg", + "$dir/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg", + + "$dir/0/09/Bad.jpg", + + "$dir/math/f/a/5/fa50b8b616463173474302ca3e63586b.png", + ) + ); + + self::deleteDirs( + array ( + "$dir/3/3a", + "$dir/3", + "$dir/thumb/6/65", + "$dir/thumb/6", + "$dir/thumb/3/3a/Foobar.jpg", + "$dir/thumb/3/3a", + "$dir/thumb/3", + + "$dir/0/09/", + "$dir/0/", + "$dir/thumb", + "$dir/math/f/a/5", + "$dir/math/f/a", + "$dir/math/f", + "$dir/math", + "$dir", + ) + ); + } + + /** + * Delete the specified files, if they exist. + * @param $files Array: full paths to files to delete. + */ + private static function deleteFiles( $files ) { + foreach ( $files as $file ) { + if ( file_exists( $file ) ) { + unlink( $file ); + } + } + } + + /** + * Delete the specified directories, if they exist. Must be empty. + * @param $dirs Array: full paths to directories to delete. + */ + private static function deleteDirs( $dirs ) { + foreach ( $dirs as $dir ) { + if ( is_dir( $dir ) ) { + rmdir( $dir ); + } + } + } + + /** + * "Running test $desc..." + */ + protected function showTesting( $desc ) { + print "Running test $desc... "; + } + + /** + * Print a happy success message. + * + * @param $desc String: the test name + * @return Boolean + */ + protected function showSuccess( $desc ) { + if ( $this->showProgress ) { + print $this->term->color( '1;32' ) . 'PASSED' . $this->term->reset() . "\n"; + } + + return true; + } + + /** + * Print a failure message and provide some explanatory output + * about what went wrong if so configured. + * + * @param $desc String: the test name + * @param $result String: expected HTML output + * @param $html String: actual HTML output + * @return Boolean + */ + protected function showFailure( $desc, $result, $html ) { + if ( $this->showFailure ) { + if ( !$this->showProgress ) { + # In quiet mode we didn't show the 'Testing' message before the + # test, in case it succeeded. Show it now: + $this->showTesting( $desc ); + } + + print $this->term->color( '31' ) . 'FAILED!' . $this->term->reset() . "\n"; + + if ( $this->showOutput ) { + print "--- Expected ---\n$result\n--- Actual ---\n$html\n"; + } + + if ( $this->showDiffs ) { + print $this->quickDiff( $result, $html ); + if ( !$this->wellFormed( $html ) ) { + print "XML error: $this->mXmlError\n"; + } + } + } + + return false; + } + + /** + * Run given strings through a diff and return the (colorized) output. + * Requires writable /tmp directory and a 'diff' command in the PATH. + * + * @param $input String + * @param $output String + * @param $inFileTail String: tailing for the input file name + * @param $outFileTail String: tailing for the output file name + * @return String + */ + protected function quickDiff( $input, $output, $inFileTail = 'expected', $outFileTail = 'actual' ) { + $prefix = wfTempDir() . "/mwParser-" . mt_rand(); + + $infile = "$prefix-$inFileTail"; + $this->dumpToFile( $input, $infile ); + + $outfile = "$prefix-$outFileTail"; + $this->dumpToFile( $output, $outfile ); + + $diff = `diff -au $infile $outfile`; + unlink( $infile ); + unlink( $outfile ); + + return $this->colorDiff( $diff ); + } + + /** + * Write the given string to a file, adding a final newline. + * + * @param $data String + * @param $filename String + */ + private function dumpToFile( $data, $filename ) { + $file = fopen( $filename, "wt" ); + fwrite( $file, $data . "\n" ); + fclose( $file ); + } + + /** + * Colorize unified diff output if set for ANSI color output. + * Subtractions are colored blue, additions red. + * + * @param $text String + * @return String + */ + protected function colorDiff( $text ) { + return preg_replace( + array( '/^(-.*)$/m', '/^(\+.*)$/m' ), + array( $this->term->color( 34 ) . '$1' . $this->term->reset(), + $this->term->color( 31 ) . '$1' . $this->term->reset() ), + $text ); + } + + /** + * Show "Reading tests from ..." + * + * @param $path String + */ + public function showRunFile( $path ) { + print $this->term->color( 1 ) . + "Reading tests from \"$path\"..." . + $this->term->reset() . + "\n"; + } + + /** + * Insert a temporary test article + * @param $name String: the title, including any prefix + * @param $text String: the article text + * @param $line Integer: the input line number, for reporting errors + */ + public function addArticle( $name, $text, $line ) { + global $wgCapitalLinks; + $oldCapitalLinks = $wgCapitalLinks; + $wgCapitalLinks = true; // We only need this from SetupGlobals() See r70917#c8637 + + $title = Title::newFromText( $name ); + + if ( is_null( $title ) ) { + wfDie( "invalid title at line $line\n" ); + } + + $aid = $title->getArticleID( GAID_FOR_UPDATE ); + + if ( $aid != 0 ) { + wfDie( "duplicate article '$name' at line $line\n" ); + } + + $art = new Article( $title ); + $art->insertNewArticle( $text, '', false, false ); + + $wgCapitalLinks = $oldCapitalLinks; + } + + /** + * Steal a callback function from the primary parser, save it for + * application to our scary parser. If the hook is not installed, + * abort processing of this file. + * + * @param $name String + * @return Bool true if tag hook is present + */ + public function requireHook( $name ) { + global $wgParser; + + $wgParser->firstCallInit( ); // make sure hooks are loaded. + + if ( isset( $wgParser->mTagHooks[$name] ) ) { + $this->hooks[$name] = $wgParser->mTagHooks[$name]; + } else { + echo " This test suite requires the '$name' hook extension, skipping.\n"; + return false; + } + + return true; + } + + /** + * Steal a callback function from the primary parser, save it for + * application to our scary parser. If the hook is not installed, + * abort processing of this file. + * + * @param $name String + * @return Bool true if function hook is present + */ + public function requireFunctionHook( $name ) { + global $wgParser; + + $wgParser->firstCallInit( ); // make sure hooks are loaded. + + if ( isset( $wgParser->mFunctionHooks[$name] ) ) { + $this->functionHooks[$name] = $wgParser->mFunctionHooks[$name]; + } else { + echo " This test suite requires the '$name' function hook extension, skipping.\n"; + return false; + } + + return true; + } + + /* + * Run the "tidy" command on text if the $wgUseTidy + * global is true + * + * @param $text String: the text to tidy + * @return String + * @static + */ + private function tidy( $text ) { + global $wgUseTidy; + + if ( $wgUseTidy ) { + $text = MWTidy::tidy( $text ); + } + + return $text; + } + + private function wellFormed( $text ) { + $html = + Sanitizer::hackDocType() . + '' . + $text . + ''; + + $parser = xml_parser_create( "UTF-8" ); + + # case folding violates XML standard, turn it off + xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false ); + + if ( !xml_parse( $parser, $html, true ) ) { + $err = xml_error_string( xml_get_error_code( $parser ) ); + $position = xml_get_current_byte_index( $parser ); + $fragment = $this->extractFragment( $html, $position ); + $this->mXmlError = "$err at byte $position:\n$fragment"; + xml_parser_free( $parser ); + + return false; + } + + xml_parser_free( $parser ); + + return true; + } + + private function extractFragment( $text, $position ) { + $start = max( 0, $position - 10 ); + $before = $position - $start; + $fragment = '...' . + $this->term->color( 34 ) . + substr( $text, $start, $before ) . + $this->term->color( 0 ) . + $this->term->color( 31 ) . + $this->term->color( 1 ) . + substr( $text, $position, 1 ) . + $this->term->color( 0 ) . + $this->term->color( 34 ) . + substr( $text, $position + 1, 9 ) . + $this->term->color( 0 ) . + '...'; + $display = str_replace( "\n", ' ', $fragment ); + $caret = ' ' . + str_repeat( ' ', $before ) . + $this->term->color( 31 ) . + '^' . + $this->term->color( 0 ); + + return "$display\n$caret"; + } + + static function getFakeTimestamp( &$parser, &$ts ) { + $ts = 123; + return true; + } +} diff --git a/maintenance/tests/parser/parserTests.txt b/maintenance/tests/parser/parserTests.txt new file mode 100644 index 0000000000..43ac4bfc8d --- /dev/null +++ b/maintenance/tests/parser/parserTests.txt @@ -0,0 +1,8224 @@ +# MediaWiki Parser test cases +# Some taken from http://meta.wikimedia.org/wiki/Parser_testing +# All (C) their respective authors and released under the GPL +# +# The syntax should be fairly self-explanatory. +# +# Currently supported test options: +# One of the following three: +# +# (default) generate HTML output +# pst apply pre-save transform +# msg apply message transform +# +# Plus any combination of these: +# +# cat add category links +# ill add inter-language links +# subpage enable subpages (disabled by default) +# noxml don't check for XML well formdness +# title=[[XXX]] run test using article title XXX +# language=XXX set content language to XXX for this test +# variant=XXX set the variant of language for this test (eg zh-tw) +# disabled do not run test +# showtitle make the first line the title +# comment run through Linker::formatComment() instead of main parser +# local format section links in edit comment text as local links +# +# For testing purposes, temporary articles can created: +# !!article / NAMESPACE:TITLE / !!text / ARTICLE TEXT / !!endarticle +# where '/' denotes a newline. + +# This is the standard article assumed to exist. +!! article +Main Page +!! text +blah blah +!! endarticle + +!!article +Template:Foo +!!text +FOO +!!endarticle + +!! article +Template:Blank +!! text +!! endarticle + +!! article +Template:! +!! text +| +!! endarticle + +!!article +MediaWiki:bad image list +!!text +* [[File:Bad.jpg]] except [[Nasty page]] +!!endarticle + +### +### Basic tests +### +!! test +Blank input +!! input +!! result +!! end + + +!! test +Simple paragraph +!! input +This is a simple paragraph. +!! result +

    This is a simple paragraph. +

    +!! end + +!! test +Simple list +!! input +* Item 1 +* Item 2 +!! result +
    • Item 1 +
    • Item 2 +
    + +!! end + +!! test +Italics and bold +!! input +* plain +* plain''italic''plain +* plain''italic''plain''italic''plain +* plain'''bold'''plain +* plain'''bold'''plain'''bold'''plain +* plain''italic''plain'''bold'''plain +* plain'''bold'''plain''italic''plain +* plain''italic'''bold-italic'''italic''plain +* plain'''bold''bold-italic''bold'''plain +* plain'''''bold-italic'''italic''plain +* plain'''''bold-italic''bold'''plain +* plain''italic'''bold-italic'''''plain +* plain'''bold''bold-italic'''''plain +* plain l'''italic''plain +* plain l''''bold''' plain +!! result +
    • plain +
    • plainitalicplain +
    • plainitalicplainitalicplain +
    • plainboldplain +
    • plainboldplainboldplain +
    • plainitalicplainboldplain +
    • plainboldplainitalicplain +
    • plainitalicbold-italicitalicplain +
    • plainboldbold-italicboldplain +
    • plainbold-italicitalicplain +
    • plainbold-italicboldplain +
    • plainitalicbold-italicplain +
    • plainboldbold-italicplain +
    • plain l'italicplain +
    • plain l'bold plain +
    + +!! end + +### +### test cases +### + +!! test + unordered list +!! input +* This is not an unordered list item. +!! result +

    * This is not an unordered list item. +

    +!! end + +!! test + spacing +!! input +Lorem ipsum dolor + +sed abit. + sed nullum. + +:and a colon + +!! result +

    Lorem ipsum dolor + +sed abit. + sed nullum. + +:and a colon + +

    +!! end + +!! test +nowiki 3 +!! input +:There is not nowiki. +:There is nowiki. + +#There is not nowiki. +#There is nowiki. + +*There is not nowiki. +*There is nowiki. +!! result +
    There is not nowiki. +
    There is nowiki. +
    +
    1. There is not nowiki. +
    2. There is nowiki. +
    +
    • There is not nowiki. +
    • There is nowiki. +
    + +!! end + + +### +### Comments +### +!! test +Comment test 1 +!! input + asdf + +!! result +
    asdf
    +
    + +!! end + +!! test +Comment test 2 +!! input +asdf + +jkl +!! result +

    asdf +jkl +

    +!! end + +!! test +Comment test 3 +!! input +asdf + + +jkl +!! result +

    asdf +jkl +

    +!! end + +!! test +Comment test 4 +!! input +asdfjkl +!! result +

    asdfjkl +

    +!! end + +!! test +Comment spacing +!! input +a + b +c +!! result +

    a +

    +
     b 
    +
    +

    c +

    +!! end + +!! test +Comment whitespace +!! input + +!! result + +!! end + +!! test +Comment semantics and delimiters +!! input + +!! result + +!! end + +!! test +Comment semantics and delimiters, redux +!! input + +!! result + +!! end + +!! test +Comment semantics and delimiters: directors cut +!! input +--> +!! result +

    --> +

    +!! end + +!! test +Comment semantics: nesting +!! input +--> +!! result +

    --> +

    +!! end + +!! test +Comment semantics: unclosed comment at end +!! input +oo}} +!! result +

    FOO +

    +!! end + +!! test +Comment on its own line post-expand +!! input +a +{{blank}} +b +!! result +

    a +

    b +

    +!! end + +### +### Preformatted text +### +!! test +Preformatted text +!! input + This is some + Preformatted text + With ''italic'' + And '''bold''' + And a [[Main Page|link]] +!! result +
    This is some
    +Preformatted text
    +With italic
    +And bold
    +And a link
    +
    +!! end + +!! test +
     with  inside (compatibility with 1.6 and earlier)
    +!! input
    +
    
    +
    +
    +
    +
    +!! result +
    +<b>
    +<cite>
    +<em>
    +
    + +!! end + +!! test +Regression with preformatted in
    +!! input +
    + Blah +
    +!! result +
    +
    Blah
    +
    +
    + +!! end + +# Expected output in the following test is not really expected (there should be +#
     in the output) -- it's only testing for well-formedness.
    +!! test
    +Bug 6200: Preformatted in 
    +!! input +
    + Blah +
    +!! result +
    + Blah +
    + +!! end + +!! test +
     with attributes (bug 3202)
    +!! input
    +
    Bluescreen of WikiDeath
    +!! result +
    Bluescreen of WikiDeath
    + +!! end + +!! test +
     with width attribute (bug 3202)
    +!! input
    +
    Narrow screen goodies
    +!! result +
    Narrow screen goodies
    + +!! end + +!! test +
     with forbidden attribute (bug 3202)
    +!! input
    +
    Narrow screen goodies
    +!! result +
    Narrow screen goodies
    + +!! end + +!! test +
     with forbidden attribute values (bug 3202)
    +!! input
    +
    Narrow screen goodies
    +!! result +
    Narrow screen goodies
    + +!! end + +### +### Definition lists +### +!! test +Simple definition +!! input +; name : Definition +!! result +
    name 
    Definition +
    + +!! end + +!! test +Definition list for indentation only +!! input +: Indented text +!! result +
    Indented text +
    + +!! end + +!! test +Definition list with no space +!! input +;name:Definition +!! result +
    name
    Definition +
    + +!!end + +!! test +Definition list with URL link +!! input +; http://example.com/ : definition +!! result +
    http://example.com/ 
    definition +
    + +!! end + +!! test +Definition list with bracketed URL link +!! input +;[http://www.example.com/ Example]:Something about it +!! result +
    Example
    Something about it +
    + +!! end + +!! test +Definition list with wikilink containing colon +!! input +; [[Help:FAQ]]: The least-read page on Wikipedia +!! result +
    Help:FAQ
    The least-read page on Wikipedia +
    + +!! end + +# At Brion's and JeLuF's insistence... :) +!! test +Definition list with news link containing colon +!! input +; news:alt.wikipedia.rox: This isn't even a real newsgroup! +!! result +
    news:alt.wikipedia.rox
    This isn't even a real newsgroup! +
    + +!! end + +!! test +Malformed definition list with colon +!! input +; news:alt.wikipedia.rox -- don't crash or enter an infinite loop +!! result +
    news:alt.wikipedia.rox -- don't crash or enter an infinite loop +
    + +!! end + +!! test +Definition lists: colon in external link text +!! input +; [http://www.wikipedia2.org/ Wikipedia : The Next Generation]: OK, I made that up +!! result +
    Wikipedia : The Next Generation
    OK, I made that up +
    + +!! end + +!! test +Definition lists: colon in HTML attribute +!! input +;bold +!! result +
    bold +
    + +!! end + + +!! test +Definition lists: self-closed tag +!! input +;one
    two : two-line fun +!! result +
    one
    two 
    two-line fun +
    + +!! end + + +### +### External links +### +!! test +External links: non-bracketed +!! input +Non-bracketed: http://example.com +!! result +

    Non-bracketed: http://example.com +

    +!! end + +!! test +External links: numbered +!! input +Numbered: [http://example.com] +Numbered: [http://example.net] +Numbered: [http://example.com] +!! result +

    Numbered: [1] +Numbered: [2] +Numbered: [3] +

    +!!end + +!! test +External links: specified text +!! input +Specified text: [http://example.com link] +!! result +

    Specified text: link +

    +!!end + +!! test +External links: trail +!! input +Linktrails should not work for external links: [http://example.com link]s +!! result +

    Linktrails should not work for external links: links +

    +!! end + +!! test +External links: dollar sign in URL +!! input +http://example.com/1$2345 +!! result +

    http://example.com/1$2345 +

    +!! end + +!! test +External links: dollar sign in URL (named) +!! input +[http://example.com/1$2345] +!! result +

    [1] +

    +!!end + +!! test +External links: open square bracket forbidden in URL (bug 4377) +!! input +http://example.com/1[2345 +!! result +

    http://example.com/1[2345 +

    +!! end + +!! test +External links: open square bracket forbidden in URL (named) (bug 4377) +!! input +[http://example.com/1[2345] +!! result +

    [2345 +

    +!!end + +!! test +External links: nowiki in URL link text (bug 6230) +!!input +[http://example.com/ ''example site''] +!! result +

    ''example site'' +

    +!! end + +!! test +External links: newline forbidden in text (bug 6230 regression check) +!! input +[http://example.com/ first +second] +!! result +

    [http://example.com/ first +second] +

    +!!end + +!! test +External image +!! input +External image: http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png +!! result +

    External image: Ncwikicol.png +

    +!! end + +!! test +External image from https +!! input +External image from https: https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png +!! result +

    External image from https: Ncwikicol.png +

    +!! end + +!! test +Link to non-http image, no img tag +!! input +Link to non-http image, no img tag: ftp://example.com/test.jpg +!! result +

    Link to non-http image, no img tag: ftp://example.com/test.jpg +

    +!! end + +!! test +External links: terminating separator +!! input +Terminating separator: http://example.com/thing, +!! result +

    Terminating separator: http://example.com/thing, +

    +!! end + +!! test +External links: intervening separator +!! input +Intervening separator: http://example.com/1,2,3 +!! result +

    Intervening separator: http://example.com/1,2,3 +

    +!! end + +!! test +External links: old bug with URL in query +!! input +Old bug with URL in query: [http://example.com/thing?url=http://example.com link] +!! result +

    Old bug with URL in query: link +

    +!! end + +!! test +External links: old URL-in-URL bug, mixed protocols +!! input +And again with mixed protocols: [ftp://example.com?url=http://example.com link] +!! result +

    And again with mixed protocols: link +

    +!!end + +!! test +External links: URL in text +!! input +URL in text: [http://example.com http://example.com] +!! result +

    URL in text: http://example.com +

    +!! end + +!! test +External links: Clickable images +!! input +ja-style clickable images: [http://example.com http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png] +!! result +

    ja-style clickable images: Ncwikicol.png +

    +!!end + +!! test +External links: raw ampersand +!! input +Old & use: http://x&y +!! result +

    Old & use: http://x&y +

    +!! end + +!! test +External links: encoded ampersand +!! input +Old & use: http://x&y +!! result +

    Old & use: http://x&y +

    +!! end + +!! test +External links: encoded equals (bug 6102) +!! input +http://example.com/?foo=bar +!! result +

    http://example.com/?foo=bar +

    +!! end + +!! test +External links: [raw ampersand] +!! input +Old & use: [http://x&y] +!! result +

    Old & use: [1] +

    +!! end + +!! test +External links: [encoded ampersand] +!! input +Old & use: [http://x&y] +!! result +

    Old & use: [1] +

    +!! end + +!! test +External links: [encoded equals] (bug 6102) +!! input +[http://example.com/?foo=bar] +!! result +

    [1] +

    +!! end + +!! test +External links: [IDN ignored character reference in hostname; strip it right off] +!! input +[http://e‌xample.com/] +!! result +

    [1] +

    +!! end + +!! test +External links: IDN ignored character reference in hostname; strip it right off +!! input +http://e‌xample.com/ +!! result +

    http://example.com/ +

    +!! end + +!! test +External links: www.jpeg.org (bug 554) +!! input +http://www.jpeg.org +!!result +

    http://www.jpeg.org +

    +!! end + +!! test +External links: URL within URL (original bug 2) +!! input +[http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp] +!! result +

    [1] +

    +!! end + +!! test +BUG 361: URL inside bracketed URL +!! input +[http://www.example.com/foo http://www.example.com/bar] +!! result +

    http://www.example.com/bar +

    +!! end + +!! test +BUG 361: URL within URL, not bracketed +!! input +http://www.example.com/foo?=http://www.example.com/bar +!! result +

    http://www.example.com/foo?=http://www.example.com/bar +

    +!! end + +!! test +BUG 289: ">"-token in URL-tail +!! input +http://www.example.com/ +!! result +

    http://www.example.com/<hello> +

    +!!end + +!! test +BUG 289: literal ">"-token in URL-tail +!! input +http://www.example.com/html +!! result +

    http://www.example.com/html +

    +!!end + +!! test +BUG 289: ">"-token in bracketed URL +!! input +[http://www.example.com/ stuff] +!! result +

    <hello> stuff +

    +!!end + +!! test +BUG 289: literal ">"-token in bracketed URL +!! input +[http://www.example.com/html stuff] +!! result +

    html stuff +

    +!!end + +!! test +BUG 289: literal double quote at end of URL +!! input +http://www.example.com/"hello" +!! result +

    http://www.example.com/"hello" +

    +!!end + +!! test +BUG 289: literal double quote in bracketed URL +!! input +[http://www.example.com/"hello" stuff] +!! result +

    "hello" stuff +

    +!!end + +!! test +External links: multiple legal whitespace is fine, Magnus. Don't break it please. (bug 5081) +!! input +[http://www.example.com test] +!! result +

    test +

    +!! end + +!! test +External links: wiki links within external link (Bug 3695) +!! input +[http://example.com [[wikilink]] embedded in ext link] +!! result +

    wikilink embedded in ext link +

    +!! end + +!! test +BUG 787: Links with one slash after the url protocol are invalid +!! input +http:/example.com + +[http:/example.com title] +!! result +

    http:/example.com +

    [http:/example.com title] +

    +!! end + +!! test +Bug 2702: Mismatched , and tags are invalid +!! input +''[http://example.com text''] +[http://example.com '''text]''' +''Something [http://example.com in italic''] +''Something [http://example.com mixed''''', even bold]''' +'''''Now [http://example.com both'''''] +!! result +

    text +text +Something in italic +Something mixed, even bold +Now both +

    +!! end + + +!! test +Bug 4781: %26 in URL +!! input +http://www.example.com/?title=AT%26T +!! result +

    http://www.example.com/?title=AT%26T +

    +!! end + +!! test +Bug 4781, 5267: %26 in URL +!! input +http://www.example.com/?title=100%25_Bran +!! result +

    http://www.example.com/?title=100%25_Bran +

    +!! end + +!! test +Bug 4781, 5267: %28, %29 in URL +!! input +http://www.example.com/?title=Ben-Hur_%281959_film%29 +!! result +

    http://www.example.com/?title=Ben-Hur_%281959_film%29 +

    +!! end + + +!! test +Bug 4781: %26 in autonumber URL +!! input +[http://www.example.com/?title=AT%26T] +!! result +

    [1] +

    +!! end + +!! test +Bug 4781, 5267: %26 in autonumber URL +!! input +[http://www.example.com/?title=100%25_Bran] +!! result +

    [1] +

    +!! end + +!! test +Bug 4781, 5267: %28, %29 in autonumber URL +!! input +[http://www.example.com/?title=Ben-Hur_%281959_film%29] +!! result +

    [1] +

    +!! end + + +!! test +Bug 4781: %26 in bracketed URL +!! input +[http://www.example.com/?title=AT%26T link] +!! result +

    link +

    +!! end + +!! test +Bug 4781, 5267: %26 in bracketed URL +!! input +[http://www.example.com/?title=100%25_Bran link] +!! result +

    link +

    +!! end + +!! test +Bug 4781, 5267: %28, %29 in bracketed URL +!! input +[http://www.example.com/?title=Ben-Hur_%281959_film%29 link] +!! result +

    link +

    +!! end + +!! test +External link containing double-single-quotes in text '' (bug 4598 sanity check) +!! input +Some [http://example.com/ pretty ''italics'' and stuff]! +!! result +

    Some pretty italics and stuff! +

    +!! end + +!! test +External link containing double-single-quotes in text embedded in italics (bug 4598 sanity check) +!! input +''Some [http://example.com/ pretty ''italics'' and stuff]!'' +!! result +

    Some pretty italics and stuff! +

    +!! end + +!! test +External link containing double-single-quotes with no space separating the url from text in italics +!! input +[http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm''La muerte de Casagemas'' (1901) en el sitio de [[Museo Picasso (París)|Museo Picasso]].] +!! result +

    La muerte de Casagemas (1901) en el sitio de Museo Picasso. +

    +!! end + +!! test +URL-encoding in URL functions (single parameter) +!! input +{{localurl:Some page|amp=&}} +!! result +

    /index.php?title=Some_page&amp=& +

    +!! end + +!! test +URL-encoding in URL functions (multiple parameters) +!! input +{{localurl:Some page|q=?&=&}} +!! result +

    /index.php?title=Some_page&q=?&amp=& +

    +!! end + +### +### Quotes +### + +!! test +Quotes +!! input +Normal text. '''Bold text.''' Normal text. ''Italic text.'' + +Normal text. '''''Bold italic text.''''' Normal text. +!!result +

    Normal text. Bold text. Normal text. Italic text. +

    Normal text. Bold italic text. Normal text. +

    +!! end + + +!! test +Unclosed and unmatched quotes +!! input +'''''Bold italic text '''with bold deactivated''' in between.''''' + +'''''Bold italic text ''with italic deactivated'' in between.''''' + +'''Bold text.. + +..spanning two paragraphs (should not work).''' + +'''Bold tag left open + +''Italic tag left open + +Normal text. + + +'''This year''''s election ''should'' beat '''last year''''s. + +''Tom'''s car is bigger than ''Susan'''s. +!! result +

    Bold italic text with bold deactivated in between. +

    Bold italic text with italic deactivated in between. +

    Bold text.. +

    ..spanning two paragraphs (should not work). +

    Bold tag left open +

    Italic tag left open +

    Normal text. +

    This year's election should beat last year's. +

    Toms car is bigger than Susans. +

    +!! end + +### +### Tables +### +### some content taken from http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide:_Using_tables +### + +# This should not produce
    as
    +# is the bare minimun required by the spec, see: +# http://www.w3.org/TR/xhtml-modularization/dtd_module_defs.html#a_module_Basic_Tables +!! test +A table with no data. +!! input +{||} +!! result +!! end + +# A table with nothing but a caption is invalid XHTML, we might want to render +# this as

    caption

    +!! test +A table with nothing but a caption +!! input +{| +|+ caption +|} +!! result + +
    caption +
    + +!! end + +!! test +Simple table +!! input +{| +| 1 || 2 +|- +| 3 || 4 +|} +!! result + + + + + + +
    1 2 +
    3 4 +
    + +!! end + +!! test +Multiplication table +!! input +{| border="1" cellpadding="2" +|+Multiplication table +|- +! × !! 1 !! 2 !! 3 +|- +! 1 +| 1 || 2 || 3 +|- +! 2 +| 2 || 4 || 6 +|- +! 3 +| 3 || 6 || 9 +|- +! 4 +| 4 || 8 || 12 +|- +! 5 +| 5 || 10 || 15 +|} +!! result + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Multiplication table +
    × 1 2 3 +
    1 + 1 2 3 +
    2 + 2 4 6 +
    3 + 3 6 9 +
    4 + 4 8 12 +
    5 + 5 10 15 +
    + +!! end + +!! test +Table rowspan +!! input +{| align=right border=1 +| Cell 1, row 1 +|rowspan=2| Cell 2, row 1 (and 2) +| Cell 3, row 1 +|- +| Cell 1, row 2 +| Cell 3, row 2 +|} +!! result + + + + + + + +
    Cell 1, row 1 + Cell 2, row 1 (and 2) + Cell 3, row 1 +
    Cell 1, row 2 + Cell 3, row 2 +
    + +!! end + +!! test +Nested table +!! input +{| border=1 +| α +| +{| bgcolor=#ABCDEF border=2 +|nested +|- +|table +|} +|the original table again +|} +!! result + + + + +
    α + + + + + +
    nested +
    table +
    +
    the original table again +
    + +!! end + +!! test +Invalid attributes in table cell (bug 1830) +!! input +{| +|Cell:|broken +|} +!! result + + +
    broken +
    + +!! end + + +!! test +Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitech-l/2006-April/022293.html) +!! input +{| +| |[ftp://|x||]" onmouseover="alert(document.cookie)">test +!! result + + + + + +
    [ftp://%7Cx]" onmouseover="alert(document.cookie)">test +
    + +!! end + + +### +### Internal links +### +!! test +Plain link, capitalized +!! input +[[Main Page]] +!! result +

    Main Page +

    +!! end + +!! test +Plain link, uncapitalized +!! input +[[main Page]] +!! result +

    main Page +

    +!! end + +!! test +Piped link +!! input +[[Main Page|The Main Page]] +!! result +

    The Main Page +

    +!! end + +!! test +Broken link +!! input +[[Zigzagzogzagzig]] +!! result +

    Zigzagzogzagzig +

    +!! end + +!! test +Broken link with fragment +!! input +[[Zigzagzogzagzig#zug]] +!! result +

    Zigzagzogzagzig#zug +

    +!! end + +!! test +Special page link with fragment +!! input +[[Special:Version#anchor]] +!! result +

    Special:Version#anchor +

    +!! end + +!! test +Nonexistent special page link with fragment +!! input +[[Special:ThisNameWillHopefullyNeverBeUsed#anchor]] +!! result +

    Special:ThisNameWillHopefullyNeverBeUsed#anchor +

    +!! end + +!! test +Link with prefix +!! input +xxx[[main Page]], xxx[[Main Page]], Xxx[[main Page]] XXX[[main Page]], XXX[[Main Page]] +!! result +

    xxxmain Page, xxxMain Page, Xxxmain Page XXXmain Page, XXXMain Page +

    +!! end + +!! test +Link with suffix +!! input +[[Main Page]]xxx, [[Main Page]]XXX, [[Main Page]]!!! +!! result +

    Main Pagexxx, Main PageXXX, Main Page!!! +

    +!! end + +!! test +Link with 3 brackets +!! input +[[[main page]]] +!! result +

    [[[main page]]] +

    +!! end + +!! test +Piped link with 3 brackets +!! input +[[[main page|the main page]]] +!! result +

    [[[main page|the main page]]] +

    +!! end + +!! test +Link with multiple pipes +!! input +[[Main Page|The|Main|Page]] +!! result +

    The|Main|Page +

    +!! end + +!! test +Link to namespaces +!! input +[[Talk:Parser testing]], [[Meta:Disclaimers]] +!! result +

    Talk:Parser testing, Meta:Disclaimers +

    +!! end + +!! test +Piped link to namespace +!! input +[[Meta:Disclaimers|The disclaimers]] +!! result +

    The disclaimers +

    +!! end + +!! test +Link containing } +!! input +[[Usually caused by a typo (oops}]] +!! result +

    [[Usually caused by a typo (oops}]] +

    +!! end + +!! test +Link containing % (not as a hex sequence) +!! input +[[7% Solution]] +!! result +

    7% Solution +

    +!! end + +!! test +Link containing % as a single hex sequence interpreted to char +!! input +[[7%25 Solution]] +!! result +

    7% Solution +

    +!!end + +!! test +Link containing % as a double hex sequence interpreted to hex sequence +!! input +[[7%2525 Solution]] +!! result +

    [[7%2525 Solution]] +

    +!!end + +!! test +Link containing "#<" and "#>" % as a hex sequences- these are valid section anchors +Example for such a section: == < == +!! input +[[%23%3c]][[%23%3e]] +!! result +

    #<#> +

    +!! end + +!! test +Link containing "<#" and ">#" as a hex sequences +!! input +[[%3c%23]][[%3e%23]] +!! result +

    [[%3c%23]][[%3e%23]] +

    +!! end + +!! test +Link containing double-single-quotes '' (bug 4598) +!! input +[[Lista d''e paise d''o munno]] +!! result +

    Lista d''e paise d''o munno +

    +!! end + +!! test +Link containing double-single-quotes '' in text (bug 4598 sanity check) +!! input +Some [[Link|pretty ''italics'' and stuff]]! +!! result +

    Some pretty italics and stuff! +

    +!! end + +!! test +Link containing double-single-quotes '' in text embedded in italics (bug 4598 sanity check) +!! input +''Some [[Link|pretty ''italics'' and stuff]]! +!! result +

    Some pretty italics and stuff! +

    +!! end + +!! test +Link with double quotes in title part (literal) and alternate part (interpreted) +!! input +[[File:Denys Savchenko ''Pentecoste''.jpg]] + +[[''Pentecoste'']] + +[[''Pentecoste''|Pentecoste]] + +[[''Pentecoste''|''Pentecoste'']] +!! result +

    File:Denys Savchenko Pentecoste.jpg +

    ''Pentecoste'' +

    Pentecoste +

    Pentecoste +

    +!! end + +!! test +Plain link to URL +!! input +[[http://www.example.com]] +!! result +

    [[1]] +

    +!! end + +# I'm fairly sure the expected result here is wrong. +# We want these to be URL links, not pseudo-pages with URLs for titles.... +# However the current output is also pretty screwy. +# +# ---- +# I'm changing it to match the current output--it arguably makes more +# sense in the light of the test above. Old expected result was: +#

    Piped link to URL: an example URL +#

    +# But I think this test is bordering on "garbage in, garbage out" anyway. +# -- wtm +!! test +Piped link to URL +!! input +Piped link to URL: [[http://www.example.com|an example URL]] +!! result +

    Piped link to URL: [example URL] +

    +!! end + +!! test +BUG 2: [[page|http://url/]] should link to page, not http://url/ +!! input +[[Main Page|http://url/]] +!! result +

    http://url/ +

    +!! end + +!! test +BUG 337: Escaped self-links should be bold +!! options +title=[[Bug462]] +!! input +[[Bug462]] [[Bug462]] +!! result +

    Bug462 Bug462 +

    +!! end + +!! test +Self-link to section should not be bold +!! options +title=[[Main Page]] +!! input +[[Main Page#section]] +!! result +

    Main Page#section +

    +!! end + +!! article +00 +!! text +This is 00. +!! endarticle + +!!test +Self-link to numeric title +!!options +title=[[0]] +!!input +[[0]] +!!result +

    0 +

    +!!end + +!!test +Link to numeric-equivalent title +!!options +title=[[0]] +!!input +[[00]] +!!result +

    00 +

    +!!end + +!! test + inside a link +!! input +[[Main Page]] [[Main Page|the main page [it's not very good]]] +!! result +

    [[Main Page]] the main page [it's not very good] +

    +!! end + +!! test +Non-breaking spaces in title +!! input +[[  Main   Page  ]] +!! result +

      Main   Page   +

    +!!end + + +### +### Interwiki links (see maintenance/interwiki.sql) +### + +!! test +Inline interwiki link +!! input +[[MeatBall:SoftSecurity]] +!! result +

    MeatBall:SoftSecurity +

    +!! end + +!! test +Inline interwiki link with empty title (bug 2372) +!! input +[[MeatBall:]] +!! result +

    MeatBall: +

    +!! end + +!! test +Interwiki link encoding conversion (bug 1636) +!! input +*[[Wikipedia:ro:Olteniţa]] +*[[Wikipedia:ro:Olteniţa]] +!! result + + +!! end + +!! test +Interwiki link with fragment (bug 2130) +!! input +[[MeatBall:SoftSecurity#foo]] +!! result +

    MeatBall:SoftSecurity#foo +

    +!! end + +!! test +Interlanguage link +!! input +Blah blah blah +[[zh:Chinese]] +!!result +

    Blah blah blah +

    +!! end + +!! test +Double interlanguage link +!! input +Blah blah blah +[[es:Spanish]] +[[zh:Chinese]] +!!result +

    Blah blah blah +

    +!! end + +!! test +Interlanguage link, with prefix links +!! options +language=ln +!! input +Blah blah blah +[[zh:Chinese]] +!!result +

    Blah blah blah +

    +!! end + +!! test +Double interlanguage link, with prefix links (bug 8897) +!! options +language=ln +!! input +Blah blah blah +[[es:Spanish]] +[[zh:Chinese]] +!!result +

    Blah blah blah +

    +!! end + + +## +## XHTML tidiness +### + +!! test +
    to
    +!! input +1
    2
    3 +!! result +

    1
    2
    3 +

    +!! end + +!! test +Incorrecly removing closing slashes from correctly formed XHTML +!! input +
    +!! result +


    +

    +!! end + +!! test +Failing to transform badly formed HTML into correct XHTML +!! input +
    +
    +
    +!! result +


    +
    +
    +

    +!!end + +!! test +Horizontal ruler (should it add that extra space?) +!! input +
    +
    +foo
    bar +!! result +
    +
    +foo
    bar + +!! end + +### +### Block-level elements +### +!! test +Common list +!! input +*Common list +* item 2 +*item 3 +!! result +
    • Common list +
    • item 2 +
    • item 3 +
    + +!! end + +!! test +Numbered list +!! input +#Numbered list +#item 2 +# item 3 +!! result +
    1. Numbered list +
    2. item 2 +
    3. item 3 +
    + +!! end + +!! test +Mixed list +!! input +*Mixed list +*# with numbers +** and bullets +*# and numbers +*bullets again +**bullet level 2 +***bullet level 3 +***#Number on level 4 +**bullet level 2 +**#Number on level 3 +**#Number on level 3 +*#number level 2 +*Level 1 +!! result +
    • Mixed list +
      1. with numbers +
      +
      • and bullets +
      +
      1. and numbers +
      +
    • bullets again +
      • bullet level 2 +
        • bullet level 3 +
          1. Number on level 4 +
          +
        +
      • bullet level 2 +
        1. Number on level 3 +
        2. Number on level 3 +
        +
      +
      1. number level 2 +
      +
    • Level 1 +
    + +!! end + +!! test +List items are not parsed correctly following a
     block (bug 785)
    +!! input
    +* 
    foo
    +*
    bar
    +* zar +!! result +
    • foo
      +
    • bar
      +
    • zar +
    + +!! end + +### +### Magic Words +### + +!! test +Magic Word: {{CURRENTDAY}} +!! input +{{CURRENTDAY}} +!! result +

    1 +

    +!! end + +!! test +Magic Word: {{CURRENTDAY2}} +!! input +{{CURRENTDAY2}} +!! result +

    01 +

    +!! end + +!! test +Magic Word: {{CURRENTDAYNAME}} +!! input +{{CURRENTDAYNAME}} +!! result +

    Thursday +

    +!! end + +!! test +Magic Word: {{CURRENTDOW}} +!! input +{{CURRENTDOW}} +!! result +

    4 +

    +!! end + +!! test +Magic Word: {{CURRENTMONTH}} +!! input +{{CURRENTMONTH}} +!! result +

    01 +

    +!! end + +!! test +Magic Word: {{CURRENTMONTHABBREV}} +!! input +{{CURRENTMONTHABBREV}} +!! result +

    Jan +

    +!! end + +!! test +Magic Word: {{CURRENTMONTHNAME}} +!! input +{{CURRENTMONTHNAME}} +!! result +

    January +

    +!! end + +!! test +Magic Word: {{CURRENTMONTHNAMEGEN}} +!! input +{{CURRENTMONTHNAMEGEN}} +!! result +

    January +

    +!! end + +!! test +Magic Word: {{CURRENTTIME}} +!! input +{{CURRENTTIME}} +!! result +

    00:02 +

    +!! end + +!! test +Magic Word: {{CURRENTWEEK}} (@bug 4594) +!! input +{{CURRENTWEEK}} +!! result +

    1 +

    +!! end + +!! test +Magic Word: {{CURRENTYEAR}} +!! input +{{CURRENTYEAR}} +!! result +

    1970 +

    +!! end + +!! test +Magic Word: {{FULLPAGENAME}} +!! options +title=[[User:Ævar Arnfjörð Bjarmason]] +!! input +{{FULLPAGENAME}} +!! result +

    User:Ævar Arnfjörð Bjarmason +

    +!! end + +!! test +Magic Word: {{FULLPAGENAMEE}} +!! options +title=[[User:Ævar Arnfjörð Bjarmason]] +!! input +{{FULLPAGENAMEE}} +!! result +

    User:%C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason +

    +!! end + +!! test +Magic Word: {{NAMESPACE}} +!! options +title=[[User:Ævar Arnfjörð Bjarmason]] +!! input +{{NAMESPACE}} +!! result +

    User +

    +!! end + +!! test +Magic Word: {{NAMESPACEE}} +!! options +title=[[User:Ævar Arnfjörð Bjarmason]] +!! input +{{NAMESPACEE}} +!! result +

    User +

    +!! end + +!! test +Magic Word: {{NUMBEROFFILES}} +!! input +{{NUMBEROFFILES}} +!! result +

    2 +

    +!! end + +!! test +Magic Word: {{PAGENAME}} +!! options +title=[[User:Ævar Arnfjörð Bjarmason]] +!! input +{{PAGENAME}} +!! result +

    Ævar Arnfjörð Bjarmason +

    +!! end + +!! test +Magic Word: {{PAGENAMEE}} +!! options +title=[[User:Ævar Arnfjörð Bjarmason]] +!! input +{{PAGENAMEE}} +!! result +

    %C3%86var_Arnfj%C3%B6r%C3%B0_Bjarmason +

    +!! end + +!! test +Magic Word: {{REVISIONID}} +!! input +{{REVISIONID}} +!! result +

    1337 +

    +!! end + +!! test +Magic Word: {{SCRIPTPATH}} +!! input +{{SCRIPTPATH}} +!! result +

    / +

    +!! end + +!! test +Magic Word: {{SERVER}} +!! input +{{SERVER}} +!! result +

    http://localhost +

    +!! end + +!! test +Magic Word: {{SERVERNAME}} +!! input +{{SERVERNAME}} +!! result +

    Britney-Spears +

    +!! end + +!! test +Magic Word: {{SITENAME}} +!! input +{{SITENAME}} +!! result +

    MediaWiki +

    +!! end + +!! test +Namespace 1 {{ns:1}} +!! input +{{ns:1}} +!! result +

    Talk +

    +!! end + +!! test +Namespace 1 {{ns:01}} +!! input +{{ns:01}} +!! result +

    Talk +

    +!! end + +!! test +Namespace 0 {{ns:0}} (bug 4783) +!! input +{{ns:0}} +!! result + +!! end + +!! test +Namespace 0 {{ns:00}} (bug 4783) +!! input +{{ns:00}} +!! result + +!! end + +!! test +Namespace -1 {{ns:-1}} +!! input +{{ns:-1}} +!! result +

    Special +

    +!! end + +!! test +Namespace User {{ns:User}} +!! input +{{ns:User}} +!! result +

    User +

    +!! end + +!! test +Namespace User talk {{ns:User_talk}} +!! input +{{ns:User_talk}} +!! result +

    User talk +

    +!! end + +!! test +Namespace User talk {{ns:uSeR tAlK}} +!! input +{{ns:uSeR tAlK}} +!! result +

    User talk +

    +!! end + +!! test +Namespace File {{ns:File}} +!! input +{{ns:File}} +!! result +

    File +

    +!! end + +!! test +Namespace File {{ns:Image}} +!! input +{{ns:Image}} +!! result +

    File +

    +!! end + +!! test +Namespace (lang=de) Benutzer {{ns:User}} +!! options +language=de +!! input +{{ns:User}} +!! result +

    Benutzer +

    +!! end + +!! test +Namespace (lang=de) Benutzer Diskussion {{ns:3}} +!! options +language=de +!! input +{{ns:3}} +!! result +

    Benutzer Diskussion +

    +!! end + + +!! test +Urlencode +!! input +{{urlencode:hi world?!}} +{{urlencode:hi world?!|WIKI}} +{{urlencode:hi world?!|PATH}} +{{urlencode:hi world?!|QUERY}} +!! result +

    hi+world%3F%21 +hi_world%3F! +hi%20world%3F%21 +hi+world%3F%21 +

    +!! end + +### +### Magic links +### +!! test +Magic links: internal link to RFC (bug 479) +!! input +[[RFC 123]] +!! result +

    RFC 123 +

    +!! end + +!! test +Magic links: RFC (bug 479) +!! input +RFC 822 +!! result +

    RFC 822 +

    +!! end + +!! test +Magic links: ISBN (bug 1937) +!! input +ISBN 0-306-40615-2 +!! result +

    ISBN 0-306-40615-2 +

    +!! end + +!! test +Magic links: PMID incorrectly converts space to underscore +!! input +PMID 1234 +!! result +

    PMID 1234 +

    +!! end + +### +### Templates +#### + +!! test +Nonexistent template +!! input +{{thistemplatedoesnotexist}} +!! result +

    Template:Thistemplatedoesnotexist +

    +!! end + +!! article +Template:test +!! text +This is a test template +!! endarticle + +!! test +Simple template +!! input +{{test}} +!! result +

    This is a test template +

    +!! end + +!! test +Template with explicit namespace +!! input +{{Template:test}} +!! result +

    This is a test template +

    +!! end + + +!! article +Template:paramtest +!! text +This is a test template with parameter {{{param}}} +!! endarticle + +!! test +Template parameter +!! input +{{paramtest|param=foo}} +!! result +

    This is a test template with parameter foo +

    +!! end + +!! article +Template:paramtestnum +!! text +[[{{{1}}}|{{{2}}}]] +!! endarticle + +!! test +Template unnamed parameter +!! input +{{paramtestnum|Main Page|the main page}} +!! result +

    the main page +

    +!! end + +!! article +Template:templatesimple +!! text +(test) +!! endarticle + +!! article +Template:templateredirect +!! text +#redirect [[Template:templatesimple]] +!! endarticle + +!! article +Template:templateasargtestnum +!! text +{{{{{1}}}}} +!! endarticle + +!! article +Template:templateasargtest +!! text +{{template{{{templ}}}}} +!! endarticle + +!! article +Template:templateasargtest2 +!! text +{{{{{templ}}}}} +!! endarticle + +!! test +Template with template name as unnamed argument +!! input +{{templateasargtestnum|templatesimple}} +!! result +

    (test) +

    +!! end + +!! test +Template with template name as argument +!! input +{{templateasargtest|templ=simple}} +!! result +

    (test) +

    +!! end + +!! test +Template with template name as argument (2) +!! input +{{templateasargtest2|templ=templatesimple}} +!! result +

    (test) +

    +!! end + +!! article +Template:templateasargtestdefault +!! text +{{{{{templ|templatesimple}}}}} +!! endarticle + +!! article +Template:templa +!! text +'''templ''' +!! endarticle + +!! test +Template with default value +!! input +{{templateasargtestdefault}} +!! result +

    (test) +

    +!! end + +!! test +Template with default value (value set) +!! input +{{templateasargtestdefault|templ=templa}} +!! result +

    templ +

    +!! end + +!! test +Template redirect +!! input +{{templateredirect}} +!! result +

    (test) +

    +!! end + +!! test +Template with argument in separate line +!! input +{{ templateasargtest | + templ = simple }} +!! result +

    (test) +

    +!! end + +!! test +Template with complex template as argument +!! input +{{paramtest| + param ={{ templateasargtest | + templ = simple }}}} +!! result +

    This is a test template with parameter (test) +

    +!! end + +!! test +Template with thumb image (with link in description) +!! input +{{paramtest| + param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}} +!! result +This is a test template with parameter + +!! end + +!! article +Template:complextemplate +!! text +{{{1}}} {{paramtest| + param ={{{param}}}}} +!! endarticle + +!! test +Template with complex arguments +!! input +{{complextemplate| + param ={{ templateasargtest | + templ = simple }}|[[Template:complextemplate|link]]}} +!! result +

    link This is a test template with parameter (test) +

    +!! end + +!! test +BUG 553: link with two variables in a piped link +!! input +{| +|[[{{{1}}}|{{{2}}}]] +|} +!! result + + +
    [[{{{1}}}|{{{2}}}]] +
    + +!! end + +!! test +Magic variable as template parameter +!! input +{{paramtest|param={{SITENAME}}}} +!! result +

    This is a test template with parameter MediaWiki +

    +!! end + +!! article +Template:linktest +!! text +[[{{{param}}}|link]] +!! endarticle + +!! test +Template parameter as link source +!! input +{{linktest|param=Main Page}} +!! result +

    link +

    +!! end + + +!!article +Template:paramtest2 +!! text +including another template, {{paramtest|param={{{arg}}}}} +!! endarticle + +!! test +Template passing argument to another template +!! input +{{paramtest2|arg='hmm'}} +!! result +

    including another template, This is a test template with parameter 'hmm' +

    +!! end + +!! article +Template:Linktest2 +!! text +Main Page +!! endarticle + +!! test +Template as link source +!! input +[[{{linktest2}}]] +!! result +

    Main Page +

    +!! end + + +!! article +Template:loop1 +!! text +{{loop2}} +!! endarticle + +!! article +Template:loop2 +!! text +{{loop1}} +!! endarticle + +!! test +Template infinite loop +!! input +{{loop1}} +!! result +

    Template loop detected: Template:Loop1 +

    +!! end + +!! test +Template from main namespace +!! input +{{:Main Page}} +!! result +

    blah blah +

    +!! end + +!! article +Template:table +!! text +{| +| 1 || 2 +|- +| 3 || 4 +|} +!! endarticle + +!! test +BUG 529: Template with table, not included at beginning of line +!! input +foo {{table}} +!! result +

    foo +

    + + + + + + +
    1 2 +
    3 4 +
    + +!! end + +!! test +BUG 523: Template shouldn't eat newline (or add an extra one before table) +!! input +foo +{{table}} +!! result +

    foo +

    + + + + + + +
    1 2 +
    3 4 +
    + +!! end + +!! test +BUG 41: Template parameters shown as broken links +!! input +{{{parameter}}} +!! result +

    {{{parameter}}} +

    +!! end + + +!! article +Template:MSGNW test +!! text +''None'' of '''this''' should be +* interpreted + but rather passed unmodified +{{test}} +!! endarticle + +# hmm, fix this or just deprecate msgnw and document its behavior? +!! test +msgnw keyword +!! options +disabled +!! input +{{msgnw:MSGNW test}} +!! result +

    ''None'' of '''this''' should be +* interpreted + but rather passed unmodified +{{test}} +

    +!! end + +!! test +int keyword +!! input +{{int:youhavenewmessages|lots of money|not!}} +!! result +

    You have lots of money (not!). +

    +!! end + +!! article +Template:Includes +!! text +Foozarbar +!! endarticle + +!! test + and being included +!! input +{{Includes}} +!! result +

    Foobar +

    +!! end + +!! article +Template:Includes2 +!! text +Foobar +!! endarticle + +!! test + being included +!! input +{{Includes2}} +!! result +

    Foo +

    +!! end + + +!! article +Template:Includes3 +!! text +Foobarzar +!! endarticle + +!! test + and being included +!! input +{{Includes3}} +!! result +

    Foo +

    +!! end + +!! test + and on a page +!! input +Foozarbar +!! result +

    Foozar +

    +!! end + +!! test + on a page +!! input +Foobar +!! result +

    Foobar +

    +!! end + +!! article +Template:Includeonly section +!! text + +==Includeonly section== + +==Section T-1== +!!endarticle + +!! test +Bug 6563: Edit link generation for section shown by +!! input +{{includeonly section}} +!! result +

    [edit] Includeonly section

    +

    [edit] Section T-1

    + +!! end + +# Uses same input as the contents of [[Template:Includeonly section]] +!! test +Bug 6563: Section extraction for section shown by +!! options +section=T-2 +!! input + +==Includeonly section== + +==Section T-2== +!! result +==Section T-2== +!! end + +!! test +Bug 6563: Edit link generation for section suppressed by +!! input + +==Includeonly section== + +==Section 1== +!! result +

    [edit] Section 1

    + +!! end + +!! test +Bug 6563: Section extraction for section suppressed by +!! options +section=1 +!! input + +==Includeonly section== + +==Section 1== +!! result +==Section 1== +!! end + +### +### Pre-save transform tests +### +!! test +pre-save transform: subst: +!! options +PST +!! input +{{subst:test}} +!! result +This is a test template +!! end + +!! test +pre-save transform: normal template +!! options +PST +!! input +{{test}} +!! result +{{test}} +!! end + +!! test +pre-save transform: nonexistent template +!! options +PST +!! input +{{thistemplatedoesnotexist}} +!! result +{{thistemplatedoesnotexist}} +!! end + + +!! test +pre-save transform: subst magic variables +!! options +PST +!! input +{{subst:SITENAME}} +!! result +MediaWiki +!! end + +# This is bug 89, which I fixed. -- wtm +!! test +pre-save transform: subst: templates with parameters +!! options +pst +!! input +{{subst:paramtest|param="something else"}} +!! result +This is a test template with parameter "something else" +!! end + +!! article +Template:nowikitest +!! text +'''not wiki''' +!! endarticle + +!! test +pre-save transform: nowiki in subst (bug 1188) +!! options +pst +!! input +{{subst:nowikitest}} +!! result +'''not wiki''' +!! end + + +!! article +Template:commenttest +!! text +This template has in it. +!! endarticle + +!! test +pre-save transform: comment in subst (bug 1936) +!! options +pst +!! input +{{subst:commenttest}} +!! result +This template has in it. +!! end + +!! test +pre-save transform: unclosed tag +!! options +pst noxml +!! input +'''not wiki''' +!! result +'''not wiki''' +!! end + +!! test +pre-save transform: mixed tag case +!! options +pst noxml +!! input +'''not wiki''' +!! result +'''not wiki''' +!! end + +!! test +pre-save transform: unclosed comment in +!! options +pst noxml +!! input +wikinowiki +!!result + +!!end + +!! test +pre-save transform: comment containing extension +!! options +pst +!! input + +!!result + +!!end + +!! test +pre-save transform: comment containing nowiki +!! options +pst +!! input + +!!result + +!!end + +!! test +pre-save transform: comment containing math +!! options +pst +!! input + +!!result + +!!end + +!! test +pre-save transform: in subst (bug 3298) +!! options +pst +!! input +{{subst:Includes}} +!! result +Foobar +!! end + +!! test +pre-save transform: in subst (bug 3298) +!! options +pst +!! input +{{subst:Includes2}} +!! result +Foo +!! end + +!! article +Template:SubstTest +!!text +{{subst:Includes}} +!! endarticle + +!! article +Template:SafeSubstTest +!! text +{{safesubst:Includes}} +!! endarticle + +!! test +bug 22297: safesubst: works during PST +!! options +pst +!! input +{{subst:SafeSubstTest}}{{safesubst:SubstTest}} +!! result +FoobarFoobar +!! end + +!! test +bug 22297: safesubst: works during normal parse +!! input +{{SafeSubstTest}} +!! result +

    Foobar +

    +!! end + +!! test: +subst: does not work during normal parse +!! input +{{SubstTest}} +!! result +

    {{subst:Includes}} +

    +!! end + +!! test +pre-save transform: context links ("pipe trick") +!! options +pst +!! input +[[Article (context)|]] +[[Bar:Article|]] +[[:Bar:Article|]] +[[Bar:Article (context)|]] +[[:Bar:Article (context)|]] +[[|Article]] +[[|Article (context)]] +[[Bar:X (Y) Z|]] +[[:Bar:X (Y) Z|]] +!! result +[[Article (context)|Article]] +[[Bar:Article|Article]] +[[:Bar:Article|Article]] +[[Bar:Article (context)|Article]] +[[:Bar:Article (context)|Article]] +[[Article]] +[[Article (context)]] +[[Bar:X (Y) Z|X (Y) Z]] +[[:Bar:X (Y) Z|X (Y) Z]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with interwiki prefix +!! options +pst +!! input +[[interwiki:Article|]] +[[:interwiki:Article|]] +[[interwiki:Bar:Article|]] +[[:interwiki:Bar:Article|]] +!! result +[[interwiki:Article|Article]] +[[:interwiki:Article|Article]] +[[interwiki:Bar:Article|Bar:Article]] +[[:interwiki:Bar:Article|Bar:Article]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with parens in title +!! options +pst title=[[Somearticle (context)]] +!! input +[[|Article]] +!! result +[[Article (context)|Article]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with comma in title +!! options +pst title=[[Someplace, Somewhere]] +!! input +[[|Otherplace]] +[[Otherplace, Elsewhere|]] +[[Otherplace, Elsewhere, Anywhere|]] +!! result +[[Otherplace, Somewhere|Otherplace]] +[[Otherplace, Elsewhere|Otherplace]] +[[Otherplace, Elsewhere, Anywhere|Otherplace]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with parens and comma +!! options +pst title=[[Someplace (IGNORED), Somewhere]] +!! input +[[|Otherplace]] +[[Otherplace (place), Elsewhere|]] +!! result +[[Otherplace, Somewhere|Otherplace]] +[[Otherplace (place), Elsewhere|Otherplace]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with comma and parens +!! options +pst title=[[Who, me? (context)]] +!! input +[[|Yes, you.]] +[[Me, Myself, and I (1937 song)|]] +!! result +[[Yes, you. (context)|Yes, you.]] +[[Me, Myself, and I (1937 song)|Me, Myself, and I]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with namespace +!! options +pst title=[[Ns:Somearticle]] +!! input +[[|Article]] +!! result +[[Ns:Article|Article]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with namespace and parens +!! options +pst title=[[Ns:Somearticle (context)]] +!! input +[[|Article]] +!! result +[[Ns:Article (context)|Article]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with namespace and comma +!! options +pst title=[[Ns:Somearticle, Context, Whatever]] +!! input +[[|Article]] +!! result +[[Ns:Article, Context, Whatever|Article]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with namespace, comma and parens +!! options +pst title=[[Ns:Somearticle, Context (context)]] +!! input +[[|Article]] +!! result +[[Ns:Article (context)|Article]] +!! end + +!! test +pre-save transform: context links ("pipe trick") with namespace, parens and comma +!! options +pst title=[[Ns:Somearticle (IGNORED), Context]] +!! input +[[|Article]] +!! result +[[Ns:Article, Context|Article]] +!! end + + +### +### Message transform tests +### +!! test +message transform: magic variables +!! options +msg +!! input +{{SITENAME}} +!! result +MediaWiki +!! end + +!! test +message transform: should not transform wiki markup +!! options +msg +!! input +''test'' +!! result +''test'' +!! end + +!! test +message transform: in transcluded template (bug 4926) +!! options +msg +!! input +{{Includes}} +!! result +Foobar +!! end + +!! test +message transform: in transcluded template (bug 4926) +!! options +msg +!! input +{{Includes2}} +!! result +Foo +!! end + +!! test +{{#special:}} page name, known +!! options +msg +!! input +{{#special:Recentchanges}} +!! result +Special:RecentChanges +!! end + +!! test +{{#special:}} page name with subpage, known +!! options +msg +!! input +{{#special:Recentchanges/param}} +!! result +Special:RecentChanges/param +!! end + +!! test +{{#special:}} page name, unknown +!! options +msg +!! input +{{#special:foobarnonexistent}} +!! result +No such special page +!! end + +### +### Images +### +!! test +Simple image +!! input +[[Image:foobar.jpg]] +!! result +

    Foobar.jpg +

    +!! end + +!! test +Right-aligned image +!! input +[[Image:foobar.jpg|right]] +!! result +
    Foobar.jpg
    + +!! end + +!! test +Simple image (using File: namespace, now canonical) +!! input +[[File:foobar.jpg]] +!! result +

    Foobar.jpg +

    +!! end + +!! test +Image with caption +!! input +[[Image:foobar.jpg|right|Caption text]] +!! result +
    Caption text
    + +!! end + +!! test +Image with link parameter, wiki target +!! input +[[Image:foobar.jpg|link=Target page]] +!! result +

    Foobar.jpg +

    +!! end + +!! test +Image with link parameter, URL target +!! input +[[Image:foobar.jpg|link=http://example.com/]] +!! result +

    Foobar.jpg +

    +!! end + +!! test +Image with empty link parameter +!! input +[[Image:foobar.jpg|link=]] +!! result +

    Foobar.jpg +

    +!! end + +!! test +Image with link parameter (wiki target) and unnamed parameter +!! input +[[Image:foobar.jpg|link=Target page|Title]] +!! result +

    Title +

    +!! end + +!! test +Image with link parameter (URL target) and unnamed parameter +!! input +[[Image:foobar.jpg|link=http://example.com/|Title]] +!! result +

    Title +

    +!! end + +!! test +Thumbnail image with link parameter +!! input +[[Image:foobar.jpg|thumb|link=http://example.com/|Title]] +!! result +
    Title
    + +!! end + +!! test +Image with frame and link +!! input +[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]]] +!! result +
    This is a test image Main Page
    + +!! end + +!! test +Image with frame and link and explicit alt +!! input +[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]|alt=Altitude]] +!! result +
    Altitude
    This is a test image Main Page
    + +!! end + +!! test +Image with wiki markup in implicit alt +!! input +[[Image:Foobar.jpg|testing '''bold''' in alt]] +!! result +

    testing bold in alt +

    +!! end + +!! test +Image with wiki markup in explicit alt +!! input +[[Image:Foobar.jpg|alt=testing '''bold''' in alt]] +!! result +

    testing bold in alt +

    +!! end + +!! test +Link to image page- image page normally doesn't exists, hence edit link +Add test with existing image page +#

    Image:test +!! input +[[:Image:test]] +!! result +

    Image:test +

    +!! end + +!! test +bug 18784 Link to non-existent image page with caption should use caption as link text +!! input +[[:Image:test|caption]] +!! result +

    caption +

    +!! end + +!! test +Frameless image caption with a free URL +!! input +[[Image:foobar.jpg|http://example.com]] +!! result +

    http://example.com +

    +!! end + +!! test +Thumbnail image caption with a free URL +!! input +[[Image:foobar.jpg|thumb|http://example.com]] +!! result + + +!! end + +!! test +Thumbnail image caption with a free URL and explicit alt +!! input +[[Image:foobar.jpg|thumb|http://example.com|alt=Alteration]] +!! result + + +!! end + +!! test +BUG 1887: A ISBN with a thumbnail +!! input +[[Image:foobar.jpg|thumb|ISBN 1235467890]] +!! result + + +!! end + +!! test +BUG 1887: A RFC with a thumbnail +!! input +[[Image:foobar.jpg|thumb|This is RFC 12354]] +!! result +
    This is RFC 12354
    + +!! end + +!! test +BUG 1887: A mailto link with a thumbnail +!! input +[[Image:foobar.jpg|thumb|Please mailto:nobody@example.com]] +!! result + + +!! end + +!! test +BUG 1887: A with a thumbnail- we don't render math in the parsertests by default, +so math is not stripped and turns up as escaped <math> tags. +!! input +[[Image:foobar.jpg|thumb|2+2]] +!! result +
    <math>2+2</math>
    + +!! end + +!! test +BUG 1887, part 2: A with a thumbnail- math enabled +!! options +math +!! input +[[Image:foobar.jpg|thumb|2+2]] +!! result +
    2 + 2
    + +!! end + +# Pending resolution to bug 368 +!! test +BUG 648: Frameless image caption with a link +!! input +[[Image:foobar.jpg|text with a [[link]] in it]] +!! result +

    text with a link in it +

    +!! end + +!! test +BUG 648: Frameless image caption with a link (suffix) +!! input +[[Image:foobar.jpg|text with a [[link]]foo in it]] +!! result +

    text with a linkfoo in it +

    +!! end + +!! test +BUG 648: Frameless image caption with an interwiki link +!! input +[[Image:foobar.jpg|text with a [[MeatBall:Link]] in it]] +!! result +

    text with a MeatBall:Link in it +

    +!! end + +!! test +BUG 648: Frameless image caption with a piped interwiki link +!! input +[[Image:foobar.jpg|text with a [[MeatBall:Link|link]] in it]] +!! result +

    text with a link in it +

    +!! end + +!! test +Escape HTML special chars in image alt text +!! input +[[Image:foobar.jpg|& < > "]] +!! result +

    & < > " +

    +!! end + +!! test +BUG 499: Alt text should have Ӓ, not &1234; +!! input +[[Image:foobar.jpg|♀]] +!! result +

    ♀ +

    +!! end + +!! test +Broken image caption with link +!! input +[[Image:Foobar.jpg|thumb|This is a broken caption. But [[Main Page|this]] is just an ordinary link. +!! result +

    [[Image:Foobar.jpg|thumb|This is a broken caption. But this is just an ordinary link. +

    +!! end + +!! test +Image caption containing another image +!! input +[[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]] +!! result +
    This is a caption with another image inside it!
    + +!! end + +!! test +Image caption containing a newline +!! input +[[Image:Foobar.jpg|This +*is some text]] +!! result +

    This *is some text +

    +!!end + + +!! test +Bug 3090: External links other than http: in image captions +!! input +[[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]] +!! result +
    This caption has irc and Secure ext links in it.
    + +!! end + +!! article +File:Barfoo.jpg +!! text +#REDIRECT [[File:Barfoo.jpg]] +!! endarticle + +!! test +Redirected image +!! input +[[Image:Barfoo.jpg]] +!! result +

    File:Barfoo.jpg +

    +!! end + +!! test +Missing image with uploads disabled +!! options +wgEnableUploads=0 +!! input +[[Image:Foobaz.jpg]] +!! result +

    File:Foobaz.jpg +

    +!! end + + +### +### Subpages +### +!! article +Subpage test/subpage +!! text +foo +!! endarticle + +!! test +Subpage link +!! options +subpage title=[[Subpage test]] +!! input +[[/subpage]] +!! result +

    /subpage +

    +!! end + +!! test +Subpage noslash link +!! options +subpage title=[[Subpage test]] +!!input +[[/subpage/]] +!! result +

    subpage +

    +!! end + +!! test +Disabled subpages +!! input +[[/subpage]] +!! result +

    /subpage +

    +!! end + +!! test +BUG 561: {{/Subpage}} +!! options +subpage title=[[Page]] +!! input +{{/Subpage}} +!! result +

    Page/Subpage +

    +!! end + +### +### Categories +### +!! article +Category:MediaWiki User's Guide +!! text +blah +!! endarticle + +!! test +Link to category +!! input +[[:Category:MediaWiki User's Guide]] +!! result +

    Category:MediaWiki User's Guide +

    +!! end + +!! test +Simple category +!! options +cat +!! input +[[Category:MediaWiki User's Guide]] +!! result +MediaWiki User's Guide +!! end + +!! test +PAGESINCATEGORY invalid title fatal (r33546 fix) +!! input +{{PAGESINCATEGORY:}} +!! result +

    0 +

    +!! end + +### +### Inter-language links +### +!! test +Inter-language links +!! options +ill +!! input +[[es:Alimento]] +[[fr:Nourriture]] +[[zh:食品]] +!! result +es:Alimento fr:Nourriture zh:食品 +!! end + +### +### Sections +### +!! test +Basic section headings +!! input +== Headline 1 == +Some text + +==Headline 2== +More +===Smaller headline=== +Blah blah +!! result +

    [edit] Headline 1

    +

    Some text +

    +

    [edit] Headline 2

    +

    More +

    +

    [edit] Smaller headline

    +

    Blah blah +

    +!! end + +!! test +Section headings with TOC +!! input +== Headline 1 == +=== Subheadline 1 === +===== Skipping a level ===== +====== Skipping a level ====== + +== Headline 2 == +Some text +===Another headline=== +!! result +

    Contents

    + +
    +

    [edit] Headline 1

    +

    [edit] Subheadline 1

    +
    [edit] Skipping a level
    +
    [edit] Skipping a level
    +

    [edit] Headline 2

    +

    Some text +

    +

    [edit] Another headline

    + +!! end + +# perl -e 'print "="x$_," Level $_ heading","="x$_,"\n" for 1..10' +!! test +Handling of sections up to level 6 and beyond +!! input += Level 1 Heading= +== Level 2 Heading== +=== Level 3 Heading=== +==== Level 4 Heading==== +===== Level 5 Heading===== +====== Level 6 Heading====== +======= Level 7 Heading======= +======== Level 8 Heading======== +========= Level 9 Heading========= +========== Level 10 Heading========== +!! result +

    Contents

    + +
    +

    [edit] Level 1 Heading

    +

    [edit] Level 2 Heading

    +

    [edit] Level 3 Heading

    +

    [edit] Level 4 Heading

    +
    [edit] Level 5 Heading
    +
    [edit] Level 6 Heading
    +
    [edit] = Level 7 Heading=
    +
    [edit] == Level 8 Heading==
    +
    [edit] === Level 9 Heading===
    +
    [edit] ==== Level 10 Heading====
    + +!! end + +!! test +TOC regression (bug 9764) +!! input +== title 1 == +=== title 1.1 === +==== title 1.1.1 ==== +=== title 1.2 === +== title 2 == +=== title 2.1 === +!! result +

    Contents

    + +
    +

    [edit] title 1

    +

    [edit] title 1.1

    +

    [edit] title 1.1.1

    +

    [edit] title 1.2

    +

    [edit] title 2

    +

    [edit] title 2.1

    + +!! end + +!! test +TOC with wgMaxTocLevel=3 (bug 6204) +!! options +wgMaxTocLevel=3 +!! input +== title 1 == +=== title 1.1 === +==== title 1.1.1 ==== +=== title 1.2 === +== title 2 == +=== title 2.1 === +!! result +

    Contents

    + +
    +

    [edit] title 1

    +

    [edit] title 1.1

    +

    [edit] title 1.1.1

    +

    [edit] title 1.2

    +

    [edit] title 2

    +

    [edit] title 2.1

    + +!! end + +!! test +TOC with wgMaxTocLevel=3 and two level four headings (bug 6204) +!! options +wgMaxTocLevel=3 +!! input +==Section 1== +===Section 1.1=== +====Section 1.1.1==== +====Section 1.1.1.1==== +==Section 2== +!! result +

    Contents

    + +
    +

    [edit] Section 1

    +

    [edit] Section 1.1

    +

    [edit] Section 1.1.1

    +

    [edit] Section 1.1.1.1

    +

    [edit] Section 2

    + +!! end + + +!! test +Resolving duplicate section names +!! input +== Foo bar == +== Foo bar == +!! result +

    [edit] Foo bar

    +

    [edit] Foo bar

    + +!! end + +!! test +Resolving duplicate section names with differing case (bug 10721) +!! input +== Foo bar == +== Foo Bar == +!! result +

    [edit] Foo bar

    +

    [edit] Foo Bar

    + +!! end + +!! article +Template:sections +!! text +===Section 1=== +==Section 2== +!! endarticle + +!! test +Template with sections, __NOTOC__ +!! input +__NOTOC__ +==Section 0== +{{sections}} +==Section 4== +!! result +

    [edit] Section 0

    +

    [edit] Section 1

    +

    [edit] Section 2

    +

    [edit] Section 4

    + +!! end + +!! test +__NOEDITSECTION__ keyword +!! input +__NOEDITSECTION__ +==Section 1== +==Section 2== +!! result +

    Section 1

    +

    Section 2

    + +!! end + +!! test +Link inside a section heading +!! input +==Section with a [[Main Page|link]] in it== +!! result +

    [edit] Section with a link in it

    + +!! end + +!! test +TOC regression (bug 12077) +!! input +__TOC__ +== title 1 == +=== title 1.1 === +== title 2 == +!! result +

    Contents

    + +
    +

    [edit] title 1

    +

    [edit] title 1.1

    +

    [edit] title 2

    + +!! end + +!! test +BUG 1219 URL next to image (good) +!! input +http://example.com [[Image:foobar.jpg]] +!! result +

    http://example.com Foobar.jpg +

    +!!end + +!! test +Short headings with trailing space should match behaviour of Parser::doHeadings (bug 19910) +!! input +=== +The line above must have a trailing space! +=== +But just in case it doesn't... +!! result +

    [edit] =

    +

    The line above must have a trailing space! +

    +

    [edit] =

    +

    But just in case it doesn't... +

    +!! end + +!! test +BUG 1219 URL next to image (broken) +!! input +http://example.com[[Image:foobar.jpg]] +!! result +

    http://example.comFoobar.jpg +

    +!!end + +!! test +Bug 1186 news: in the middle of text +!! input +http://en.wikinews.org/wiki/Wikinews:Workplace +!! result +

    http://en.wikinews.org/wiki/Wikinews:Workplace +

    +!!end + + +!! test +Namespaced link must have a title +!! input +[[Project:]] +!! result +

    [[Project:]] +

    +!!end + +!! test +Namespaced link must have a title (bad fragment version) +!! input +[[Project:#fragment]] +!! result +

    [[Project:#fragment]] +

    +!!end + + +!! test +div with no attributes +!! input +
    HTML rocks
    +!! result +
    HTML rocks
    + +!! end + +!! test +div with double-quoted attribute +!! input +
    HTML rocks
    +!! result +
    HTML rocks
    + +!! end + +!! test +div with single-quoted attribute +!! input +
    HTML rocks
    +!! result +
    HTML rocks
    + +!! end + +!! test +div with unquoted attribute +!! input +
    HTML rocks
    +!! result +
    HTML rocks
    + +!! end + +!! test +div with illegal double attributes +!! input +
    HTML rocks
    +!! result +
    HTML rocks
    + +!!end + +!! test +HTML multiple attributes correction +!! input +

    Awesome!

    +!! result +

    Awesome!

    + +!!end + +!! test +Table multiple attributes correction +!! input +{| +!+ class="error" class="awesome"| status +|} +!! result + + +
    status +
    + +!!end + +!! test +DIV IN UPPERCASE +!! input +
    HTML ROCKS
    +!! result +
    HTML ROCKS
    + +!!end + + +!! test +text with amp in the middle of nowhere +!! input +Remember AT&T? +!!result +

    Remember AT&T? +

    +!! end + +!! test +text with character entity: eacute +!! input +I always thought é was a cute letter. +!! result +

    I always thought é was a cute letter. +

    +!! end + +!! test +text with undefined character entity: xacute +!! input +I always thought &xacute; was a cute letter. +!! result +

    I always thought &xacute; was a cute letter. +

    +!! end + + +### +### Media links +### + +!! test +Media link +!! input +[[Media:Foobar.jpg]] +!! result +

    Media:Foobar.jpg +

    +!! end + +!! test +Media link with text +!! input +[[Media:Foobar.jpg|A neat file to look at]] +!! result +

    A neat file to look at +

    +!! end + +# FIXME: this is still bad HTML tag nesting +!! test +Media link with nasty text +fixme: doBlockLevels won't wrap this in a paragraph because it contains a div +!! input +[[Media:Foobar.jpg|Safe Link
    " onmouseover="alert(document.cookie)" onfoo="
    ]] +!! result +Safe Link<div style="display:none">" onmouseover="alert(document.cookie)" onfoo="</div> + +!! end + +!! test +Media link to nonexistent file (bug 1702) +!! input +[[Media:No such.jpg]] +!! result +

    Media:No such.jpg +

    +!! end + +!! test +Image link to nonexistent file (bug 1850 - good) +!! input +[[Image:No such.jpg]] +!! result +

    File:No such.jpg +

    +!! end + +!! test +:Image link to nonexistent file (bug 1850 - bad) +!! input +[[:Image:No such.jpg]] +!! result +

    Image:No such.jpg +

    +!! end + + + +!! test +Character reference normalization in link text (bug 1938) +!! input +[[Main Page|this&that]] +!! result +

    this&that +

    +!!end + +!! article +אַ +!! text +Test for unicode normalization + +The page's name is U+05d0 U+05b7, with non-canonical form U+FB2E +!! endarticle + +!! test +(bug 19451) Links should refer to the normalized form. +!! input +[[אַ]] +[[אַ]] +[[אÖ·]] +[[אַ]] +[[אַ]] +!! result +

    +אַ +אÖ· +אַ +אַ +

    +!! end + +!! test +Empty attribute crash test (bug 2067) +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Empty attribute crash test single-quotes (bug 2067) +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Attribute test: equals, then nothing +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Attribute test: unquoted value +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Attribute test: unquoted but illegal value (hash) +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Attribute test: no value +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Bug 2095: link with three closing brackets +!! input +[[Main Page]]] +!! result +

    Main Page] +

    +!! end + +!! test +Bug 2095: link with pipe and three closing brackets +!! input +[[Main Page|link]]] +!! result +

    link] +

    +!! end + +!! test +Bug 2095: link with pipe and three closing brackets, version 2 +!! input +[[Main Page|[http://example.com/]]] +!! result +

    [http://example.com/] +

    +!! end + + +### +### Safety +### + +!! article +Template:Dangerous attribute +!! text +" onmouseover="alert(document.cookie) +!! endarticle + +!! article +Template:Dangerous style attribute +!! text +border-size: expression(alert(document.cookie)) +!! endarticle + +!! article +Template:Div style +!! text +
    Magic div
    +!! endarticle + +!! test +Bug 2304: HTML attribute safety (safe template; regression bug 2309) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (dangerous template; 2309) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (dangerous style template; 2309) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (safe parameter; 2309) +!! input +{{div style|width: 200px}} +!! result +
    Magic div
    + +!! end + +!! test +Bug 2304: HTML attribute safety (unsafe parameter; 2309) +!! input +{{div style|width: expression(alert(document.cookie))}} +!! result +
    Magic div
    + +!! end + +!! test +Bug 2304: HTML attribute safety (unsafe breakout parameter; 2309) +!! input +{{div style|">}} +!! result +
    <script>alert(document.cookie)</script>">Magic div
    + +!! end + +!! test +Bug 2304: HTML attribute safety (unsafe breakout parameter 2; 2309) +!! input +{{div style|" >}} +!! result +
    <script>alert(document.cookie)</script>">Magic div
    + +!! end + +!! test +Bug 2304: HTML attribute safety (link) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (italics) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (bold) +!! input +
    +!! result +
    + +!! end + + +!! test +Bug 2304: HTML attribute safety (ISBN) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (RFC) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (PMID) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (web link) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 2304: HTML attribute safety (named web link) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 3244: HTML attribute safety (extension; safe) +!! input +
    +!! result +
    + +!! end + +!! test +Bug 3244: HTML attribute safety (extension; unsafe) +!! input +
    +!! result +
    + +!! end + +!! test +Math section safety when disabled +!! input + +!! result +

    <math><script>alert(document.cookies);</script></math> +

    +!! end + +# More MSIE fun discovered by Tom Gilder + +!! test +MSIE CSS safety test: spurious slash +!! input +
    evil
    +!! result +
    evil
    + +!! end + +!! test +MSIE CSS safety test: hex code +!! input +
    evil
    +!! result +
    evil
    + +!! end + +!! test +MSIE CSS safety test: comment in url +!! input +
    evil
    +!! result +
    evil
    + +!! end + +!! test +MSIE CSS safety test: comment in expression +!! input +
    evil4
    +!! result +
    evil4
    + +!! end + + +!! test +Table attribute legitimate extension +!! input +{| +!+ style="color:blue"| status +|} +!! result + + +
    status +
    + +!!end + +!! test +Table attribute safety +!! input +{| +!+ style="border-width:expression(0+alert(document.cookie))"| status +|} +!! result + + +
    status +
    + +!! end + +!! test +CSS line continuation 1 +!! input +
    +!! result +
    + +!! end + +!! test +CSS line continuation 2 +!! input +
    +!! result +
    + +!! end + +!! article +Template:Identity +!! text +{{{1}}} +!! endarticle + +!! test +Expansion of multi-line templates in attribute values (bug 6255) +!! input +
    -
    +!! result +
    -
    + +!! end + + +!! test +Expansion of multi-line templates in attribute values (bug 6255 sanity check) +!! input +
    -
    +!! result +
    -
    + +!! end + +!! test +Expansion of multi-line templates in attribute values (bug 6255 sanity check 2) +!! input +
    -
    +!! result +
    -
    + +!! end + +### +### Parser hooks (see maintenance/parserTestsParserHook.php for the extension) +### +!! test +Parser hook: empty input +!! input + +!! result +
    +string(0) ""
    +array(0) {
    +}
    +
    + +!! end + +!! test +Parser hook: empty input using terminated empty elements +!! input + +!! result +
    +NULL
    +array(0) {
    +}
    +
    + +!! end + +!! test +Parser hook: empty input using terminated empty elements (space before) +!! input + +!! result +
    +NULL
    +array(0) {
    +}
    +
    + +!! end + +!! test +Parser hook: basic input +!! input +input +!! result +
    +string(5) "input"
    +array(0) {
    +}
    +
    + +!! end + + +!! test +Parser hook: case insensitive +!! input +input +!! result +
    +string(5) "input"
    +array(0) {
    +}
    +
    + +!! end + + +!! test +Parser hook: case insensitive, redux +!! input +input +!! result +
    +string(5) "input"
    +array(0) {
    +}
    +
    + +!! end + +!! test +Parser hook: nested tags +!! options +noxml +!! input + +!! result +
    +string(5) ""
    +array(0) {
    +}
    +
    </tag> + +!! end + +!! test +Parser hook: basic arguments +!! input + +!! result +
    +string(0) ""
    +array(4) {
    +  ["width"]=>
    +  string(3) "200"
    +  ["height"]=>
    +  string(3) "100"
    +  ["depth"]=>
    +  string(2) "50"
    +  ["square"]=>
    +  string(6) "square"
    +}
    +
    + +!! end + +!! test +Parser hook: argument containing a forward slash (bug 5344) +!! input + +!! result +
    +string(0) ""
    +array(1) {
    +  ["filename"]=>
    +  string(8) "/tmp/bla"
    +}
    +
    + +!! end + +!! test +Parser hook: empty input using terminated empty elements (bug 2374) +!! input +text +!! result +
    +NULL
    +array(1) {
    +  ["foo"]=>
    +  string(3) "bar"
    +}
    +
    text + +!! end + +#
    should be output literally since there is no matching tag that begins it +!! test +Parser hook: basic arguments using terminated empty elements (bug 2374) +!! input + +other stuff + +!! result +
    +NULL
    +array(4) {
    +  ["width"]=>
    +  string(3) "200"
    +  ["height"]=>
    +  string(3) "100"
    +  ["depth"]=>
    +  string(2) "50"
    +  ["square"]=>
    +  string(6) "square"
    +}
    +
    +

    other stuff +</tag> +

    +!! end + +### +### (see maintenance/parserTestsStaticParserHook.php for the extension) +### + +!! test +Parser hook: static parser hook not inside a comment +!! input +hello, world + +!! result +

    hello, world +

    +!! end + + +!! test +Parser hook: static parser hook inside a comment +!! input + + +!! result +


    +

    +!! end + +# Nested template calls; this case was broken by Parser.php rev 1.506, +# since reverted. + +!! article +Template:One-parameter +!! text +(My parameter is: {{{1}}}) +!! endarticle + +!! article +Template:Map-one-parameter +!! text +{{{{{1}}}|{{{2}}}}} +!! endarticle + +!! test +Nested template calls +!! input +{{Map-one-parameter|One-parameter|param}} +!! result +

    (My parameter is: param) +

    +!! end + + +### +### Sanitizer +### +!! test +Sanitizer: Closing of open tags +!! input +
    +!! result +
    + +!! end + +!! test +Sanitizer: Closing of open but not closed tags +!! input +foo +!! result +

    foo +

    +!! end + +!! test +Sanitizer: Closing of closed but not open tags +!! input +
    +!! result +

    </s> +

    +!! end + +!! test +Sanitizer: Closing of closed but not open table tags +!! input +Table not started +!! result +

    Table not started</td></tr></table> +

    +!! end + +!! test +Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id="" +!! input +byte[[#æ: v|backlink]] +!! result +

    bytebacklink +

    +!! end + +!! test +Sanitizer: Validating the contents of the id attribute (bug 4515) +!! options +disabled +!! input +
    +!! result +Something, but definitely not
    ... +!! end + +!! test +Sanitizer: Validating id attribute uniqueness (bug 4515, bug 6301) +!! options +disabled +!! input +

    +!! result +Something need to be done. foo-2 ? +!! end + +!! test +Language converter: output gets cut off unexpectedly (bug 5757) +!! options +language=zh +!! input +this bit is safe: }- + +but if we add a conversion instance: -{zh-cn:xxx;zh-tw:yyy}- + +then we get cut off here: }- + +all additional text is vanished +!! result +

    this bit is safe: }- +

    but if we add a conversion instance: xxx +

    then we get cut off here: }- +

    all additional text is vanished +

    +!! end + +!! test +Self closed html pairs (bug 5487) +!! options +!! input +
    Centered text
    +
    In div text
    +!! result +
    <font id="bug" />Centered text
    +
    <font id="bug2" />In div text
    + +!! end + +# +# +# + +!! test +Punctuation: nbsp before exclamation +!! input +C'est grave ! +!! result +

    C'est grave ! +

    +!! end + +!! test +Punctuation: CSS !important (bug 11874) +!! input +
    important
    +!! result +
    important
    + +!!end + +!! test +Punctuation: CSS ! important (bug 11874; with space after) +!! input +
    important
    +!! result +
    important
    + +!!end + + +!! test +HTML bullet list, closed tags (bug 5497) +!! input +
      +
    • One
    • +
    • Two
    • +
    +!! result +
      +
    • One
    • +
    • Two
    • +
    + +!! end + +!! test +HTML bullet list, unclosed tags (bug 5497) +!! options +disabled +!! input +
      +
    • One +
    • Two +
    +!! result +
      +
    • One +
    • Two +
    + +!! end + +!! test +HTML ordered list, closed tags (bug 5497) +!! input +
      +
    1. One
    2. +
    3. Two
    4. +
    +!! result +
      +
    1. One
    2. +
    3. Two
    4. +
    + +!! end + +!! test +HTML ordered list, unclosed tags (bug 5497) +!! options +disabled +!! input +
      +
    1. One +
    2. Two +
    +!! result +
      +
    1. One +
    2. Two +
    + +!! end + +!! test +HTML nested bullet list, closed tags (bug 5497) +!! input +
      +
    • One
    • +
    • Two: +
        +
      • Sub-one
      • +
      • Sub-two
      • +
      +
    • +
    +!! result +
      +
    • One
    • +
    • Two: +
        +
      • Sub-one
      • +
      • Sub-two
      • +
      +
    • +
    + +!! end + +!! test +HTML nested bullet list, open tags (bug 5497) +!! options +disabled +!! input +
      +
    • One +
    • Two: +
        +
      • Sub-one +
      • Sub-two +
      +
    +!! result +
      +
    • One +
    • Two: +
        +
      • Sub-one +
      • Sub-two +
      +
    + +!! end + +!! test +HTML nested ordered list, closed tags (bug 5497) +!! input +
      +
    1. One
    2. +
    3. Two: +
        +
      1. Sub-one
      2. +
      3. Sub-two
      4. +
      +
    4. +
    +!! result +
      +
    1. One
    2. +
    3. Two: +
        +
      1. Sub-one
      2. +
      3. Sub-two
      4. +
      +
    4. +
    + +!! end + +!! test +HTML nested ordered list, open tags (bug 5497) +!! options +disabled +!! input +
      +
    1. One +
    2. Two: +
        +
      1. Sub-one +
      2. Sub-two +
      +
    +!! result +
      +
    1. One +
    2. Two: +
        +
      1. Sub-one +
      2. Sub-two +
      +
    + +!! end + +!! test +HTML ordered list item with parameters oddity +!! input +
    1. One
    +!! result +
    1. One
    + +!! end + +!!test +bug 5918: autonumbering +!! input +[http://first/] [http://second] [ftp://ftp] + +ftp://inlineftp + +[mailto:enclosed@mail.tld With target] + +[mailto:enclosed@mail.tld] + +mailto:inline@mail.tld +!! result +

    [1] [2] [3] +

    ftp://inlineftp +

    With target +

    [4] +

    mailto:inline@mail.tld +

    +!! end + + +# +# Security and HTML correctness +# From Nick Jenkins' fuzz testing +# + +!! test +Fuzz testing: Parser13 +!! input +{| +| http://a| +!! result + + + + +
    +
    + +!! end + +!! test +Fuzz testing: Parser14 +!! input +== onmouseover= == +http://__TOC__ +!! result +

    [edit] onmouseover=

    +http://

    Contents

    + +
    + +!! end + +!! test +Fuzz testing: Parser14-table +!! input +==a== +{| STYLE=__TOC__ +!! result +

    [edit] a

    + + +
    + +!! end + +# Known to produce bogus xml (extra ) +!! test +Fuzz testing: Parser16 +!! options +noxml +!! input +{| +!https://|||||| +!! result + + + + + + +
    https:// + +
    + +!! end + +!! test +Fuzz testing: Parser21 +!! input +{| +! irc://{{ftp://a" onmouseover="alert('hello world');" +| +!! result + + + + + +
    irc://{{ftp://a" onmouseover="alert('hello world');" + +
    + +!! end + +!! test +Fuzz testing: Parser22 +!! input +http://===r:::https://b + +{| +!!result +

    http://===r:::https://b +

    + + +
    + +!! end + +# Known to produce bad XML for now +!! test +Fuzz testing: Parser24 +!! options +noxml +!! input +{| +{{{| +}}}} > +
    + +MOVE YOUR MOUSE CURSOR OVER THIS TEXT +| +!! result + +{{{| +}}}} > +
    + +MOVE YOUR MOUSE CURSOR OVER THIS TEXT +
    + + +
    +
    + +!! end + +# Note: the current result listed for this is not what the original one was, +# but the original bug was JavaScript injection, which is fixed in any case. +# It's not clear that the original result listed was any more correct than the +# current one. Original result: +#

    {{{| +#

    +#
  • +# }}}blah" onmouseover="alert('hello world');" align="left"MOVE MOUSE CURSOR OVER HERE +!!test +Fuzz testing: Parser25 (bug 6055) +!! input +{{{ +| +
  • +}}}blah" onmouseover="alert('hello world');" align="left"'''MOVE MOUSE CURSOR OVER HERE +!! result +

    <LI CLASS=blah" onmouseover="alert('hello world');" align="left"MOVE MOUSE CURSOR OVER HERE +

    +!! end + +!!test +Fuzz testing: URL adjacent extension (with space, clean) +!! options +!! input +http://example.com junk +!! result +

    http://example.com junk +

    +!!end + +!!test +Fuzz testing: URL adjacent extension (no space, dirty; nowiki) +!! options +!! input +http://example.comjunk +!! result +

    http://example.comjunk +

    +!!end + +!!test +Fuzz testing: URL adjacent extension (no space, dirty; pre) +!! options +!! input +http://example.com
    junk
    +!! result +http://example.com
    junk
    + +!!end + +!!test +Fuzz testing: image with bogus manual thumbnail +!!input +[[Image:foobar.jpg|thumbnail= ]] +!!result +
    Error creating thumbnail:
    + +!!end + +!! test +Fuzz testing: encoded newline in generated HTML replacements (bug 6577) +!! input +
    
    +!! result
    +
    
    +
    +!! end
    +
    +!! test
    +Parsing optional HTML elements (Bug 6171)
    +!! options
    +!! input
    +
    +  
    +    
    +    
    +  
    +
    Some tabular data More tabular data ... + And yet som tabular data
    +!! result + + + + + +
    Some tabular data More tabular data ... + And yet som tabular data
    + +!! end + +!! test +Correct handling of , (Bug 6171) +!! options +!! input + + + + + + +
    Some tabular data More tabular data ... And yet som tabular data
    +!! result + + + + + + +
    Some tabular data More tabular data ... And yet som tabular data
    + +!! end + + +!! test +Parsing crashing regression (fr:JavaScript) +!! input + +!! result +

    </body></x> +

    +!! end + +!! test +Inline wiki vs wiki block nesting +!! input +'''Bold paragraph + +New wiki paragraph +!! result +

    Bold paragraph +

    New wiki paragraph +

    +!! end + +!! test +Inline HTML vs wiki block nesting +!! options +disabled +!! input +Bold paragraph + +New wiki paragraph +!! result +

    Bold paragraph +

    New wiki paragraph +

    +!! end + +# Original result was this: +#

    boldboldbolditalics +#

    +# While that might be marginally more intuitive, maybe, the six-apostrophe +# construct is clearly pathological and the result stated here (which is what +# the parser actually does) is about as reasonable as anything. +!!test +Mixing markup for italics and bold +!! options +!! input +'''bold''''''bold''bolditalics''''' +!! result +

    'bold'boldbolditalics +

    +!! end + + +!! article +Xyzzyx +!! text +Article for special page transclusion test +!! endarticle + +!! test +Special page transclusion +!! options +!! input +{{Special:Prefixindex/Xyzzyx}} +!! result +


    +

    +
    Xyzzyx
    + +!! end + +!! test +Special page transclusion twice (bug 5021) +!! options +!! input +{{Special:Prefixindex/Xyzzyx}} +{{Special:Prefixindex/Xyzzyx}} +!! result +


    +

    +
    Xyzzyx
    +


    +

    +
    Xyzzyx
    + +!! end + +!! test +Transclusion of default MediaWiki message +!! input +{{MediaWiki:Mainpage}} +!!result +

    Main Page +

    +!! end + +!! test +Transclusion of nonexistent MediaWiki message +!! input +{{MediaWiki:Mainpagexxx}} +!!result +

    MediaWiki:Mainpagexxx +

    +!! end + +!! test +Transclusion of MediaWiki message with underscore +!! input +{{MediaWiki:history_short}} +!! result +

    History +

    +!! end + +!! test +Transclusion of MediaWiki message with space +!! input +{{MediaWiki:history short}} +!! result +

    History +

    +!! end + +!! test +Invalid header with following text +!! input += x = y +!! result +

    = x = y +

    +!! end + + +!! test +Section extraction test (section 0) +!! options +section=0 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +!! end + +!! test +Section extraction test (section 1) +!! options +section=1 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +==a== +===aa=== +====aaa==== +!! end + +!! test +Section extraction test (section 2) +!! options +section=2 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +===aa=== +====aaa==== +!! end + +!! test +Section extraction test (section 3) +!! options +section=3 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +====aaa==== +!! end + +!! test +Section extraction test (section 4) +!! options +section=4 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +==b== +===ba=== +===bb=== +====bba==== +===bc=== +!! end + +!! test +Section extraction test (section 5) +!! options +section=5 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +===ba=== +!! end + +!! test +Section extraction test (section 6) +!! options +section=6 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +===bb=== +====bba==== +!! end + +!! test +Section extraction test (section 7) +!! options +section=7 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +====bba==== +!! end + +!! test +Section extraction test (section 8) +!! options +section=8 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +===bc=== +!! end + +!! test +Section extraction test (section 9) +!! options +section=9 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +==c== +===ca=== +!! end + +!! test +Section extraction test (section 10) +!! options +section=10 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +===ca=== +!! end + +!! test +Section extraction test (nonexistent section 11) +!! options +section=11 +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +!! end + +!! test +Section extraction test with bogus heading (section 1) +!! options +section=1 +!! input +==a== +==bogus== not a legal section +==b== +!! result +==a== +==bogus== not a legal section +!! end + +!! test +Section extraction test with bogus heading (section 2) +!! options +section=2 +!! input +==a== +==bogus== not a legal section +==b== +!! result +==b== +!! end + +!! test +Section extraction test with comment after heading (section 1) +!! options +section=1 +!! input +==a== +==b== +==c== +!! result +==a== +!! end + +!! test +Section extraction test with comment after heading (section 2) +!! options +section=2 +!! input +==a== +==b== +==c== +!! result +==b== +!! end + +!! test +Section extraction test with bogus heading (section 1) +!! options +section=1 +!! input +==a== +==bogus== not a legal section +==b== +!! result +==a== +==bogus== not a legal section +!! end + +!! test +Section extraction test with bogus heading (section 2) +!! options +section=2 +!! input +==a== +==bogus== not a legal section +==b== +!! result +==b== +!! end + + +# Formerly testing for bug 2587, now resolved by the use of unmarked sections +# instead of respecting commented sections +!! test +Section extraction prefixed by comment (section 1) +!! options +section=1 +!! input +==sec1== +==sec2== +!!result +==sec2== +!!end + +!! test +Section extraction prefixed by comment (section 2) +!! options +section=2 +!! input +==sec1== +==sec2== +!!result + +!!end + + +# Formerly testing for bug 2607, now resolved by the use of unmarked sections +# instead of respecting HTML-style headings +!! test +Section extraction, mixed wiki and html (section 1) +!! options +section=1 +!! input +

    unmarked

    +unmarked +==1== +one +==2== +two +!! result +==1== +one +!! end + +!! test +Section extraction, mixed wiki and html (section 2) +!! options +section=2 +!! input +

    unmarked

    +unmarked +==1== +one +==2== +two +!! result +==2== +two +!! end + + +# Formerly testing for bug 3342 +!! test +Section extraction, heading surrounded by +!! options +section=1 +!! input +==unmarked== +==marked== +!! result +==marked== +!!end + +# Test behaviour of bug 19910 +!! test +Sectiion with all-equals +!! options +section=2 +!! input +=== +The line above must have a trailing space +=== +But just in case it doesn't... +!! result +=== +But just in case it doesn't... +!! end + +!! test +Section replacement test (section 0) +!! options +replace=0,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +xxx + +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 1) +!! options +replace=1,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +xxx + +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 2) +!! options +replace=2,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +xxx + +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 3) +!! options +replace=3,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +xxx + +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 4) +!! options +replace=4,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +xxx + +==c== +===ca=== +!! end + +!! test +Section replacement test (section 5) +!! options +replace=5,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +==b== +xxx + +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 6) +!! options +replace=6,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +xxx + +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 7) +!! options +replace=7,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +xxx + +===bc=== +==c== +===ca=== +!! end + +!! test +Section replacement test (section 8) +!! options +replace=8,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +xxx + +==c== +===ca=== +!!end + +!! test +Section replacement test (section 9) +!! options +replace=9,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +xxx +!! end + +!! test +Section replacement test (section 10) +!! options +replace=10,"xxx" +!! input +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +===ca=== +!! result +start +==a== +===aa=== +====aaa==== +==b== +===ba=== +===bb=== +====bba==== +===bc=== +==c== +xxx +!! end + +!! test +Section replacement test with initial whitespace (bug 13728) +!! options +replace=2,"xxx" +!! input + Preformatted initial line +==a== +===a=== +!! result + Preformatted initial line +==a== +xxx +!! end + + +!! test +Section extraction, heading followed by pre with 20 spaces (bug 6398) +!! options +section=1 +!! input +==a== + a +!! result +==a== + a +!! end + +!! test +Section extraction, heading followed by pre with 19 spaces (bug 6398 sanity check) +!! options +section=1 +!! input +==a== + a +!! result +==a== + a +!! end + + +!! test +Section extraction,
     around bogus header (bug 10309)
    +!! options
    +noxml section=2
    +!! input
    +== Section One ==
    +
    +=======
    +
    + +== Section Two == +stuff +!! result +== Section Two == +stuff +!! end + +!! test +Section replacement,
     around bogus header (bug 10309)
    +!! options
    +noxml replace=2,"xxx"
    +!! input
    +== Section One ==
    +
    +=======
    +
    + +== Section Two == +stuff +!! result +== Section One == +
    +=======
    +
    + +xxx +!! end + + + +!! test +Handling of in URLs +!! input +**irc:// a +!! result + + +!!end + +!! test +5 quotes, code coverage +1 line +!! input +''''' +!! result +!! end + +!! test +Special:Search page linking. +!! input +{{Special:search}} +!! result +

    Special:Search +

    +!! end + +!! test +Say the magic word +!! input +* {{PAGENAME}} +* {{BASEPAGENAME}} +* {{SUBPAGENAME}} +* {{SUBPAGENAMEE}} +* {{BASEPAGENAME}} +* {{BASEPAGENAMEE}} +* {{TALKPAGENAME}} +* {{TALKPAGENAMEE}} +* {{SUBJECTPAGENAME}} +* {{SUBJECTPAGENAMEE}} +* {{NAMESPACEE}} +* {{NAMESPACE}} +* {{TALKSPACE}} +* {{TALKSPACEE}} +* {{SUBJECTSPACE}} +* {{SUBJECTSPACEE}} +* {{Dynamic|{{NUMBEROFUSERS}}|{{NUMBEROFPAGES}}|{{CURRENTVERSION}}|{{CONTENTLANGUAGE}}|{{DIRECTIONMARK}}|{{CURRENTTIMESTAMP}}|{{NUMBEROFARTICLES}}}} +!! result +
    • Parser test +
    • Parser test +
    • Parser test +
    • Parser_test +
    • Parser test +
    • Parser_test +
    • Talk:Parser test +
    • Talk:Parser_test +
    • Parser test +
    • Parser_test +
    • +
    • +
    • Talk +
    • Talk +
    • +
    • +
    • Template:Dynamic +
    + +!! end +### Note: Above tests excludes the "{{NUMBEROFADMINS}}" magic word because it generates a MySQL error when included. + +!! test +Gallery +!! input + +image1.png | +image2.gif||||| + +image3| +image4 |300px| centre + image5.svg| http:///////// +[[x|xx]]]] +* image6 + +!! result + + + + + + + + + + + + + +!! end + +!! test +Gallery (with options) +!! input + +File:Nonexistant.jpg|caption +File:Nonexistant.jpg +image:foobar.jpg|some '''caption''' [[Main Page]] +image:foobar.jpg + +!! result + + + + + + + + + + + + +!! end + +!! test +gallery (with showfilename option) +!! input + +File:Nonexistant.jpg|caption +File:Nonexistant.jpg +image:foobar.jpg|some '''caption''' [[Main Page]] +File:Foobar.jpg + +!! result + + + + + + + + + +!! end + +!! test +HTML Hex character encoding (spells the word "JavaScript") +!! input +JavaScript +!! result +

    JavaScript +

    +!! end + +!! test +__FORCETOC__ override +!! input +__NEWSECTIONLINK__ +__FORCETOC__ +!! result +


    +

    +!! end + +!! test +ISBN code coverage +!! input +ISBN 978-0-1234-56 789 +!! result +

    ISBN 978-0-1234-56 789 +

    +!! end + +!! test +ISBN followed by 5 spaces +!! input +ISBN +!! result +

    ISBN +

    +!! end + +!! test +Double ISBN +!! input +ISBN ISBN 1234567890 +!! result +

    ISBN ISBN 1234567890 +

    +!! end + +!! test +Bug 22905: followed by ISBN followed by +!! input +(fr) ISBN 2753300917 [http://www.example.com example.com] +!! result +

    (fr) ISBN 2753300917 example.com +

    +!! end + +!! test +Double RFC +!! input +RFC RFC 1234 +!! result +

    RFC RFC 1234 +

    +!! end + +!! test +Double RFC with a wiki link +!! input +RFC [[RFC 1234]] +!! result +

    RFC RFC 1234 +

    +!! end + +!! test +RFC code coverage +!! input +RFC 983 987 +!! result +

    RFC 983 987 +

    +!! end + +!! test +Centre-aligned image +!! input +[[Image:foobar.jpg|centre]] +!! result +
    Foobar.jpg
    + +!!end + +!! test +None-aligned image +!! input +[[Image:foobar.jpg|none]] +!! result +
    Foobar.jpg
    + +!!end + +!! test +Width + Height sized image (using px) (height is ignored) +!! input +[[Image:foobar.jpg|640x480px]] +!! result +

    Foobar.jpg +

    +!!end + +!! test +Width-sized image (using px, no following whitespace) +!! input +[[Image:foobar.jpg|640px]] +!! result +

    Foobar.jpg +

    +!!end + +!! test +Width-sized image (using px, with following whitespace - test regression from r39467) +!! input +[[Image:foobar.jpg|640px ]] +!! result +

    Foobar.jpg +

    +!!end + +!! test +Width-sized image (using px, with preceding whitespace - test regression from r39467) +!! input +[[Image:foobar.jpg| 640px]] +!! result +

    Foobar.jpg +

    +!!end + +!! test +Another italics / bold test +!! input + ''' ''x' +!! result +
    ' x'
    +
    +!!end + +# Note the results may be incorrect, as parserTest output included this: +# XML error: Mismatched tag at byte 6120: +# ...
    +
    +
    +
    +
    +
    +
    + +!!end + + +# Images with the "|" character in external URLs in comment tags; Eats half the comment, leaves unmatched "" tag. +!! test +Images with the "|" character in the comment +!! input +[[image:Foobar.jpg|thumb|An [http://test/?param1=|left|¶m2=|x external] URL]] +!! result +
    An external URL
    + +!!end + +!! test +[Before] HTML without raw HTML enabled ($wgRawHtml==false) +!! input + +!! result +

    <html><script>alert(1);</script></html> +

    +!! end + +!! test +HTML with raw HTML ($wgRawHtml==true) +!! options +rawhtml +!! input + +!! result +

    +

    +!! end + +!! test +Parents of subpages, one level up +!! options +subpage title=[[Subpage test/L1/L2/L3]] +!! input +[[../|L2]] +!! result +

    L2 +

    +!! end + + +!! test +Parents of subpages, one level up, not named +!! options +subpage title=[[Subpage test/L1/L2/L3]] +!! input +[[../]] +!! result +

    Subpage test/L1/L2 +

    +!! end + + + +!! test +Parents of subpages, two levels up +!! options +subpage title=[[Subpage test/L1/L2/L3]] +!! input +[[../../|L1]]2 + +[[../../|L1]]l +!! result +

    L12 +

    L1l +

    +!! end + +!! test +Parents of subpages, two levels up, without trailing slash or name. +!! options +subpage title=[[Subpage test/L1/L2/L3]] +!! input +[[../..]] +!! result +

    [[../..]] +

    +!! end + +!! test +Parents of subpages, two levels up, with lots of extra trailing slashes. +!! options +subpage title=[[Subpage test/L1/L2/L3]] +!! input +[[../../////]] +!! result +

    /// +

    +!! end + +!! test +Definition list code coverage +!! input +; title : def +; title : def +;title: def +!! result +
    title  
    def +
    title 
    def +
    title
    def +
    + +!! end + +!! test +Don't fall for the self-closing div +!! input +
    hello world
    +!! result +
    hello world
    + +!! end + +!! test +MSGNW magic word +!! input +{{MSGNW:msg}} +!! result +

    [[:Template:Msg]] +

    +!! end + +!! test +RAW magic word +!! input +{{RAW:QUERTY}} +!! result +

    Template:QUERTY +

    +!! end + +# This isn't needed for XHTML conformance, but would be handy as a fallback security measure +!! test +Always escape literal '>' in output, not just after '<' +!! input +><> +!! result +

    ><> +

    +!! end + +!! test +Template caching +!! input +{{Test}} +{{Test}} +!! result +

    This is a test template +This is a test template +

    +!! end + + +!! article +MediaWiki:Fake +!! text +==header== +!! endarticle + +!! test +Inclusion of !userCanEdit() content +!! input +{{MediaWiki:Fake}} +!! result +

    [edit] header

    + +!! end + + +!! test +Out-of-order TOC heading levels +!! input +==2== +======6====== +===3=== +=1= +=====5===== +==2== +!! result +

    Contents

    + +
    +

    [edit] 2

    +
    [edit] 6
    +

    [edit] 3

    +

    [edit] 1

    +
    [edit] 5
    +

    [edit] 2

    + +!! end + + +!! test +ISBN with a dummy number +!! input +ISBN --- +!! result +

    ISBN --- +

    +!! end + + +!! test +ISBN with space-delimited number +!! input +ISBN 92 9017 032 8 +!! result +

    ISBN 92 9017 032 8 +

    +!! end + + +!! test +ISBN with multiple spaces, no number +!! input +ISBN foo +!! result +

    ISBN foo +

    +!! end + + +!! test +ISBN length +!! input +ISBN 123456789 + +ISBN 1234567890 + +ISBN 12345678901 +!! result +

    ISBN 123456789 +

    ISBN 1234567890 +

    ISBN 12345678901 +

    +!! end + + +!! test +ISBN with trailing year (bug 8110) +!! input +ISBN 1-234-56789-0 - 2006 + +ISBN 1 234 56789 0 - 2006 +!! result +

    ISBN 1-234-56789-0 - 2006 +

    ISBN 1 234 56789 0 - 2006 +

    +!! end + + +!! test +anchorencode +!! input +{{anchorencode:foo bar©#%n}} +!! result +

    foo_bar.C2.A9.23.25n +

    +!! end + +!! test +anchorencode trims spaces +!! input +{{anchorencode: __pretty__please__}} +!! result +

    pretty_please +

    +!! end + +!! test +anchorencode deals with links +!! input +{{anchorencode: [[hello|world]] [[hi]]}} +!! result +

    world_hi +

    +!! end + +!! test +anchorencode deals with templates +!! input +{{anchorencode: {{Foo}} }} +!! result +

    FOO +

    +!! end + +!! test +anchorencode encodes like the TOC generator: (bug 18431) +!! input +=== _ +:.3A%3A&&]] === +{{anchorencode: _ +:.3A%3A&&]] }} +__NOEDITSECTION__ +!! result +

    _ +:.3A%3A&&]]

    +

    .2B:.3A.253A.26.26.5D.5D +

    +!! end + +# Expected output in the following test is not necessarily expected (there +# should probably be

    tags inside the

    in the output) -- it's +# only testing for well-formedness. +!! test +Bug 6200: blockquotes and paragraph formatting +!! input +
    +foo +
    + +bar + + baz +!! result +
    +foo +
    +

    bar +

    +
    baz
    +
    +!! end + +!! test +Bug 8293: Use of center tag ruins paragraph formatting +!! input +
    +foo +
    + +bar + + baz +!! result +
    +

    foo +

    +
    +

    bar +

    +
    baz
    +
    +!! end + + +### +### Language variants related tests +### +!! test +Self-link in language variants +!! options +title=[[Dunav]] language=sr +!! input +Both [[Dunav]] and [[Дунав]] are names for this river. +!! result +

    Both Dunav and Дунав are names for this river. +

    +!!end + + +!! test +Link to pages in language variants +!! options +language=sr +!! input +Main Page can be written as [[Маин Паге]] +!! result +

    Main Page can be written as Маин Паге +

    +!!end + + +!! test +Multiple links to pages in language variants +!! options +language=sr +!! input +[[Main Page]] can be written as [[Маин Паге]] same as [[Маин Паге]]. +!! result +

    Main Page can be written as Маин Паге same as Маин Паге. +

    +!!end + + +!! test +Simple template in language variants +!! options +language=sr +!! input +{{тест}} +!! result +

    This is a test template +

    +!! end + + +!! test +Template with explicit namespace in language variants +!! options +language=sr +!! input +{{Template:тест}} +!! result +

    This is a test template +

    +!! end + + +!! test +Basic test for template parameter in language variants +!! options +language=sr +!! input +{{парамтест|param=foo}} +!! result +

    This is a test template with parameter foo +

    +!! end + + +!! test +Simple category in language variants +!! options +language=sr cat +!! input +[[Category:МедиаWики Усер'с Гуиде]] +!! result +MediaWiki User's Guide +!! end + + +!! test +Stripping -{}- tags (language variants) +!! options +language=sr +!! input +Latin proverb: -{Ne nuntium necare}- +!! result +

    Latin proverb: Ne nuntium necare +

    +!! end + + +!! test +Prevent conversion with -{}- tags (language variants) +!! options +language=sr variant=sr-ec +!! input +Latinski: -{Ne nuntium necare}- +!! result +

    Латински: Ne nuntium necare +

    +!! end + + +!! test +Prevent conversion of text with -{}- tags (language variants) +!! options +language=sr variant=sr-ec +!! input +Latinski: -{Ne nuntium necare}- +!! result +

    Латински: Ne nuntium necare +

    +!! end + + +!! test +Prevent conversion of links with -{}- tags (language variants) +!! options +language=sr variant=sr-ec +!! input +-{[[Main Page]]}- +!! result +

    Main Page +

    +!! end + + +!! test +-{}- tags within headlines (within html for parserConvert()) +!! options +language=sr variant=sr-ec +!! input +== -{Naslov}- == +!! result +

    [уреди] Naslov

    + +!! end + + +!! test +Explicit definition of language variant alternatives +!! options +language=zh variant=zh-tw +!! input +-{zh:China;zh-tw:Taiwan}-, not China +!! result +

    Taiwan, not China +

    +!! end + + +!! test +Explicit session-wise language variant mapping (A flag and - flag) +!! options +language=zh variant=zh-tw +!! input +Taiwan is not China. +But -{A|zh:China;zh-tw:Taiwan}- is China, +(This-{-|zh:China;zh-tw:Taiwan}- should be stripped!) +and -{China}- is China. +!! result +

    Taiwan is not China. +But Taiwan is Taiwan, +(This should be stripped!) +and China is China. +

    +!! end + +!! test +Explicit session-wise language variant mapping (H flag for hide) +!! options +language=zh variant=zh-tw +!! input +(This-{H|zh:China;zh-tw:Taiwan}- should be stripped!) +Taiwan is China. +!! result +

    (This should be stripped!) +Taiwan is Taiwan. +

    +!! end + +!! test +Adding explicit conversion rule for title (T flag) +!! options +language=zh variant=zh-tw showtitle +!! input +Should be stripped-{T|zh:China;zh-tw:Taiwan}-! +!! result +Taiwan +

    Should be stripped! +

    +!! end + +!! test +Testing that changing the language variant here in the tests actually works +!! options +language=zh variant=zh showtitle +!! input +Should be stripped-{T|zh:China;zh-tw:Taiwan}-! +!! result +China +

    Should be stripped! +

    +!! end + +!! test +Bug 24072: more test on conversion rule for title +!! options +language=zh variant=zh-tw showtitle +!! input +This should be stripped-{T|zh:China;zh-tw:Taiwan}-! +This won't take interferes with the title rule-{H|zh:Beijing;zh-tw:Taipei}-. +!! result +Taiwan +

    This should be stripped! +This won't take interferes with the title rule. +

    +!! end + +!! test +Raw output of variant escape tags (R flag) +!! options +language=zh variant=zh-tw +!! input +Raw: -{R|zh:China;zh-tw:Taiwan}- +!! result +

    Raw: zh:China;zh-tw:Taiwan +

    +!! end + +!! test +Nested using of manual convert syntax +!! options +language=zh variant=zh-hk +!! input +Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiwan;zh-hk:H-{ong}- K-{}-ong;}-;}-! +!! result +

    Nested: Hello Hong Kong! +

    +!! end + +!! test +Do not convert roman numbers to language variants +!! options +language=sr variant=sr-ec +!! input +Fridrih IV je car. +!! result +

    Фридрих IV је цар. +

    +!! end + +!! test +Unclosed language converter markup "-{" +!! options +language=sr +!! input +-{T|hello +!! result +

    -{T|hello +

    +!! end + +!! test +Don't convert raw rule "-{R|=>}-" to "=>" +!! options +language=sr +!! input +-{R|=>}- +!! result +

    => +

    +!!end + +!!article +Template:Bullet +!!text +* Bar +!!endarticle + +!! test +Bug 529: Uncovered bullet +!! input +* Foo {{bullet}} +!! result +
    • Foo +
    • Bar +
    + +!! end + +!! test +Bug 529: Uncovered table already at line-start +!! input +x + +{{table}} +y +!! result +

    x +

    + + + + + + +
    1 2 +
    3 4 +
    +

    y +

    +!! end + +!! test +Bug 529: Uncovered bullet in parser function result +!! input +* Foo {{lc:{{bullet}} }} +!! result +
    • Foo +
    • bar +
    + +!! end + +!! test +Bug 5678: Double-parsed template argument +!! input +{{lc:{{{1}}}|hello}} +!! result +

    {{{1}}} +

    +!! end + +!! test +Bug 5678: Double-parsed template invocation +!! input +{{lc:{{paramtest {{!}} param = hello }} }} +!! result +

    {{paramtest | param = hello }} +

    +!! end + +!! test +Case insensitivity of parser functions for non-ASCII characters (bug 8143) +!! options +language=cs +title=[[Main Page]] +!! input +{{PRVNÍVELKÉ:ěščř}} +{{prvnívelké:ěščř}} +{{PRVNÍMALÉ:ěščř}} +{{prvnímalé:ěščř}} +{{MALÁ:ěščř}} +{{malá:ěščř}} +{{VELKÁ:ěščř}} +{{velká:ěščř}} +!! result +

    Ěščř +Ěščř +ěščř +ěščř +ěščř +ěščř +ĚŠČŘ +ĚŠČŘ +

    +!! end + +!! test +Morwen/13: Unclosed link followed by heading +!! input +[[link +==heading== +!! result +

    [[link +

    +

    [edit] heading

    + +!! end + +!! test +HHP2.1: Heuristics for headings in preprocessor parenthetical structures +!! input +{{foo| +=heading= +!! result +

    {{foo| +

    +

    heading

    + +!! end + +!! test +HHP2.2: Heuristics for headings in preprocessor parenthetical structures +!! input +{{foo| +==heading== +!! result +

    {{foo| +

    +

    [edit] heading

    + +!! end + +!! test +Tildes in comments +!! options +pst +!! input + +!! result + +!! end + +!! test +Paragraphs inside divs (no extra line breaks) +!! input +
    Line one + +Line two
    +!! result +
    Line one +Line two
    + +!! end + +!! test +Paragraphs inside divs (extra line break on open) +!! input +
    +Line one + +Line two
    +!! result +
    +

    Line one +

    +Line two
    + +!! end + +!! test +Paragraphs inside divs (extra line break on close) +!! input +
    Line one + +Line two +
    +!! result +
    Line one +

    Line two +

    +
    + +!! end + +!! test +Paragraphs inside divs (extra line break on open and close) +!! input +
    +Line one + +Line two +
    +!! result +
    +

    Line one +

    Line two +

    +
    + +!! end + +!! test +Nesting tags, paragraphs on lines which begin with
    +!! options +disabled +!! input +
    A +B +!! result +
    +

    A +B +

    +!! end + +# Bug 6200:
    should behave like
    with respect to line breaks +!! test +Bug 6200: paragraphs inside blockquotes (no extra line breaks) +!! options +disabled +!! input +
    Line one + +Line two
    +!! result +
    Line one +Line two
    + +!! end + +!! test +Bug 6200: paragraphs inside blockquotes (extra line break on open) +!! options +disabled +!! input +
    +Line one + +Line two
    +!! result +
    +

    Line one +

    +Line two
    + +!! end + +!! test +Bug 6200: paragraphs inside blockquotes (extra line break on close) +!! options +disabled +!! input +
    Line one + +Line two +
    +!! result +
    Line one +

    Line two +

    +
    + +!! end + +!! test +Bug 6200: paragraphs inside blockquotes (extra line break on open and close) +!! options +disabled +!! input +
    +Line one + +Line two +
    +!! result +
    +

    Line one +

    Line two +

    +
    + +!! end + +!! test +Paragraphs inside blockquotes/divs (no extra line breaks) +!! input +
    Line one + +Line two
    +!! result +
    Line one +Line two
    + +!! end + +!! test +Paragraphs inside blockquotes/divs (extra line break on open) +!! input +
    +Line one + +Line two
    +!! result +
    +

    Line one +

    +Line two
    + +!! end + +!! test +Paragraphs inside blockquotes/divs (extra line break on close) +!! input +
    Line one + +Line two +
    +!! result +
    Line one +

    Line two +

    +
    + +!! end + +!! test +Paragraphs inside blockquotes/divs (extra line break on open and close) +!! input +
    +Line one + +Line two +
    +!! result +
    +

    Line one +

    Line two +

    +
    + +!! end + +!! test +Interwiki links trounced by replaceExternalLinks after early LinkHolderArray expansion +!! options +wgLinkHolderBatchSize=0 +!! input +[[meatball:1]] +[[meatball:2]] +[[meatball:3]] +!! result +

    meatball:1 +meatball:2 +meatball:3 +

    +!! end + +!! test +Free external link invading image caption +!! input +[[Image:Foobar.jpg|thumb|http://x|hello]] +!! result +
    hello
    + +!! end + +!! test +Bug 15196: localised external link numbers +!! options +language=fa +!! input +[http://en.wikipedia.org/] +!! result +

    [Û±] +

    +!! end + +!! test +Multibyte character in padleft +!! input +{{padleft:-Hello|7|Æ}} +!! result +

    Æ-Hello +

    +!! end + +!! test +Multibyte character in padright +!! input +{{padright:Hello-|7|Æ}} +!! result +

    Hello-Æ +

    +!! end + +!! test +Formatted date +!! config +wgUseDynamicDates=1 +!! input +[[2009-03-24]] +!! result +

    2009-03-24 +

    +!!end + +!!test +formatdate parser function +!!input +{{#formatdate:2009-03-24}} +!! result +

    2009-03-24 +

    +!! end + +!!test +formatdate parser function, with default format +!!input +{{#formatdate:2009-03-24|mdy}} +!! result +

    March 24, 2009 +

    +!! end + +!! test +Linked date with autoformatting disabled +!! config +wgUseDynamicDates=false +!! input +[[2009-03-24]] +!! result +

    2009-03-24 +

    +!! end + +!! test +Spacing of numbers in formatted dates +!! input +{{#formatdate:January 15}} +!! result +

    January 15 +

    +!! end + +!! test +Spacing of numbers in formatted dates (linked) +!! config +wgUseDynamicDates=true +!! input +[[January 15]] +!! result +

    January 15 +

    +!! end + +# +# +# + +# +# Edit comments +# + +!! test +Edit comment with link +!! options +comment +!! input +I like the [[Main Page]] a lot +!! result +I like the Main Page a lot +!!end + +!! test +Edit comment with link and link text +!! options +comment +!! input +I like the [[Main Page|best pages]] a lot +!! result +I like the best pages a lot +!!end + +!! test +Edit comment with link and link text with suffix +!! options +comment +!! input +I like the [[Main Page|best page]]s a lot +!! result +I like the best pages a lot +!!end + +!! test +Edit comment with section link (non-local, eg in history list) +!! options +comment title=[[Main Page]] +!! input +/* External links */ removed bogus entries +!! result +→External links: removed bogus entries +!!end + +!! test +Edit comment with section link (local, eg in diff view) +!! options +comment local title=[[Main Page]] +!! input +/* External links */ removed bogus entries +!! result +→External links: removed bogus entries +!!end + +!! test +Edit comment with subpage link (bug 14080) +!! options +comment +subpage +title=[[Subpage test]] +!! input +Poked at a [[/subpage]] here... +!! result +Poked at a /subpage here... +!!end + +!! test +Edit comment with subpage link and link text (bug 14080) +!! options +comment +subpage +title=[[Subpage test]] +!! input +Poked at a [[/subpage|neat little page]] here... +!! result +Poked at a neat little page here... +!!end + +!! test +Edit comment with bogus subpage link in non-subpage NS (bug 14080) +!! options +comment +title=[[Subpage test]] +!! input +Poked at a [[/subpage]] here... +!! result +Poked at a /subpage here... +!!end + +!! test +Edit comment with bare anchor link (local, as on diff) +!! options +comment +local +title=[[Main Page]] +!!input +[[#section]] +!! result +#section +!! end + +!! test +Edit comment with bare anchor link (non-local, as on history) +!! options +comment +title=[[Main Page]] +!!input +[[#section]] +!! result +#section +!! end + +!! test +Space normalisation on autocomment (bug 22784) +!! options +comment +title=[[Main Page]] +!!input +/* __hello__world__ */ +!! result +→__hello__world__ +!! end + +!! test +Bad images - basic functionality +!! input +[[File:Bad.jpg]] +!! result +!! end + +!! test +Bad images - bug 16039: text after bad image disappears +!! input +Foo bar +[[File:Bad.jpg]] +Bar foo +!! result +

    Foo bar +

    Bar foo +

    +!! end + +!! test +Verify that displaytitle works (bug #22501) no displaytitle +!! options +showtitle +!! config +wgAllowDisplayTitle=true +wgRestrictDisplayTitle=false +!! input +this is not the the title +!! result +Parser test +

    this is not the the title +

    +!! end + +!! test +Verify that displaytitle works (bug #22501) RestrictDisplayTitle=false +!! options +showtitle +title=[[Screen]] +!! config +wgAllowDisplayTitle=true +wgRestrictDisplayTitle=false +!! input +this is not the the title +{{DISPLAYTITLE:whatever}} +!! result +whatever +

    this is not the the title +

    +!! end + +!! test +Verify that displaytitle works (bug #22501) RestrictDisplayTitle=true mismatch +!! options +showtitle +title=[[Screen]] +!! config +wgAllowDisplayTitle=true +wgRestrictDisplayTitle=true +!! input +this is not the the title +{{DISPLAYTITLE:whatever}} +!! result +Screen +

    this is not the the title +

    +!! end + +!! test +Verify that displaytitle works (bug #22501) RestrictDisplayTitle=true matching +!! options +showtitle +title=[[Screen]] +!! config +wgAllowDisplayTitle=true +wgRestrictDisplayTitle=true +!! input +this is not the the title +{{DISPLAYTITLE:screen}} +!! result +screen +

    this is not the the title +

    +!! end + +!! test +Verify that displaytitle works (bug #22501) AllowDisplayTitle=false +!! options +showtitle +title=[[Screen]] +!! config +wgAllowDisplayTitle=false +!! input +this is not the the title +{{DISPLAYTITLE:screen}} +!! result +Screen +

    this is not the the title +Template:DISPLAYTITLE:screen +

    +!! end + +!! test +Verify that displaytitle works (bug #22501) AllowDisplayTitle=false no DISPLAYTITLE +!! options +showtitle +title=[[Screen]] +!! config +wgAllowDisplayTitle=false +!! input +this is not the the title +!! result +Screen +

    this is not the the title +

    +!! end + +!! test +preload: check and +!! options +preload +!! input +Hello cruelkind world. +!! result +Hello kind world. +!! end + +!! test +preload: check +!! options +preload +!! input +Goodbye Hello world +!! result +Hello world +!! end + +!! test +preload: can pass tags through if we want to +!! options +preload +!! input +<includeonly>Hello world</includeonly> +!! result +Hello world +!! end + +!! test +preload: check that it doesn't try to do tricks +!! options +preload +!! input +* ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}} +!! result +* ''{{world}}'' {{subst:How are you}}{{ {{{|safesubst:}}} #if:1|2|3}} +!! end + +!! test +Play a bit with r67090 and bug 3158 +!! options +disabled +!! input +
     
    +
     
    +
     
    +
     
    +!! result +
     
    +
     
    +
     
    +
     
    + +!! end + +!! test +HTML5 data attributes +!! input +Baz +

    Quuz

    +!! result +

    Baz +

    +

    Quuz

    + +!! end + + +TODO: +more images +more tables +math +character entities +and much more +Try for 100% code coverage diff --git a/maintenance/tests/parser/parserTestsParserHook.php b/maintenance/tests/parser/parserTestsParserHook.php new file mode 100644 index 0000000000..6387208af3 --- /dev/null +++ b/maintenance/tests/parser/parserTestsParserHook.php @@ -0,0 +1,46 @@ + + */ + +class ParserTestParserHook { + + static function setup( &$parser ) { + $parser->setHook( 'tag', array( __CLASS__, 'hook' ) ); + + return true; + } + + static function hook( $in, $argv ) { + ob_start(); + var_dump( + $in, + $argv + ); + $ret = ob_get_clean(); + + return "
    \n$ret
    "; + } +} diff --git a/maintenance/tests/parser/parserTestsStaticParserHook.php b/maintenance/tests/parser/parserTestsStaticParserHook.php new file mode 100644 index 0000000000..72f82276c8 --- /dev/null +++ b/maintenance/tests/parser/parserTestsStaticParserHook.php @@ -0,0 +1,58 @@ + + */ + +class ParserTestStaticParserHook { + static function setup( &$parser ) { + $parser->setHook( 'statictag', array( __CLASS__, 'hook' ) ); + + return true; + } + + static function hook( $in, $argv, $parser ) { + if ( ! count( $argv ) ) { + $parser->static_tag_buf = $in; + return ''; + } else if ( count( $argv ) === 1 && isset( $argv['action'] ) + && $argv['action'] === 'flush' && $in === null ) + { + // Clear the buffer, we probably don't need to + if ( isset( $parser->static_tag_buf ) ) { + $tmp = $parser->static_tag_buf; + } else { + $tmp = ''; + } + $parser->static_tag_buf = null; + return $tmp; + } else + // wtf? + return + "\nCall this extension as string or as" . + " , not in any other way.\n" . + "text: " . var_export( $in, true ) . "\n" . + "argv: " . var_export( $argv, true ) . "\n"; + } +} diff --git a/maintenance/tests/parserTests.php b/maintenance/tests/parserTests.php new file mode 100644 index 0000000000..a0aabd175f --- /dev/null +++ b/maintenance/tests/parserTests.php @@ -0,0 +1,90 @@ + +# http://www.mediawiki.org/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.gnu.org/copyleft/gpl.html + +/** + * @file + * @ingroup Maintenance + */ + +$options = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record', 'run-disabled' ); +$optionsWithArgs = array( 'regex', 'seed', 'setversion' ); + +require_once( dirname( __FILE__ ) . '/../commandLine.inc' ); + +if ( isset( $options['help'] ) ) { + echo << Run test cases from a custom file instead of parserTests.txt + --record Record tests in database + --compare Compare with recorded results, without updating the database. + --setversion When using --record, set the version string to use (useful + with git-svn so that you can get the exact revision) + --keep-uploads Re-use the same upload directory for each test, don't delete it + --fuzz Do a fuzz test instead of a normal test + --seed Start the fuzz test from the specified seed + --help Show this help message + --run-disabled run disabled tests + --upload Upload test results to remote wiki (per \$wgParserTestRemote) + +ENDS; + exit( 0 ); +} + +# Cases of weird db corruption were encountered when running tests on earlyish +# versions of SQLite +if ( $wgDBtype == 'sqlite' ) { + $db = wfGetDB( DB_MASTER ); + $version = $db->getServerVersion(); + if ( version_compare( $version, '3.6' ) < 0 ) { + die( "Parser tests require SQLite version 3.6 or later, you have $version\n" ); + } +} + +# There is a convention that the parser should never +# refer to $wgTitle directly, but instead use the title +# passed to it. +$wgTitle = Title::newFromText( 'Parser test script do not use' ); +$tester = new ParserTest($options); + +if ( isset( $options['file'] ) ) { + $files = array( $options['file'] ); +} else { + // Default parser tests and any set from extensions or local config + $files = $wgParserTestFiles; +} + +# Print out software version to assist with locating regressions +$version = SpecialVersion::getVersion(); +echo( "This is MediaWiki version {$version}.\n\n" ); + +if ( isset( $options['fuzz'] ) ) { + $tester->fuzzTest( $files ); +} else { + $ok = $tester->runTestsFromFiles( $files ); + exit ( $ok ? 0 : 1 ); +} diff --git a/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php b/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php index 58be416667..49d13367e5 100644 --- a/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php +++ b/maintenance/tests/phpunit/includes/parser/MediaWikiParserTest.php @@ -24,7 +24,7 @@ class MediaWikiParserTestSuite extends PHPUnit_Framework_TestSuite { $wgMemc = new FakeMemCachedClient; $this->backend->setupDatabase(); - $iter = new TestFileIterator( "$IP/maintenance/parserTests.txt" ); + $iter = new TestFileIterator( "$IP/maintenance/tests/parser/parserTests.txt" ); $iter->setParser( $this->backend ); $this->count = 0; diff --git a/maintenance/tests/testHelpers.inc b/maintenance/tests/testHelpers.inc new file mode 100644 index 0000000000..6153ca31b7 --- /dev/null +++ b/maintenance/tests/testHelpers.inc @@ -0,0 +1,663 @@ +color( 0 ); + } +} + +/* A colour-less terminal */ +class DummyTermColorer { + public function color( $color ) { + return ''; + } + + public function reset() { + return ''; + } +} + +class TestRecorder { + var $parent; + var $term; + + function __construct( $parent ) { + $this->parent = $parent; + $this->term = $parent->term; + } + + function start() { + $this->total = 0; + $this->success = 0; + } + + function record( $test, $result ) { + $this->total++; + $this->success += ( $result ? 1 : 0 ); + } + + function end() { + // dummy + } + + function report() { + if ( $this->total > 0 ) { + $this->reportPercentage( $this->success, $this->total ); + } else { + wfDie( "No tests found.\n" ); + } + } + + function reportPercentage( $success, $total ) { + $ratio = wfPercent( 100 * $success / $total ); + print $this->term->color( 1 ) . "Passed $success of $total tests ($ratio)... "; + + if ( $success == $total ) { + print $this->term->color( 32 ) . "ALL TESTS PASSED!"; + } else { + $failed = $total - $success ; + print $this->term->color( 31 ) . "$failed tests failed!"; + } + + print $this->term->reset() . "\n"; + + return ( $success == $total ); + } +} + +class DbTestPreviewer extends TestRecorder { + protected $lb; // /< Database load balancer + protected $db; // /< Database connection to the main DB + protected $curRun; // /< run ID number for the current run + protected $prevRun; // /< run ID number for the previous run, if any + protected $results; // /< Result array + + /** + * This should be called before the table prefix is changed + */ + function __construct( $parent ) { + parent::__construct( $parent ); + + $this->lb = wfGetLBFactory()->newMainLB(); + // This connection will have the wiki's table prefix, not parsertest_ + $this->db = $this->lb->getConnection( DB_MASTER ); + } + + /** + * Set up result recording; insert a record for the run with the date + * and all that fun stuff + */ + function start() { + parent::start(); + + if ( ! $this->db->tableExists( 'testrun' ) + or ! $this->db->tableExists( 'testitem' ) ) + { + print "WARNING> `testrun` table not found in database.\n"; + $this->prevRun = false; + } else { + // We'll make comparisons against the previous run later... + $this->prevRun = $this->db->selectField( 'testrun', 'MAX(tr_id)' ); + } + + $this->results = array(); + } + + function record( $test, $result ) { + parent::record( $test, $result ); + $this->results[$test] = $result; + } + + function report() { + if ( $this->prevRun ) { + // f = fail, p = pass, n = nonexistent + // codes show before then after + $table = array( + 'fp' => 'previously failing test(s) now PASSING! :)', + 'pn' => 'previously PASSING test(s) removed o_O', + 'np' => 'new PASSING test(s) :)', + + 'pf' => 'previously passing test(s) now FAILING! :(', + 'fn' => 'previously FAILING test(s) removed O_o', + 'nf' => 'new FAILING test(s) :(', + 'ff' => 'still FAILING test(s) :(', + ); + + $prevResults = array(); + + $res = $this->db->select( 'testitem', array( 'ti_name', 'ti_success' ), + array( 'ti_run' => $this->prevRun ), __METHOD__ ); + + foreach ( $res as $row ) { + if ( !$this->parent->regex + || preg_match( "/{$this->parent->regex}/i", $row->ti_name ) ) + { + $prevResults[$row->ti_name] = $row->ti_success; + } + } + + $combined = array_keys( $this->results + $prevResults ); + + # Determine breakdown by change type + $breakdown = array(); + foreach ( $combined as $test ) { + if ( !isset( $prevResults[$test] ) ) { + $before = 'n'; + } elseif ( $prevResults[$test] == 1 ) { + $before = 'p'; + } else /* if ( $prevResults[$test] == 0 )*/ { + $before = 'f'; + } + + if ( !isset( $this->results[$test] ) ) { + $after = 'n'; + } elseif ( $this->results[$test] == 1 ) { + $after = 'p'; + } else /*if ( $this->results[$test] == 0 ) */ { + $after = 'f'; + } + + $code = $before . $after; + + if ( isset( $table[$code] ) ) { + $breakdown[$code][$test] = $this->getTestStatusInfo( $test, $after ); + } + } + + # Write out results + foreach ( $table as $code => $label ) { + if ( !empty( $breakdown[$code] ) ) { + $count = count( $breakdown[$code] ); + printf( "\n%4d %s\n", $count, $label ); + + foreach ( $breakdown[$code] as $differing_test_name => $statusInfo ) { + print " * $differing_test_name [$statusInfo]\n"; + } + } + } + } else { + print "No previous test runs to compare against.\n"; + } + + print "\n"; + parent::report(); + } + + /** + * Returns a string giving information about when a test last had a status change. + * Could help to track down when regressions were introduced, as distinct from tests + * which have never passed (which are more change requests than regressions). + */ + private function getTestStatusInfo( $testname, $after ) { + // If we're looking at a test that has just been removed, then say when it first appeared. + if ( $after == 'n' ) { + $changedRun = $this->db->selectField ( 'testitem', + 'MIN(ti_run)', + array( 'ti_name' => $testname ), + __METHOD__ ); + $appear = $this->db->selectRow ( 'testrun', + array( 'tr_date', 'tr_mw_version' ), + array( 'tr_id' => $changedRun ), + __METHOD__ ); + + return "First recorded appearance: " + . date( "d-M-Y H:i:s", strtotime ( $appear->tr_date ) ) + . ", " . $appear->tr_mw_version; + } + + // Otherwise, this test has previous recorded results. + // See when this test last had a different result to what we're seeing now. + $conds = array( + 'ti_name' => $testname, + 'ti_success' => ( $after == 'f' ? "1" : "0" ) ); + + if ( $this->curRun ) { + $conds[] = "ti_run != " . $this->db->addQuotes ( $this->curRun ); + } + + $changedRun = $this->db->selectField ( 'testitem', 'MAX(ti_run)', $conds, __METHOD__ ); + + // If no record of ever having had a different result. + if ( is_null ( $changedRun ) ) { + if ( $after == "f" ) { + return "Has never passed"; + } else { + return "Has never failed"; + } + } + + // Otherwise, we're looking at a test whose status has changed. + // (i.e. it used to work, but now doesn't; or used to fail, but is now fixed.) + // In this situation, give as much info as we can as to when it changed status. + $pre = $this->db->selectRow ( 'testrun', + array( 'tr_date', 'tr_mw_version' ), + array( 'tr_id' => $changedRun ), + __METHOD__ ); + $post = $this->db->selectRow ( 'testrun', + array( 'tr_date', 'tr_mw_version' ), + array( "tr_id > " . $this->db->addQuotes ( $changedRun ) ), + __METHOD__, + array( "LIMIT" => 1, "ORDER BY" => 'tr_id' ) + ); + + if ( $post ) { + $postDate = date( "d-M-Y H:i:s", strtotime ( $post->tr_date ) ) . ", {$post->tr_mw_version}"; + } else { + $postDate = 'now'; + } + + return ( $after == "f" ? "Introduced" : "Fixed" ) . " between " + . date( "d-M-Y H:i:s", strtotime ( $pre->tr_date ) ) . ", " . $pre->tr_mw_version + . " and $postDate"; + + } + + /** + * Commit transaction and clean up for result recording + */ + function end() { + $this->lb->commitMasterChanges(); + $this->lb->closeAll(); + parent::end(); + } + +} + +class DbTestRecorder extends DbTestPreviewer { + var $version; + + /** + * Set up result recording; insert a record for the run with the date + * and all that fun stuff + */ + function start() { + global $wgDBtype; + $this->db->begin(); + + if ( ! $this->db->tableExists( 'testrun' ) + or ! $this->db->tableExists( 'testitem' ) ) + { + print "WARNING> `testrun` table not found in database. Trying to create table.\n"; + if ( $wgDBtype === 'postgres' ) { + $this->db->sourceFile( dirname( __FILE__ ) . '/testRunner.postgres.sql' ); + } elseif ( $wgDBtype === 'oracle' ) { + $this->db->sourceFile( dirname( __FILE__ ) . '/testRunner.ora.sql' ); + } else { + $this->db->sourceFile( dirname( __FILE__ ) . '/testRunner.sql' ); + } + + echo "OK, resuming.\n"; + } + + parent::start(); + + $this->db->insert( 'testrun', + array( + 'tr_date' => $this->db->timestamp(), + 'tr_mw_version' => $this->version, + 'tr_php_version' => phpversion(), + 'tr_db_version' => $this->db->getServerVersion(), + 'tr_uname' => php_uname() + ), + __METHOD__ ); + if ( $wgDBtype === 'postgres' ) { + $this->curRun = $this->db->currentSequenceValue( 'testrun_id_seq' ); + } else { + $this->curRun = $this->db->insertId(); + } + } + + /** + * Record an individual test item's success or failure to the db + * + * @param $test String + * @param $result Boolean + */ + function record( $test, $result ) { + parent::record( $test, $result ); + + $this->db->insert( 'testitem', + array( + 'ti_run' => $this->curRun, + 'ti_name' => $test, + 'ti_success' => $result ? 1 : 0, + ), + __METHOD__ ); + } +} + +class RemoteTestRecorder extends TestRecorder { + function start() { + parent::start(); + + $this->results = array(); + $this->ping( 'running' ); + } + + function record( $test, $result ) { + parent::record( $test, $result ); + $this->results[$test] = (bool)$result; + } + + function end() { + $this->ping( 'complete', $this->results ); + parent::end(); + } + + /** + * Inform a CodeReview instance that we've started or completed a test run... + * + * @param $status string: "running" - tell it we've started + * "complete" - provide test results array + * "abort" - something went horribly awry + * @param $results array of test name => true/false + */ + function ping( $status, $results = false ) { + global $wgParserTestRemote, $IP; + + $remote = $wgParserTestRemote; + $revId = SpecialVersion::getSvnRevision( $IP ); + $jsonResults = FormatJson::encode( $results ); + + if ( !$remote ) { + print "Can't do remote upload without configuring \$wgParserTestRemote!\n"; + exit( 1 ); + } + + // Generate a hash MAC to validate our credentials + $message = array( + $remote['repo'], + $remote['suite'], + $revId, + $status, + ); + + if ( $status == "complete" ) { + $message[] = $jsonResults; + } + $hmac = hash_hmac( "sha1", implode( "|", $message ), $remote['secret'] ); + + $postData = array( + 'action' => 'codetestupload', + 'format' => 'json', + 'repo' => $remote['repo'], + 'suite' => $remote['suite'], + 'rev' => $revId, + 'status' => $status, + 'hmac' => $hmac, + ); + + if ( $status == "complete" ) { + $postData['results'] = $jsonResults; + } + + $response = $this->post( $remote['api-url'], $postData ); + + if ( $response === false ) { + print "CodeReview info upload failed to reach server.\n"; + exit( 1 ); + } + + $responseData = FormatJson::decode( $response, true ); + + if ( !is_array( $responseData ) ) { + print "CodeReview API response not recognized...\n"; + wfDebug( "Unrecognized CodeReview API response: $response\n" ); + exit( 1 ); + } + + if ( isset( $responseData['error'] ) ) { + $code = $responseData['error']['code']; + $info = $responseData['error']['info']; + print "CodeReview info upload failed: $code $info\n"; + exit( 1 ); + } + } + + function post( $url, $data ) { + return Http::post( $url, array( 'postData' => $data ) ); + } +} + +class TestFileIterator implements Iterator { + private $file; + private $fh; + private $parser; + private $index = 0; + private $test; + private $lineNum; + private $eof; + + function __construct( $file, $parser = null ) { + global $IP; + + $this->file = $file; + $this->fh = fopen( $this->file, "rt" ); + + if ( !$this->fh ) { + wfDie( "Couldn't open file '$file'\n" ); + } + + $this->parser = $parser; + + if ( $this->parser ) { + $this->parser->showRunFile( wfRelativePath( $this->file, $IP ) ); + } + + $this->lineNum = $this->index = 0; + } + + function setParser( ParserTest $parser ) { + $this->parser = $parser; + } + + function rewind() { + if ( fseek( $this->fh, 0 ) ) { + wfDie( "Couldn't fseek to the start of '$this->file'\n" ); + } + + $this->index = -1; + $this->lineNum = 0; + $this->eof = false; + $this->next(); + + return true; + } + + function current() { + return $this->test; + } + + function key() { + return $this->index; + } + + function next() { + if ( $this->readNextTest() ) { + $this->index++; + return true; + } else { + $this->eof = true; + } + } + + function valid() { + return $this->eof != true; + } + + function readNextTest() { + $data = array(); + $section = null; + + while ( false !== ( $line = fgets( $this->fh ) ) ) { + $this->lineNum++; + $matches = array(); + + if ( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) { + $section = strtolower( $matches[1] ); + + if ( $section == 'endarticle' ) { + if ( !isset( $data['text'] ) ) { + wfDie( "'endarticle' without 'text' at line {$this->lineNum} of $this->file\n" ); + } + + if ( !isset( $data['article'] ) ) { + 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 ); + } + + $data = array(); + $section = null; + + continue; + } + + if ( $section == 'endhooks' ) { + if ( !isset( $data['hooks'] ) ) { + wfDie( "'endhooks' without 'hooks' at line {$this->lineNum} of $this->file\n" ); + } + + foreach ( explode( "\n", $data['hooks'] ) as $line ) { + $line = trim( $line ); + + if ( $line ) { + if ( $this->parser && !$this->parser->requireHook( $line ) ) { + return false; + } + } + } + + $data = array(); + $section = null; + + continue; + } + + if ( $section == 'endfunctionhooks' ) { + if ( !isset( $data['functionhooks'] ) ) { + wfDie( "'endfunctionhooks' without 'functionhooks' at line {$this->lineNum} of $this->file\n" ); + } + + foreach ( explode( "\n", $data['functionhooks'] ) as $line ) { + $line = trim( $line ); + + if ( $line ) { + if ( $this->parser && !$this->parser->requireFunctionHook( $line ) ) { + return false; + } + } + } + + $data = array(); + $section = null; + + continue; + } + + if ( $section == 'end' ) { + if ( !isset( $data['test'] ) ) { + wfDie( "'end' without 'test' at line {$this->lineNum} of $this->file\n" ); + } + + if ( !isset( $data['input'] ) ) { + wfDie( "'end' without 'input' at line {$this->lineNum} of $this->file\n" ); + } + + if ( !isset( $data['result'] ) ) { + wfDie( "'end' without 'result' at line {$this->lineNum} of $this->file\n" ); + } + + if ( !isset( $data['options'] ) ) { + $data['options'] = ''; + } + + if ( !isset( $data['config'] ) ) + $data['config'] = ''; + + if ( $this->parser + && ( ( preg_match( '/\\bdisabled\\b/i', $data['options'] ) && !$this->parser->runDisabled ) + || !preg_match( "/" . $this->parser->regex . "/i", $data['test'] ) ) ) { + # disabled test + $data = array(); + $section = null; + + continue; + } + + global $wgUseTeX; + + if ( $this->parser && + preg_match( '/\\bmath\\b/i', $data['options'] ) && !$wgUseTeX ) { + # don't run math tests if $wgUseTeX is set to false in LocalSettings + $data = array(); + $section = null; + + continue; + } + + 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'] ) ); + } else { + $this->test['test'] = $data['test']; + } + + return true; + } + + if ( isset ( $data[$section] ) ) { + wfDie( "duplicate section '$section' at line {$this->lineNum} of $this->file\n" ); + } + + $data[$section] = ''; + + continue; + } + + if ( $section ) { + $data[$section] .= $line; + } + } + + return false; + } +}