diff options
Diffstat (limited to 'www/wiki/tests/phpunit/includes/site')
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() ); + } +} |