Merge "ApiUpload: Better handle unreasonably large metadata in 'imageinfo'"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 26 Aug 2016 17:02:32 +0000 (17:02 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 26 Aug 2016 17:02:32 +0000 (17:02 +0000)
21 files changed:
RELEASE-NOTES-1.28
includes/DefaultSettings.php
includes/EditPage.php
includes/Message.php
includes/OutputPage.php
includes/api/ApiCSPReport.php
includes/debug/logger/MonologSpi.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/MysqlUpdater.php
includes/parser/Parser.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderSiteStylesModule.php
includes/specialpage/LoginSignupSpecialPage.php
includes/upload/UploadBase.php
maintenance/archives/patch-pl-tl-il-nonunique.sql [new file with mode: 0644]
maintenance/archives/patch-pl-tl-il-unique.sql [deleted file]
maintenance/sqlite.php
resources/Resources.php
tests/phpunit/includes/parser/NewParserTest.php
tests/phpunit/includes/parser/PreprocessorTest.php

index 92ac869..1463c6d 100644 (file)
@@ -24,8 +24,11 @@ production.
   input methods provided by the UniversalLanguageSelector extension.
 * When $wgPingback is true, MediaWiki will periodically ping
   https://www.mediawiki.org/beacon with basic information about the local
-  MediaWiki installation.  This data includes, for example, the type of system,
+  MediaWiki installation. This data includes, for example, the type of system,
   PHP version, and chosen database backend. This behavior is off by default.
+* When $wgEditButtonPublishNotSave is true, MediaWiki will label the button to
+  store-to-database-and-show-to-others as "Publish page"/"Publish changes"; if
+  false, the default, they will be "Save page"/"Save changes".
 
 === New features in 1.28 ===
 * User::isBot() method for checking if an account is a bot role account.
@@ -100,7 +103,7 @@ changes to languages because of Phabricator reports.
 
 === Other changes in 1.28 ===
 * (T128697) Improved handling of large diffs.
-* [BREAKING CHANGE] $wgExtendedLoginCookies has been removed.  You can
+* [BREAKING CHANGE] $wgExtendedLoginCookies has been removed. You can
   use or update a custom session provider if needed.
 * Deprecated APIEditBeforeSave hook in favor of EditFilterMergedContent.
 * The 'UploadVerification' hook is deprecated. Use 'UploadVerifyFile' instead.
index f1afc4c..b7fbbb7 100644 (file)
@@ -8381,6 +8381,28 @@ $wgEventRelayerConfig = [
  */
 $wgPingback = false;
 
+/**
+ * List of urls which appear often to be triggering CSP reports
+ * but do not appear to be caused by actual content, but by client
+ * software inserting scripts (i.e. Ad-Ware).
+ * List based on results from Wikimedia logs.
+ *
+ * @since 1.28
+ */
+$wgCSPFalsePositiveUrls = [
+       'https://3hub.co' => true,
+       'https://morepro.info' => true,
+       'https://p.ato.mx' => true,
+       'https://s.ato.mx' => true,
+       'https://adserver.adtech.de' => true,
+       'https://ums.adtechus.com' => true,
+       'https://cas.criteo.com' => true,
+       'https://cat.nl.eu.criteo.com' => true,
+       'https://atpixel.alephd.com' => true,
+       'https://rtb.metrigo.com' => true,
+       'https://d5p.de17a.com' => true,
+];
+
 /**
  * For really cool vim folding this needs to be at the end:
  * vim: foldmarker=@{,@} foldmethod=marker
index 738eaec..0da7e6e 100644 (file)
@@ -4070,10 +4070,11 @@ HTML
                $buttons = [];
 
                $labelAsPublish = $this->mArticle->getContext()->getConfig()->get( 'EditButtonPublishNotSave' );
+               // Can't use $this->isNew as that's also true if we're adding a new section to an extant page
                if ( $labelAsPublish ) {
-                       $buttonLabelKey = $this->isNew ? 'publishpage' : 'publishchanges';
+                       $buttonLabelKey = !$this->mTitle->exists() ? 'publishpage' : 'publishchanges';
                } else {
-                       $buttonLabelKey = $this->isNew ? 'savearticle' : 'savechanges';
+                       $buttonLabelKey = !$this->mTitle->exists() ? 'savearticle' : 'savechanges';
                }
                $buttonLabel = wfMessage( $buttonLabelKey )->text();
                $attribs = [
index 2c979de..c2c954a 100644 (file)
  *
  * @code
  *     // old style:
- *     wfMsgExt( 'key', array( 'parseinline' ), 'apple' );
+ *     wfMsgExt( 'key', [ 'parseinline' ], 'apple' );
  *     // new style:
  *     wfMessage( 'key', 'apple' )->parse();
  * @endcode
  * Places where HTML cannot be used. {{-transformation is done.
  * @code
  *     // old style:
- *     wfMsgExt( 'key', array( 'parsemag' ), 'apple', 'pear' );
+ *     wfMsgExt( 'key', [ 'parsemag' ], 'apple', 'pear' );
  *     // new style:
  *     wfMessage( 'key', 'apple', 'pear' )->text();
  * @endcode
index c7499b1..77dbde7 100644 (file)
@@ -2688,12 +2688,6 @@ class OutputPage extends ContextSource {
                                                        // Special case in buildExemptModules()
                                                        return false;
                                                }
-                                               if ( $name === 'site.styles' ) {
-                                                       // HACK: Technically, 'site.styles' isn't in a separate request group.
-                                                       // But, in order to ensure its styles are in the right position,
-                                                       // pretend it's in a group called 'site'.
-                                                       $group = 'site';
-                                               }
                                                if ( isset( $exemptGroups[$group] ) ) {
                                                        $exemptStates[$name] = 'ready';
                                                        if ( !$module->isKnownEmpty( $context ) ) {
index 5271996..407ae71 100644 (file)
@@ -87,6 +87,7 @@ class ApiCSPReport extends ApiBase {
                $reportOnly = $this->getParameter( 'reportonly' );
                $userAgent = $this->getRequest()->getHeader( 'user-agent' );
                $source = $this->getParameter( 'source' );
+               $falsePositives = $this->getConfig()->get( 'CSPFalsePositiveUrls' );
 
                $flags = [];
                if ( $source !== 'internal' ) {
@@ -95,6 +96,16 @@ class ApiCSPReport extends ApiBase {
                if ( $reportOnly ) {
                        $flags[] = 'report-only';
                }
+
+               if (
+                       ( isset( $report['blocked-uri'] ) &&
+                       isset( $falsePositives[$report['blocked-uri']] ) )
+                       || ( isset( $report['source-file'] ) &&
+                       isset( $falsePositives[$report['source-file']] ) )
+               ) {
+                       // Report caused by Ad-Ware
+                       $flags[] = 'false-positive';
+               }
                return $flags;
        }
 
index 49ad9e6..f44ff1c 100644 (file)
@@ -39,73 +39,73 @@ use ObjectFactory;
  * global configuration variable used by LoggerFactory to construct its
  * default SPI provider:
  * @code
- * $wgMWLoggerDefaultSpi = array(
+ * $wgMWLoggerDefaultSpi = [
  *   'class' => '\\MediaWiki\\Logger\\MonologSpi',
- *   'args' => array( array(
- *       'loggers' => array(
- *           '@default' => array(
- *               'processors' => array( 'wiki', 'psr', 'pid', 'uid', 'web' ),
- *               'handlers'   => array( 'stream' ),
- *           ),
- *           'runJobs' => array(
- *               'processors' => array( 'wiki', 'psr', 'pid' ),
- *               'handlers'   => array( 'stream' ),
- *           )
- *       ),
- *       'processors' => array(
- *           'wiki' => array(
+ *   'args' => [ [
+ *       'loggers' => [
+ *           '@default' => [
+ *               'processors' => [ 'wiki', 'psr', 'pid', 'uid', 'web' ],
+ *               'handlers'   => [ 'stream' ],
+ *           ],
+ *           'runJobs' => [
+ *               'processors' => [ 'wiki', 'psr', 'pid' ],
+ *               'handlers'   => [ 'stream' ],
+ *           ]
+ *       ],
+ *       'processors' => [
+ *           'wiki' => [
  *               'class' => '\\MediaWiki\\Logger\\Monolog\\WikiProcessor',
- *           ),
- *           'psr' => array(
+ *           ],
+ *           'psr' => [
  *               'class' => '\\Monolog\\Processor\\PsrLogMessageProcessor',
- *           ),
- *           'pid' => array(
+ *           ],
+ *           'pid' => [
  *               'class' => '\\Monolog\\Processor\\ProcessIdProcessor',
- *           ),
- *           'uid' => array(
+ *           ],
+ *           'uid' => [
  *               'class' => '\\Monolog\\Processor\\UidProcessor',
- *           ),
- *           'web' => array(
+ *           ],
+ *           'web' => [
  *               'class' => '\\Monolog\\Processor\\WebProcessor',
- *           ),
- *       ),
- *       'handlers' => array(
- *           'stream' => array(
+ *           ],
+ *       ],
+ *       'handlers' => [
+ *           'stream' => [
  *               'class'     => '\\Monolog\\Handler\\StreamHandler',
- *               'args'      => array( 'path/to/your.log' ),
+ *               'args'      => [ 'path/to/your.log' ],
  *               'formatter' => 'line',
- *           ),
- *           'redis' => array(
+ *           ],
+ *           'redis' => [
  *               'class'     => '\\Monolog\\Handler\\RedisHandler',
- *               'args'      => array( function() {
+ *               'args'      => [ function() {
  *                       $redis = new Redis();
  *                       $redis->connect( '127.0.0.1', 6379 );
  *                       return $redis;
  *                   },
  *                   'logstash'
- *               ),
+ *               ],
  *               'formatter' => 'logstash',
  *               'buffer' => true,
- *           ),
- *           'udp2log' => array(
+ *           ],
+ *           'udp2log' => [
  *               'class' => '\\MediaWiki\\Logger\\Monolog\\LegacyHandler',
- *               'args' => array(
+ *               'args' => [
  *                   'udp://127.0.0.1:8420/mediawiki
- *               ),
+ *               ],
  *               'formatter' => 'line',
- *           ),
- *       ),
- *       'formatters' => array(
- *           'line' => array(
+ *           ],
+ *       ],
+ *       'formatters' => [
+ *           'line' => [
  *               'class' => '\\Monolog\\Formatter\\LineFormatter',
- *            ),
- *            'logstash' => array(
+ *            ],
+ *            'logstash' => [
  *                'class' => '\\Monolog\\Formatter\\LogstashFormatter',
- *                'args'  => array( 'mediawiki', php_uname( 'n' ), null, '', 1 ),
- *            ),
- *       ),
- *   ) ),
- * );
+ *                'args'  => [ 'mediawiki', php_uname( 'n' ), null, '', 1 ],
+ *            ],
+ *       ],
+ *   ] ],
+ * ];
  * @endcode
  *
  * @see https://github.com/Seldaek/monolog
index d508d76..eafb9d4 100644 (file)
@@ -1437,10 +1437,10 @@ abstract class Installer {
 
        /**
         * Get an array of install steps. Should always be in the format of
-        * array(
+        * [
         *   'name'     => 'someuniquename',
-        *   'callback' => array( $obj, 'method' ),
-        * )
+        *   'callback' => [ $obj, 'method' ],
+        * ]
         * There must be a config-install-$name message defined per step, which will
         * be shown on install.
         *
@@ -1724,7 +1724,7 @@ abstract class Installer {
         * Add an installation step following the given step.
         *
         * @param callable $callback A valid installation callback array, in this form:
-        *    array( 'name' => 'some-unique-name', 'callback' => array( $obj, 'function' ) );
+        *    [ 'name' => 'some-unique-name', 'callback' => [ $obj, 'function' ] ];
         * @param string $findStep The step to find. Omit to put the step at the beginning
         */
        public function addInstallStep( $callback, $findStep = 'BEGINNING' ) {
index 1d7c7f2..a9e3e85 100644 (file)
@@ -98,7 +98,7 @@ class LocalSettingsGenerator {
         * For $wgGroupPermissions, set a given ['group']['permission'] value.
         * @param string $group Group name
         * @param array $rightsArr An array of permissions, in the form of:
-        *   array( 'right' => true, 'right2' => false )
+        *   [ 'right' => true, 'right2' => false ]
         */
        public function setGroupRights( $group, $rightsArr ) {
                $this->groupPermissions[$group] = $rightsArr;
index 6989969..65af086 100644 (file)
@@ -155,7 +155,6 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'addField', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ],
 
                        // 1.15
-                       [ 'doUniquePlTlIl' ],
                        [ 'addTable', 'change_tag', 'patch-change_tag.sql' ],
                        [ 'addTable', 'tag_summary', 'patch-tag_summary.sql' ],
                        [ 'addTable', 'valid_tag', 'patch-valid_tag.sql' ],
@@ -287,7 +286,8 @@ class MysqlUpdater extends DatabaseUpdater {
                        // 1.28
                        [ 'addIndex', 'recentchanges', 'rc_name_type_patrolled_timestamp',
                                'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
-                       [ 'doRevisionPageRevIndexNonUnique' ]
+                       [ 'doRevisionPageRevIndexNonUnique' ],
+                       [ 'doNonUniquePlTlIl' ],
                ];
        }
 
@@ -974,24 +974,24 @@ class MysqlUpdater extends DatabaseUpdater {
                return true;
        }
 
-       protected function doUniquePlTlIl() {
+       protected function doNonUniquePlTlIl() {
                $info = $this->db->indexInfo( 'pagelinks', 'pl_namespace' );
-               if ( is_array( $info ) && !$info[0]->Non_unique ) {
-                       $this->output( "...pl_namespace, tl_namespace, il_to indices are already UNIQUE.\n" );
+               if ( is_array( $info ) && $info[0]->Non_unique ) {
+                       $this->output( "...pl_namespace, tl_namespace, il_to indices are already non-UNIQUE.\n" );
 
                        return true;
                }
                if ( $this->skipSchema ) {
                        $this->output( "...skipping schema change (making pl_namespace, tl_namespace " .
-                               "and il_to indices UNIQUE).\n" );
+                               "and il_to indices non-UNIQUE).\n" );
 
                        return false;
                }
 
                return $this->applyPatch(
-                       'patch-pl-tl-il-unique.sql',
+                       'patch-pl-tl-il-nonunique.sql',
                        false,
-                       'Making pl_namespace, tl_namespace and il_to indices UNIQUE'
+                       'Making pl_namespace, tl_namespace and il_to indices non-UNIQUE'
                );
        }
 
index b116bd4..035baac 100644 (file)
@@ -906,11 +906,11 @@ class Parser {
         * the form:
         *
         * @code
-        *   'UNIQ-xxxxx' => array(
+        *   'UNIQ-xxxxx' => [
         *     'element',
         *     'tag content',
-        *     array( 'param' => 'x' ),
-        *     '<element param="x">tag content</element>' ) )
+        *     [ 'param' => 'x' ],
+        *     '<element param="x">tag content</element>' ]
         * @endcode
         *
         * @param array $elements List of element names. Comments are always extracted.
index 48e7937..de89fc7 100644 (file)
@@ -264,8 +264,8 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         *
         * @param ResourceLoaderContext $context
         * @return array List of CSS strings or array of CSS strings keyed by media type.
-        *  like array( 'screen' => '.foo { width: 0 }' );
-        *  or array( 'screen' => array( '.foo { width: 0 }' ) );
+        *  like [ 'screen' => '.foo { width: 0 }' ];
+        *  or [ 'screen' => [ '.foo { width: 0 }' ] ];
         */
        public function getStyles( ResourceLoaderContext $context ) {
                // Stub, override expected
@@ -279,7 +279,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         * load the files directly. See also getScriptURLsForDebug()
         *
         * @param ResourceLoaderContext $context
-        * @return array Array( mediaType => array( URL1, URL2, ... ), ... )
+        * @return array [ mediaType => [ URL1, URL2, ... ], ... ]
         */
        public function getStyleURLsForDebug( ResourceLoaderContext $context ) {
                $resourceLoader = $context->getResourceLoader();
@@ -637,7 +637,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
                // Styles
                if ( $context->shouldIncludeStyles() ) {
                        $styles = [];
-                       // Don't create empty stylesheets like array( '' => '' ) for modules
+                       // Don't create empty stylesheets like [ '' => '' ] for modules
                        // that don't *have* any stylesheets (bug 38024).
                        $stylePairs = $this->getStyles( $context );
                        if ( count( $stylePairs ) ) {
index 46808a1..79922bf 100644 (file)
@@ -50,4 +50,11 @@ class ResourceLoaderSiteStylesModule extends ResourceLoaderWikiModule {
        public function getType() {
                return self::LOAD_STYLES;
        }
+
+       /**
+        * @return string
+        */
+       public function getGroup() {
+               return 'site';
+       }
 }
index 22c38cb..c3d43df 100644 (file)
@@ -835,6 +835,12 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                                'class' => 'mw-ui-flush-right mw-secure',
                        ], $this->msg( 'userlogin-signwithsecure' )->text() );
                }
+               $usernameHelpLink = '';
+               if ( !$this->msg( 'createacct-helpusername' )->isDisabled() ) {
+                       $usernameHelpLink = Html::rawElement( 'span', [
+                               'class' => 'mw-ui-flush-right',
+                       ], $this->msg( 'createacct-helpusername' )->parse() );
+               }
 
                if ( $this->isSignup() ) {
                        $fieldDefinitions = [
@@ -847,9 +853,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                                        'weight' => -105,
                                ],
                                'username' => [
-                                       'label-message' => 'userlogin-yourname',
-                                       // FIXME help-message does not match old formatting
-                                       'help-message' => 'createacct-helpusername',
+                                       'label-raw' => $this->msg( 'userlogin-yourname' )->escaped() . $usernameHelpLink,
                                        'id' => 'wpName2',
                                        'placeholder-message' => $isLoggedIn ? 'createacct-another-username-ph'
                                                : 'userlogin-yourname-ph',
index e2f7763..b37c831 100644 (file)
@@ -1659,7 +1659,7 @@ abstract class UploadBase {
         * @return array Containing the namespace URI and prefix
         */
        private static function splitXmlNamespace( $element ) {
-               // 'http://www.w3.org/2000/svg:script' -> array( 'http://www.w3.org/2000/svg', 'script' )
+               // 'http://www.w3.org/2000/svg:script' -> [ 'http://www.w3.org/2000/svg', 'script' ]
                $parts = explode( ':', strtolower( $element ) );
                $name = array_pop( $parts );
                $ns = implode( ':', $parts );
diff --git a/maintenance/archives/patch-pl-tl-il-nonunique.sql b/maintenance/archives/patch-pl-tl-il-nonunique.sql
new file mode 100644 (file)
index 0000000..8e1715b
--- /dev/null
@@ -0,0 +1,11 @@
+-- Make reorderings of UNIQUE indices non-UNIQUE
+-- Since 1.24, these indices have been non-UNIQUE in tables.sql.
+-- However, an earlier update from 1.15 that made the indices
+-- UNIQUE was not removed until 1.28 (T78513).
+
+DROP INDEX /*i*/pl_namespace ON /*_*/pagelinks;
+CREATE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace, pl_title, pl_from);
+DROP INDEX /*i*/tl_namespace ON /*_*/templatelinks;
+CREATE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace, tl_title, tl_from);
+DROP INDEX /*i*/il_to ON /*_*/imagelinks;
+CREATE INDEX /*i*/il_to ON /*_*/imagelinks (il_to, il_from);
diff --git a/maintenance/archives/patch-pl-tl-il-unique.sql b/maintenance/archives/patch-pl-tl-il-unique.sql
deleted file mode 100644 (file)
index a356670..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---
--- patch-pl-tl-il-unique-index.sql
---
--- Make reorderings of UNIQUE indices UNIQUE as well
-
-DROP INDEX /*i*/pl_namespace ON /*_*/pagelinks;
-CREATE UNIQUE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace, pl_title, pl_from);
-DROP INDEX /*i*/tl_namespace ON /*_*/templatelinks;
-CREATE UNIQUE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace, tl_title, tl_from);
-DROP INDEX /*i*/il_to ON /*_*/imagelinks;
-CREATE UNIQUE INDEX /*i*/il_to ON /*_*/imagelinks (il_to, il_from);
index 454c506..e74a86c 100644 (file)
@@ -132,7 +132,7 @@ class SqliteMaintenance extends Maintenance {
                        $this->error( "Error: SQLite support not found\n" );
                }
                $files = [ $this->getOption( 'check-syntax' ) ];
-               $files += $this->mArgs;
+               $files = array_merge( $files, $this->mArgs );
                $result = Sqlite::checkSqlSyntax( $files );
                if ( $result === true ) {
                        $this->output( "SQL syntax check: no errors detected.\n" );
index 76c5191..b6c3007 100644 (file)
@@ -567,6 +567,7 @@ return [
                'group' => 'jquery.ui',
        ],
        'jquery.ui.position' => [
+               'deprecated' => true,
                'scripts' => 'resources/lib/jquery.ui/jquery.ui.position.js',
                'group' => 'jquery.ui',
        ],
index e7abd15..ad84c20 100644 (file)
@@ -712,6 +712,7 @@ class NewParserTest extends MediaWikiTestCase {
                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' );
+                       $this->teardownGlobals();
                        return;
                }
 
@@ -719,6 +720,7 @@ class NewParserTest extends MediaWikiTestCase {
                        // parser tests frequently assume that the main namespace contains wikitext.
                        // @todo When setting up pages, force the content model. Only skip if
                        //        $wgtContentModelUseDB is false.
+                       $this->teardownGlobals();
                        $this->markTestSkipped( "Main namespace does not support wikitext,"
                                . "skipping parser test: $desc" );
                }
@@ -749,8 +751,10 @@ class NewParserTest extends MediaWikiTestCase {
                        global $wgTexvc;
 
                        if ( !isset( $wgTexvc ) ) {
+                               $this->teardownGlobals();
                                $this->markTestSkipped( "SKIPPED: \$wgTexvc is not set" );
                        } elseif ( !is_executable( $wgTexvc ) ) {
+                               $this->teardownGlobals();
                                $this->markTestSkipped( "SKIPPED: texvc binary does not exist"
                                        . " or is not executable.\n"
                                        . "Current configuration is:\n\$wgTexvc = '$wgTexvc'" );
@@ -759,12 +763,14 @@ class NewParserTest extends MediaWikiTestCase {
 
                if ( isset( $opts['djvu'] ) ) {
                        if ( !$this->djVuSupport->isEnabled() ) {
+                               $this->teardownGlobals();
                                $this->markTestSkipped( "SKIPPED: djvu binaries do not exist or are not executable.\n" );
                        }
                }
 
                if ( isset( $opts['tidy'] ) ) {
                        if ( !$this->tidySupport->isEnabled() ) {
+                               $this->teardownGlobals();
                                $this->markTestSkipped( "SKIPPED: tidy extension is not installed.\n" );
                        } else {
                                $options->setTidy( true );
index c557a6e..6710b19 100644 (file)
@@ -1,5 +1,29 @@
 <?php
 
+/**
+ * @covers Preprocessor
+ *
+ * @covers Preprocessor_DOM
+ * @covers PPDStack
+ * @covers PPDStackElement
+ * @covers PPDPart
+ * @covers PPFrame_DOM
+ * @covers PPTemplateFrame_DOM
+ * @covers PPCustomFrame_DOM
+ * @covers PPNode_DOM
+ *
+ * @covers Preprocessor_Hash
+ * @covers PPDStack_Hash
+ * @covers PPDStackElement_Hash
+ * @covers PPDPart_Hash
+ * @covers PPFrame_Hash
+ * @covers PPTemplateFrame_Hash
+ * @covers PPCustomFrame_Hash
+ * @covers PPNode_Hash_Tree
+ * @covers PPNode_Hash_Text
+ * @covers PPNode_Hash_Array
+ * @covers PPNode_Hash_Attr
+ */
 class PreprocessorTest extends MediaWikiTestCase {
        protected $mTitle = 'Page title';
        protected $mPPNodeCount = 0;
@@ -174,7 +198,6 @@ class PreprocessorTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideCases
-        * @covers Preprocessor_DOM::preprocessToXml
         */
        public function testPreprocessorOutput( $className, $wikiText, $expectedXml ) {
                $this->assertEquals( $this->normalizeXml( $expectedXml ),
@@ -198,7 +221,6 @@ class PreprocessorTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideFiles
-        * @covers Preprocessor_DOM::preprocessToXml
         */
        public function testPreprocessorOutputFiles( $className, $filename ) {
                $folder = __DIR__ . "/../../../parser/preprocess";
@@ -264,7 +286,6 @@ class PreprocessorTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideHeadings
-        * @covers Preprocessor_DOM::preprocessToXml
         */
        public function testHeadings( $className, $wikiText, $expectedXml ) {
                $this->assertEquals( $this->normalizeXml( $expectedXml ),