Merge "(bug 260) Handle <pre> overflow automatically with a scroll bar"
[lhc/web/wiklou.git] / tests / phpunit / includes / parser / NewParserTest.php
index 5d52d7d..11f9471 100644 (file)
@@ -1,18 +1,19 @@
 <?php
 
 /**
+ * Although marked as a stub, can work independently.
+ *
  * @group Database
  * @group Parser
- * @group Stub (can also work independently)
+ * @group Stub
  */
 class NewParserTest extends MediaWikiTestCase {
-
        static protected $articles = array();   // Array of test articles defined by the tests
        /* The dataProvider is run on a different instance than the test, so it must be static
         * When running tests from several files, all tests will see all articles.
         */
-       
-       public $uploadDir;
+       static protected $backendToUse;
+
        public $keepUploads = false;
        public $runDisabled = false;
        public $regex = '';
@@ -29,16 +30,12 @@ class NewParserTest extends MediaWikiTestCase {
        public $memoryLimit = 50;
 
        protected $file = false;
-       
-       /*function __construct($a = null,$b = array(),$c = null ) {
-               parent::__construct($a,$b,$c);
-       }*/
-       
+
        function setUp() {
                global $wgContLang, $wgNamespaceProtection, $wgNamespaceAliases;
                global $wgHooks, $IP;
                $wgContLang = Language::factory( 'en' );
-               
+
                //Setup CLI arguments
                if ( $this->getCliArg( 'regex=' ) ) {
                        $this->regex = $this->getCliArg( 'regex=' );
@@ -46,11 +43,11 @@ class NewParserTest extends MediaWikiTestCase {
                        # Matches anything
                        $this->regex = '';
                }
-               
+
                $this->keepUploads = $this->getCliArg( 'keep-uploads' );
-                               
+
                $tmpGlobals = array();
-               
+
                $tmpGlobals['wgScript'] = '/index.php';
                $tmpGlobals['wgScriptPath'] = '/';
                $tmpGlobals['wgArticlePath'] = '/wiki/$1';
@@ -58,15 +55,14 @@ class NewParserTest extends MediaWikiTestCase {
                $tmpGlobals['wgStylePath'] = '/skins';
                $tmpGlobals['wgThumbnailScriptPath'] = false;
                $tmpGlobals['wgLocalFileRepo'] = array(
-                       'class' => 'LocalRepo',
-                       'name' => 'local',
-                       'directory' => wfTempDir() . '/test-repo',
-                       'url' => 'http://example.com/images',
-                       'deletedDir' => wfTempDir() . '/test-repo/delete',
-                       'hashLevels' => 2,
+                       'class'           => 'LocalRepo',
+                       'name'            => 'local',
+                       'url'             => 'http://example.com/images',
+                       'hashLevels'      => 2,
                        'transformVia404' => false,
+                       'backend'         => 'local-backend'
                );
-               
+               $tmpGlobals['wgForeignFileRepos'] = array();
                $tmpGlobals['wgEnableParserCache'] = false;
                $tmpGlobals['wgHooks'] = $wgHooks;
                $tmpGlobals['wgDeferredUpdateList'] = array();
@@ -76,16 +72,17 @@ class NewParserTest extends MediaWikiTestCase {
 
                // $tmpGlobals['wgContLang'] = new StubContLang;
                $tmpGlobals['wgUser'] = new User;
-               $tmpGlobals['wgLang'] = new StubUserLang;
-               $tmpGlobals['wgOut'] = new StubObject( 'wgOut', 'OutputPage' );
+               $context = new RequestContext();
+               $tmpGlobals['wgLang'] = $context->getLanguage();
+               $tmpGlobals['wgOut'] = $context->getOutput();
                $tmpGlobals['wgParser'] = new StubObject( 'wgParser', $GLOBALS['wgParserConf']['class'], array( $GLOBALS['wgParserConf'] ) );
-               $tmpGlobals['wgRequest'] = new WebRequest;
+               $tmpGlobals['wgRequest'] = $context->getRequest();
 
                if ( $GLOBALS['wgStyleDirectory'] === false ) {
                        $tmpGlobals['wgStyleDirectory'] = "$IP/skins";
                }
-               
-               
+
+
                foreach ( $tmpGlobals as $var => $val ) {
                        if ( array_key_exists( $var, $GLOBALS ) ) {
                                $this->savedInitialGlobals[$var] = $GLOBALS[$var];
@@ -93,31 +90,38 @@ class NewParserTest extends MediaWikiTestCase {
 
                        $GLOBALS[$var] = $val;
                }
-               
+
                $this->savedWeirdGlobals['mw_namespace_protection'] = $wgNamespaceProtection[NS_MEDIAWIKI];
                $this->savedWeirdGlobals['image_alias'] = $wgNamespaceAliases['Image'];
                $this->savedWeirdGlobals['image_talk_alias'] = $wgNamespaceAliases['Image_talk'];
-               
+
                $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface';
                $wgNamespaceAliases['Image'] = NS_FILE;
                $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK;
-               
        }
-       
+
        public function tearDown() {
-       
                foreach ( $this->savedInitialGlobals as $var => $val ) {
                        $GLOBALS[$var] = $val;
                }
-               
+
                global $wgNamespaceProtection, $wgNamespaceAliases;
-               
+
                $wgNamespaceProtection[NS_MEDIAWIKI] = $this->savedWeirdGlobals['mw_namespace_protection'];
                $wgNamespaceAliases['Image'] = $this->savedWeirdGlobals['image_alias'];
                $wgNamespaceAliases['Image_talk'] = $this->savedWeirdGlobals['image_talk_alias'];
+
+               // Restore backends
+               RepoGroup::destroySingleton();
+               FileBackendGroup::destroySingleton();
        }
-       
+
        function addDBData() {
+               $this->tablesUsed[] = 'site_stats';
+               $this->tablesUsed[] = 'interwiki';
+               # disabled for performance
+               #$this->tablesUsed[] = 'image';
+
                # Hack: insert a few Wikipedia in-project interwiki prefixes,
                # for testing inter-language links
                $this->db->insert( 'interwiki', array(
@@ -151,11 +155,19 @@ class NewParserTest extends MediaWikiTestCase {
                                   'iw_api'    => '',
                                   'iw_wikiid' => '',
                                   'iw_local'  => 1 ),
-                       ) );
+                       /**
+                        * @todo Fixme! Why are we inserting duplicate data here? Shouldn't
+                        * need this IGNORE or shouldn't need the insert at all.
+                        */
+                       ), __METHOD__, array( 'IGNORE' )
+               );
 
 
                # Update certain things in site_stats
-               $this->db->insert( 'site_stats', array( 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ) );
+               $this->db->insert( 'site_stats',
+                       array( 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ),
+                       __METHOD__
+               );
 
                # Reinitialise the LocalisationCache to match the database state
                Language::getLocalisationCache()->unloadAll();
@@ -163,50 +175,66 @@ class NewParserTest extends MediaWikiTestCase {
                # Clear the message cache
                MessageCache::singleton()->clear();
 
-               $this->uploadDir = $this->setupUploadDir();
-
                $user = User::newFromId( 0 );
                LinkCache::singleton()->clear(); # Avoids the odd failure at creating the nullRevision
-               
+
+               # Upload DB table entries for files.
+               # We will upload the actual files later. Note that if anything causes LocalFile::load()
+               # to be triggered before then, it will break via maybeUpgrade() setting the fileExists
+               # member to false and storing it in cache.
                $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'        => wfBaseConvert( '', 16, 36, 31 ),
-                       'fileExists'  => true
-                       ), $this->db->timestamp( '20010115123500' ), $user );
+               if ( !$this->db->selectField( 'image', '1', array( 'img_name' => $image->getName() ) ) ) {
+                       $image->recordUpload2(
+                               '', // archive name
+                               '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'        => wfBaseConvert( '', 16, 36, 31 ),
+                                       'fileExists'  => true ), 
+                               $this->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'        => wfBaseConvert( '', 16, 36, 31 ),
-                       'fileExists'  => true
-                       ), $this->db->timestamp( '20010115123500' ), $user );
-
+               if ( !$this->db->selectField( 'image', '1', array( 'img_name' => $image->getName() ) ) ) {
+                       $image->recordUpload2(
+                               '', // archive name
+                               'zomgnotcensored', 
+                               'Borderline image', 
+                               array(
+                                       'size'        => 12345,
+                                       'width'       => 320,
+                                       'height'      => 240,
+                                       'bits'        => 24,
+                                       'media_type'  => MEDIATYPE_BITMAP,
+                                       'mime'        => 'image/jpeg',
+                                       'metadata'    => serialize( array() ),
+                                       'sha1'        => wfBaseConvert( '', 16, 36, 31 ),
+                                       'fileExists'  => true ), 
+                               $this->db->timestamp( '20010115123500' ), $user
+                       );
+               }
        }
-       
-       
-       
-       
+
+
+
+
        //ParserTest setup/teardown functions
-       
+
        /**
         * Set up the global variables for a consistent environment for each test.
         * Ideally this should replace the global configuration entirely.
         */
        protected function setupGlobals( $opts = '', $config = '' ) {
+               global $wgFileBackends;
                # Find out values for some special options.
                $lang =
                        self::getOptionValue( 'language', $opts, 'en' );
@@ -217,19 +245,48 @@ class NewParserTest extends MediaWikiTestCase {
                $linkHolderBatchSize =
                        self::getOptionValue( 'wgLinkHolderBatchSize', $opts, 1000 );
 
+               $uploadDir = $this->getUploadDir();
+               if ( $this->getCliArg( 'use-filebackend=' ) ) {
+                       if ( self::$backendToUse ) {
+                               $backend = self::$backendToUse;
+                       } else {
+                               $name = $this->getCliArg( 'use-filebackend=' );
+                               $useConfig = array();
+                               foreach ( $wgFileBackends as $conf ) {
+                                       if ( $conf['name'] == $name ) {
+                                               $useConfig = $conf;
+                                       }
+                               }
+                               $useConfig['name'] = 'local-backend'; // swap name
+                               $class = $conf['class'];
+                               self::$backendToUse = new $class( $useConfig );
+                               $backend = self::$backendToUse;
+                       }
+               } else {
+                       $backend = new FSFileBackend( array(
+                               'name'        => 'local-backend',
+                               'lockManager' => 'nullLockManager',
+                               'containerPaths' => array(
+                                       'local-public' => "$uploadDir",
+                                       'local-thumb'  => "$uploadDir/thumb",
+                               )
+                       ) );
+               }
+
                $settings = array(
                        'wgServer' => 'http://Britney-Spears',
                        'wgScript' => '/index.php',
                        'wgScriptPath' => '/',
                        'wgArticlePath' => '/wiki/$1',
+                       'wgExtensionAssetsPath' => '/extensions',
                        'wgActionPaths' => array(),
                        'wgLocalFileRepo' => array(
-                               'class' => 'LocalRepo',
-                               'name' => 'local',
-                               'directory' => $this->uploadDir,
-                               'url' => 'http://example.com/images',
-                               'hashLevels' => 2,
+                               'class'           => 'LocalRepo',
+                               'name'            => 'local',
+                               'url'             => 'http://example.com/images',
+                               'hashLevels'      => 2,
                                'transformVia404' => false,
+                               'backend'         => $backend
                        ),
                        'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ),
                        'wgStylePath' => '/skins',
@@ -248,7 +305,7 @@ class NewParserTest extends MediaWikiTestCase {
                        'wgThumbnailScriptPath' => false,
                        'wgUseImageResize' => false,
                        'wgUseTeX' => isset( $opts['math'] ),
-                       'wgMathDirectory' => $this->uploadDir . '/math',
+                       'wgMathDirectory' => $uploadDir . '/math',
                        'wgLocaltimezone' => 'UTC',
                        'wgAllowExternalImages' => true,
                        'wgUseTidy' => false,
@@ -269,6 +326,7 @@ class NewParserTest extends MediaWikiTestCase {
                        'wgExternalLinkTarget' => false,
                        'wgAlwaysUseTidy' => false,
                        'wgHtml5' => true,
+                       'wgCleanupPresentationalAttributes' => true,
                        'wgWellFormedXml' => true,
                        'wgAllowMicrodataAttributes' => true,
                        'wgAdaptiveMessageCache' => true,
@@ -296,52 +354,43 @@ class NewParserTest extends MediaWikiTestCase {
                }
 
                $langObj = Language::factory( $lang );
-               $GLOBALS['wgLang'] = $langObj;
                $GLOBALS['wgContLang'] = $langObj;
+               $context = new RequestContext();
+               $GLOBALS['wgLang'] = $context->getLanguage();
+
                $GLOBALS['wgMemc'] = new EmptyBagOStuff;
-               $GLOBALS['wgOut'] = new OutputPage;
+               $GLOBALS['wgOut'] = $context->getOutput();
+               $GLOBALS['wgUser'] = $context->getUser();
 
                global $wgHooks;
 
                $wgHooks['ParserTestParser'][] = 'ParserTestParserHook::setup';
-               $wgHooks['ParserTestParser'][] = 'ParserTestStaticParserHook::setup';
                $wgHooks['ParserGetVariableValueTs'][] = 'ParserTest::getFakeTimestamp';
 
                MagicWord::clearCache();
+               RepoGroup::destroySingleton();
+               FileBackendGroup::destroySingleton();
+
+               # Create dummy files in storage
+               $this->setupUploads();
 
                # Publish the articles after we have the final language set
                $this->publishTestArticles();
 
                # The entries saved into RepoGroup cache with previous globals will be wrong.
                RepoGroup::destroySingleton();
+               FileBackendGroup::destroySingleton();
                MessageCache::singleton()->destroyInstance();
-               
-               global $wgUser;
-               $wgUser = new User();
-       }
-       
-       /**
-        * Restore default values and perform any necessary clean-up
-        * after each test runs.
-        */
-       protected function teardownGlobals() {
-               RepoGroup::destroySingleton();
-               LinkCache::singleton()->clear();
 
-               foreach ( $this->savedGlobals as $var => $val ) {
-                       $GLOBALS[$var] = $val;
-               }
+               return $context;
        }
-       
+
        /**
-        * Create a dummy uploads directory which will contain a couple
-        * of files in order to pass existence tests.
+        * Get an FS upload directory (only applies to FSFileBackend)
         *
         * @return String: the directory
         */
-       protected function setupUploadDir() {
-               global $IP;
-
+       protected function getUploadDir() {
                if ( $this->keepUploads ) {
                        $dir = wfTempDir() . '/mwParser-images';
 
@@ -358,14 +407,94 @@ class NewParserTest extends MediaWikiTestCase {
                        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;
        }
-       
+
+       /**
+        * Create a dummy uploads directory which will contain a couple
+        * of files in order to pass existence tests.
+        *
+        * @return String: the directory
+        */
+       protected function setupUploads() {
+               global $IP;
+
+               $base = $this->getBaseDir();
+               $backend = RepoGroup::singleton()->getLocalRepo()->getBackend();
+               $backend->prepare( array( 'dir' => "$base/local-public/3/3a" ) );
+               $backend->store( array(
+                       'src' => "$IP/skins/monobook/headbg.jpg", 'dst' => "$base/local-public/3/3a/Foobar.jpg"
+               ) );
+               $backend->prepare( array( 'dir' => "$base/local-public/0/09" ) );
+               $backend->store( array(
+                       'src' => "$IP/skins/monobook/headbg.jpg", 'dst' => "$base/local-public/0/09/Bad.jpg"
+               ) );
+       }
+
+       /**
+        * Restore default values and perform any necessary clean-up
+        * after each test runs.
+        */
+       protected function teardownGlobals() {
+               $this->teardownUploads();
+
+               foreach ( $this->savedGlobals as $var => $val ) {
+                       $GLOBALS[$var] = $val;
+               }
+
+               RepoGroup::destroySingleton();
+               LinkCache::singleton()->clear();
+       }
+
+       /**
+        * Remove the dummy uploads directory
+        */
+       private function teardownUploads() {
+               if ( $this->keepUploads ) {
+                       return;
+               }
+
+               $base = $this->getBaseDir();
+               // delete the files first, then the dirs.
+               self::deleteFiles(
+                       array (
+                               "$base/local-public/3/3a/Foobar.jpg",
+                               "$base/local-thumb/3/3a/Foobar.jpg/180px-Foobar.jpg",
+                               "$base/local-thumb/3/3a/Foobar.jpg/200px-Foobar.jpg",
+                               "$base/local-thumb/3/3a/Foobar.jpg/640px-Foobar.jpg",
+                               "$base/local-thumb/3/3a/Foobar.jpg/120px-Foobar.jpg",
+
+                               "$base/local-public/0/09/Bad.jpg",
+                               "$base/local-thumb/0/09/Bad.jpg",
+
+                               "$base/local-public/math/f/a/5/fa50b8b616463173474302ca3e63586b.png",
+                       )
+               );
+       }
+
+       /**
+        * Delete the specified files, if they exist.
+        * @param $files Array: full paths to files to delete.
+        */
+       private static function deleteFiles( $files ) {
+               $backend = RepoGroup::singleton()->getLocalRepo()->getBackend();
+               foreach ( $files as $file ) {
+                       $backend->delete( array( 'src' => $file ), array( 'force' => 1 ) );
+               }
+               foreach ( $files as $file ) {
+                       $tmp = $file;
+                       while ( $tmp = FileBackend::parentStoragePath( $tmp ) ) {
+                               if ( !$backend->clean( array( 'dir' => $tmp ) )->isOK() ) {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       protected function getBaseDir() {
+               return 'mwstore://local-backend';
+       }
+
        public function parserTestProvider() {
                if ( $this->file === false ) {
                        global $wgParserTestFiles;
@@ -373,22 +502,32 @@ class NewParserTest extends MediaWikiTestCase {
                }
                return new TestFileIterator( $this->file, $this );
        }
-       
+
        /**
         * Set the file from whose tests will be run by this instance
         */
        public function setParserTestFile( $filename ) {
                $this->file = $filename;
        }
-       
-       /** @dataProvider parserTestProvider */
+
+       /**
+        * @group medium
+        * @dataProvider parserTestProvider
+        */
        public function testParserTest( $desc, $input, $result, $opts, $config ) {
-               if ( !preg_match( '/' . $this->regex . '/', $desc ) ) return; //$this->markTestSkipped( 'Filtered out by the user' );
+               if ( $this->regex != '' && !preg_match( '/' . $this->regex . '/', $desc ) ) {
+                       $this->assertTrue( true ); // XXX: don't flood output with "test made no assertions"
+                       //$this->markTestSkipped( 'Filtered out by the user' );
+                       return;
+               }
+
+               wfDebug( "Running parser test: $desc\n" );
+
                $opts = $this->parseOptions( $opts );
-               $this->setupGlobals( $opts, $config );
+               $context = $this->setupGlobals( $opts, $config );
 
-               $user = new User();
-               $options = ParserOptions::newFromUser( $user );
+               $user = $context->getUser();
+               $options = ParserOptions::newFromContext( $context );
 
                if ( isset( $opts['title'] ) ) {
                        $titleText = $opts['title'];
@@ -400,13 +539,13 @@ class NewParserTest extends MediaWikiTestCase {
                $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 );
+                       $out = $parser->transformMsg( $input, $options, $title );
                } elseif ( isset( $opts['section'] ) ) {
                        $section = $opts['section'];
                        $out = $parser->getSection( $input, $section );
@@ -415,8 +554,7 @@ class NewParserTest extends MediaWikiTestCase {
                        $replace = $opts['replace'][1];
                        $out = $parser->replaceSection( $input, $section, $replace );
                } elseif ( isset( $opts['comment'] ) ) {
-                       $linker = $user->getSkin();
-                       $out = $linker->formatComment( $input, $title, $local );
+                       $out = Linker::formatComment( $input, $title, $local );
                } elseif ( isset( $opts['preload'] ) ) {
                        $out = $parser->getpreloadText( $input, $title, $options );
                } else {
@@ -434,10 +572,9 @@ class NewParserTest extends MediaWikiTestCase {
                        if ( isset( $opts['ill'] ) ) {
                                $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) );
                        } elseif ( isset( $opts['cat'] ) ) {
-                               global $wgOut;
-
-                               $wgOut->addCategoryLinks( $output->getCategories() );
-                               $cats = $wgOut->getCategoryLinks();
+                               $outputPage = $context->getOutput();
+                               $outputPage->addCategoryLinks( $output->getCategories() );
+                               $cats = $outputPage->getCategoryLinks();
 
                                if ( isset( $cats['normal'] ) ) {
                                        $out = $this->tidy( implode( ' ', $cats['normal'] ) );
@@ -451,30 +588,31 @@ class NewParserTest extends MediaWikiTestCase {
                }
 
                $this->teardownGlobals();
-               
+
                $this->assertEquals( $result, $out, $desc );
        }
-       
+
        /**
         * Run a fuzz test series
         * Draw input from a set of test files
+        *
+        * @todo fixme Needs some work to not eat memory until the world explodes
+        *
+        * @group ParserFuzz
         */
        function testFuzzTests() {
-               
-               $this->markTestIncomplete( 'Breaks tesla due to memory restrictions' );
-               
                global $wgParserTestFiles;
-               
+
                $files = $wgParserTestFiles;
-               
+
                if( $this->getCliArg( 'file=' ) ) {
                        $files = array( $this->getCliArg( 'file=' ) );
                }
-               
+
                $dict = $this->getFuzzInput( $files );
                $dictSize = strlen( $dict );
                $logMaxLength = log( $this->maxFuzzTestLength );
-               
+
                ini_set( 'memory_limit', $this->memoryLimit * 1048576 );
 
                $user = new User;
@@ -482,9 +620,9 @@ class NewParserTest extends MediaWikiTestCase {
                $title = Title::makeTitle( NS_MAIN, 'Parser_test' );
 
                $id = 1;
-               
+
                while ( true ) {
-                       
+
                        // Generate test input
                        mt_srand( ++$this->fuzzSeed );
                        $totalLength = mt_rand( 1, $this->maxFuzzTestLength );
@@ -506,7 +644,7 @@ class NewParserTest extends MediaWikiTestCase {
                                $this->assertTrue( true, "Test $id, fuzz seed {$this->fuzzSeed}" );
                        } catch ( Exception $exception ) {
                                $input_dump = sprintf( "string(%d) \"%s\"\n", strlen( $input ), $input );
-                               
+
                                $this->assertTrue( false, "Test $id, fuzz seed {$this->fuzzSeed}. \n\nInput: $input_dump\n\nError: {$exception->getMessage()}\n\nBacktrace: {$exception->getTraceAsString()}" );
                        }
 
@@ -523,18 +661,18 @@ class NewParserTest extends MediaWikiTestCase {
                                        foreach ( $memStats as $name => $usage ) {
                                                $ret .= "$name: $usage\n";
                                        }
-                                       
+
                                        throw new MWException( $ret );
                                }
                        }
-                       
+
                        $id++;
-                       
+
                }
        }
 
        //Various getter functions
-       
+
        /**
         * Get an input dictionary from a set of parser test files
         */
@@ -552,7 +690,7 @@ class NewParserTest extends MediaWikiTestCase {
 
                return $dict;
        }
-       
+
        /**
         * Get a memory usage breakdown
         */
@@ -587,7 +725,7 @@ class NewParserTest extends MediaWikiTestCase {
 
                return $memStats;
        }
-       
+
        /**
         * Get a Parser object
         */
@@ -605,23 +743,20 @@ class NewParserTest extends MediaWikiTestCase {
        //Various action functions
 
        public function addArticle( $name, $text, $line ) {
-               self::$articles[$name] = $text;
-       }       
-       
+               self::$articles[$name] = array( $text, $line );
+       }
+
        public function publishTestArticles() {
                if ( empty( self::$articles ) ) {
                        return;
                }
 
-               foreach ( self::$articles as $name => $text ) {
-                       $title = Title::newFromText( $name );
-
-                       if ( $title->getArticleID( Title::GAID_FOR_UPDATE ) == 0 ) {
-                               ParserTest::addArticle( $name, $text );
-                       }
+               foreach ( self::$articles as $name => $info ) {
+                       list( $text, $line ) = $info;
+                       ParserTest::addArticle( $name, $text, $line, 'ignoreduplicate' );
                }
        }
-       
+
        /**
         * Steal a callback function from the primary parser, save it for
         * application to our scary parser. If the hook is not installed,
@@ -642,14 +777,13 @@ class NewParserTest extends MediaWikiTestCase {
                return isset( $wgParser->mFunctionHooks[$name] );
        }
        //Various "cleanup" functions
-       
-       /*
+
+       /**
         * Run the "tidy" command on text if the $wgUseTidy
         * global is true
         *
         * @param $text String: the text to tidy
         * @return String
-        * @static
         */
        protected function tidy( $text ) {
                global $wgUseTidy;
@@ -660,7 +794,7 @@ class NewParserTest extends MediaWikiTestCase {
 
                return $text;
        }
-       
+
        /**
         * Remove last character if it is a newline
         */
@@ -673,12 +807,8 @@ class NewParserTest extends MediaWikiTestCase {
                }
        }
 
-       public function showRunFile( $file ) {
-               /* NOP */
-       }
-
        //Test options parser functions
-       
+
        protected function parseOptions( $instring ) {
                $opts = array();
                // foo
@@ -733,7 +863,7 @@ class NewParserTest extends MediaWikiTestCase {
                }
                return $opts;
        }
-       
+
        protected function cleanupOption( $opt ) {
                if ( substr( $opt, 0, 1 ) == '"' ) {
                        return substr( $opt, 1, -1 );
@@ -744,7 +874,7 @@ class NewParserTest extends MediaWikiTestCase {
                }
                return $opt;
        }
-       
+
        /**
         * Use a regex to find out the value of an option
         * @param $key String: name of option val to retrieve