%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/tests/unit/ |
Current File : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/tests/unit/UtilTest.php |
<?php namespace CirrusSearch; use CirrusSearch\Test\HashSearchConfig; use MediaWiki\MediaWikiServices; use MediaWikiTestCase; use Language; /** * Test Util functions. * * 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 */ class UtilTest extends MediaWikiTestCase { /** * @dataProvider recursiveSameTestCases */ public function testRecursiveSame( $same, $lhs, $rhs ) { $this->assertEquals( $same, Util::recursiveSame( $lhs, $rhs ) ); } public static function recursiveSameTestCases() { return [ [ true, [], [] ], [ false, [ true ], [] ], [ false, [ true ], [ false ] ], [ true, [ true ], [ true ] ], [ false, [ 1 ], [ 2 ] ], [ false, [ 1, 2 ], [ 2, 1 ] ], [ true, [ 1, 2, 3 ], [ 1, 2, 3 ] ], [ false, [ [ 1 ] ], [ [ 2 ] ] ], [ true, [ [ 1 ] ], [ [ 1 ] ] ], [ true, [ 'candle' => [ 'wax' => 'foo' ] ], [ 'candle' => [ 'wax' => 'foo' ] ] ], [ false, [ 'candle' => [ 'wax' => 'foo' ] ], [ 'candle' => [ 'wax' => 'bar' ] ] ], ]; } /** * @dataProvider cleanUnusedFieldsProvider */ public function testCleanUnusedFields( $data, $properties, $expect ) { $result = Util::cleanUnusedFields( $data, $properties ); $this->assertArrayEquals( $result, $expect ); } public static function cleanUnusedFieldsProvider() { return [ // sample [ // data [ 'title' => "I'm a title", 'useless' => "I'm useless", ], // properties [ 'title' => 'params-for-title' ], // expect [ 'title' => "I'm a title", ], ], // Flow data - untouched [ // data (as seen in https://gerrit.wikimedia.org/r/#/c/195889/1//COMMIT_MSG) [ 'namespace' => 1, 'namespace_text' => "Talk", 'pageid' => 2, 'title' => "Main Page", 'timestamp' => "2014-02-07T01:42:57Z", 'update_timestamp' => "2014-02-25T14:12:40Z", 'revisions' => [ [ 'id' => "rpvwvywl9po7ih77", 'text' => "topic title content", 'source_text' => "topic title content", 'moderation_state' => "", 'timestamp' => "2014-02-07T01:42:57Z", 'update_timestamp' => "2014-02-07T01:42:57Z", 'type' => "topic" ], [ 'id' => "ropuzninqgyf19ko", 'text' => "reply content", 'source_text' => "reply '''content'''", 'moderation_state' => "hide", 'timestamp' => "2014-02-25T14:12:40Z", 'update_timestamp' => "2014-02-25T14:12:40Z", 'type' => "post" ], ] ], // properties (as seen in https://gerrit.wikimedia.org/r/#/c/161251/26/includes/Search/maintenance/MappingConfigBuilder.php) [ 'namespace' => [ '...' ], 'namespace_text' => [ '...' ], 'pageid' => [ '...' ], 'title' => [ '...' ], 'timestamp' => [ '...' ], 'update_timestamp' => [ '...' ], 'revisions' => [ 'properties' => [ 'id' => [ '...' ], 'text' => [ '...' ], 'source_text' => [ '...' ], 'moderation_state' => [ '...' ], 'timestamp' => [ '...' ], 'update_timestamp' => [ '...' ], 'type' => [ '...' ], ] ], ], // expect [ 'namespace' => 1, 'namespace_text' => "Talk", 'pageid' => 2, 'title' => "Main Page", 'timestamp' => "2014-02-07T01:42:57Z", 'update_timestamp' => "2014-02-25T14:12:40Z", 'revisions' => [ [ 'id' => "rpvwvywl9po7ih77", 'text' => "topic title content", 'source_text' => "topic title content", 'moderation_state' => "", 'timestamp' => "2014-02-07T01:42:57Z", 'update_timestamp' => "2014-02-07T01:42:57Z", 'type' => "topic" ], [ 'id' => "ropuzninqgyf19ko", 'text' => "reply content", 'source_text' => "reply '''content'''", 'moderation_state' => "hide", 'timestamp' => "2014-02-25T14:12:40Z", 'update_timestamp' => "2014-02-25T14:12:40Z", 'type' => "post" ], ] ], ], // Flow data - deleted columns in config [ // data (as seen in https://gerrit.wikimedia.org/r/#/c/195889/1//COMMIT_MSG) [ 'namespace' => 1, 'namespace_text' => "Talk", 'pageid' => 2, 'title' => "Main Page", 'timestamp' => "2014-02-07T01:42:57Z", 'update_timestamp' => "2014-02-25T14:12:40Z", 'revisions' => [ [ 'id' => "rpvwvywl9po7ih77", 'text' => "topic title content", 'source_text' => "topic title content", 'moderation_state' => "", 'timestamp' => "2014-02-07T01:42:57Z", 'update_timestamp' => "2014-02-07T01:42:57Z", 'type' => "topic" ], [ 'id' => "ropuzninqgyf19ko", 'text' => "reply content", 'source_text' => "reply '''content'''", 'moderation_state' => "hide", 'timestamp' => "2014-02-25T14:12:40Z", 'update_timestamp' => "2014-02-25T14:12:40Z", 'type' => "post" ], ] ], // properties (as seen in https://gerrit.wikimedia.org/r/#/c/161251/26/includes/Search/maintenance/MappingConfigBuilder.php) [ 'namespace' => [ '...' ], 'namespace_text' => [ '...' ], 'pageid' => [ '...' ], 'title' => [ '...' ], // deleted timestamp & update_timestamp columns 'revisions' => [ 'properties' => [ 'id' => [ '...' ], 'text' => [ '...' ], 'source_text' => [ '...' ], 'moderation_state' => [ '...' ], // deleted timestamp & update_timestamp columns 'type' => [ '...' ], ] ], ], // expect [ 'namespace' => 1, 'namespace_text' => "Talk", 'pageid' => 2, 'title' => "Main Page", // deleted timestamp & update_timestamp columns 'revisions' => [ [ 'id' => "rpvwvywl9po7ih77", 'text' => "topic title content", 'source_text' => "topic title content", 'moderation_state' => "", // deleted timestamp & update_timestamp columns 'type' => "topic" ], [ 'id' => "ropuzninqgyf19ko", 'text' => "reply content", 'source_text' => "reply '''content'''", 'moderation_state' => "hide", // deleted timestamp & update_timestamp columns 'type' => "post" ], ] ], ], ]; } public function testChooseBestRedirect() { $convert = function( $x ) { $redirect = []; foreach( $x as $t ) { $redirect[] = [ 'title' => $t, 'namespace' => 0 ]; } return $redirect; }; $input = $convert( [ 'Al. Einstein', 'Albert Einstein', 'A. Einstein', 'Einstein, Albert' ] ); $this->assertEquals( 'Al. Einstein', Util::chooseBestRedirect( 'a', $input ) ); $this->assertEquals( 'Al. Einstein', Util::chooseBestRedirect( 'al', $input ) ); $this->assertEquals( 'Albert Einstein', Util::chooseBestRedirect( 'albet', $input ) ); $this->assertEquals( 'Einstein, Albert', Util::chooseBestRedirect( 'Einstein', $input ) ); $this->assertEquals( 'Einstein, Albert', Util::chooseBestRedirect( 'Ens', $input ) ); } public function teststripQuestionMarks() { // tests are input, strippingLevel, expectedOutput $tests = [ [ 'pickles', 'all', 'pickles' ], [ 'pic?les', 'all', 'pic les' ], [ 'pic?les', 'break', 'pic?les' ], [ 'pic?les', 'no', 'pic?les' ], [ 'pic?les', 'final', 'pic?les' ], [ 'pickle?', 'all', 'pickle ' ], [ 'pickle?', 'break', 'pickle' ], [ 'მწნილი?', 'no', 'მწნილი?' ], [ 'მწნილი?', 'final', 'მწნილი' ], [ '?漬物', 'all', ' 漬物' ], [ '?漬物', 'break', '?漬物' ], [ 'pic? les', 'all', 'pic les' ], [ 'pic? les', 'break', 'pic les' ], [ 'pic\?les', 'all', 'pic?les' ], [ 'pic\?les', 'break', 'pic?les' ], [ 'pic\?les', 'no', 'pic\?les' ], [ 'pic\?les', 'final', 'pic?les' ], [ 'insource:/x?/', 'all', 'insource:/x?/' ], [ 'insource:/x?/', 'break', 'insource:/x?/' ], [ 'insource:/x?/', 'no', 'insource:/x?/' ], [ 'insource:/x?/', 'final', 'insource:/x?/' ], [ '??', 'all', '??' ], [ '¿.; ?', 'all', '¿.; ?' ], ]; foreach ( $tests as $test ) { $this->assertEquals( Util::stripQuestionMarks( $test[0], $test[1] ), $test[2] ); } } /** * Produces mock message cache for injecting messages * @return MessageCache */ private function getMockCache() { $mock = $this->getMockBuilder( 'MessageCache' )->disableOriginalConstructor()->getMock(); $mock->method( 'get' )->willReturnCallback( function ( $key, $useDB, Language $lang ) { return "This is $key in {$lang->getCode()}|100%"; } ); return $mock; } /** * Set message cache instance to given object. * TODO: we wouldn't have to do this if we had some proper way to mock message cache. * @param $class * @param $var * @param $value */ private function setPrivateVar( $class, $var, $value ) { // nasty hack - reset message cache instance $mc = new \ReflectionClass( $class ); $mcInstance = $mc->getProperty( $var ); $mcInstance->setAccessible( true ); $mcInstance->setValue( $value ); } /** * Create test hash config for a wiki. * @param string $wiki * @param mixed[] $moreData additional config * @return HashSearchConfig */ private function getHashConfig( $wiki, array $moreData = array() ) { if ( !isset( $moreData['CirrusSearchBoostTemplates'] ) ) { $moreData['CirrusSearchBoostTemplates'] = []; } if ( !isset( $moreData['CirrusSearchIgnoreOnWikiBoostTemplates'] ) ) { $moreData['CirrusSearchIgnoreOnWikiBoostTemplates'] = false; } $moreData[ '_wikiID' ] = $wiki; $config = new HashSearchConfig( $moreData ); return $config; } /** * Put data for a wiki into test cache. * @param \BagOStuff $cache * @param $wiki */ private function putDataIntoCache( \BagOStuff $cache, $wiki ) { $key = $cache->makeGlobalKey( 'cirrussearch-boost-templates', $wiki ); $cache->set( $key, ["Data for $wiki" => 2] ); } /** * Create test local cache * @return \BagOStuff */ private function makeLocalCache() { $this->setMwGlobals( [ 'wgMainCacheType' => 'UtilTest', 'wgObjectCaches' => [ 'UtilTest' => [ 'class' => \HashBagOStuff::class ] ] ] ); return \ObjectCache::getLocalClusterInstance(); } /** * @covers Utils::getDefaultBoostTemplates */ public function testgetDefaultBoostTemplates() { $cache = $this->makeLocalCache(); $this->putDataIntoCache( $cache, 'ruwiki' ); $this->putDataIntoCache( $cache, 'cywiki' ); $cy = Util::getDefaultBoostTemplates( $this->getHashConfig( 'cywiki' ) ); $ru = Util::getDefaultBoostTemplates( $this->getHashConfig( 'ruwiki' ) ); $this->assertNotEquals( $cy, $ru, 'Boosts should change with language' ); // no cache means empty array $this->assertArrayEquals( [ ], Util::getDefaultBoostTemplates( $this->getHashConfig( 'hywiki' ) ) ); } /** * @covers Utils::getDefaultBoostTemplates */ public function testCustomizeBoostTemplatesByConfig() { $configValues = [ 'CirrusSearchBoostTemplates' => [ 'Featured' => 2, ], ]; $config = $this->getHashConfig( 'ruwiki', $configValues ); $ru = Util::getDefaultBoostTemplates( $config ); $this->assertArrayEquals( $configValues['CirrusSearchBoostTemplates'], $ru ); } /** * @covers Utils::getDefaultBoostTemplates */ public function testOverrideBoostTemplatesWithOnWikiConfig() { $configValues = [ 'CirrusSearchBoostTemplates' => [ 'Featured' => 2, ], ]; $config = $this->getHashConfig( 'ruwiki', $configValues ); // On wiki config should override config templates $cache = $this->makeLocalCache(); $this->putDataIntoCache( $cache, 'ruwiki' ); $ru = Util::getDefaultBoostTemplates( $config ); $this->assertNotEquals( $configValues['CirrusSearchBoostTemplates'], $ru ); } /** * @covers Utils::getDefaultBoostTemplates */ public function testOverrideBoostTemplatesWithOnCurrentWikiConfig() { $configValues = [ 'CirrusSearchBoostTemplates' => [ 'Featured' => 2, ], ]; $config = $this->getHashConfig( wfWikiID(), $configValues ); // On wiki config should override config templates $cache = $this->makeLocalCache(); $this->putDataIntoCache( $cache, wfWikiID() ); $ru = Util::getDefaultBoostTemplates( $config ); $this->assertNotEquals( $configValues['CirrusSearchBoostTemplates'], $ru ); } /** * @covers Utils::getDefaultBoostTemplates */ public function testDisableOverrideBoostTemplatesWithOnWikiConfig() { $configValues = [ 'CirrusSearchBoostTemplates' => [ 'Featured' => 2, ], // we can disable on wiki customization 'CirrusSearchIgnoreOnWikiBoostTemplates' => true, ]; $config = $this->getHashConfig( 'ruwiki', $configValues ); $cache = $this->makeLocalCache(); $this->putDataIntoCache( $cache, 'ruwiki' ); $ru = Util::getDefaultBoostTemplates( $this->getHashConfig( 'ruwiki' ) ); $this->assertArrayEquals( $configValues['CirrusSearchBoostTemplates'], $ru ); } public function testgetDefaultBoostTemplatesLocal() { global $wgContLang; $this->setPrivateVar( \MessageCache::class, 'instance', $this->getMockCache() ); $this->setPrivateVar( Util::class, 'defaultBoostTemplates', null ); $cache = $this->makeLocalCache(); $config = $this->getHashConfig( wfWikiID() ); $key = $cache->makeGlobalKey( 'cirrussearch-boost-templates', $config->getWikiId() ); // FIXME: we cannot really test the default value for $config // with Util::getDefaultBoostTemplates(). It looks like // MediaWikiServices initializes the current wiki SearchConfig // when wfWikiID() == 'wiki' and then it's cached, the test // framework seems to update the wiki name to wiki-unittest_ // making it impossible to test if we are running on the local // wiki. // resetting MediaWikiServices would be nice but it does not // seem to be trivial. $cur = Util::getDefaultBoostTemplates( $config ); reset( $cur ); $this->assertContains( ' in ' . $wgContLang->getCode(), key( $cur ) ); // Check we cached it $cached = $cache->get( $key ); $this->assertNotEmpty( $cached, 'Should cache the value' ); } public function tearDown() { // reset cache so that our mock won't pollute other tests $this->setPrivateVar( \MessageCache::class, 'instance', null ); $this->setPrivateVar( Util::class, 'defaultBoostTemplates', null ); parent::tearDown(); } }