From: daniel Date: Sat, 23 Apr 2016 19:00:18 +0000 (+0200) Subject: Introduce InterwikiTest X-Git-Tag: 1.31.0-rc.0~7165^2 X-Git-Url: http://git.cyclocoop.org/ecrire?a=commitdiff_plain;h=ff764440da623c34c37f290a1ecd9f167f68433f;p=lhc%2Fweb%2Fwiklou.git Introduce InterwikiTest This test class verifies that Interwiki currectly handles information from the database, CDB files, and plain arrays. This is intended to allow confident refactoring when implementing T113034. Bug: T113034 Change-Id: I2b68d11e3e946d81fa5f5f65a28fc399e7936c0f --- diff --git a/includes/interwiki/Interwiki.php b/includes/interwiki/Interwiki.php index 9a5a3ffba0..f68651bc1f 100644 --- a/includes/interwiki/Interwiki.php +++ b/includes/interwiki/Interwiki.php @@ -60,8 +60,8 @@ class Interwiki { $this->mURL = $url; $this->mAPI = $api; $this->mWikiID = $wikiId; - $this->mLocal = $local; - $this->mTrans = $trans; + $this->mLocal = (bool)$local; + $this->mTrans = (bool)$trans; } /** @@ -115,7 +115,16 @@ class Interwiki { } /** - * Purge the cache for an interwiki prefix + * Resets locally cached Interwiki objects. This is intended for use during testing only. + * This does not invalidate entries in the persistent cache, as invalidateCache() does. + * @since 1.27 + */ + public static function resetLocalCache() { + static::$smCache = []; + } + + /** + * Purge the cache (local and persistent) for an interwiki prefix. * @param string $prefix * @since 1.26 */ @@ -123,6 +132,7 @@ class Interwiki { $cache = ObjectCache::getMainWANInstance(); $key = wfMemcKey( 'interwiki', $prefix ); $cache->delete( $key ); + unset( static::$smCache[$prefix] ); } /** @@ -141,7 +151,7 @@ class Interwiki { // Split values list( $local, $url ) = explode( ' ', $value, 2 ); $s->mURL = $url; - $s->mLocal = (int)$local; + $s->mLocal = (bool)$local; } else { $s = false; } @@ -262,8 +272,8 @@ class Interwiki { if ( isset( $mc['iw_url'] ) ) { $iw = new Interwiki(); $iw->mURL = $mc['iw_url']; - $iw->mLocal = isset( $mc['iw_local'] ) ? $mc['iw_local'] : 0; - $iw->mTrans = isset( $mc['iw_trans'] ) ? $mc['iw_trans'] : 0; + $iw->mLocal = isset( $mc['iw_local'] ) ? (bool)$mc['iw_local'] : false; + $iw->mTrans = isset( $mc['iw_trans'] ) ? (bool)$mc['iw_trans'] : false; $iw->mAPI = isset( $mc['iw_api'] ) ? $mc['iw_api'] : ''; $iw->mWikiID = isset( $mc['iw_wikiid'] ) ? $mc['iw_wikiid'] : ''; @@ -453,7 +463,7 @@ class Interwiki { public function getName() { $msg = wfMessage( 'interwiki-name-' . $this->mPrefix )->inContentLanguage(); - return !$msg->exists() ? '' : $msg; + return !$msg->exists() ? '' : $msg->text(); } /** @@ -464,7 +474,7 @@ class Interwiki { public function getDescription() { $msg = wfMessage( 'interwiki-desc-' . $this->mPrefix )->inContentLanguage(); - return !$msg->exists() ? '' : $msg; + return !$msg->exists() ? '' : $msg->text(); } /** diff --git a/tests/phpunit/includes/interwiki/InterwikiTest.php b/tests/phpunit/includes/interwiki/InterwikiTest.php new file mode 100644 index 0000000000..411d6a3ff6 --- /dev/null +++ b/tests/phpunit/includes/interwiki/InterwikiTest.php @@ -0,0 +1,254 @@ +setContentLang( 'qqx' ); + + $this->assertSame( '(interwiki-name-xyz)', $interwiki->getName() ); + $this->assertSame( '(interwiki-desc-xyz)', $interwiki->getDescription() ); + $this->assertSame( 'http://xyz.acme.test/w/api.php', $interwiki->getAPI() ); + $this->assertSame( 'http://xyz.acme.test/wiki/$1', $interwiki->getURL() ); + $this->assertSame( 'xyzwiki', $interwiki->getWikiID() ); + $this->assertTrue( $interwiki->isLocal() ); + $this->assertFalse( $interwiki->isTranscludable() ); + } + + public function testGetUrl() { + $interwiki = new Interwiki( + 'xyz', + 'http://xyz.acme.test/wiki/$1' + ); + + $this->assertSame( 'http://xyz.acme.test/wiki/$1', $interwiki->getURL() ); + $this->assertSame( 'http://xyz.acme.test/wiki/Foo%26Bar', $interwiki->getURL( 'Foo&Bar' ) ); + } + + //// tests for static data access methods below /////////////////////////////////////////////// + + private function populateDB( $iwrows ) { + $dbw = wfGetDB( DB_MASTER ); + $dbw->delete( 'interwiki', '*', __METHOD__ ); + $dbw->insert( 'interwiki', array_values( $iwrows ), __METHOD__ ); + $this->tablesUsed[] = 'interwiki'; + } + + public function testDatabaseStorage() { + // NOTE: database setup is expensive, so we only do + // it once and run all the tests in one go. + $dewiki = [ + 'iw_prefix' => 'de', + 'iw_url' => 'http://de.wikipedia.org/wiki/', + 'iw_api' => 'http://de.wikipedia.org/w/api.php', + 'iw_wikiid' => 'dewiki', + 'iw_local' => 1, + 'iw_trans' => 0 + ]; + + $zzwiki = [ + 'iw_prefix' => 'zz', + 'iw_url' => 'http://zzwiki.org/wiki/', + 'iw_api' => 'http://zzwiki.org/w/api.php', + 'iw_wikiid' => 'zzwiki', + 'iw_local' => 0, + 'iw_trans' => 0 + ]; + + $this->populateDB( [ $dewiki, $zzwiki ] ); + + Interwiki::resetLocalCache(); + $this->setMwGlobals( 'wgInterwikiCache', false ); + + $this->assertEquals( + [ $dewiki, $zzwiki ], + Interwiki::getAllPrefixes(), + 'getAllPrefixes()' + ); + $this->assertEquals( + [ $dewiki ], + Interwiki::getAllPrefixes( true ), + 'getAllPrefixes()' + ); + $this->assertEquals( + [ $zzwiki ], + Interwiki::getAllPrefixes( false ), + 'getAllPrefixes()' + ); + + $this->assertTrue( Interwiki::isValidInterwiki( 'de' ), 'known prefix is valid' ); + $this->assertFalse( Interwiki::isValidInterwiki( 'xyz' ), 'unknown prefix is valid' ); + + $this->assertNull( Interwiki::fetch( null ), 'no prefix' ); + $this->assertFalse( Interwiki::fetch( 'xyz' ), 'unknown prefix' ); + + $interwiki = Interwiki::fetch( 'de' ); + $this->assertInstanceOf( 'Interwiki', $interwiki ); + $this->assertSame( $interwiki, Interwiki::fetch( 'de' ), 'in-process caching' ); + + $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' ); + $this->assertSame( 'http://de.wikipedia.org/w/api.php', $interwiki->getAPI(), 'getAPI' ); + $this->assertSame( 'dewiki', $interwiki->getWikiID(), 'getWikiID' ); + $this->assertSame( true, $interwiki->isLocal(), 'isLocal' ); + $this->assertSame( false, $interwiki->isTranscludable(), 'isTranscludable' ); + + Interwiki::invalidateCache( 'de' ); + $this->assertNotSame( $interwiki, Interwiki::fetch( 'de' ), 'invalidate cache' ); + } + + /** + * @param string $thisSite + * @param string[] $local + * @param string[] $global + * + * @return string[] + */ + private function populateHash( $thisSite, $local, $global ) { + $hash = []; + $hash[ '__sites:' . wfWikiID() ] = $thisSite; + + $globals = []; + $locals = []; + + foreach ( $local as $row ) { + $prefix = $row['iw_prefix']; + $data = $row['iw_local'] . ' ' . $row['iw_url']; + $locals[] = $prefix; + $hash[ "_{$thisSite}:{$prefix}" ] = $data; + } + + foreach ( $global as $row ) { + $prefix = $row['iw_prefix']; + $data = $row['iw_local'] . ' ' . $row['iw_url']; + $globals[] = $prefix; + $hash[ "__global:{$prefix}" ] = $data; + } + + $hash[ '__list:__global' ] = implode( ' ', $globals ); + $hash[ '__list:_' . $thisSite ] = implode( ' ', $locals ); + + return $hash; + } + + private function populateCDB( $thisSite, $local, $global ) { + $cdbFile = tempnam( wfTempDir(), 'MW-ClassicInterwikiLookupTest-' ) . '.cdb'; + $cdb = CdbWriter::open( $cdbFile ); + + $hash = $this->populateHash( $thisSite, $local, $global ); + + foreach ( $hash as $key => $value ) { + $cdb->set( $key, $value ); + } + + $cdb->close(); + return $cdbFile; + } + + public function testCDBStorage() { + // NOTE: CDB setup is expensive, so we only do + // it once and run all the tests in one go. + + $dewiki = [ + 'iw_prefix' => 'de', + 'iw_url' => 'http://de.wikipedia.org/wiki/', + 'iw_local' => 1 + ]; + + $zzwiki = [ + 'iw_prefix' => 'zz', + 'iw_url' => 'http://zzwiki.org/wiki/', + 'iw_local' => 0 + ]; + + $cdbFile = $this->populateCDB( + 'en', + [ $dewiki ], + [ $zzwiki ] + ); + + Interwiki::resetLocalCache(); + $this->setMwGlobals( 'wgInterwikiCache', $cdbFile ); + + $this->assertEquals( + [ $dewiki, $zzwiki ], + Interwiki::getAllPrefixes(), + 'getAllPrefixes()' + ); + + $this->assertTrue( Interwiki::isValidInterwiki( 'de' ), 'known prefix is valid' ); + $this->assertTrue( Interwiki::isValidInterwiki( 'zz' ), 'known prefix is valid' ); + + $interwiki = Interwiki::fetch( 'de' ); + $this->assertInstanceOf( 'Interwiki', $interwiki ); + + $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' ); + $this->assertSame( true, $interwiki->isLocal(), 'isLocal' ); + + $interwiki = Interwiki::fetch( 'zz' ); + $this->assertInstanceOf( 'Interwiki', $interwiki ); + + $this->assertSame( 'http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL' ); + $this->assertSame( false, $interwiki->isLocal(), 'isLocal' ); + + // cleanup temp file + unlink( $cdbFile ); + } + + public function testArrayStorage() { + $dewiki = [ + 'iw_prefix' => 'de', + 'iw_url' => 'http://de.wikipedia.org/wiki/', + 'iw_local' => 1 + ]; + + $zzwiki = [ + 'iw_prefix' => 'zz', + 'iw_url' => 'http://zzwiki.org/wiki/', + 'iw_local' => 0 + ]; + + $cdbData = $this->populateHash( + 'en', + [ $dewiki ], + [ $zzwiki ] + ); + + Interwiki::resetLocalCache(); + $this->setMwGlobals( 'wgInterwikiCache', $cdbData ); + + $this->assertEquals( + [ $dewiki, $zzwiki ], + Interwiki::getAllPrefixes(), + 'getAllPrefixes()' + ); + + $this->assertTrue( Interwiki::isValidInterwiki( 'de' ), 'known prefix is valid' ); + $this->assertTrue( Interwiki::isValidInterwiki( 'zz' ), 'known prefix is valid' ); + + $interwiki = Interwiki::fetch( 'de' ); + $this->assertInstanceOf( 'Interwiki', $interwiki ); + + $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' ); + $this->assertSame( true, $interwiki->isLocal(), 'isLocal' ); + + $interwiki = Interwiki::fetch( 'zz' ); + $this->assertInstanceOf( 'Interwiki', $interwiki ); + + $this->assertSame( 'http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL' ); + $this->assertSame( false, $interwiki->isLocal(), 'isLocal' ); + } + +}