Daniel Kinzler has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/203809

Change subject: Isolate unit tests for wbsearchentities.
......................................................................

Isolate unit tests for wbsearchentities.

This implements DI for the SearchEntities class and migrates
the test case to use mock services.

Change-Id: Ia55f43c694470f481a26705d3216dc6a0c9de59a
---
M lib/tests/phpunit/store/MockTermIndex.php
M repo/includes/api/SearchEntities.php
M repo/tests/phpunit/includes/api/SearchEntitiesTest.php
3 files changed, 285 insertions(+), 43 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/09/203809/1

diff --git a/lib/tests/phpunit/store/MockTermIndex.php 
b/lib/tests/phpunit/store/MockTermIndex.php
index 42d386d..02826ca 100644
--- a/lib/tests/phpunit/store/MockTermIndex.php
+++ b/lib/tests/phpunit/store/MockTermIndex.php
@@ -291,21 +291,47 @@
                        if ( ( $language === null || $term->getLanguage() === 
$language )
                                && ( $entityType === null || 
$term->getEntityType() === $entityType )
                                && ( $termType === null || $term->getType() === 
$termType )
-                               && $this->termMatchesTemplates( $term, $terms )
+                               && $this->termMatchesTemplates( $term, $terms, 
$options )
                        ) {
 
                                $matchingTerms[] = $term;
                        }
                }
 
+               $limit = isset( $options['LIMIT'] ) ? $options['LIMIT'] : 0;
+
+               if ( $limit > 0 ) {
+                       $matchingTerms = array_slice( $matchingTerms, 0, $limit 
);
+               }
+
                return $matchingTerms;
        }
 
        /**
-        * @throws Exception always
+        * @param Term[] $terms
+        * @param null $entityType
+        * @param array $options
+        *
+        * @return \Wikibase\DataModel\Entity\EntityId[]
         */
        public function getMatchingIDs( array $terms, $entityType = null, array 
$options = array() ) {
-               throw new Exception( 'not implemented by mock class ' );
+               $limit = isset( $options['LIMIT'] ) ? $options['LIMIT'] : 0;
+               unset( $options['LIMIT'] );
+
+               $terms = $this->getMatchingTerms( $terms, null, $entityType, 
$options );
+
+               $ids = array();
+               foreach ( $terms as $term ) {
+                       $id = $term->getEntityId();
+                       $key = $id->getSerialization();
+                       $ids[$key] = $id;
+               }
+
+               if ( $limit > 0 ) {
+                       $ids = array_slice( $ids, 0, $limit );
+               }
+
+               return $ids;
        }
 
        /**
@@ -353,10 +379,11 @@
        /**
         * @param Term $term
         * @param Term[] $templates
+        * @param array $options
         *
         * @return bool
         */
-       private function termMatchesTemplates( Term $term, array $templates ) {
+       private function termMatchesTemplates( Term $term, array $templates, 
array $options = array() ) {
                foreach ( $templates as $template ) {
                        if ( $template->getType() !== null && 
$template->getType() != $term->getType() ) {
                                continue;
@@ -370,7 +397,7 @@
                                continue;
                        }
 
-                       if ( $template->getText() !== null && 
$template->getText() != $term->getText() ) {
+                       if ( $template->getText() !== null && 
!$this->textMatches( $template->getText(), $term->getText(), $options ) ) {
                                continue;
                        }
 
@@ -384,4 +411,17 @@
                return false;
        }
 
+       private function textMatches( $find, $text, array $options = array() ) {
+
+               if ( isset( $options[ 'caseSensitive' ] ) && !$options[ 
'caseSensitive' ] ) {
+                       $find = strtolower( $find );
+                       $text = strtolower( $text );
+               }
+
+               if ( isset( $options[ 'prefixSearch' ] ) && $options[ 
'prefixSearch' ] ) {
+                       $text = substr( $text, 0, strlen( $find ) );
+               }
+
+               return $find === $text;
+       }
 }
diff --git a/repo/includes/api/SearchEntities.php 
b/repo/includes/api/SearchEntities.php
index b774947..1dedced 100644
--- a/repo/includes/api/SearchEntities.php
+++ b/repo/includes/api/SearchEntities.php
@@ -7,9 +7,11 @@
 use Wikibase\DataModel\Entity\EntityId;
 use Wikibase\DataModel\Entity\EntityIdParser;
 use Wikibase\DataModel\Entity\EntityIdParsingException;
+use Wikibase\Lib\ContentLanguages;
 use Wikibase\Lib\Store\EntityTitleLookup;
 use Wikibase\Repo\WikibaseRepo;
 use Wikibase\Term;
+use Wikibase\TermIndex;
 
 /**
  * API module to search for Wikibase entities.
@@ -42,6 +44,21 @@
        private $idParser;
 
        /**
+        * @var TermIndex
+        */
+       private $termIndex;
+
+       /**
+        * @var ContentLanguages
+        */
+       private $termsLanguages;
+
+       /**
+        * @var string[]
+        */
+       private $entityTypes;
+
+       /**
         * @param ApiMain $mainModule
         * @param string $moduleName
         * @param string $modulePrefix
@@ -51,9 +68,37 @@
        public function __construct( ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
                parent::__construct( $mainModule, $moduleName, $modulePrefix );
 
-               //TODO: provide a mechanism to override the services
-               $this->titleLookup = 
WikibaseRepo::getDefaultInstance()->getEntityTitleLookup();
-               $this->idParser = 
WikibaseRepo::getDefaultInstance()->getEntityIdParser();
+               $repo = WikibaseRepo::getDefaultInstance();
+               $this->setServices(
+                       $repo->getStore()->getTermIndex(),
+                       $repo->getEntityTitleLookup(),
+                       $repo->getEntityIdParser(),
+                       $repo->getEntityFactory()->getEntityTypes(),
+                       $repo->getTermsLanguages()
+               );
+       }
+
+       /**
+        * Override services, for use for testing.
+        *
+        * @param TermIndex $termIndex
+        * @param EntityTitleLookup $titleLookup
+        * @param EntityIdParser $idParser
+        * @param array $entityTypes
+        * @param ContentLanguages $termLanguages
+        */
+       public function setServices(
+               TermIndex $termIndex,
+               EntityTitleLookup $titleLookup,
+               EntityIdParser $idParser,
+               array $entityTypes,
+               ContentLanguages $termLanguages
+       ) {
+               $this->termIndex = $termIndex;
+               $this->titleLookup = $titleLookup;
+               $this->idParser = $idParser;
+               $this->entityTypes = $entityTypes;
+               $this->termsLanguages = $termLanguages;
        }
 
        /**
@@ -69,17 +114,17 @@
         * @return EntityId[]
         */
        private function searchEntities( $term, $entityType, $language, $limit, 
$prefixSearch ) {
-               return 
WikibaseRepo::getDefaultInstance()->getStore()->getTermIndex()->getMatchingIDs(
+               return $this->termIndex->getMatchingIDs(
                        array(
                                new Term( array(
-                                       'termType'              => 
Term::TYPE_LABEL,
-                                       'termLanguage'  => $language,
-                                       'termText'              => $term
+                               'termType'              => Term::TYPE_LABEL,
+                               'termLanguage'  => $language,
+                               'termText'              => $term
                                ) ),
                                new Term( array(
-                                       'termType'              => 
Term::TYPE_ALIAS,
-                                       'termLanguage'  => $language,
-                                       'termText'              => $term
+                               'termType'              => Term::TYPE_ALIAS,
+                               'termLanguage'  => $language,
+                               'termText'              => $term
                                ) )
                        ),
                        $entityType,
@@ -204,7 +249,7 @@
                }
 
                // Find all the remaining terms for the given entities
-               $terms = 
WikibaseRepo::getDefaultInstance()->getStore()->getTermIndex()->getTermsOfEntities(
+               $terms = $this->termIndex->getTermsOfEntities(
                        $entityIds, null, array( $languageCode ) );
                // TODO: This needs to be rethought when a different search 
engine is used
                $aliasPattern = '/^' . preg_quote( $search, '/' ) . '/i';
@@ -305,7 +350,6 @@
         * @see ApiBase::getAllowedParams
         */
        protected function getAllowedParams() {
-               $entityFactory = 
WikibaseRepo::getDefaultInstance()->getEntityFactory();
 
                return array(
                        'search' => array(
@@ -313,11 +357,11 @@
                                ApiBase::PARAM_REQUIRED => true,
                        ),
                        'language' => array(
-                               ApiBase::PARAM_TYPE => 
WikibaseRepo::getDefaultInstance()->getTermsLanguages()->getLanguages(),
+                               ApiBase::PARAM_TYPE => 
$this->termsLanguages->getLanguages(),
                                ApiBase::PARAM_REQUIRED => true,
                        ),
                        'type' => array(
-                               ApiBase::PARAM_TYPE => 
$entityFactory->getEntityTypes(),
+                               ApiBase::PARAM_TYPE => $this->entityTypes,
                                ApiBase::PARAM_DFLT => 'item',
                        ),
                        'limit' => array(
diff --git a/repo/tests/phpunit/includes/api/SearchEntitiesTest.php 
b/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
index 46811de..b35f3e7 100644
--- a/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
+++ b/repo/tests/phpunit/includes/api/SearchEntitiesTest.php
@@ -2,11 +2,23 @@
 
 namespace Wikibase\Test\Api;
 
+use ApiMain;
+use FauxRequest;
+use RequestContext;
+use Title;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\Lib\ContentLanguages;
+use Wikibase\Lib\Store\EntityTitleLookup;
+use Wikibase\Term;
+use Wikibase\TermIndex;
+use Wikibase\Api\SearchEntities;
+use Wikibase\DataModel\Entity\BasicEntityIdParser;
+use Wikibase\Test\MockTermIndex;
+
 /**
  * @covers Wikibase\Api\SearchEntities
  *
  * @group API
- * @group Database
  * @group Wikibase
  * @group WikibaseAPI
  * @group WikibaseRepo
@@ -15,20 +27,167 @@
  *
  * @licence GNU GPL v2+
  * @author Adam Shorland
+ * @author Daniel Kinzler
  */
-class SearchEntitiesTest extends WikibaseApiTestCase {
+class SearchEntitiesTest extends \PHPUnit_Framework_TestCase {
 
-       private static $hasSetup;
+       private static $terms = array(
+               'Berlin' => array(
+                       "id" => 'Q64',
+                       "labels" => array(
+                               array( "language" => "en", "value" => "Berlin" 
),
+                               array( "language" => "de", "value" => "Berlin" 
),
+                       ),
+                       "aliases" => array(
+                               array( array( "language" => "de", "value" => 
"Dickes B" ) ),
+                               array( array( "language" => "en", "value" => 
"Dickes B" ) ),
+                       ),
+                       "descriptions" => array(
+                               array( "language" => "en", "value" => "Capital 
city and a federated state of the Federal Republic of Germany." ),
+                               array( "language" => "de", "value" => 
"Bundeshauptstadt und Regierungssitz der Bundesrepublik Deutschland." ),
+                       ),
+               ),
+               'Bern' => array(
+                       "id" => "Q45",
+                       "labels" => array(
+                               array( "language" => "en", "value" => "Bern" ),
+                               array( "language" => "de", "value" => "Bern" ),
+                               array( "language" => "fr", "value" => "Berne" ),
+                               array( "language" => "it", "value" => "Berna" ),
+                       ),
+                       "aliases" => array(
+                       ),
+                       "descriptions" => array(
+                               array( "language" => "de", "value" => "Stadt in 
der Schweiz." ),
+                       ),
+               ),
+               'Guangzhou' => array(
+                       "id" => "Q231",
+                       "labels" => array(
+                               array( "language" => "en", "value" => 
"Guangzhou" ),
+                               array( "language" => "yue", "value" => "廣州" ),
+                               array( "language" => "zh-cn", "value" => "广州市" 
),
+                       ),
+                       "aliases" => array(
+                       ),
+                       "descriptions" => array(
+                               array( "language" => "en", "value" => "Capital 
of Guangdong." ),
+                               array( "language" => "zh-hk", "value" => 
"廣東的省會。" ),
+                       ),
+               ),
+       );
 
-       protected function setUp() {
-               parent::setUp();
+       private function getEntityId( $handle ) {
+               $parser = new BasicEntityIdParser();
+               return $parser->parse( self::$terms[$handle]['id'] );
+       }
 
-               if( !isset( self::$hasSetup ) ) {
-                       $this->initTestEntities( array( 'StringProp', 'Berlin', 
'London', 'Oslo', 'Episkopi',
-                               'Leipzig', 'Guangzhou', 'Osaka' )
-                       );
+       private function getEntityData( $handle ) {
+               return self::$terms[$handle];
+       }
+
+       /**
+        * @param array $params
+        *
+        * @return ApiMain
+        */
+       private function getApiMain( array $params ) {
+               $context = new RequestContext();
+               $context->setRequest( new FauxRequest( $params, true ) );
+
+               $main = new ApiMain( $context );
+               return $main;
+       }
+
+       /**
+        * @return EntityTitleLookup
+        */
+       private function getTitleLookup() {
+               $titleLookup = $this->getMock( 
'Wikibase\Lib\Store\EntityTitleLookup' );
+               $titleLookup->expects( $this->any() )->method( 'getTitleForId' )
+                       ->will( $this->returnCallback( function( EntityId $id ) 
{
+                               $title = Title::makeTitle( NS_MAIN, 
$id->getEntityType() . ':' . $id->getSerialization() );
+                               $title->resetArticleID( $id->getNumericId() );
+                               return $title;
+                       } ) );
+
+               return $titleLookup;
+       }
+
+       /**
+        * @return ContentLanguages
+        */
+       private function getContentLanguages() {
+               $titleLookup = $this->getMock( 'Wikibase\Lib\ContentLanguages' 
);
+               $titleLookup->expects( $this->any() )->method( 'getLanguages' )
+                       ->will( $this->returnValue( array( 'de', 'de-ch', 'en', 
'ii', 'nn', 'ru', 'zh-cn' ) ) );
+
+               return $titleLookup;
+       }
+
+       /**
+        * @return TermIndex
+        */
+       private function getTermIndex() {
+               $idParser = new BasicEntityIdParser();
+               $termObjects = array();
+               foreach ( self::$terms as $entity ) {
+                       $id = $idParser->parse( $entity['id'] );
+
+                       foreach ( $entity['labels'] as $row ) {
+                               $termObjects[] = $this->newTermFromDataRow( 
$id, Term::TYPE_LABEL, $row );
+                       }
+
+                       foreach ( $entity['descriptions'] as $row ) {
+                               $termObjects[] = $this->newTermFromDataRow( 
$id, Term::TYPE_DESCRIPTION, $row );
+                       }
+
+                       foreach ( $entity['aliases'] as $rows ) {
+                               foreach ( $rows as $row ) {
+                                       $termObjects[] = 
$this->newTermFromDataRow( $id, Term::TYPE_ALIAS, $row );
+                               }
+                       }
                }
-               self::$hasSetup = true;
+
+               $termIndex = new MockTermIndex( $termObjects );
+
+               return $termIndex;
+       }
+
+       private function newTermFromDataRow( EntityId $entityId, $type, $row ) {
+               return new Term( array(
+                       'termType' => $type,
+                       'termLanguage' => $row['language'],
+                       'termText' => $row['value'],
+                       'entityType' => $entityId->getEntityType(),
+                       'entityId' => $entityId->getNumericId()
+               ) );
+       }
+
+       /**
+        * @param array $params
+        *
+        * @return array[]
+        */
+       private function callApiModule( array $params ) {
+               $module = new SearchEntities(
+                       $this->getApiMain( $params ),
+                       'wbsearchentities'
+               );
+
+               $module->setServices(
+                       $this->getTermIndex(),
+                       $this->getTitleLookup(),
+                       new BasicEntityIdParser(),
+                       array( 'item', 'property' ),
+                       $this->getContentLanguages()
+
+               );
+
+               $module->execute();
+
+               $result = $module->getResult();
+               return $result->getData();
        }
 
        public function provideData() {
@@ -36,14 +195,13 @@
 
                //Search via full Labels
                $testCases[] = array( array( 'search' => 'berlin', 'language' 
=> 'en' ), array( 'handle' => 'Berlin' ) );
-               $testCases[] = array( array( 'search' => 'LoNdOn', 'language' 
=> 'en' ), array( 'handle' => 'London' ) );
-               $testCases[] = array( array( 'search' => 'OSLO', 'language' => 
'en' ), array( 'handle' => 'Oslo' ) );
+               $testCases[] = array( array( 'search' => 'bERliN', 'language' 
=> 'en' ), array( 'handle' => 'Berlin' ) );
+               $testCases[] = array( array( 'search' => 'BERLIN', 'language' 
=> 'en' ), array( 'handle' => 'Berlin' ) );
                $testCases[] = array( array( 'search' => '广州市', 'language' => 
'zh-cn' ), array( 'handle' => 'Guangzhou' ) );
 
                //Search via partial Labels
-               $testCases[] = array( array( 'search' => 'BER', 'language' => 
'nn' ), array( 'handle' => 'Berlin' ) );
-               $testCases[] = array( array( 'search' => 'Episkop', 'language' 
=> 'de' ), array( 'handle' => 'Episkopi' ) );
-               $testCases[] = array( array( 'search' => 'L', 'language' => 
'de' ), array( 'handle' => 'Leipzig' ) );
+               $testCases[] = array( array( 'search' => 'BER', 'language' => 
'de' ), array( 'handle' => 'Berlin' ) );
+               $testCases[] = array( array( 'search' => '广', 'language' => 
'zh-cn' ), array( 'handle' => 'Guangzhou' ) );
 
                return $testCases;
        }
@@ -54,7 +212,7 @@
        public function testSearchEntities( $params, $expected ) {
                $params['action'] = 'wbsearchentities';
 
-               list( $result,, ) = $this->doApiRequest( $params );
+               $result = $this->callApiModule( $params );
 
                $this->assertResultLooksGood( $result );
                $this->assertApiResultHasExpected( $result['search'], $params, 
$expected );
@@ -63,31 +221,30 @@
        public function testSearchExactMatch() {
                $params = array(
                        'action' => 'wbsearchentities',
-                       'search' => EntityTestHelper::getId( 'Berlin' ),
+                       'search' => $this->getEntityId( 'Berlin' ),
                        'language' => 'en'
                );
 
                $expected = array( 'handle' => 'Berlin' );
 
-               list( $result,, ) = $this->doApiRequest( $params );
+               $result = $this->callApiModule( $params );
                $this->assertApiResultHasExpected( $result['search'], $params, 
$expected );
        }
 
        public function testSearchContinue() {
                $params = array(
                        'action' => 'wbsearchentities',
-                       'search' => 'O',
-                       'language' => 'en',
+                       'search' => 'B',
+                       'language' => 'de',
                        'limit' => 1
                );
 
-               list( $result,, ) = $this->doApiRequest( $params );
+               $result = $this->callApiModule( $params );
 
                $this->assertArrayHasKey( 'search-continue', $result );
        }
 
        private function assertResultLooksGood( $result ) {
-               $this->assertResultSuccess( $result );
                $this->assertArrayHasKey( 'searchinfo', $result );
                $this->assertArrayHasKey( 'search', $result['searchinfo'] );
                $this->assertArrayHasKey( 'search', $result );
@@ -103,8 +260,8 @@
        private function assertApiResultHasExpected( $searchResults, $params, 
$expected ) {
                $foundResult = 0;
 
-               $expectedId = EntityTestHelper::getId( $expected['handle'] );
-               $expectedData = EntityTestHelper::getEntityData( 
$expected['handle'] );
+               $expectedId = $this->getEntityId( $expected['handle'] 
)->getSerialization();
+               $expectedData = $this->getEntityData( $expected['handle'] );
 
                foreach( $searchResults as $searchResult ) {
                        $assertFound = $this->assertSearchResultHasExpected( 
$searchResult, $params, $expectedId, $expectedData );
@@ -145,4 +302,5 @@
                        }
                }
        }
+
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/203809
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia55f43c694470f481a26705d3216dc6a0c9de59a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to