| Current File : /home/jvzmxxx/wiki/extensions/Wikibase/lib/tests/phpunit/Store/EntityInfoBuilderTest.php |
<?php
namespace Wikibase\Test;
use Wikibase\DataModel\Entity\EntityDocument;
use Wikibase\DataModel\Entity\EntityId;
use Wikibase\DataModel\Entity\Item;
use Wikibase\DataModel\Entity\ItemId;
use Wikibase\DataModel\Entity\Property;
use Wikibase\DataModel\Entity\PropertyId;
use Wikibase\Lib\Store\Sql\SqlEntityInfoBuilder;
/**
* Base class for tests of EntityInfoBuilder implementation.
* This abstract test case tests conformance to the contract of the EntityInfoBuilder interface.
*
* @license GPL-2.0+
* @author Daniel Kinzler
*/
abstract class EntityInfoBuilderTest extends \MediaWikiTestCase {
/**
* @return EntityId[]
*/
protected function getKnownRedirects() {
return array(
'Q7' => new ItemId( 'Q2' ),
'Q12' => new ItemId( 'Q2' ),
'Q22' => new ItemId( 'Q2' ),
);
}
/**
* @return EntityDocument[]
*/
protected function getKnownEntities() {
$q1 = new Item( new ItemId( 'Q1' ) );
$q1->setLabel( 'en', 'label:Q1/en' );
$q1->setLabel( 'de', 'label:Q1/de' );
$q1->setDescription( 'en', 'description:Q1/en' );
$q1->setDescription( 'de', 'description:Q1/de' );
$q1->setAliases( 'en', array( 'alias:Q1/en#1' ) );
$q1->setAliases( 'de', array( 'alias:Q1/de#1', 'alias:Q1/de#2' ) );
$q2 = new Item( new ItemId( 'Q2' ) );
$q2->setLabel( 'en', 'label:Q2/en' );
$q2->setLabel( 'de', 'label:Q2/de' );
$q2->setAliases( 'en', array( 'alias:Q2/en#1' ) );
$q2->setAliases( 'de', array( 'alias:Q2/de#1', 'alias:Q2/de#2' ) );
$p2 = Property::newFromType( 'string' );
$p2->setId( new PropertyId( 'P2' ) );
$p2->setLabel( 'en', 'label:P2/en' );
$p2->setLabel( 'de', 'label:P2/de' );
$p2->setDescription( 'en', 'description:P2/en' );
$p2->setDescription( 'de', 'description:P2/de' );
$p2->setAliases( 'en', array( 'alias:P2/en#1' ) );
$p2->setAliases( 'de', array( 'alias:P2/de#1', 'alias:P2/de#2' ) );
$p3 = Property::newFromType( 'string' );
$p3->setId( new PropertyId( 'P3' ) );
$p3->setLabel( 'en', 'label:P3/en' );
$p3->setLabel( 'de', 'label:P3/de' );
$p3->setDescription( 'en', 'description:P3/en' );
$p3->setDescription( 'de', 'description:P3/de' );
return array( $q1, $q2, $p2, $p3 );
}
/**
* @param EntityId[] $ids
*
* @return SqlEntityInfoBuilder
*/
abstract protected function newEntityInfoBuilder( array $ids );
public function getEntityInfoProvider() {
return array(
array(
array(),
array()
),
array(
array(
new ItemId( 'Q1' ),
new PropertyId( 'P3' )
),
array(
'Q1' => array( 'id' => 'Q1', 'type' => Item::ENTITY_TYPE ),
'P3' => array( 'id' => 'P3', 'type' => Property::ENTITY_TYPE ),
)
),
array(
array(
new ItemId( 'Q1' ),
new ItemId( 'Q1' ),
),
array(
'Q1' => array( 'id' => 'Q1', 'type' => Item::ENTITY_TYPE ),
)
),
);
}
/**
* @dataProvider getEntityInfoProvider
*/
public function testGetEntityInfo( array $ids, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$actual = $builder->getEntityInfo()->asArray();
$this->assertArrayEquals( $expected, $actual, false, true );
}
public function resolveRedirectsProvider() {
return array(
'empty' => array(
array(),
array()
),
'some redirects' => array(
array(
new ItemId( 'Q2' ),
new ItemId( 'Q12' ),
new ItemId( 'Q22' ),
),
array(
'Q2' => 'Q2',
'Q12' => 'Q2',
'Q22' => 'Q2',
),
),
);
}
/**
* @dataProvider resolveRedirectsProvider
*/
public function testResolveRedirects( array $ids, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->resolveRedirects();
$entityInfo = $builder->getEntityInfo()->asArray();
$resolvedIds = array_map(
function( $record ) {
return $record['id'];
},
$entityInfo
);
$this->assertArrayEquals( $expected, $resolvedIds );
}
/**
* Converts a map of the form $language => $value into a ist of records
* of the form $language => array( 'language' => $language, 'value' => $value ).
*
* @param array $map map if the form $language => $value
* @param string|null $language For the language for all entries. Useful if $map is a list, not an associative array.
*
* @return array map if the form $language => array( 'language' => $language, 'value' => $value )
*/
protected function makeLanguageValueRecords( array $map, $language = null ) {
$records = array();
foreach ( $map as $key => $value ) {
if ( $language !== null ) {
$lang = $language;
} else {
$lang = $key;
}
if ( is_array( $value ) ) {
$records[$key] = $this->makeLanguageValueRecords( $value, $lang );
} else {
$records[$key] = array(
'language' => $lang,
'value' => $value
);
}
}
return $records;
}
public function collectTermsProvider() {
return array(
array(
array(),
null,
null,
array()
),
array(
array(
new ItemId( 'Q1' ),
new PropertyId( 'P3' ),
new ItemId( 'Q7' ),
),
null,
null,
array(
'Q1' => array( 'id' => 'Q1', 'type' => Item::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array(
'en' => 'label:Q1/en', 'de' => 'label:Q1/de' ) ),
'descriptions' => $this->makeLanguageValueRecords( array(
'en' => 'description:Q1/en', 'de' => 'description:Q1/de' ) ),
'aliases' => $this->makeLanguageValueRecords( array(
'en' => array( 'alias:Q1/en#1' ),
'de' => array( 'alias:Q1/de#1', 'alias:Q1/de#2' ) ) ),
),
'P3' => array( 'id' => 'P3', 'type' => Property::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array(
'en' => 'label:P3/en', 'de' => 'label:P3/de' ) ),
'descriptions' => $this->makeLanguageValueRecords( array(
'en' => 'description:P3/en', 'de' => 'description:P3/de' ) ),
'aliases' => array(),
),
'Q7' => array( 'id' => 'Q7', 'type' => Item::ENTITY_TYPE,
'labels' => array(),
'descriptions' => array(),
'aliases' => array()
),
)
),
array(
array(
new ItemId( 'Q1' ),
new PropertyId( 'P3' ),
new ItemId( 'Q7' ),
),
array( 'label' ),
array( 'de' ),
array(
'Q1' => array( 'id' => 'Q1', 'type' => Item::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array( 'de' => 'label:Q1/de' ) ),
),
'P3' => array( 'id' => 'P3', 'type' => Property::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array( 'de' => 'label:P3/de' ) ),
),
'Q7' => array( 'id' => 'Q7', 'type' => Item::ENTITY_TYPE, 'labels' => array() ),
)
),
);
}
/**
* @dataProvider collectTermsProvider
*/
public function testCollectTerms(
array $ids,
array $types = null,
array $languages = null,
array $expected
) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->collectTerms( $types, $languages );
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertSameSize( $expected, $entityInfo );
foreach ( $expected as $id => $expectedRecord ) {
$this->assertArrayHasKey( $id, $entityInfo );
$actualRecord = $entityInfo[$id];
$this->assertArrayEquals( $expectedRecord, $actualRecord, false, true );
}
}
public function testCollectTerms_redirect() {
$ids = array( new ItemId( 'Q7' ), new ItemId( 'Q1' ) );
$expected = array(
'Q1' => array( 'id' => 'Q1', 'type' => Item::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array( 'de' => 'label:Q1/de' ) ),
),
'Q2' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array( 'de' => 'label:Q2/de' ) ),
),
'Q7' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE,
'labels' => $this->makeLanguageValueRecords( array( 'de' => 'label:Q2/de' ) ),
)
);
$builder = $this->newEntityInfoBuilder( $ids );
$builder->resolveRedirects();
$builder->collectTerms( array( 'label' ), array( 'de' ) );
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertEquals( array_keys( $expected ), array_keys( $entityInfo ) );
foreach ( $expected as $id => $expectedRecord ) {
$this->assertArrayHasKey( $id, $entityInfo );
$actualRecord = $entityInfo[$id];
$this->assertArrayEquals( $expectedRecord, $actualRecord, false, true );
}
}
public function collectDataTypesProvider() {
return array(
array(
array(),
array()
),
array(
array(
new PropertyId( 'P2' ),
new PropertyId( 'P3' ),
new ItemId( 'Q7' ),
new PropertyId( 'P7' ),
),
array(
'P2' => array( 'id' => 'P2', 'type' => Property::ENTITY_TYPE, 'datatype' => 'string' ),
'P3' => array( 'id' => 'P3', 'type' => Property::ENTITY_TYPE, 'datatype' => 'string' ),
'Q7' => array( 'id' => 'Q7', 'type' => Item::ENTITY_TYPE ),
'P7' => array( 'id' => 'P7', 'type' => Property::ENTITY_TYPE, 'datatype' => null ),
)
),
);
}
/**
* @dataProvider collectDataTypesProvider
*/
public function testCollectDataTypes( array $ids, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->collectDataTypes();
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertSameSize( $expected, $entityInfo );
foreach ( $expected as $id => $expectedRecord ) {
$this->assertArrayHasKey( $id, $entityInfo );
$actualRecord = $entityInfo[$id];
$this->assertArrayEquals( $expectedRecord, $actualRecord, false, true );
}
}
public function removeMissingAndRedirectsProvider() {
return array(
'empty' => array(
array(),
array()
),
'found' => array(
array(
new ItemId( 'Q2' ),
),
array(
'Q2' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE ),
),
),
'missing' => array(
array(
new ItemId( 'Q77' ),
),
array()
),
'some found' => array(
array(
new ItemId( 'Q2' ),
new PropertyId( 'P7' ),
new ItemId( 'Q7' ),
new PropertyId( 'P2' ),
),
array(
'P2' => array( 'id' => 'P2', 'type' => Property::ENTITY_TYPE ),
'Q2' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE ),
)
),
);
}
/**
* @dataProvider removeMissingAndRedirectsProvider
*/
public function testRemoveMissingAndRedirects( array $ids, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->removeMissing( 'remove-redirects' );
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertArrayEquals( array_keys( $expected ), array_keys( $entityInfo ) );
}
public function removeMissingButKeepRedirects() {
return array(
'empty' => array(
array(),
array()
),
'unrelated redirect' => array(
array(
new ItemId( 'Q2' ),
),
array(
'Q2' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE ),
),
),
'redirect resolved' => array(
array(
new ItemId( 'Q7' ),
),
array(
'Q7' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE ),
),
),
'some found, some resolved' => array(
array(
new ItemId( 'Q2' ),
new PropertyId( 'P7' ),
new ItemId( 'Q7' ),
new PropertyId( 'P2' ),
),
array(
'P2' => array( 'id' => 'P2', 'type' => Property::ENTITY_TYPE ),
'Q2' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE ),
'Q7' => array( 'id' => 'Q2', 'type' => Item::ENTITY_TYPE ),
)
),
);
}
/**
* @dataProvider removeMissingButKeepRedirects
*/
public function testRemoveMissingButKeepRedirects( array $ids, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->removeMissing();
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertArrayEquals( array_keys( $expected ), array_keys( $entityInfo ) );
}
public function removeEntityInfoProvider() {
return array(
'empty' => array(
array(),
array(),
array(),
),
'remove nonexisting' => array(
array(
new ItemId( 'Q1' ),
),
array(
new ItemId( 'Q2' ),
),
array( 'Q1' ),
),
'remove some' => array(
array(
new ItemId( 'Q1' ),
new ItemId( 'Q2' ),
new ItemId( 'Q3' ),
),
array(
new ItemId( 'Q2' ),
),
array( 'Q1', 'Q3' ),
),
);
}
/**
* @dataProvider removeEntityInfoProvider
*/
public function testRemoveEntityInfo( array $ids, array $remove, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->removeEntityInfo( $remove );
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertArrayEquals( $expected, array_keys( $entityInfo ) );
}
public function retainEntityInfoProvider() {
return array(
'empty' => array(
array(),
array(),
array(),
),
'retain nonexisting' => array(
array(
new ItemId( 'Q1' ),
),
array(
new ItemId( 'Q2' ),
),
array(),
),
'retain some' => array(
array(
new ItemId( 'Q1' ),
new ItemId( 'Q2' ),
new ItemId( 'Q3' ),
),
array(
new ItemId( 'Q2' ),
),
array( 'Q2' ),
),
);
}
/**
* @dataProvider retainEntityInfoProvider
*/
public function testRetainEntityInfo( array $ids, array $retain, array $expected ) {
$builder = $this->newEntityInfoBuilder( $ids );
$builder->retainEntityInfo( $retain );
$entityInfo = $builder->getEntityInfo()->asArray();
$this->assertArrayEquals( $expected, array_keys( $entityInfo ) );
}
}