Completed
Push — constructors3 ( 18c935...3f87c3 )
by no
06:01 queued 02:46
created

ReferenceListTest::testGivenEmptyList_isEmpty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\DataModel\Tests;
4
5
use Hashable;
6
use InvalidArgumentException;
7
use PHPUnit_Framework_TestCase;
8
use Wikibase\DataModel\Entity\PropertyId;
9
use Wikibase\DataModel\Reference;
10
use Wikibase\DataModel\ReferenceList;
11
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
12
use Wikibase\DataModel\Snak\SnakList;
13
14
/**
15
 * @covers Wikibase\DataModel\ReferenceList
16
 *
17
 * @group Wikibase
18
 * @group WikibaseDataModel
19
 * @group WikibaseReference
20
 *
21
 * @license GPL-2.0+
22
 * @author Jeroen De Dauw < [email protected] >
23
 * @author Thiemo Mättig
24
 */
25
class ReferenceListTest extends PHPUnit_Framework_TestCase {
26
27
	public function instanceProvider() {
28
		return [
29
			[ new ReferenceList( [] ) ],
30
			[ new ReferenceList( [
31
				new Reference(),
32
				new Reference( [ new PropertyNoValueSnak( 2 ) ] ),
33
				new Reference( [ new PropertyNoValueSnak( 3 ) ] ),
34
			] ) ],
35
		];
36
	}
37
38
	public function testCanConstructWithReferenceListObject() {
39
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
40
		$original = new ReferenceList( [ $reference ] );
41
		$copy = new ReferenceList( $original );
42
43
		$this->assertSame( 1, $copy->count() );
44
		$this->assertNotNull( $copy->getReference( $reference->getHash() ) );
45
	}
46
47
	public function testConstructorIgnoresIdenticalObjects() {
48
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
49
		$list = new ReferenceList( [ $reference, $reference ] );
50
		$this->assertCount( 1, $list );
51
	}
52
53
	public function testConstructorDoesNotIgnoreCopies() {
54
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
55
		$list = new ReferenceList( [ $reference, clone $reference ] );
56
		$this->assertCount( 2, $list );
57
	}
58
59
	/**
60
	 * @dataProvider invalidConstructorArgumentsProvider
61
	 * @expectedException InvalidArgumentException
62
	 */
63
	public function testGivenInvalidConstructorArguments_constructorThrowsException( $input ) {
64
		new ReferenceList( $input );
65
	}
66
67
	public function invalidConstructorArgumentsProvider() {
68
		$id1 = new PropertyId( 'P1' );
69
70
		return [
71
			[ null ],
72
			[ false ],
73
			[ 1 ],
74
			[ 0.1 ],
75
			[ 'string' ],
76
			[ $id1 ],
77
			[ new PropertyNoValueSnak( $id1 ) ],
78
			[ new SnakList( [ new PropertyNoValueSnak( $id1 ) ] ) ],
79
			[ [ new PropertyNoValueSnak( $id1 ) ] ],
80
			[ [ new ReferenceList() ] ],
81
			[ [ new SnakList() ] ],
82
		];
83
	}
84
85
	public function testGetIterator_isTraversable() {
86
		$references = new ReferenceList();
87
		$references->addNewReference( new PropertyNoValueSnak( 1 ) );
88
		$iterator = $references->getIterator();
89
90
		$this->assertInstanceOf( 'Traversable', $iterator );
91
		$this->assertCount( 1, $iterator );
92
		foreach ( $references as $reference ) {
93
			$this->assertInstanceOf( 'Wikibase\DataModel\Reference', $reference );
94
		}
95
	}
96
97
	/**
98
	 * @dataProvider instanceProvider
99
	 */
100
	public function testHasReferenceBeforeRemoveButNotAfter( ReferenceList $array ) {
101
		if ( $array->count() === 0 ) {
102
			$this->assertTrue( true );
103
			return;
104
		}
105
106
		/**
107
		 * @var Reference $hashable
108
		 */
109
		foreach ( iterator_to_array( $array ) as $hashable ) {
110
			$this->assertTrue( $array->hasReference( $hashable ) );
111
			$array->removeReference( $hashable );
112
			$this->assertFalse( $array->hasReference( $hashable ) );
113
		}
114
	}
115
116
	public function testGivenCloneOfReferenceInList_hasReferenceReturnsTrue() {
117
		$list = new ReferenceList();
118
119
		$reference = new Reference( [ new PropertyNoValueSnak( 42 ) ] );
120
		$sameReference = unserialize( serialize( $reference ) );
121
122
		$list->addReference( $reference );
123
124
		$this->assertTrue(
125
			$list->hasReference( $sameReference ),
126
			'hasReference should return true when a reference with the same value is present, even when its another instance'
127
		);
128
	}
129
130
	/**
131
	 * @dataProvider instanceProvider
132
	 */
133
	public function testRemoveReference( ReferenceList $array ) {
134
		$elementCount = count( $array );
135
136
		/**
137
		 * @var Reference $element
138
		 */
139
		foreach ( iterator_to_array( $array ) as $element ) {
140
			$this->assertTrue( $array->hasReference( $element ) );
141
142
			$array->removeReference( $element );
143
144
			$this->assertFalse( $array->hasReference( $element ) );
145
			$this->assertSame( --$elementCount, count( $array ) );
146
		}
147
	}
148
149
	public function testRemoveReferenceRemovesIdenticalObjects() {
150
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
151
		$references = new ReferenceList( [ $reference, $reference ] );
152
153
		$references->removeReference( $reference );
154
155
		$this->assertTrue( $references->isEmpty() );
156
	}
157
158
	public function testRemoveReferenceDoesNotRemoveCopies() {
159
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
160
		$references = new ReferenceList( [ $reference, clone $reference ] );
161
162
		$references->removeReference( $reference );
163
164
		$this->assertFalse( $references->isEmpty() );
165
		$this->assertTrue( $references->hasReference( $reference ) );
166
		$this->assertNotSame( $reference, $references->getReference( $reference->getHash() ) );
167
	}
168
169
	public function testAddReferenceOnEmptyList() {
170
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
171
172
		$references = new ReferenceList();
173
		$references->addReference( $reference );
174
175
		$this->assertCount( 1, $references );
176
177
		$expectedList = new ReferenceList( [ $reference ] );
178
		$this->assertSameReferenceOrder( $expectedList, $references );
179
	}
180
181
	private function assertSameReferenceOrder( ReferenceList $expectedList, ReferenceList $references ) {
182
		$this->assertSame(
183
			iterator_to_array( $expectedList ),
184
			iterator_to_array( $references )
185
		);
186
	}
187
188
	public function testAddReferenceAtTheEnd() {
189
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
190
		$reference2 = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
191
		$reference3 = new Reference( [ new PropertyNoValueSnak( 3 ) ] );
192
193
		$references = new ReferenceList( [ $reference1, $reference2 ] );
194
		$references->addReference( $reference3 );
195
196
		$this->assertCount( 3, $references );
197
198
		$expectedList = new ReferenceList( [ $reference1, $reference2, $reference3 ] );
199
		$this->assertSameReferenceOrder( $expectedList, $references );
200
	}
201
202
	public function testAddReferenceBetweenExistingReferences() {
203
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
204
		$reference2 = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
205
		$list = new ReferenceList( [ $reference1, $reference2 ] );
206
207
		$reference3 = new Reference( [ new PropertyNoValueSnak( 3 ) ] );
208
		$list->addReference( $reference3, 1 );
209
210
		$this->assertCount( 3, $list );
211
		$this->assertSame( 1, $list->indexOf( $reference3 ) );
212
	}
213
214
	public function testAddReferenceIgnoresIdenticalObjects() {
215
		$list = new ReferenceList();
216
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
217
		$list->addReference( $reference );
218
		$list->addReference( $reference );
219
		$this->assertCount( 1, $list );
220
	}
221
222
	public function testAddReferenceDoesNotIgnoreCopies() {
223
		$list = new ReferenceList();
224
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
225
		$list->addReference( $reference );
226
		$list->addReference( clone $reference );
227
		$this->assertCount( 2, $list );
228
	}
229
230
	public function testAddReferenceAtIndexIgnoresIdenticalObjects() {
231
		$list = new ReferenceList();
232
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
233
		$list->addReference( $reference, 0 );
234
		$list->addReference( $reference, 0 );
235
		$this->assertCount( 1, $list );
236
	}
237
238
	public function testAddReferenceAtIndexMovesIdenticalObjects() {
239
		$list = new ReferenceList();
240
		$list->addNewReference( new PropertyNoValueSnak( 1 ) );
241
		$reference = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
242
		$list->addReference( $reference );
243
		$this->assertSame( 1, $list->indexOf( $reference ), 'pre condition' );
244
245
		$list->addReference( $reference, 0 );
246
247
		$this->assertCount( 2, $list, 'not added' );
248
		$this->assertSame( 0, $list->indexOf( $reference ), 'can decrease index' );
249
250
		$list->addReference( $reference, 2 );
251
252
		$this->assertCount( 2, $list, 'not added' );
253
		$this->assertSame( 0, $list->indexOf( $reference ), 'can not increase index' );
254
	}
255
256
	public function testAddReferenceAtIndexZero() {
257
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
258
		$reference2 = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
259
		$reference3 = new Reference( [ new PropertyNoValueSnak( 3 ) ] );
260
261
		$references = new ReferenceList( [ $reference1, $reference2 ] );
262
		$references->addReference( $reference3, 0 );
263
264
		$expectedList = new ReferenceList( [ $reference3, $reference1, $reference2 ] );
265
		$this->assertSameReferenceOrder( $expectedList, $references );
266
	}
267
268
	public function testAddReferenceAtNegativeIndex() {
269
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
270
		$referenceList = new ReferenceList();
271
272
		$this->setExpectedException( 'InvalidArgumentException' );
273
		$referenceList->addReference( $reference, -1 );
274
	}
275
276
	public function testGivenEmptyReference_addReferenceDoesNotAdd() {
277
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
278
		$reference2 = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
279
		$emptyReference = new Reference( [] );
280
281
		$references = new ReferenceList( [ $reference1, $reference2 ] );
282
		$references->addReference( $emptyReference );
283
284
		$expectedList = new ReferenceList( [ $reference1, $reference2 ] );
285
		$this->assertSameReferenceOrder( $expectedList, $references );
286
	}
287
288
	public function testGivenEmptyReferenceAndIndex_addReferenceDoesNotAdd() {
289
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
290
		$reference2 = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
291
		$emptyReference = new Reference( [] );
292
293
		$references = new ReferenceList( [ $reference1, $reference2 ] );
294
		$references->addReference( $emptyReference, 0 );
295
296
		$expectedList = new ReferenceList( [ $reference1, $reference2 ] );
297
		$this->assertSameReferenceOrder( $expectedList, $references );
298
	}
299
300
	/**
301
	 * @dataProvider instanceProvider
302
	 */
303
	public function testIndexOf( ReferenceList $array ) {
304
		$this->assertFalse( $array->indexOf( new Reference() ) );
305
306
		$i = 0;
307
		foreach ( $array as $reference ) {
308
			$this->assertSame( $i++, $array->indexOf( $reference ) );
309
		}
310
	}
311
312
	public function testIndexOf_checksForIdentity() {
313
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
314
		$reference2 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
315
		$referenceList = new ReferenceList( [ $reference1 ] );
316
317
		$this->assertNotSame( $reference1, $reference2, 'post condition' );
318
		$this->assertTrue( $reference1->equals( $reference2 ), 'post condition' );
319
		$this->assertSame( 0, $referenceList->indexOf( $reference1 ), 'identity' );
320
		$this->assertFalse( $referenceList->indexOf( $reference2 ), 'not equality' );
321
	}
322
323
	/**
324
	 * @dataProvider instanceProvider
325
	 */
326
	public function testEquals( ReferenceList $array ) {
327
		$this->assertTrue( $array->equals( $array ) );
328
		$this->assertFalse( $array->equals( 42 ) );
329
	}
330
331
	/**
332
	 * @dataProvider instanceProvider
333
	 */
334
	public function testGetValueHashReturnsString( ReferenceList $array ) {
335
		$this->assertInternalType( 'string', $array->getValueHash() );
336
	}
337
338
	/**
339
	 * @dataProvider instanceProvider
340
	 */
341
	public function testGetValueHashIsTheSameForClone( ReferenceList $array ) {
342
		$copy = unserialize( serialize( $array ) );
343
		$this->assertSame( $array->getValueHash(), $copy->getValueHash() );
344
	}
345
346
	/**
347
	 * @dataProvider instanceProvider
348
	 */
349
	public function testHasReferenceHash( ReferenceList $references ) {
350
		$this->assertFalse( $references->hasReferenceHash( '~=[,,_,,]:3' ) );
351
352
		/**
353
		 * @var Hashable $reference
354
		 */
355
		foreach ( $references as $reference ) {
356
			$this->assertTrue( $references->hasReferenceHash( $reference->getHash() ) );
357
		}
358
	}
359
360
	/**
361
	 * @dataProvider instanceProvider
362
	 */
363
	public function testGetReference( ReferenceList $references ) {
364
		$this->assertNull( $references->getReference( '~=[,,_,,]:3' ) );
365
366
		/**
367
		 * @var Reference $reference
368
		 */
369
		foreach ( $references as $reference ) {
370
			$this->assertTrue( $reference->equals( $references->getReference( $reference->getHash() ) ) );
371
		}
372
	}
373
374
	/**
375
	 * @dataProvider instanceProvider
376
	 */
377
	public function testRemoveReferenceHash( ReferenceList $references ) {
378
		$references->removeReferenceHash( '~=[,,_,,]:3' );
379
380
		$hashes = [];
381
382
		/**
383
		 * @var Reference $reference
384
		 */
385
		foreach ( $references as $reference ) {
386
			$hashes[] = $reference->getHash();
387
		}
388
389
		foreach ( $hashes as $hash ) {
390
			$references->removeReferenceHash( $hash );
391
		}
392
393
		$this->assertTrue( $references->isEmpty() );
394
	}
395
396
	public function testRemoveReferenceHashRemovesIdenticalObjects() {
397
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
398
		$references = new ReferenceList( [ $reference, $reference ] );
399
400
		$references->removeReferenceHash( $reference->getHash() );
401
402
		$this->assertTrue( $references->isEmpty() );
403
	}
404
405
	public function testRemoveReferenceHashDoesNotRemoveCopies() {
406
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
407
		$references = new ReferenceList( [ $reference, clone $reference ] );
408
409
		$references->removeReferenceHash( $reference->getHash() );
410
411
		$this->assertFalse( $references->isEmpty() );
412
		$this->assertTrue( $references->hasReference( $reference ) );
413
		$this->assertNotSame( $reference, $references->getReference( $reference->getHash() ) );
414
	}
415
416
	public function testRemoveReferenceHashUpdatesIndexes() {
417
		$reference1 = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
418
		$reference2 = new Reference( [ new PropertyNoValueSnak( 2 ) ] );
419
		$references = new ReferenceList( [ $reference1, $reference2 ] );
420
421
		$references->removeReferenceHash( $reference1->getHash() );
422
423
		$this->assertSame( 0, $references->indexOf( $reference2 ) );
424
	}
425
426
	public function testGivenOneSnak_addNewReferenceAddsSnak() {
427
		$references = new ReferenceList();
428
		$snak = new PropertyNoValueSnak( 1 );
429
430
		$references->addNewReference( $snak );
431
		$this->assertTrue( $references->hasReference( new Reference( [ $snak ] ) ) );
432
	}
433
434
	public function testGivenMultipleSnaks_addNewReferenceAddsThem() {
435
		$references = new ReferenceList();
436
		$snak1 = new PropertyNoValueSnak( 1 );
437
		$snak2 = new PropertyNoValueSnak( 3 );
438
		$snak3 = new PropertyNoValueSnak( 2 );
439
440
		$references->addNewReference( $snak1, $snak2, $snak3 );
441
442
		$expectedSnaks = [ $snak1, $snak2, $snak3 ];
443
		$this->assertTrue( $references->hasReference( new Reference( $expectedSnaks ) ) );
444
	}
445
446
	public function testGivenAnArrayOfSnaks_addNewReferenceAddsThem() {
447
		$references = new ReferenceList();
448
		$snaks = [
449
			new PropertyNoValueSnak( 1 ),
450
			new PropertyNoValueSnak( 3 ),
451
			new PropertyNoValueSnak( 2 )
452
		];
453
454
		$references->addNewReference( $snaks );
455
		$this->assertTrue( $references->hasReference( new Reference( $snaks ) ) );
456
	}
457
458
	public function testAddNewReferenceDoesNotIgnoreIdenticalObjects() {
459
		$list = new ReferenceList();
460
		$snak = new PropertyNoValueSnak( 1 );
461
		$list->addNewReference( $snak );
462
		$list->addNewReference( $snak );
463
		$this->assertCount( 2, $list );
464
	}
465
466
	public function testAddNewReferenceDoesNotIgnoreCopies() {
467
		$list = new ReferenceList();
468
		$snak = new PropertyNoValueSnak( 1 );
469
		$list->addNewReference( $snak );
470
		$list->addNewReference( clone $snak );
471
		$this->assertCount( 2, $list );
472
	}
473
474
	public function testGivenNoneSnak_addNewReferenceThrowsException() {
475
		$references = new ReferenceList();
476
477
		$this->setExpectedException( 'InvalidArgumentException' );
478
		$references->addNewReference( new PropertyNoValueSnak( 1 ), null );
479
	}
480
481
	public function testEmptySerializationStability() {
482
		$list = new ReferenceList();
483
		$this->assertSame( 'a:0:{}', $list->serialize() );
484
	}
485
486
	public function testSerializationStability() {
487
		$list = new ReferenceList();
488
		$list->addNewReference( new PropertyNoValueSnak( 1 ) );
489
		$this->assertSame(
490
			"a:1:{i:0;O:28:\"Wikibase\\DataModel\\Reference\":1:{s:35:\"\x00Wikibase\\DataModel\\"
491
			. "Reference\x00snaks\";C:32:\"Wikibase\\DataModel\\Snak\\SnakList\":102:{a:2:{s:4:\""
492
			. 'data";a:1:{i:0;C:43:"Wikibase\\DataModel\\Snak\\PropertyNoValueSnak":4:{i:1;}}s:5'
493
			. ':"index";i:0;}}}}',
494
			$list->serialize()
495
		);
496
	}
497
498
	public function testSerializeUnserializeRoundtrip() {
499
		$original = new ReferenceList();
500
		$original->addNewReference( new PropertyNoValueSnak( 1 ) );
501
502
		/** @var ReferenceList $clone */
503
		$clone = unserialize( serialize( $original ) );
504
505
		$this->assertTrue( $original->equals( $clone ) );
506
		$this->assertSame( $original->getValueHash(), $clone->getValueHash() );
507
		$this->assertSame( $original->serialize(), $clone->serialize() );
508
	}
509
510
	public function testUnserializeCreatesNonIdenticalClones() {
511
		$original = new ReferenceList();
512
		$reference = new Reference( [ new PropertyNoValueSnak( 1 ) ] );
513
		$original->addReference( $reference );
514
515
		/** @var ReferenceList $clone */
516
		$clone = unserialize( serialize( $original ) );
517
		$clone->addReference( $reference );
518
519
		$this->assertCount( 2, $clone );
520
	}
521
522
	public function testGivenEmptyList_isEmpty() {
523
		$references = new ReferenceList();
524
		$this->assertTrue( $references->isEmpty() );
525
	}
526
527
	public function testGivenNonEmptyList_isNotEmpty() {
528
		$references = new ReferenceList();
529
		$references->addNewReference( new PropertyNoValueSnak( 1 ) );
530
531
		$this->assertFalse( $references->isEmpty() );
532
	}
533
534
}
535