Use DB domain in JobQueueGroup and make WikiMap domain ID methods stricter
[lhc/web/wiklou.git] / tests / phpunit / includes / WikiMapTest.php
index 2092e0c..1fb8aff 100644 (file)
@@ -1,55 +1,83 @@
 <?php
+use Wikimedia\Rdbms\DatabaseDomain;
 
 /**
  * @covers WikiMap
+ *
+ * @group Database
  */
-
 class WikiMapTest extends MediaWikiLangTestCase {
 
        public function setUp() {
                parent::setUp();
 
                $conf = new SiteConfiguration();
-               $conf->settings = array(
-                       'wgServer' => array(
+               $conf->settings = [
+                       'wgServer' => [
                                'enwiki' => 'http://en.example.org',
                                'ruwiki' => '//ru.example.org',
-                       ),
-                       'wgArticlePath' => array(
+                               'nopathwiki' => '//nopath.example.org',
+                               'thiswiki' => '//this.wiki.org'
+                       ],
+                       'wgArticlePath' => [
                                'enwiki' => '/w/$1',
                                'ruwiki' => '/wiki/$1',
-                       ),
-               );
-               $conf->suffixes = array( 'wiki' );
-               $this->setMwGlobals( array(
+                       ],
+               ];
+               $conf->suffixes = [ 'wiki' ];
+               $this->setMwGlobals( [
                        'wgConf' => $conf,
-               ) );
+                       'wgLocalDatabases' => [ 'enwiki', 'ruwiki', 'nopathwiki' ],
+                       'wgCanonicalServer' => '//this.wiki.org',
+                       'wgDBname' => 'thiswiki',
+                       'wgDBprefix' => ''
+               ] );
+
+               TestSites::insertIntoDb();
        }
 
        public function provideGetWiki() {
+               // As provided by $wgConf
                $enwiki = new WikiReference( 'http://en.example.org', '/w/$1' );
                $ruwiki = new WikiReference( '//ru.example.org', '/wiki/$1' );
 
-               return array(
-                       'unknown' => array( false, 'xyzzy' ),
-                       'enwiki' => array( $enwiki, 'enwiki' ),
-                       'ruwiki' => array( $ruwiki, 'ruwiki' ),
-               );
+               // Created from site objects
+               $nlwiki = new WikiReference( 'https://nl.wikipedia.org', '/wiki/$1' );
+               // enwiktionary doesn't have an interwiki id, thus this falls back to minor = lang code
+               $enwiktionary = new WikiReference( 'https://en.wiktionary.org', '/wiki/$1' );
+
+               return [
+                       'unknown' => [ null, 'xyzzy' ],
+                       'enwiki (wgConf)' => [ $enwiki, 'enwiki' ],
+                       'ruwiki (wgConf)' => [ $ruwiki, 'ruwiki' ],
+                       'nlwiki (sites)' => [ $nlwiki, 'nlwiki', false ],
+                       'enwiktionary (sites)' => [ $enwiktionary, 'enwiktionary', false ],
+                       'non MediaWiki site' => [ null, 'spam', false ],
+                       'boguswiki' => [ null, 'boguswiki' ],
+                       'nopathwiki' => [ null, 'nopathwiki' ],
+               ];
        }
 
        /**
         * @dataProvider provideGetWiki
         */
-       public function testGetWiki( $expected, $wikiId ) {
+       public function testGetWiki( $expected, $wikiId, $useWgConf = true ) {
+               if ( !$useWgConf ) {
+                       $this->setMwGlobals( [
+                               'wgConf' => new SiteConfiguration(),
+                       ] );
+               }
+
                $this->assertEquals( $expected, WikiMap::getWiki( $wikiId ) );
        }
 
        public function provideGetWikiName() {
-               return array(
-                       'unknown' => array( 'xyzzy', 'xyzzy' ),
-                       'enwiki' => array( 'en.example.org', 'enwiki' ),
-                       'ruwiki' => array( 'ru.example.org', 'ruwiki' ),
-               );
+               return [
+                       'unknown' => [ 'xyzzy', 'xyzzy' ],
+                       'enwiki' => [ 'en.example.org', 'enwiki' ],
+                       'ruwiki' => [ 'ru.example.org', 'ruwiki' ],
+                       'enwiktionary (sites)' => [ 'en.wiktionary.org', 'enwiktionary' ],
+               ];
        }
 
        /**
@@ -60,22 +88,29 @@ class WikiMapTest extends MediaWikiLangTestCase {
        }
 
        public function provideMakeForeignLink() {
-               return array(
-                       'unknown' => array( false, 'xyzzy', 'Foo' ),
-                       'enwiki' => array(
+               return [
+                       'unknown' => [ false, 'xyzzy', 'Foo' ],
+                       'enwiki' => [
                                '<a class="external" rel="nofollow" ' .
                                        'href="http://en.example.org/w/Foo">Foo</a>',
                                'enwiki',
                                'Foo'
-                       ),
-                       'ruwiki' => array(
+                       ],
+                       'ruwiki' => [
                                '<a class="external" rel="nofollow" ' .
                                        'href="//ru.example.org/wiki/%D0%A4%D1%83">вар</a>',
                                'ruwiki',
                                'Фу',
                                'вар'
-                       ),
-               );
+                       ],
+                       'enwiktionary (sites)' => [
+                               '<a class="external" rel="nofollow" ' .
+                                       'href="https://en.wiktionary.org/wiki/Kitten">Kittens!</a>',
+                               'enwiktionary',
+                               'Kitten',
+                               'Kittens!'
+                       ],
+               ];
        }
 
        /**
@@ -89,22 +124,29 @@ class WikiMapTest extends MediaWikiLangTestCase {
        }
 
        public function provideForeignUserLink() {
-               return array(
-                       'unknown' => array( false, 'xyzzy', 'Foo' ),
-                       'enwiki' => array(
+               return [
+                       'unknown' => [ false, 'xyzzy', 'Foo' ],
+                       'enwiki' => [
                                '<a class="external" rel="nofollow" ' .
                                        'href="http://en.example.org/w/User:Foo">User:Foo</a>',
                                'enwiki',
                                'Foo'
-                       ),
-                       'ruwiki' => array(
+                       ],
+                       'ruwiki' => [
                                '<a class="external" rel="nofollow" ' .
                                        'href="//ru.example.org/wiki/User:%D0%A4%D1%83">вар</a>',
                                'ruwiki',
                                'Фу',
                                'вар'
-                       ),
-               );
+                       ],
+                       'enwiktionary (sites)' => [
+                               '<a class="external" rel="nofollow" ' .
+                                       'href="https://en.wiktionary.org/wiki/User:Dummy">Whatever</a>',
+                               'enwiktionary',
+                               'Dummy',
+                               'Whatever'
+                       ],
+               ];
        }
 
        /**
@@ -115,16 +157,21 @@ class WikiMapTest extends MediaWikiLangTestCase {
        }
 
        public function provideGetForeignURL() {
-               return array(
-                       'unknown' => array( false, 'xyzzy', 'Foo' ),
-                       'enwiki' => array( 'http://en.example.org/w/Foo', 'enwiki', 'Foo' ),
-                       'ruwiki with fragement' => array(
+               return [
+                       'unknown' => [ false, 'xyzzy', 'Foo' ],
+                       'enwiki' => [ 'http://en.example.org/w/Foo', 'enwiki', 'Foo' ],
+                       'enwiktionary (sites)' => [
+                               'https://en.wiktionary.org/wiki/Testme',
+                               'enwiktionary',
+                               'Testme'
+                       ],
+                       'ruwiki with fragment' => [
                                '//ru.example.org/wiki/%D0%A4%D1%83#%D0%B2%D0%B0%D1%80',
                                'ruwiki',
                                'Фу',
                                'вар'
-                       ),
-               );
+                       ],
+               ];
        }
 
        /**
@@ -134,4 +181,127 @@ class WikiMapTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, WikiMap::getForeignURL( $wikiId, $page, $fragment ) );
        }
 
+       /**
+        * @covers WikiMap::getCanonicalServerInfoForAllWikis()
+        */
+       public function testGetCanonicalServerInfoForAllWikis() {
+               $expected = [
+                       'thiswiki' => [
+                               'url' => '//this.wiki.org',
+                               'parts' => [ 'scheme' => '', 'host' => 'this.wiki.org', 'delimiter' => '//' ]
+                       ],
+                       'enwiki' => [
+                               'url' => 'http://en.example.org',
+                               'parts' => [
+                                       'scheme' => 'http', 'host' => 'en.example.org', 'delimiter' => '://' ]
+                       ],
+                       'ruwiki' => [
+                               'url' => '//ru.example.org',
+                               'parts' => [ 'scheme' => '', 'host' => 'ru.example.org', 'delimiter' => '//' ]
+                       ]
+               ];
+
+               $this->assertArrayEquals(
+                       $expected,
+                       WikiMap::getCanonicalServerInfoForAllWikis(),
+                       true,
+                       true
+               );
+       }
+
+       public function provideGetWikiFromUrl() {
+               return [
+                       [ 'http://this.wiki.org', 'thiswiki' ],
+                       [ 'https://this.wiki.org', 'thiswiki' ],
+                       [ 'http://this.wiki.org/$1', 'thiswiki' ],
+                       [ 'https://this.wiki.org/$2', 'thiswiki' ],
+                       [ 'http://en.example.org', 'enwiki' ],
+                       [ 'https://en.example.org', 'enwiki' ],
+                       [ 'http://en.example.org/$1', 'enwiki' ],
+                       [ 'https://en.example.org/$2', 'enwiki' ],
+                       [ 'http://ru.example.org', 'ruwiki' ],
+                       [ 'https://ru.example.org', 'ruwiki' ],
+                       [ 'http://ru.example.org/$1', 'ruwiki' ],
+                       [ 'https://ru.example.org/$2', 'ruwiki' ],
+                       [ 'http://not.defined.org', false ]
+               ];
+       }
+
+       /**
+        * @dataProvider provideGetWikiFromUrl
+        * @covers WikiMap::getWikiFromUrl()
+        */
+       public function testGetWikiFromUrl( $url, $wiki ) {
+               $this->assertEquals( $wiki, WikiMap::getWikiFromUrl( $url ) );
+       }
+
+       public function provideGetWikiIdFromDomain() {
+               return [
+                       [ 'db-prefix', 'db-prefix' ],
+                       [ wfWikiID(), wfWikiID() ],
+                       [ new DatabaseDomain( 'db-dash', null, 'prefix' ), 'db-dash-prefix' ],
+                       [ wfWikiID(), wfWikiID() ],
+                       [ new DatabaseDomain( 'db-dash', null, 'prefix' ), 'db-dash-prefix' ],
+                       [ new DatabaseDomain( 'db', 'mediawiki', 'prefix' ), 'db-prefix' ], // schema ignored
+                       [ new DatabaseDomain( 'db', 'custom', 'prefix' ), 'db-custom-prefix' ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideGetWikiIdFromDomain
+        * @covers WikiMap::getWikiIdFromDomain()
+        */
+       public function testGetWikiIdFromDomain( $domain, $wikiId ) {
+               $this->assertEquals( $wikiId, WikiMap::getWikiIdFromDomain( $domain ) );
+       }
+
+       /**
+        * @covers WikiMap::isCurrentWikiDomain()
+        * @covers WikiMap::getCurrentWikiDomain()
+        */
+       public function testIsCurrentWikiDomain() {
+               $this->assertTrue( WikiMap::isCurrentWikiDomain( wfWikiID() ) );
+
+               $localDomain = DatabaseDomain::newFromId( wfWikiID() );
+               $domain1 = new DatabaseDomain(
+                       $localDomain->getDatabase(), 'someschema', $localDomain->getTablePrefix() );
+               $domain2 = new DatabaseDomain(
+                       $localDomain->getDatabase(), null, $localDomain->getTablePrefix() );
+
+               $this->assertTrue( WikiMap::isCurrentWikiDomain( $domain1 ), 'Schema ignored' );
+               $this->assertTrue( WikiMap::isCurrentWikiDomain( $domain2 ), 'Schema ignored' );
+
+               $this->assertTrue( WikiMap::isCurrentWikiDomain( WikiMap::getCurrentWikiDomain() ) );
+       }
+
+       public function provideIsCurrentWikiId() {
+               return [
+                       [ 'db', 'db', null, '' ],
+                       [ 'db-schema-','db', 'schema', '' ],
+                       [ 'db','db', 'mediawiki', '' ], // common b/c case
+                       [ 'db-prefix', 'db', null, 'prefix' ],
+                       [ 'db-schema-prefix', 'db', 'schema', 'prefix' ],
+                       [ 'db-prefix', 'db', 'mediawiki', 'prefix' ], // common b/c case
+                       // Bad hyphen cases (best effort support)
+                       [ 'db-stuff', 'db-stuff', null, '' ],
+                       [ 'db-stuff-prefix', 'db-stuff', null, 'prefix' ],
+                       [ 'db-stuff-schema-', 'db-stuff', 'schema', '' ],
+                       [ 'db-stuff-schema-prefix', 'db-stuff', 'schema', 'prefix' ],
+                       [ 'db-stuff-prefix', 'db-stuff', 'mediawiki', 'prefix' ] // common b/c case
+               ];
+       }
+
+       /**
+        * @dataProvider provideIsCurrentWikiId
+        * @covers WikiMap::isCurrentWikiId()
+        * @covers WikiMap::getCurrentWikiDomain()
+        * @covers WikiMap::getWikiIdFromDomain()
+        */
+       public function testIsCurrentWikiId( $wikiId, $db, $schema, $prefix ) {
+               $this->setMwGlobals(
+                       [ 'wgDBname' => $db, 'wgDBmwschema' => $schema, 'wgDBprefix' => $prefix ] );
+
+               $this->assertTrue( WikiMap::isCurrentWikiId( $wikiId ), "ID matches" );
+               $this->assertNotTrue( WikiMap::isCurrentWikiId( $wikiId . '-more' ), "Bogus ID" );
+       }
 }