Completed
Pull Request — master (#631)
by Bene
10:17 queued 07:17
created

PropertyTest::cloneProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 10
rs 9.4285
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\DataModel\Tests\Entity;
4
5
use InvalidArgumentException;
6
use PHPUnit_Framework_TestCase;
7
use Wikibase\DataModel\Entity\Property;
8
use Wikibase\DataModel\Entity\PropertyId;
9
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
10
use Wikibase\DataModel\Snak\PropertySomeValueSnak;
11
use Wikibase\DataModel\Statement\Statement;
12
use Wikibase\DataModel\Statement\StatementList;
13
use Wikibase\DataModel\Term\AliasGroup;
14
use Wikibase\DataModel\Term\AliasGroupList;
15
use Wikibase\DataModel\Term\Fingerprint;
16
use Wikibase\DataModel\Term\Term;
17
use Wikibase\DataModel\Term\TermList;
18
19
/**
20
 * @covers Wikibase\DataModel\Entity\Property
21
 * @covers Wikibase\DataModel\Entity\Entity
22
 *
23
 * @group Wikibase
24
 * @group WikibaseProperty
25
 * @group WikibaseDataModel
26
 * @group PropertyTest
27
 *
28
 * @licence GNU GPL v2+
29
 * @author Jeroen De Dauw < [email protected] >
30
 */
31
class PropertyTest extends PHPUnit_Framework_TestCase {
32
33
	private function getNewEmpty() {
34
		return Property::newFromType( 'string' );
35
	}
36
37
	public function testConstructorWithAllParameters() {
38
		$property = new Property(
39
			new PropertyId( 'P42' ),
40
			new Fingerprint(),
41
			'string',
42
			new StatementList()
43
		);
44
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property );
45
		$this->assertEquals( new PropertyId( 'P42' ), $property->getId() );
46
		$this->assertEquals( new Fingerprint(), $property->getFingerprint() );
47
		$this->assertEquals( 'string', $property->getDataTypeId() );
48
		$this->assertEquals( new StatementList(), $property->getStatements() );
49
	}
50
51
	public function testConstructorWithMinimalParameters() {
52
		$property = new Property( null, null, '' );
53
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property );
54
		$this->assertNull( $property->getId() );
55
		$this->assertEquals( new Fingerprint(), $property->getFingerprint() );
56
		$this->assertEquals( '', $property->getDataTypeId() );
57
		$this->assertEquals( new StatementList(), $property->getStatements() );
58
	}
59
60
	/**
61
	 * @expectedException InvalidArgumentException
62
	 */
63
	public function testGivenInvalidType_ConstructorThrowsException() {
64
		new Property( null, null, null );
65
	}
66
67
	public function testNewFromType() {
68
		$property = Property::newFromType( 'string' );
69
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property );
70
		$this->assertEquals( 'string', $property->getDataTypeId() );
71
	}
72
73
	public function testSetAndGetDataTypeId() {
74
		$property = Property::newFromType( 'string' );
75
76
		foreach ( array( 'string', 'foobar', 'nyan', 'string' ) as $typeId ) {
77
			$property->setDataTypeId( $typeId );
78
			$this->assertEquals( $typeId, $property->getDataTypeId() );
79
		}
80
	}
81
82
	public function testWhenIdSetWithNumber_GetIdReturnsPropertyId() {
83
		$property = Property::newFromType( 'string' );
84
		$property->setId( 42 );
85
86
		$this->assertHasCorrectIdType( $property );
87
	}
88
89
	protected function assertHasCorrectIdType( Property $property ) {
90
		$this->assertInstanceOf( 'Wikibase\DataModel\Entity\PropertyId', $property->getId() );
91
	}
92
93
	public function testWhenIdSetWithPropertyId_GetIdReturnsPropertyId() {
94
		$property = Property::newFromType( 'string' );
95
		$property->setId( new PropertyId( 'P42' ) );
96
97
		$this->assertHasCorrectIdType( $property );
98
	}
99
100
	public function testPropertyWithTypeIsEmpty() {
101
		$this->assertTrue( Property::newFromType( 'string' )->isEmpty() );
102
	}
103
104
	public function testPropertyWithIdIsEmpty() {
105
		$property = Property::newFromType( 'string' );
106
		$property->setId( 1337 );
107
		$this->assertTrue( $property->isEmpty() );
108
	}
109
110
	public function testPropertyWithFingerprintIsNotEmpty() {
111
		$property = Property::newFromType( 'string' );
112
		$property->getFingerprint()->setAliasGroup( 'en', array( 'foo' ) );
113
		$this->assertFalse( $property->isEmpty() );
114
	}
115
116
	public function testClearRemovesAllButId() {
117
		$property = Property::newFromType( 'string' );
118
		$property->setId( 42 );
119
		$property->getFingerprint()->setLabel( 'en', 'foo' );
120
		$property->getStatements()->addNewStatement( new PropertyNoValueSnak( 1 ) );
121
122
		$property->clear();
123
124
		$this->assertEquals( new PropertyId( 'P42' ), $property->getId() );
125
		$this->assertTrue( $property->isEmpty() );
126
	}
127
128
	public function testGetStatementsReturnsEmptyListForEmptyProperty() {
129
		$property = Property::newFromType( 'string' );
130
131
		$this->assertEquals( new StatementList(), $property->getStatements() );
132
	}
133
134
	public function testSetAndGetStatements() {
135
		$property = Property::newFromType( 'string' );
136
137
		$statementList = $this->newNonEmptyStatementList();
138
		$property->setStatements( $statementList );
139
140
		$this->assertEquals( $statementList, $property->getStatements() );
141
	}
142
143
	private function newNonEmptyStatementList() {
144
		$statementList = new StatementList();
145
		$statementList->addNewStatement( new PropertyNoValueSnak( 42 ) );
146
		$statementList->addNewStatement( new PropertyNoValueSnak( 1337 ) );
147
148
		return $statementList;
149
	}
150
151
	public function equalsProvider() {
152
		$firstProperty = Property::newFromType( 'string' );
153
		$firstProperty->setStatements( $this->newNonEmptyStatementList() );
154
155
		$secondProperty = Property::newFromType( 'string' );
156
		$secondProperty->setStatements( $this->newNonEmptyStatementList() );
157
158
		$secondPropertyWithId = $secondProperty->copy();
159
		$secondPropertyWithId->setId( 42 );
160
161
		$differentId = $secondPropertyWithId->copy();
162
		$differentId->setId( 43 );
163
164
		return array(
165
			array( Property::newFromType( 'string' ), Property::newFromType( 'string' ) ),
166
			array( $firstProperty, $secondProperty ),
167
			array( $secondProperty, $secondPropertyWithId ),
168
			array( $secondPropertyWithId, $differentId ),
169
		);
170
	}
171
172
	/**
173
	 * @dataProvider equalsProvider
174
	 */
175
	public function testEquals( Property $firstProperty, Property $secondProperty ) {
176
		$this->assertTrue( $firstProperty->equals( $secondProperty ) );
177
		$this->assertTrue( $secondProperty->equals( $firstProperty ) );
178
	}
179
180
	private function getBaseProperty() {
181
		$property = Property::newFromType( 'string' );
182
183
		$property->setId( 42 );
184
		$property->getFingerprint()->setLabel( 'en', 'Same' );
185
		$property->getFingerprint()->setDescription( 'en', 'Same' );
186
		$property->getFingerprint()->setAliasGroup( 'en', array( 'Same' ) );
187
		$property->setStatements( $this->newNonEmptyStatementList() );
188
189
		return $property;
190
	}
191
192
	public function notEqualsProvider() {
193
		$differentLabel = $this->getBaseProperty();
194
		$differentLabel->getFingerprint()->setLabel( 'en', 'Different' );
195
196
		$differentDescription = $this->getBaseProperty();
197
		$differentDescription->getFingerprint()->setDescription( 'en', 'Different' );
198
199
		$differentAlias = $this->getBaseProperty();
200
		$differentAlias->getFingerprint()->setAliasGroup( 'en', array( 'Different' ) );
201
202
		$differentStatement = $this->getBaseProperty();
203
		$differentStatement->setStatements( new StatementList() );
204
205
		$property = $this->getBaseProperty();
206
207
		return array(
208
			'empty' => array( $property, Property::newFromType( 'string' ) ),
209
			'label' => array( $property, $differentLabel ),
210
			'description' => array( $property, $differentDescription ),
211
			'alias' => array( $property, $differentAlias ),
212
			'dataType' => array( Property::newFromType( 'string' ), Property::newFromType( 'foo' ) ),
213
			'statement' => array( $property, $differentStatement ),
214
		);
215
	}
216
217
	/**
218
	 * @dataProvider notEqualsProvider
219
	 */
220
	public function testNotEquals( Property $firstProperty, Property $secondProperty ) {
221
		$this->assertFalse( $firstProperty->equals( $secondProperty ) );
222
		$this->assertFalse( $secondProperty->equals( $firstProperty ) );
223
	}
224
225
	public function testPropertyWithStatementsIsNotEmpty() {
226
		$property = Property::newFromType( 'string' );
227
		$property->setStatements( $this->newNonEmptyStatementList() );
228
229
		$this->assertFalse( $property->isEmpty() );
230
	}
231
232
	public function cloneProvider() {
233
		$property = new Property( new PropertyId( 'P1' ), null, 'string' );
234
		$property->setLabel( 'en', 'original' );
235
		$property->getStatements()->addNewStatement( new PropertyNoValueSnak( 1 ) );
236
237
		return array(
238
			'copy' => array( $property, $property->copy() ),
239
			'native clone' => array( $property, clone $property ),
240
		);
241
	}
242
243
	/**
244
	 * @dataProvider cloneProvider
245
	 */
246
	public function testCloneIsEqualButNotIdentical( Property $original, Property $clone ) {
247
		$this->assertNotSame( $original, $clone );
248
		$this->assertTrue( $original->equals( $clone ) );
249
		$this->assertSame(
250
			$original->getId(),
251
			$clone->getId(),
252
			'id is immutable and must not be cloned'
253
		);
254
255
		// The clone must not reference the same mutable objects
256
		$this->assertNotSame( $original->getFingerprint(), $clone->getFingerprint() );
257
		$this->assertNotSame( $original->getStatements(), $clone->getStatements() );
258
		$this->assertNotSame(
259
			$original->getStatements()->getFirstStatementWithGuid( null ),
260
			$clone->getStatements()->getFirstStatementWithGuid( null )
261
		);
262
	}
263
264
	/**
265
	 * @dataProvider cloneProvider
266
	 */
267
	public function testOriginalDoesNotChangeWithClone( Property $original, Property $clone ) {
268
		$originalStatement = $original->getStatements()->getFirstStatementWithGuid( null );
269
		$clonedStatement = $clone->getStatements()->getFirstStatementWithGuid( null );
270
271
		$clone->setLabel( 'en', 'clone' );
272
		$clone->setDescription( 'en', 'clone' );
273
		$clone->setAliases( 'en', array( 'clone' ) );
274
		$clonedStatement->setGuid( 'clone' );
275
		$clonedStatement->setMainSnak( new PropertySomeValueSnak( 666 ) );
276
		$clonedStatement->setRank( Statement::RANK_DEPRECATED );
277
		$clonedStatement->getQualifiers()->addSnak( new PropertyNoValueSnak( 1 ) );
278
		$clonedStatement->getReferences()->addNewReference( new PropertyNoValueSnak( 1 ) );
279
280
		$this->assertSame( 'original', $original->getFingerprint()->getLabel( 'en' )->getText() );
281
		$this->assertFalse( $original->getFingerprint()->hasDescription( 'en' ) );
282
		$this->assertFalse( $original->getFingerprint()->hasAliasGroup( 'en' ) );
283
		$this->assertNull( $originalStatement->getGuid() );
284
		$this->assertSame( 'novalue', $originalStatement->getMainSnak()->getType() );
285
		$this->assertSame( Statement::RANK_NORMAL, $originalStatement->getRank() );
286
		$this->assertTrue( $originalStatement->getQualifiers()->isEmpty() );
287
		$this->assertTrue( $originalStatement->getReferences()->isEmpty() );
288
	}
289
290
	// Below are tests copied from EntityTest
291
292
	public function labelProvider() {
293
		return array(
294
			array( 'en', 'spam' ),
295
			array( 'en', 'spam', 'spam' ),
296
			array( 'de', 'foo bar baz' ),
297
		);
298
	}
299
300
	/**
301
	 * @dataProvider labelProvider
302
	 * @param string $languageCode
303
	 * @param string $labelText
304
	 * @param string $moarText
305
	 */
306
	public function testSetLabel( $languageCode, $labelText, $moarText = 'ohi there' ) {
307
		$entity = $this->getNewEmpty();
308
309
		$entity->setLabel( $languageCode, $labelText );
310
311
		$this->assertEquals( $labelText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
312
313
		$entity->setLabel( $languageCode, $moarText );
314
315
		$this->assertEquals( $moarText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
316
	}
317
318
	public function descriptionProvider() {
319
		return array(
320
			array( 'en', 'spam' ),
321
			array( 'en', 'spam', 'spam' ),
322
			array( 'de', 'foo bar baz' ),
323
		);
324
	}
325
326
	/**
327
	 * @dataProvider descriptionProvider
328
	 * @param string $languageCode
329
	 * @param string $description
330
	 * @param string $moarText
331
	 */
332
	public function testSetDescription( $languageCode, $description, $moarText = 'ohi there' ) {
333
		$entity = $this->getNewEmpty();
334
335
		$entity->setDescription( $languageCode, $description );
336
337
		$this->assertEquals( $description, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
338
339
		$entity->setDescription( $languageCode, $moarText );
340
341
		$this->assertEquals( $moarText, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
342
	}
343
344
	public function aliasesProvider() {
345
		return array(
346
			array( array(
347
				       'en' => array( array( 'spam' ) )
348
			       ) ),
349
			array( array(
350
				       'en' => array( array( 'foo', 'bar', 'baz' ) )
351
			       ) ),
352
			array( array(
353
				       'en' => array( array( 'foo', 'bar' ), array( 'baz', 'spam' ) )
354
			       ) ),
355
			array( array(
356
				       'en' => array( array( 'foo', 'bar', 'baz' ) ),
357
				       'de' => array( array( 'foobar' ), array( 'baz' ) ),
358
			       ) ),
359
			// with duplicates
360
			array( array(
361
				       'en' => array( array( 'spam', 'ham', 'ham' ) )
362
			       ) ),
363
			array( array(
364
				       'en' => array( array( 'foo', 'bar' ), array( 'bar', 'spam' ) )
365
			       ) ),
366
		);
367
	}
368
369
	/**
370
	 * @dataProvider aliasesProvider
371
	 */
372
	public function testSetAliases( array $aliasesLists ) {
373
		$entity = $this->getNewEmpty();
374
375
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
376
			foreach ( $aliasesList as $aliases ) {
377
				$entity->setAliases( $langCode, $aliases );
378
			}
379
		}
380
381
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
382
			$expected = array_values( array_unique( array_pop( $aliasesList ) ) );
383
			asort( $aliasesList );
384
385
			$actual = $entity->getFingerprint()->getAliasGroup( $langCode )->getAliases();
386
			asort( $actual );
387
388
			$this->assertEquals( $expected, $actual );
389
		}
390
	}
391
392
	/**
393
	 * @dataProvider aliasesProvider
394
	 */
395
	public function testSetEmptyAlias( array $aliasesLists ) {
396
		$entity = $this->getNewEmpty();
397
398
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
399
			foreach ( $aliasesList as $aliases ) {
400
				$entity->setAliases( $langCode, $aliases );
401
			}
402
		}
403
		$entity->setAliases( 'zh', array( 'wind', 'air', '', 'fire' ) );
404
		$entity->setAliases( 'zu', array( '', '' ) );
405
406
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
407
			$expected = array_values( array_unique( array_pop( $aliasesList ) ) );
408
			asort( $aliasesList );
409
410
			$actual = $entity->getFingerprint()->getAliasGroup( $langCode )->getAliases();
411
			asort( $actual );
412
413
			$this->assertEquals( $expected, $actual );
414
		}
415
	}
416
417
	public function instanceProvider() {
418
		$entities = array();
419
420
		// empty
421
		$entity = $this->getNewEmpty();
422
		$entities[] = $entity;
423
424
		// ID only
425
		$entity = clone $entity;
426
		$entity->setId( 44 );
427
428
		$entities[] = $entity;
429
430
		// with labels and stuff
431
		$entity = $this->getNewEmpty();
432
		$entity->setAliases( 'en', array( 'o', 'noez' ) );
433
		$entity->setLabel( 'de', 'spam' );
434
		$entity->setDescription( 'en', 'foo bar baz' );
435
436
		$entities[] = $entity;
437
438
		// with labels etc and ID
439
		$entity = clone $entity;
440
		$entity->setId( 42 );
441
442
		$entities[] = $entity;
443
444
		$argLists = array();
445
446
		foreach ( $entities as $entity ) {
447
			$argLists[] = array( $entity );
448
		}
449
450
		return $argLists;
451
	}
452
453
	/**
454
	 * @dataProvider instanceProvider
455
	 * @param Property $entity
456
	 */
457
	public function testCopy( Property $entity ) {
458
		$copy = $entity->copy();
459
460
		// The equality method alone is not enough since it does not check the IDs.
461
		$this->assertTrue( $entity->equals( $copy ) );
462
		$this->assertEquals( $entity->getId(), $copy->getId() );
463
464
		$this->assertNotSame( $entity, $copy );
465
	}
466
467
	public function testCopyRetainsLabels() {
468
		$property = Property::newFromType( 'string' );
469
470
		$property->getFingerprint()->setLabel( 'en', 'foo' );
471
		$property->getFingerprint()->setLabel( 'de', 'bar' );
472
473
		$newProperty = $property->copy();
474
475
		$this->assertTrue( $newProperty->getFingerprint()->getLabels()->hasTermForLanguage( 'en' ) );
476
		$this->assertTrue( $newProperty->getFingerprint()->getLabels()->hasTermForLanguage( 'de' ) );
477
	}
478
479
	/**
480
	 * @dataProvider instanceProvider
481
	 * @param Property $entity
482
	 */
483
	public function testSerialize( Property $entity ) {
484
		$string = serialize( $entity );
485
486
		$this->assertInternalType( 'string', $string );
487
488
		$instance = unserialize( $string );
489
490
		$this->assertTrue( $entity->equals( $instance ) );
491
		$this->assertEquals( $entity->getId(), $instance->getId() );
492
	}
493
494
	public function testWhenNoStuffIsSet_getFingerprintReturnsEmptyFingerprint() {
495
		$entity = $this->getNewEmpty();
496
497
		$this->assertEquals(
498
			new Fingerprint(),
499
			$entity->getFingerprint()
500
		);
501
	}
502
503
	public function testWhenLabelsAreSet_getFingerprintReturnsFingerprintWithLabels() {
504
		$entity = $this->getNewEmpty();
505
506
		$entity->setLabel( 'en', 'foo' );
507
		$entity->setLabel( 'de', 'bar' );
508
509
		$this->assertEquals(
510
			new Fingerprint(
511
				new TermList( array(
512
					new Term( 'en', 'foo' ),
513
					new Term( 'de', 'bar' ),
514
				) )
515
			),
516
			$entity->getFingerprint()
517
		);
518
	}
519
520
	public function testWhenTermsAreSet_getFingerprintReturnsFingerprintWithTerms() {
521
		$entity = $this->getNewEmpty();
522
523
		$entity->setLabel( 'en', 'foo' );
524
		$entity->setDescription( 'en', 'foo bar' );
525
		$entity->setAliases( 'en', array( 'foo', 'bar' ) );
526
527
		$this->assertEquals(
528
			new Fingerprint(
529
				new TermList( array(
530
					new Term( 'en', 'foo' ),
531
				) ),
532
				new TermList( array(
533
					new Term( 'en', 'foo bar' )
534
				) ),
535
				new AliasGroupList( array(
536
					new AliasGroup( 'en', array( 'foo', 'bar' ) )
537
				) )
538
			),
539
			$entity->getFingerprint()
540
		);
541
	}
542
543
	public function testGivenEmptyFingerprint_noTermsAreSet() {
544
		$entity = $this->getNewEmpty();
545
		$entity->setFingerprint( new Fingerprint() );
546
547
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
548
	}
549
550
	public function testGivenEmptyFingerprint_existingTermsAreRemoved() {
551
		$entity = $this->getNewEmpty();
552
553
		$entity->setLabel( 'en', 'foo' );
554
		$entity->setDescription( 'en', 'foo bar' );
555
		$entity->setAliases( 'en', array( 'foo', 'bar' ) );
556
557
		$entity->setFingerprint( new Fingerprint() );
558
559
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
560
	}
561
562
	public function testWhenSettingFingerprint_getFingerprintReturnsIt() {
563
		$fingerprint = new Fingerprint(
564
			new TermList( array(
565
				new Term( 'en', 'english label' ),
566
			) ),
567
			new TermList( array(
568
				new Term( 'en', 'english description' )
569
			) ),
570
			new AliasGroupList( array(
571
				new AliasGroup( 'en', array( 'first en alias', 'second en alias' ) )
572
			) )
573
		);
574
575
		$entity = $this->getNewEmpty();
576
		$entity->setFingerprint( $fingerprint );
577
		$newFingerprint = $entity->getFingerprint();
578
579
		$this->assertSame( $fingerprint, $newFingerprint );
580
	}
581
582
}
583