summaryrefslogtreecommitdiff
path: root/www/wiki/tests/phpunit/includes/site
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/tests/phpunit/includes/site')
-rw-r--r--www/wiki/tests/phpunit/includes/site/CachingSiteStoreTest.php163
-rw-r--r--www/wiki/tests/phpunit/includes/site/DBSiteStoreTest.php166
-rw-r--r--www/wiki/tests/phpunit/includes/site/FileBasedSiteLookupTest.php103
-rw-r--r--www/wiki/tests/phpunit/includes/site/HashSiteStoreTest.php105
-rw-r--r--www/wiki/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php117
-rw-r--r--www/wiki/tests/phpunit/includes/site/MediaWikiSiteTest.php108
-rw-r--r--www/wiki/tests/phpunit/includes/site/SiteExporterTest.php150
-rw-r--r--www/wiki/tests/phpunit/includes/site/SiteImporterTest.php202
-rw-r--r--www/wiki/tests/phpunit/includes/site/SiteImporterTest.xml19
-rw-r--r--www/wiki/tests/phpunit/includes/site/SiteListTest.php239
-rw-r--r--www/wiki/tests/phpunit/includes/site/SiteTest.php295
-rw-r--r--www/wiki/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php137
-rw-r--r--www/wiki/tests/phpunit/includes/site/TestSites.php112
13 files changed, 1916 insertions, 0 deletions
diff --git a/www/wiki/tests/phpunit/includes/site/CachingSiteStoreTest.php b/www/wiki/tests/phpunit/includes/site/CachingSiteStoreTest.php
new file mode 100644
index 00000000..0fdcf6da
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/CachingSiteStoreTest.php
@@ -0,0 +1,163 @@
+<?php
+
+/**
+ * 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
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class CachingSiteStoreTest extends MediaWikiTestCase {
+
+ /**
+ * @covers CachingSiteStore::getSites
+ */
+ public function testGetSites() {
+ $testSites = TestSites::getSites();
+
+ $store = new CachingSiteStore(
+ $this->getHashSiteStore( $testSites ),
+ wfGetMainCache()
+ );
+
+ $sites = $store->getSites();
+
+ $this->assertInstanceOf( SiteList::class, $sites );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertInstanceOf( Site::class, $site );
+ }
+
+ foreach ( $testSites as $site ) {
+ if ( $site->getGlobalId() !== null ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @covers CachingSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new CachingSiteStore( new HashSiteStore(), wfGetMainCache() );
+
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'ertrywuutr' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'sdfhxujgkfpth' );
+ $site->setLanguageCode( 'nl' );
+ $sites[] = $site;
+
+ $this->assertTrue( $store->saveSites( $sites ) );
+
+ $site = $store->getSite( 'ertrywuutr' );
+ $this->assertInstanceOf( Site::class, $site );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+
+ $site = $store->getSite( 'sdfhxujgkfpth' );
+ $this->assertInstanceOf( Site::class, $site );
+ $this->assertEquals( 'nl', $site->getLanguageCode() );
+ }
+
+ /**
+ * @covers CachingSiteStore::reset
+ */
+ public function testReset() {
+ $dbSiteStore = $this->getMockBuilder( SiteStore::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dbSiteStore->expects( $this->any() )
+ ->method( 'getSite' )
+ ->will( $this->returnValue( $this->getTestSite() ) );
+
+ $dbSiteStore->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnCallback( function () {
+ $siteList = new SiteList();
+ $siteList->setSite( $this->getTestSite() );
+
+ return $siteList;
+ } ) );
+
+ $store = new CachingSiteStore( $dbSiteStore, wfGetMainCache() );
+
+ // initialize internal cache
+ $this->assertGreaterThan( 0, $store->getSites()->count(), 'count sites' );
+
+ $store->getSite( 'enwiki' )->setLanguageCode( 'en-ca' );
+
+ // sanity check: $store should have the new language code for 'enwiki'
+ $this->assertEquals( 'en-ca', $store->getSite( 'enwiki' )->getLanguageCode(), 'sanity check' );
+
+ // purge cache
+ $store->reset();
+
+ // the internal cache of $store should be updated, and now pulling
+ // the site from the 'fallback' DBSiteStore with the original language code.
+ $this->assertEquals( 'en', $store->getSite( 'enwiki' )->getLanguageCode(), 'reset' );
+ }
+
+ public function getTestSite() {
+ $enwiki = new MediaWikiSite();
+ $enwiki->setGlobalId( 'enwiki' );
+ $enwiki->setLanguageCode( 'en' );
+
+ return $enwiki;
+ }
+
+ /**
+ * @covers CachingSiteStore::clear
+ */
+ public function testClear() {
+ $store = new CachingSiteStore( new HashSiteStore(), wfGetMainCache() );
+ $this->assertTrue( $store->clear() );
+
+ $site = $store->getSite( 'enwiki' );
+ $this->assertNull( $site );
+
+ $sites = $store->getSites();
+ $this->assertEquals( 0, $sites->count() );
+ }
+
+ /**
+ * @param Site[] $sites
+ *
+ * @return SiteStore
+ */
+ private function getHashSiteStore( array $sites ) {
+ $siteStore = new HashSiteStore();
+ $siteStore->saveSites( $sites );
+
+ return $siteStore;
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/site/DBSiteStoreTest.php b/www/wiki/tests/phpunit/includes/site/DBSiteStoreTest.php
new file mode 100644
index 00000000..7c16f6c5
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/DBSiteStoreTest.php
@@ -0,0 +1,166 @@
+<?php
+
+/**
+ * Tests for the DBSiteStore class.
+ *
+ * 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
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class DBSiteStoreTest extends MediaWikiTestCase {
+
+ /**
+ * @return DBSiteStore
+ */
+ private function newDBSiteStore() {
+ // NOTE: Use the real DB load balancer for now. Eventually, the test framework should
+ // provide a LoadBalancer that is safe to use in unit tests.
+ return new DBSiteStore( wfGetLB() );
+ }
+
+ /**
+ * @covers DBSiteStore::getSites
+ */
+ public function testGetSites() {
+ $expectedSites = TestSites::getSites();
+ TestSites::insertIntoDb();
+
+ $store = $this->newDBSiteStore();
+
+ $sites = $store->getSites();
+
+ $this->assertInstanceOf( SiteList::class, $sites );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertInstanceOf( Site::class, $site );
+ }
+
+ foreach ( $expectedSites as $site ) {
+ if ( $site->getGlobalId() !== null ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @covers DBSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = $this->newDBSiteStore();
+
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'ertrywuutr' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'sdfhxujgkfpth' );
+ $site->setLanguageCode( 'nl' );
+ $sites[] = $site;
+
+ $this->assertTrue( $store->saveSites( $sites ) );
+
+ $site = $store->getSite( 'ertrywuutr' );
+ $this->assertInstanceOf( Site::class, $site );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+ $this->assertTrue( is_int( $site->getInternalId() ) );
+ $this->assertTrue( $site->getInternalId() >= 0 );
+
+ $site = $store->getSite( 'sdfhxujgkfpth' );
+ $this->assertInstanceOf( Site::class, $site );
+ $this->assertEquals( 'nl', $site->getLanguageCode() );
+ $this->assertTrue( is_int( $site->getInternalId() ) );
+ $this->assertTrue( $site->getInternalId() >= 0 );
+ }
+
+ /**
+ * @covers DBSiteStore::reset
+ */
+ public function testReset() {
+ $store1 = $this->newDBSiteStore();
+ $store2 = $this->newDBSiteStore();
+
+ // initialize internal cache
+ $this->assertGreaterThan( 0, $store1->getSites()->count() );
+ $this->assertGreaterThan( 0, $store2->getSites()->count() );
+
+ // Clear actual data. Will purge the external cache and reset the internal
+ // cache in $store1, but not the internal cache in store2.
+ $this->assertTrue( $store1->clear() );
+
+ // sanity check: $store2 should have a stale cache now
+ $this->assertNotNull( $store2->getSite( 'enwiki' ) );
+
+ // purge cache
+ $store2->reset();
+
+ // ...now the internal cache of $store2 should be updated and thus empty.
+ $site = $store2->getSite( 'enwiki' );
+ $this->assertNull( $site );
+ }
+
+ /**
+ * @covers DBSiteStore::clear
+ */
+ public function testClear() {
+ $store = $this->newDBSiteStore();
+ $this->assertTrue( $store->clear() );
+
+ $site = $store->getSite( 'enwiki' );
+ $this->assertNull( $site );
+
+ $sites = $store->getSites();
+ $this->assertEquals( 0, $sites->count() );
+ }
+
+ /**
+ * @covers DBSiteStore::getSites
+ */
+ public function testGetSitesDefaultOrder() {
+ $store = $this->newDBSiteStore();
+ $siteB = new Site();
+ $siteB->setGlobalId( 'B' );
+ $siteA = new Site();
+ $siteA->setGlobalId( 'A' );
+ $store->saveSites( [ $siteB, $siteA ] );
+
+ $sites = $store->getSites();
+ $siteIdentifiers = [];
+ /** @var Site $site */
+ foreach ( $sites as $site ) {
+ $siteIdentifiers[] = $site->getGlobalId();
+ }
+ $this->assertSame( [ 'A', 'B' ], $siteIdentifiers );
+
+ // Note: SiteList::getGlobalIdentifiers uses an other internal state. Iteration must be
+ // tested separately.
+ $this->assertSame( [ 'A', 'B' ], $sites->getGlobalIdentifiers() );
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/FileBasedSiteLookupTest.php b/www/wiki/tests/phpunit/includes/site/FileBasedSiteLookupTest.php
new file mode 100644
index 00000000..69e0e389
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/FileBasedSiteLookupTest.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * 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
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @covers FileBasedSiteLookup
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class FileBasedSiteLookupTest extends PHPUnit\Framework\TestCase {
+
+ use MediaWikiCoversValidator;
+
+ protected function setUp() {
+ $this->cacheFile = $this->getCacheFile();
+ }
+
+ protected function tearDown() {
+ unlink( $this->cacheFile );
+ }
+
+ public function testGetSites() {
+ $sites = $this->getSites();
+ $cacheBuilder = $this->newSitesCacheFileBuilder( $sites );
+ $cacheBuilder->build();
+
+ $cache = new FileBasedSiteLookup( $this->cacheFile );
+ $this->assertEquals( $sites, $cache->getSites() );
+ }
+
+ public function testGetSite() {
+ $sites = $this->getSites();
+ $cacheBuilder = $this->newSitesCacheFileBuilder( $sites );
+ $cacheBuilder->build();
+
+ $cache = new FileBasedSiteLookup( $this->cacheFile );
+
+ $this->assertEquals( $sites->getSite( 'enwiktionary' ), $cache->getSite( 'enwiktionary' ) );
+ }
+
+ private function newSitesCacheFileBuilder( SiteList $sites ) {
+ return new SitesCacheFileBuilder(
+ $this->getSiteLookup( $sites ),
+ $this->cacheFile
+ );
+ }
+
+ private function getSiteLookup( SiteList $sites ) {
+ $siteLookup = $this->getMockBuilder( SiteLookup::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $siteLookup->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( $sites ) );
+
+ return $siteLookup;
+ }
+
+ private function getSites() {
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'foobar' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'enwiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'enwiktionary' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ return new SiteList( $sites );
+ }
+
+ private function getCacheFile() {
+ return tempnam( sys_get_temp_dir(), 'mw-test-sitelist' );
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/site/HashSiteStoreTest.php b/www/wiki/tests/phpunit/includes/site/HashSiteStoreTest.php
new file mode 100644
index 00000000..6269fd39
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/HashSiteStoreTest.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * 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
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class HashSiteStoreTest extends MediaWikiTestCase {
+
+ /**
+ * @covers HashSiteStore::getSites
+ */
+ public function testGetSites() {
+ $expectedSites = [];
+
+ foreach ( TestSites::getSites() as $testSite ) {
+ $siteId = $testSite->getGlobalId();
+ $expectedSites[$siteId] = $testSite;
+ }
+
+ $siteStore = new HashSiteStore( $expectedSites );
+
+ $this->assertEquals( new SiteList( $expectedSites ), $siteStore->getSites() );
+ }
+
+ /**
+ * @covers HashSiteStore::saveSite
+ * @covers HashSiteStore::getSite
+ */
+ public function testSaveSite() {
+ $store = new HashSiteStore();
+
+ $site = new Site();
+ $site->setGlobalId( 'dewiki' );
+
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+
+ $store->saveSite( $site );
+
+ $this->assertCount( 1, $store->getSites(), 'Store has 1 sites' );
+ $this->assertEquals( $site, $store->getSite( 'dewiki' ), 'Store has dewiki' );
+ }
+
+ /**
+ * @covers HashSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new HashSiteStore();
+
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'enwiki' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'eswiki' );
+ $site->setLanguageCode( 'es' );
+ $sites[] = $site;
+
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+
+ $store->saveSites( $sites );
+
+ $this->assertCount( 2, $store->getSites(), 'Store has 2 sites' );
+ $this->assertTrue( $store->getSites()->hasSite( 'enwiki' ), 'Store has enwiki' );
+ $this->assertTrue( $store->getSites()->hasSite( 'eswiki' ), 'Store has eswiki' );
+ }
+
+ /**
+ * @covers HashSiteStore::clear
+ */
+ public function testClear() {
+ $store = new HashSiteStore();
+
+ $site = new Site();
+ $site->setGlobalId( 'arwiki' );
+ $store->saveSite( $site );
+
+ $this->assertCount( 1, $store->getSites(), '1 site in store' );
+
+ $store->clear();
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php b/www/wiki/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php
new file mode 100644
index 00000000..2ac27146
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php
@@ -0,0 +1,117 @@
+<?php
+
+use MediaWiki\Site\MediaWikiPageNameNormalizer;
+
+/**
+ * @covers MediaWiki\Site\MediaWikiPageNameNormalizer
+ *
+ * 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
+ *
+ * @since 1.27
+ *
+ * @group Site
+ * @group medium
+ *
+ * @author Marius Hoch
+ */
+class MediaWikiPageNameNormalizerTest extends PHPUnit\Framework\TestCase {
+
+ use MediaWikiCoversValidator;
+
+ /**
+ * @dataProvider normalizePageTitleProvider
+ */
+ public function testNormalizePageTitle( $expected, $pageName, $getResponse ) {
+ MediaWikiPageNameNormalizerTestMockHttp::$response = $getResponse;
+
+ $normalizer = new MediaWikiPageNameNormalizer(
+ new MediaWikiPageNameNormalizerTestMockHttp()
+ );
+
+ $this->assertSame(
+ $expected,
+ $normalizer->normalizePageName( $pageName, 'https://www.wikidata.org/w/api.php' )
+ );
+ }
+
+ public function normalizePageTitleProvider() {
+ // Response are taken from wikidata and kkwiki using the following API request
+ // api.php?action=query&prop=info&redirects=1&converttitles=1&format=json&titles=…
+ return [
+ 'universe (Q1)' => [
+ 'Q1',
+ 'Q1',
+ '{"batchcomplete":"","query":{"pages":{"129":{"pageid":129,"ns":0,'
+ . '"title":"Q1","contentmodel":"wikibase-item","pagelanguage":"en",'
+ . '"pagelanguagehtmlcode":"en","pagelanguagedir":"ltr",'
+ . '"touched":"2016-06-23T05:11:21Z","lastrevid":350004448,"length":58001}}}}'
+ ],
+ 'Q404 redirects to Q395' => [
+ 'Q395',
+ 'Q404',
+ '{"batchcomplete":"","query":{"redirects":[{"from":"Q404","to":"Q395"}],"pages"'
+ . ':{"601":{"pageid":601,"ns":0,"title":"Q395","contentmodel":"wikibase-item",'
+ . '"pagelanguage":"en","pagelanguagehtmlcode":"en","pagelanguagedir":"ltr",'
+ . '"touched":"2016-06-23T08:00:20Z","lastrevid":350021914,"length":60108}}}}'
+ ],
+ 'D converted to Д (Latin to Cyrillic) (taken from kkwiki)' => [
+ 'Д',
+ 'D',
+ '{"batchcomplete":"","query":{"converted":[{"from":"D","to":"\u0414"}],'
+ . '"pages":{"510541":{"pageid":510541,"ns":0,"title":"\u0414",'
+ . '"contentmodel":"wikitext","pagelanguage":"kk","pagelanguagehtmlcode":"kk",'
+ . '"pagelanguagedir":"ltr","touched":"2015-11-22T09:16:18Z",'
+ . '"lastrevid":2373618,"length":3501}}}}'
+ ],
+ 'there is no Q0' => [
+ false,
+ 'Q0',
+ '{"batchcomplete":"","query":{"pages":{"-1":{"ns":0,"title":"Q0",'
+ . '"missing":"","contentmodel":"wikibase-item","pagelanguage":"en",'
+ . '"pagelanguagehtmlcode":"en","pagelanguagedir":"ltr"}}}}'
+ ],
+ 'invalid title' => [
+ false,
+ '{{',
+ '{"batchcomplete":"","query":{"pages":{"-1":{"title":"{{",'
+ . '"invalidreason":"The requested page title contains invalid '
+ . 'characters: \"{\".","invalid":""}}}}'
+ ],
+ 'error on get' => [ false, 'ABC', false ]
+ ];
+ }
+
+}
+
+/**
+ * @private
+ * @see Http
+ */
+class MediaWikiPageNameNormalizerTestMockHttp extends Http {
+
+ /**
+ * @var mixed
+ */
+ public static $response;
+
+ public static function get( $url, $options = [], $caller = __METHOD__ ) {
+ PHPUnit_Framework_Assert::assertInternalType( 'string', $url );
+ PHPUnit_Framework_Assert::assertInternalType( 'array', $options );
+ PHPUnit_Framework_Assert::assertInternalType( 'string', $caller );
+
+ return self::$response;
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/MediaWikiSiteTest.php b/www/wiki/tests/phpunit/includes/site/MediaWikiSiteTest.php
new file mode 100644
index 00000000..b3679799
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/MediaWikiSiteTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * Tests for the MediaWikiSite class.
+ *
+ * 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
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class MediaWikiSiteTest extends SiteTest {
+
+ public function testNormalizePageTitle() {
+ $this->setMwGlobals( [
+ 'wgCapitalLinks' => true,
+ ] );
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'enwiki' );
+
+ // NOTE: this does not actually call out to the enwiki site to perform the normalization,
+ // but uses a local Title object to do so. This is hardcoded on SiteLink::normalizePageTitle
+ // for the case that MW_PHPUNIT_TEST is set.
+ $this->assertEquals( 'Foo', $site->normalizePageName( ' foo ' ) );
+ }
+
+ public function fileUrlProvider() {
+ return [
+ // url, filepath, path arg, expected
+ [ 'https://en.wikipedia.org', '/w/$1', 'api.php', 'https://en.wikipedia.org/w/api.php' ],
+ [ 'https://en.wikipedia.org', '/w/', 'api.php', 'https://en.wikipedia.org/w/' ],
+ [
+ 'https://en.wikipedia.org',
+ '/foo/page.php?name=$1',
+ 'api.php',
+ 'https://en.wikipedia.org/foo/page.php?name=api.php'
+ ],
+ [
+ 'https://en.wikipedia.org',
+ '/w/$1',
+ '',
+ 'https://en.wikipedia.org/w/'
+ ],
+ [
+ 'https://en.wikipedia.org',
+ '/w/$1',
+ 'foo/bar/api.php',
+ 'https://en.wikipedia.org/w/foo/bar/api.php'
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider fileUrlProvider
+ * @covers MediaWikiSite::getFileUrl
+ */
+ public function testGetFileUrl( $url, $filePath, $pathArgument, $expected ) {
+ $site = new MediaWikiSite();
+ $site->setFilePath( $url . $filePath );
+
+ $this->assertEquals( $expected, $site->getFileUrl( $pathArgument ) );
+ }
+
+ public static function provideGetPageUrl() {
+ return [
+ // path, page, expected substring
+ [ 'http://acme.test/wiki/$1', 'Berlin', '/wiki/Berlin' ],
+ [ 'http://acme.test/wiki/', 'Berlin', '/wiki/' ],
+ [ 'http://acme.test/w/index.php?title=$1', 'Berlin', '/w/index.php?title=Berlin' ],
+ [ 'http://acme.test/wiki/$1', '', '/wiki/' ],
+ [ 'http://acme.test/wiki/$1', 'Berlin/sub page', '/wiki/Berlin/sub_page' ],
+ [ 'http://acme.test/wiki/$1', 'Cork (city) ', '/Cork_(city)' ],
+ [ 'http://acme.test/wiki/$1', 'M&M', '/wiki/M%26M' ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideGetPageUrl
+ * @covers MediaWikiSite::getPageUrl
+ */
+ public function testGetPageUrl( $path, $page, $expected ) {
+ $site = new MediaWikiSite();
+ $site->setLinkPath( $path );
+
+ $this->assertContains( $path, $site->getPageUrl() );
+ $this->assertContains( $expected, $site->getPageUrl( $page ) );
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/SiteExporterTest.php b/www/wiki/tests/phpunit/includes/site/SiteExporterTest.php
new file mode 100644
index 00000000..db900da9
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/SiteExporterTest.php
@@ -0,0 +1,150 @@
+<?php
+
+/**
+ * Tests for the SiteExporter class.
+ *
+ * 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 Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @covers SiteExporter
+ *
+ * @author Daniel Kinzler
+ */
+class SiteExporterTest extends PHPUnit\Framework\TestCase {
+
+ use MediaWikiCoversValidator;
+ use PHPUnit4And6Compat;
+
+ public function testConstructor_InvalidArgument() {
+ $this->setExpectedException( InvalidArgumentException::class );
+
+ new SiteExporter( 'Foo' );
+ }
+
+ public function testExportSites() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $tmp = tmpfile();
+ $exporter = new SiteExporter( $tmp );
+
+ $exporter->exportSites( [ $foo, $acme ] );
+
+ fseek( $tmp, 0 );
+ $xml = fread( $tmp, 16 * 1024 );
+
+ $this->assertContains( '<sites ', $xml );
+ $this->assertContains( '<site>', $xml );
+ $this->assertContains( '<globalid>Foo</globalid>', $xml );
+ $this->assertContains( '</site>', $xml );
+ $this->assertContains( '<globalid>acme.com</globalid>', $xml );
+ $this->assertContains( '<group>Test</group>', $xml );
+ $this->assertContains( '<localid type="interwiki">acme</localid>', $xml );
+ $this->assertContains( '<path type="link">http://acme.com/</path>', $xml );
+ $this->assertContains( '</sites>', $xml );
+
+ // NOTE: HHVM (at least on wmf Jenkins) doesn't like file URLs.
+ $xsdFile = __DIR__ . '/../../../../docs/sitelist-1.0.xsd';
+ $xsdData = file_get_contents( $xsdFile );
+
+ $document = new DOMDocument();
+ $document->loadXML( $xml, LIBXML_NONET );
+ $document->schemaValidateSource( $xsdData );
+ }
+
+ private function newSiteStore( SiteList $sites ) {
+ $store = $this->getMockBuilder( SiteStore::class )->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'saveSites' )
+ ->will( $this->returnCallback( function ( $moreSites ) use ( $sites ) {
+ foreach ( $moreSites as $site ) {
+ $sites->setSite( $site );
+ }
+ } ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( new SiteList() ) );
+
+ return $store;
+ }
+
+ public function provideRoundTrip() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $dewiki = Site::newForType( Site::TYPE_MEDIAWIKI );
+ $dewiki->setGlobalId( 'dewiki' );
+ $dewiki->setGroup( 'wikipedia' );
+ $dewiki->setForward( true );
+ $dewiki->addLocalId( Site::ID_INTERWIKI, 'wikipedia' );
+ $dewiki->addLocalId( Site::ID_EQUIVALENT, 'de' );
+ $dewiki->setPath( Site::PATH_LINK, 'http://de.wikipedia.org/w/' );
+ $dewiki->setPath( MediaWikiSite::PATH_PAGE, 'http://de.wikipedia.org/wiki/' );
+ $dewiki->setSource( 'meta.wikimedia.org' );
+
+ return [
+ 'empty' => [
+ new SiteList()
+ ],
+
+ 'some' => [
+ new SiteList( [ $foo, $acme, $dewiki ] ),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideRoundTrip()
+ */
+ public function testRoundTrip( SiteList $sites ) {
+ $tmp = tmpfile();
+ $exporter = new SiteExporter( $tmp );
+
+ $exporter->exportSites( $sites );
+
+ fseek( $tmp, 0 );
+ $xml = fread( $tmp, 16 * 1024 );
+
+ $actualSites = new SiteList();
+ $store = $this->newSiteStore( $actualSites );
+
+ $importer = new SiteImporter( $store );
+ $importer->importFromXML( $xml );
+
+ $this->assertEquals( $sites, $actualSites );
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/site/SiteImporterTest.php b/www/wiki/tests/phpunit/includes/site/SiteImporterTest.php
new file mode 100644
index 00000000..bd95a501
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/SiteImporterTest.php
@@ -0,0 +1,202 @@
+<?php
+
+/**
+ * Tests for the SiteImporter class.
+ *
+ * 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 Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @covers SiteImporter
+ *
+ * @author Daniel Kinzler
+ */
+class SiteImporterTest extends PHPUnit\Framework\TestCase {
+
+ use MediaWikiCoversValidator;
+ use PHPUnit4And6Compat;
+
+ private function newSiteImporter( array $expectedSites, $errorCount ) {
+ $store = $this->getMockBuilder( SiteStore::class )->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'saveSites' )
+ ->will( $this->returnCallback( function ( $sites ) use ( $expectedSites ) {
+ $this->assertSitesEqual( $expectedSites, $sites );
+ } ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( new SiteList() ) );
+
+ $errorHandler = $this->getMockBuilder( Psr\Log\LoggerInterface::class )->getMock();
+ $errorHandler->expects( $this->exactly( $errorCount ) )
+ ->method( 'error' );
+
+ $importer = new SiteImporter( $store );
+ $importer->setExceptionCallback( [ $errorHandler, 'error' ] );
+
+ return $importer;
+ }
+
+ public function assertSitesEqual( $expected, $actual, $message = '' ) {
+ $this->assertEquals(
+ $this->getSerializedSiteList( $expected ),
+ $this->getSerializedSiteList( $actual ),
+ $message
+ );
+ }
+
+ public function provideImportFromXML() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $dewiki = Site::newForType( Site::TYPE_MEDIAWIKI );
+ $dewiki->setGlobalId( 'dewiki' );
+ $dewiki->setGroup( 'wikipedia' );
+ $dewiki->setForward( true );
+ $dewiki->addLocalId( Site::ID_INTERWIKI, 'wikipedia' );
+ $dewiki->addLocalId( Site::ID_EQUIVALENT, 'de' );
+ $dewiki->setPath( Site::PATH_LINK, 'http://de.wikipedia.org/w/' );
+ $dewiki->setPath( MediaWikiSite::PATH_PAGE, 'http://de.wikipedia.org/wiki/' );
+ $dewiki->setSource( 'meta.wikimedia.org' );
+
+ return [
+ 'empty' => [
+ '<sites></sites>',
+ [],
+ ],
+ 'no sites' => [
+ '<sites><Foo><globalid>Foo</globalid></Foo><Bar><quux>Bla</quux></Bar></sites>',
+ [],
+ ],
+ 'minimal' => [
+ '<sites>' .
+ '<site><globalid>Foo</globalid></site>' .
+ '</sites>',
+ [ $foo ],
+ ],
+ 'full' => [
+ '<sites>' .
+ '<site><globalid>Foo</globalid></site>' .
+ '<site>' .
+ '<globalid>acme.com</globalid>' .
+ '<localid type="interwiki">acme</localid>' .
+ '<group>Test</group>' .
+ '<path type="link">http://acme.com/</path>' .
+ '</site>' .
+ '<site type="mediawiki">' .
+ '<source>meta.wikimedia.org</source>' .
+ '<globalid>dewiki</globalid>' .
+ '<localid type="interwiki">wikipedia</localid>' .
+ '<localid type="equivalent">de</localid>' .
+ '<group>wikipedia</group>' .
+ '<forward/>' .
+ '<path type="link">http://de.wikipedia.org/w/</path>' .
+ '<path type="page_path">http://de.wikipedia.org/wiki/</path>' .
+ '</site>' .
+ '</sites>',
+ [ $foo, $acme, $dewiki ],
+ ],
+ 'skip' => [
+ '<sites>' .
+ '<site><globalid>Foo</globalid></site>' .
+ '<site><barf>Foo</barf></site>' .
+ '<site>' .
+ '<globalid>acme.com</globalid>' .
+ '<localid type="interwiki">acme</localid>' .
+ '<silly>boop!</silly>' .
+ '<group>Test</group>' .
+ '<path type="link">http://acme.com/</path>' .
+ '</site>' .
+ '</sites>',
+ [ $foo, $acme ],
+ 1
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideImportFromXML
+ */
+ public function testImportFromXML( $xml, array $expectedSites, $errorCount = 0 ) {
+ $importer = $this->newSiteImporter( $expectedSites, $errorCount );
+ $importer->importFromXML( $xml );
+ }
+
+ public function testImportFromXML_malformed() {
+ $this->setExpectedException( Exception::class );
+
+ $store = $this->getMockBuilder( SiteStore::class )->getMock();
+ $importer = new SiteImporter( $store );
+ $importer->importFromXML( 'THIS IS NOT XML' );
+ }
+
+ public function testImportFromFile() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $dewiki = Site::newForType( Site::TYPE_MEDIAWIKI );
+ $dewiki->setGlobalId( 'dewiki' );
+ $dewiki->setGroup( 'wikipedia' );
+ $dewiki->setForward( true );
+ $dewiki->addLocalId( Site::ID_INTERWIKI, 'wikipedia' );
+ $dewiki->addLocalId( Site::ID_EQUIVALENT, 'de' );
+ $dewiki->setPath( Site::PATH_LINK, 'http://de.wikipedia.org/w/' );
+ $dewiki->setPath( MediaWikiSite::PATH_PAGE, 'http://de.wikipedia.org/wiki/' );
+ $dewiki->setSource( 'meta.wikimedia.org' );
+
+ $importer = $this->newSiteImporter( [ $foo, $acme, $dewiki ], 0 );
+
+ $file = __DIR__ . '/SiteImporterTest.xml';
+ $importer->importFromFile( $file );
+ }
+
+ /**
+ * @param Site[] $sites
+ *
+ * @return array[]
+ */
+ private function getSerializedSiteList( $sites ) {
+ $serialized = [];
+
+ foreach ( $sites as $site ) {
+ $key = $site->getGlobalId();
+ $data = unserialize( $site->serialize() );
+
+ $serialized[$key] = $data;
+ }
+
+ return $serialized;
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/SiteImporterTest.xml b/www/wiki/tests/phpunit/includes/site/SiteImporterTest.xml
new file mode 100644
index 00000000..720b1faf
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/SiteImporterTest.xml
@@ -0,0 +1,19 @@
+<sites version="1.0" xmlns="http://www.mediawiki.org/xml/sitelist-1.0/">
+ <site><globalid>Foo</globalid></site>
+ <site>
+ <globalid>acme.com</globalid>
+ <localid type="interwiki">acme</localid>
+ <group>Test</group>
+ <path type="link">http://acme.com/</path>
+ </site>
+ <site type="mediawiki">
+ <source>meta.wikimedia.org</source>
+ <globalid>dewiki</globalid>
+ <localid type="interwiki">wikipedia</localid>
+ <localid type="equivalent">de</localid>
+ <group>wikipedia</group>
+ <forward/>
+ <path type="link">http://de.wikipedia.org/w/</path>
+ <path type="page_path">http://de.wikipedia.org/wiki/</path>
+ </site>
+</sites>
diff --git a/www/wiki/tests/phpunit/includes/site/SiteListTest.php b/www/wiki/tests/phpunit/includes/site/SiteListTest.php
new file mode 100644
index 00000000..a4a171c9
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/SiteListTest.php
@@ -0,0 +1,239 @@
+<?php
+
+/**
+ * Tests for the SiteList class.
+ *
+ * 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
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SiteListTest extends MediaWikiTestCase {
+
+ /**
+ * Returns instances of SiteList implementing objects.
+ * @return array
+ */
+ public function siteListProvider() {
+ $sitesArrays = $this->siteArrayProvider();
+
+ $listInstances = [];
+
+ foreach ( $sitesArrays as $sitesArray ) {
+ $listInstances[] = new SiteList( $sitesArray[0] );
+ }
+
+ return $this->arrayWrap( $listInstances );
+ }
+
+ /**
+ * Returns arrays with instances of Site implementing objects.
+ * @return array
+ */
+ public function siteArrayProvider() {
+ $sites = TestSites::getSites();
+
+ $siteArrays = [];
+
+ $siteArrays[] = $sites;
+
+ $siteArrays[] = [ array_shift( $sites ) ];
+
+ $siteArrays[] = [ array_shift( $sites ), array_shift( $sites ) ];
+
+ return $this->arrayWrap( $siteArrays );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::isEmpty
+ */
+ public function testIsEmpty( SiteList $sites ) {
+ $this->assertEquals( count( $sites ) === 0, $sites->isEmpty() );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::getSite
+ */
+ public function testGetSiteByGlobalId( SiteList $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertEquals( $site, $sites->getSite( $site->getGlobalId() ) );
+ }
+
+ $this->assertTrue( true );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::getSiteByInternalId
+ */
+ public function testGetSiteByInternalId( $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ if ( is_int( $site->getInternalId() ) ) {
+ $this->assertEquals( $site, $sites->getSiteByInternalId( $site->getInternalId() ) );
+ }
+ }
+
+ $this->assertTrue( true );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::getSiteByNavigationId
+ */
+ public function testGetSiteByNavigationId( $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $ids = $site->getNavigationIds();
+ foreach ( $ids as $navId ) {
+ $this->assertEquals( $site, $sites->getSiteByNavigationId( $navId ) );
+ }
+ }
+
+ $this->assertTrue( true );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::hasSite
+ */
+ public function testHasGlobalId( $sites ) {
+ $this->assertFalse( $sites->hasSite( 'non-existing-global-id' ) );
+ $this->assertFalse( $sites->hasInternalId( 720101010 ) );
+
+ if ( !$sites->isEmpty() ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::hasInternalId
+ */
+ public function testHasInternallId( $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ if ( is_int( $site->getInternalId() ) ) {
+ $this->assertTrue( $site, $sites->hasInternalId( $site->getInternalId() ) );
+ }
+ }
+
+ $this->assertFalse( $sites->hasInternalId( -1 ) );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::hasNavigationId
+ */
+ public function testHasNavigationId( $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $ids = $site->getNavigationIds();
+ foreach ( $ids as $navId ) {
+ $this->assertTrue( $sites->hasNavigationId( $navId ) );
+ }
+ }
+
+ $this->assertFalse( $sites->hasNavigationId( 'non-existing-navigation-id' ) );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ * @covers SiteList::getGlobalIdentifiers
+ */
+ public function testGetGlobalIdentifiers( SiteList $sites ) {
+ $identifiers = $sites->getGlobalIdentifiers();
+
+ $this->assertTrue( is_array( $identifiers ) );
+
+ $expected = [];
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $expected[] = $site->getGlobalId();
+ }
+
+ $this->assertArrayEquals( $expected, $identifiers );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ *
+ * @since 1.21
+ *
+ * @param SiteList $list
+ * @covers SiteList::getSerializationData
+ * @covers SiteList::unserialize
+ */
+ public function testSerialization( SiteList $list ) {
+ $serialization = serialize( $list );
+ /**
+ * @var SiteList $copy
+ */
+ $copy = unserialize( $serialization );
+
+ $this->assertArrayEquals( $list->getGlobalIdentifiers(), $copy->getGlobalIdentifiers() );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $list as $site ) {
+ $this->assertTrue( $copy->hasInternalId( $site->getInternalId() ) );
+
+ foreach ( $site->getNavigationIds() as $navId ) {
+ $this->assertTrue(
+ $copy->hasNavigationId( $navId ),
+ 'unserialized data expects nav id ' . $navId . ' for site ' . $site->getGlobalId()
+ );
+ }
+ }
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/SiteTest.php b/www/wiki/tests/phpunit/includes/site/SiteTest.php
new file mode 100644
index 00000000..ac5f956e
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/SiteTest.php
@@ -0,0 +1,295 @@
+<?php
+
+/**
+ * Tests for the Site class.
+ *
+ * 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
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SiteTest extends MediaWikiTestCase {
+
+ public function instanceProvider() {
+ return $this->arrayWrap( TestSites::getSites() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getInterwikiIds
+ */
+ public function testGetInterwikiIds( Site $site ) {
+ $this->assertInternalType( 'array', $site->getInterwikiIds() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getNavigationIds
+ */
+ public function testGetNavigationIds( Site $site ) {
+ $this->assertInternalType( 'array', $site->getNavigationIds() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::addNavigationId
+ */
+ public function testAddNavigationId( Site $site ) {
+ $site->addNavigationId( 'foobar' );
+ $this->assertTrue( in_array( 'foobar', $site->getNavigationIds(), true ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::addInterwikiId
+ */
+ public function testAddInterwikiId( Site $site ) {
+ $site->addInterwikiId( 'foobar' );
+ $this->assertTrue( in_array( 'foobar', $site->getInterwikiIds(), true ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getLanguageCode
+ */
+ public function testGetLanguageCode( Site $site ) {
+ $this->assertTypeOrValue( 'string', $site->getLanguageCode(), null );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::setLanguageCode
+ */
+ public function testSetLanguageCode( Site $site ) {
+ $site->setLanguageCode( 'en' );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::normalizePageName
+ */
+ public function testNormalizePageName( Site $site ) {
+ $this->assertInternalType( 'string', $site->normalizePageName( 'Foobar' ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getGlobalId
+ */
+ public function testGetGlobalId( Site $site ) {
+ $this->assertTypeOrValue( 'string', $site->getGlobalId(), null );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::setGlobalId
+ */
+ public function testSetGlobalId( Site $site ) {
+ $site->setGlobalId( 'foobar' );
+ $this->assertEquals( 'foobar', $site->getGlobalId() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getType
+ */
+ public function testGetType( Site $site ) {
+ $this->assertInternalType( 'string', $site->getType() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getPath
+ */
+ public function testGetPath( Site $site ) {
+ $this->assertTypeOrValue( 'string', $site->getPath( 'page_path' ), null );
+ $this->assertTypeOrValue( 'string', $site->getPath( 'file_path' ), null );
+ $this->assertTypeOrValue( 'string', $site->getPath( 'foobar' ), null );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::getAllPaths
+ */
+ public function testGetAllPaths( Site $site ) {
+ $this->assertInternalType( 'array', $site->getAllPaths() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::setPath
+ * @covers Site::removePath
+ */
+ public function testSetAndRemovePath( Site $site ) {
+ $count = count( $site->getAllPaths() );
+
+ $site->setPath( 'spam', 'http://www.wikidata.org/$1' );
+ $site->setPath( 'spam', 'http://www.wikidata.org/foo/$1' );
+ $site->setPath( 'foobar', 'http://www.wikidata.org/bar/$1' );
+
+ $this->assertEquals( $count + 2, count( $site->getAllPaths() ) );
+
+ $this->assertInternalType( 'string', $site->getPath( 'foobar' ) );
+ $this->assertEquals( 'http://www.wikidata.org/foo/$1', $site->getPath( 'spam' ) );
+
+ $site->removePath( 'spam' );
+ $site->removePath( 'foobar' );
+
+ $this->assertEquals( $count, count( $site->getAllPaths() ) );
+
+ $this->assertNull( $site->getPath( 'foobar' ) );
+ $this->assertNull( $site->getPath( 'spam' ) );
+ }
+
+ /**
+ * @covers Site::setLinkPath
+ */
+ public function testSetLinkPath() {
+ $site = new Site();
+ $path = "TestPath/$1";
+
+ $site->setLinkPath( $path );
+ $this->assertEquals( $path, $site->getLinkPath() );
+ }
+
+ /**
+ * @covers Site::getLinkPathType
+ */
+ public function testGetLinkPathType() {
+ $site = new Site();
+
+ $path = 'TestPath/$1';
+ $site->setLinkPath( $path );
+ $this->assertEquals( $path, $site->getPath( $site->getLinkPathType() ) );
+
+ $path = 'AnotherPath/$1';
+ $site->setPath( $site->getLinkPathType(), $path );
+ $this->assertEquals( $path, $site->getLinkPath() );
+ }
+
+ /**
+ * @covers Site::setPath
+ */
+ public function testSetPath() {
+ $site = new Site();
+
+ $path = 'TestPath/$1';
+ $site->setPath( 'foo', $path );
+
+ $this->assertEquals( $path, $site->getPath( 'foo' ) );
+ }
+
+ /**
+ * @covers Site::setPath
+ * @covers Site::getProtocol
+ */
+ public function testProtocolRelativePath() {
+ $site = new Site();
+
+ $type = $site->getLinkPathType();
+ $path = '//acme.com/'; // protocol-relative URL
+ $site->setPath( $type, $path );
+
+ $this->assertEquals( '', $site->getProtocol() );
+ }
+
+ public static function provideGetPageUrl() {
+ // NOTE: the assumption that the URL is built by replacing $1
+ // with the urlencoded version of $page
+ // is true for Site but not guaranteed for subclasses.
+ // Subclasses need to override this provider appropriately.
+
+ return [
+ [ # 0
+ 'http://acme.test/TestPath/$1',
+ 'Foo',
+ '/TestPath/Foo',
+ ],
+ [ # 1
+ 'http://acme.test/TestScript?x=$1&y=bla',
+ 'Foo',
+ 'TestScript?x=Foo&y=bla',
+ ],
+ [ # 2
+ 'http://acme.test/TestPath/$1',
+ 'foo & bar/xyzzy (quux-shmoox?)',
+ '/TestPath/foo%20%26%20bar%2Fxyzzy%20%28quux-shmoox%3F%29',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideGetPageUrl
+ * @covers Site::getPageUrl
+ */
+ public function testGetPageUrl( $path, $page, $expected ) {
+ $site = new Site();
+
+ // NOTE: the assumption that getPageUrl is based on getLinkPath
+ // is true for Site but not guaranteed for subclasses.
+ // Subclasses need to override this test case appropriately.
+ $site->setLinkPath( $path );
+ $this->assertContains( $path, $site->getPageUrl() );
+
+ $this->assertContains( $expected, $site->getPageUrl( $page ) );
+ }
+
+ protected function assertTypeOrFalse( $type, $value ) {
+ if ( $value === false ) {
+ $this->assertTrue( true );
+ } else {
+ $this->assertInternalType( $type, $value );
+ }
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ * @covers Site::serialize
+ * @covers Site::unserialize
+ */
+ public function testSerialization( Site $site ) {
+ $this->assertInstanceOf( Serializable::class, $site );
+
+ $serialization = serialize( $site );
+ $newInstance = unserialize( $serialization );
+
+ $this->assertInstanceOf( Site::class, $newInstance );
+
+ $this->assertEquals( $serialization, serialize( $newInstance ) );
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php b/www/wiki/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php
new file mode 100644
index 00000000..8c84ce57
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * 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
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @covers SitesCacheFileBuilder
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class SitesCacheFileBuilderTest extends PHPUnit\Framework\TestCase {
+
+ use MediaWikiCoversValidator;
+
+ protected function setUp() {
+ $this->cacheFile = $this->getCacheFile();
+ }
+
+ protected function tearDown() {
+ unlink( $this->cacheFile );
+ }
+
+ public function testBuild() {
+ $cacheBuilder = $this->newSitesCacheFileBuilder( $this->getSites() );
+ $cacheBuilder->build();
+
+ $contents = file_get_contents( $this->cacheFile );
+ $this->assertEquals( json_encode( $this->getExpectedData() ), $contents );
+ }
+
+ private function getExpectedData() {
+ return [
+ 'sites' => [
+ 'foobar' => [
+ 'globalid' => 'foobar',
+ 'type' => 'unknown',
+ 'group' => 'none',
+ 'source' => 'local',
+ 'language' => null,
+ 'localids' => [],
+ 'config' => [],
+ 'data' => [],
+ 'forward' => false,
+ 'internalid' => null,
+ 'identifiers' => []
+ ],
+ 'enwiktionary' => [
+ 'globalid' => 'enwiktionary',
+ 'type' => 'mediawiki',
+ 'group' => 'wiktionary',
+ 'source' => 'local',
+ 'language' => 'en',
+ 'localids' => [
+ 'equivalent' => [ 'enwiktionary' ]
+ ],
+ 'config' => [],
+ 'data' => [
+ 'paths' => [
+ 'page_path' => 'https://en.wiktionary.org/wiki/$1',
+ 'file_path' => 'https://en.wiktionary.org/w/$1'
+ ]
+ ],
+ 'forward' => false,
+ 'internalid' => null,
+ 'identifiers' => [
+ [
+ 'type' => 'equivalent',
+ 'key' => 'enwiktionary'
+ ]
+ ]
+ ]
+ ]
+ ];
+ }
+
+ private function newSitesCacheFileBuilder( SiteList $sites ) {
+ return new SitesCacheFileBuilder(
+ $this->getSiteLookup( $sites ),
+ $this->cacheFile
+ );
+ }
+
+ private function getSiteLookup( SiteList $sites ) {
+ $siteLookup = $this->getMockBuilder( SiteLookup::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $siteLookup->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( $sites ) );
+
+ return $siteLookup;
+ }
+
+ private function getSites() {
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'foobar' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'enwiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'enwiktionary' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ return new SiteList( $sites );
+ }
+
+ private function getCacheFile() {
+ return tempnam( sys_get_temp_dir(), 'mw-test-sitelist' );
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/site/TestSites.php b/www/wiki/tests/phpunit/includes/site/TestSites.php
new file mode 100644
index 00000000..a66fce29
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/site/TestSites.php
@@ -0,0 +1,112 @@
+<?php
+
+/**
+ * Holds sites for testing purposes.
+ *
+ * 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
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class TestSites {
+
+ /**
+ * @since 1.21
+ *
+ * @return array
+ */
+ public static function getSites() {
+ $sites = [];
+
+ $site = new Site();
+ $site->setGlobalId( 'foobar' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'enwiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'enwiktionary' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'dewiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setLanguageCode( 'de' );
+ $site->addInterwikiId( 'dewiktionary' );
+ $site->addInterwikiId( 'wiktionaryde' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://de.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://de.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ $site = new Site();
+ $site->setGlobalId( 'spam' );
+ $site->setGroup( 'spam' );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'spam' );
+ $site->addNavigationId( 'spamz' );
+ $site->addInterwikiId( 'spamzz' );
+ $site->setLinkPath( "http://spamzz.test/testing/" );
+ $sites[] = $site;
+
+ /**
+ * Add at least one right-to-left language (current RTL languages in MediaWiki core are:
+ * aeb, ar, arc, arz, azb, bcc, bqi, ckb, dv, en_rtl, fa, glk, he, khw, kk_arab, kk_cn,
+ * ks_arab, ku_arab, lrc, mzn, pnb, ps, sd, ug_arab, ur, yi).
+ */
+ $languageCodes = [
+ 'de',
+ 'en',
+ 'fa', // right-to-left
+ 'nl',
+ 'nn',
+ 'no',
+ 'sr',
+ 'sv',
+ ];
+ foreach ( $languageCodes as $langCode ) {
+ $site = new MediaWikiSite();
+ $site->setGlobalId( $langCode . 'wiki' );
+ $site->setGroup( 'wikipedia' );
+ $site->setLanguageCode( $langCode );
+ $site->addInterwikiId( $langCode );
+ $site->addNavigationId( $langCode );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://$langCode.wikipedia.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://$langCode.wikipedia.org/w/$1" );
+ $sites[] = $site;
+ }
+
+ return $sites;
+ }
+
+ /**
+ * Inserts sites into the database for the unit tests that need them.
+ *
+ * @since 0.1
+ */
+ public static function insertIntoDb() {
+ $sitesTable = \MediaWiki\MediaWikiServices::getInstance()->getSiteStore();
+ $sitesTable->clear();
+ $sitesTable->saveSites( self::getSites() );
+ }
+}