Passed
Push — int32EntityId ( fa80fb )
by no
05:13
created

testRemoveReferenceHashUpdatesIndexes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
rs 9.6666
cc 1
eloc 6
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 array(
29
			array( new ReferenceList( array() ) ),
30
			array( new ReferenceList( array(
31
				new Reference(),
32
				new Reference( array( new PropertyNoValueSnak( 2 ) ) ),
33
				new Reference( array( new PropertyNoValueSnak( 3 ) ) ),
34
			) ) ),
35
		);
36
	}
37
38
	public function testCanConstructWithReferenceListObject() {
39
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
40
		$original = new ReferenceList( array( $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( array( new PropertyNoValueSnak( 1 ) ) );
49
		$list = new ReferenceList( array( $reference, $reference ) );
50
		$this->assertCount( 1, $list );
51
	}
52
53
	public function testConstructorDoesNotIgnoreCopies() {
54
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
55
		$list = new ReferenceList( array( $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 array(
71
			array( null ),
72
			array( false ),
73
			array( 1 ),
74
			array( 0.1 ),
75
			array( 'string' ),
76
			array( $id1 ),
77
			array( new PropertyNoValueSnak( $id1 ) ),
78
			array( new Reference() ),
79
			array( new SnakList( array( new PropertyNoValueSnak( $id1 ) ) ) ),
80
			array( array( new PropertyNoValueSnak( $id1 ) ) ),
81
			array( array( new ReferenceList() ) ),
82
			array( array( new SnakList() ) ),
83
		);
84
	}
85
86
	public function testGetIterator_isTraversable() {
87
		$references = new ReferenceList();
88
		$references->addNewReference( new PropertyNoValueSnak( 1 ) );
89
		$iterator = $references->getIterator();
90
91
		$this->assertInstanceOf( 'Traversable', $iterator );
92
		$this->assertCount( 1, $iterator );
93
		foreach ( $references as $reference ) {
94
			$this->assertInstanceOf( 'Wikibase\DataModel\Reference', $reference );
95
		}
96
	}
97
98
	/**
99
	 * @dataProvider instanceProvider
100
	 */
101
	public function testHasReferenceBeforeRemoveButNotAfter( ReferenceList $array ) {
102
		if ( $array->count() === 0 ) {
103
			$this->assertTrue( true );
104
			return;
105
		}
106
107
		/**
108
		 * @var Reference $hashable
109
		 */
110
		foreach ( iterator_to_array( $array ) as $hashable ) {
111
			$this->assertTrue( $array->hasReference( $hashable ) );
112
			$array->removeReference( $hashable );
113
			$this->assertFalse( $array->hasReference( $hashable ) );
114
		}
115
	}
116
117
	public function testGivenCloneOfReferenceInList_hasReferenceReturnsTrue() {
118
		$list = new ReferenceList();
119
120
		$reference = new Reference( array( new PropertyNoValueSnak( 42 ) ) );
121
		$sameReference = unserialize( serialize( $reference ) );
122
123
		$list->addReference( $reference );
124
125
		$this->assertTrue(
126
			$list->hasReference( $sameReference ),
127
			'hasReference should return true when a reference with the same value is present, even when its another instance'
128
		);
129
	}
130
131
	/**
132
	 * @dataProvider instanceProvider
133
	 */
134
	public function testRemoveReference( ReferenceList $array ) {
135
		$elementCount = count( $array );
136
137
		/**
138
		 * @var Reference $element
139
		 */
140
		foreach ( iterator_to_array( $array ) as $element ) {
141
			$this->assertTrue( $array->hasReference( $element ) );
142
143
			$array->removeReference( $element );
144
145
			$this->assertFalse( $array->hasReference( $element ) );
146
			$this->assertEquals( --$elementCount, count( $array ) );
147
		}
148
	}
149
150
	public function testRemoveReferenceRemovesIdenticalObjects() {
151
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
152
		$references = new ReferenceList( array( $reference, $reference ) );
153
154
		$references->removeReference( $reference );
155
156
		$this->assertTrue( $references->isEmpty() );
157
	}
158
159
	public function testRemoveReferenceDoesNotRemoveCopies() {
160
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
161
		$references = new ReferenceList( array( $reference, clone $reference ) );
162
163
		$references->removeReference( $reference );
164
165
		$this->assertFalse( $references->isEmpty() );
166
		$this->assertTrue( $references->hasReference( $reference ) );
167
		$this->assertNotSame( $reference, $references->getReference( $reference->getHash() ) );
168
	}
169
170
	public function testAddReferenceOnEmptyList() {
171
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
172
173
		$references = new ReferenceList();
174
		$references->addReference( $reference );
175
176
		$this->assertCount( 1, $references );
177
178
		$expectedList = new ReferenceList( array( $reference ) );
179
		$this->assertSameReferenceOrder( $expectedList, $references );
180
	}
181
182
	private function assertSameReferenceOrder( ReferenceList $expectedList, ReferenceList $references ) {
183
		$this->assertEquals(
184
			iterator_to_array( $expectedList ),
185
			iterator_to_array( $references )
186
		);
187
	}
188
189
	public function testAddReferenceOnNonEmptyList() {
190
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
191
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
192
		$reference3 = new Reference( array( new PropertyNoValueSnak( 3 ) ) );
193
194
		$references = new ReferenceList( array( $reference1, $reference2 ) );
195
		$references->addReference( $reference3 );
196
197
		$this->assertCount( 3, $references );
198
199
		$expectedList = new ReferenceList( array( $reference1, $reference2, $reference3 ) );
200
		$this->assertSameReferenceOrder( $expectedList, $references );
201
	}
202
203
	public function testAddReferenceIgnoresIdenticalObjects() {
204
		$list = new ReferenceList();
205
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
206
		$list->addReference( $reference );
207
		$list->addReference( $reference );
208
		$this->assertCount( 1, $list );
209
	}
210
211
	public function testAddReferenceDoesNotIgnoreCopies() {
212
		$list = new ReferenceList();
213
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
214
		$list->addReference( $reference );
215
		$list->addReference( clone $reference );
216
		$this->assertCount( 2, $list );
217
	}
218
219
	public function testAddReferenceAtIndexIgnoresIdenticalObjects() {
220
		$list = new ReferenceList();
221
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
222
		$list->addReference( $reference, 0 );
223
		$list->addReference( $reference, 0 );
224
		$this->assertCount( 1, $list );
225
	}
226
227
	public function testAddReferenceAtIndexMovesIdenticalObjects() {
228
		$list = new ReferenceList();
229
		$list->addNewReference( new PropertyNoValueSnak( 1 ) );
230
		$reference = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
231
		$list->addReference( $reference );
232
		$this->assertSame( 1, $list->indexOf( $reference ), 'pre condition' );
233
234
		$list->addReference( $reference, 0 );
235
236
		$this->assertCount( 2, $list, 'not added' );
237
		$this->assertSame( 0, $list->indexOf( $reference ), 'can decrease index' );
238
239
		$list->addReference( $reference, 2 );
240
241
		$this->assertCount( 2, $list, 'not added' );
242
		$this->assertSame( 0, $list->indexOf( $reference ), 'can not increase index' );
243
	}
244
245
	public function testAddReferenceAtIndexZero() {
246
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
247
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
248
		$reference3 = new Reference( array( new PropertyNoValueSnak( 3 ) ) );
249
250
		$references = new ReferenceList( array( $reference1, $reference2 ) );
251
		$references->addReference( $reference3, 0 );
252
253
		$expectedList = new ReferenceList( array( $reference3, $reference1, $reference2 ) );
254
		$this->assertSameReferenceOrder( $expectedList, $references );
255
	}
256
257
	public function testAddReferenceAtNegativeIndex() {
258
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
259
		$referenceList = new ReferenceList();
260
261
		$this->setExpectedException( 'InvalidArgumentException' );
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
262
		$referenceList->addReference( $reference, -1 );
263
	}
264
265
	public function testGivenEmptyReference_addReferenceDoesNotAdd() {
266
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
267
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
268
		$emptyReference = new Reference( array() );
269
270
		$references = new ReferenceList( array( $reference1, $reference2 ) );
271
		$references->addReference( $emptyReference );
272
273
		$expectedList = new ReferenceList( array( $reference1, $reference2 ) );
274
		$this->assertSameReferenceOrder( $expectedList, $references );
275
	}
276
277
	public function testGivenEmptyReferenceAndIndex_addReferenceDoesNotAdd() {
278
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
279
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
280
		$emptyReference = new Reference( array() );
281
282
		$references = new ReferenceList( array( $reference1, $reference2 ) );
283
		$references->addReference( $emptyReference, 0 );
284
285
		$expectedList = new ReferenceList( array( $reference1, $reference2 ) );
286
		$this->assertSameReferenceOrder( $expectedList, $references );
287
	}
288
289
	/**
290
	 * @dataProvider instanceProvider
291
	 */
292
	public function testIndexOf( ReferenceList $array ) {
293
		$this->assertFalse( $array->indexOf( new Reference() ) );
294
295
		$i = 0;
296
		foreach ( $array as $reference ) {
297
			$this->assertEquals( $i++, $array->indexOf( $reference ) );
298
		}
299
	}
300
301
	public function testIndexOf_checksForIdentity() {
302
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
303
		$reference2 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
304
		$referenceList = new ReferenceList( array( $reference1 ) );
305
306
		$this->assertNotSame( $reference1, $reference2, 'post condition' );
307
		$this->assertTrue( $reference1->equals( $reference2 ), 'post condition' );
308
		$this->assertSame( 0, $referenceList->indexOf( $reference1 ), 'identity' );
309
		$this->assertFalse( $referenceList->indexOf( $reference2 ), 'not equality' );
310
	}
311
312
	/**
313
	 * @dataProvider instanceProvider
314
	 */
315
	public function testEquals( ReferenceList $array ) {
316
		$this->assertTrue( $array->equals( $array ) );
317
		$this->assertFalse( $array->equals( 42 ) );
318
	}
319
320
	/**
321
	 * @dataProvider instanceProvider
322
	 */
323
	public function testGetValueHashReturnsString( ReferenceList $array ) {
324
		$this->assertInternalType( 'string', $array->getValueHash() );
325
	}
326
327
	/**
328
	 * @dataProvider instanceProvider
329
	 */
330
	public function testGetValueHashIsTheSameForClone( ReferenceList $array ) {
331
		$copy = unserialize( serialize( $array ) );
332
		$this->assertEquals( $array->getValueHash(), $copy->getValueHash() );
333
	}
334
335
	/**
336
	 * @dataProvider instanceProvider
337
	 */
338
	public function testHasReferenceHash( ReferenceList $references ) {
339
		$this->assertFalse( $references->hasReferenceHash( '~=[,,_,,]:3' ) );
340
341
		/**
342
		 * @var Hashable $reference
343
		 */
344
		foreach ( $references as $reference ) {
345
			$this->assertTrue( $references->hasReferenceHash( $reference->getHash() ) );
346
		}
347
	}
348
349
	/**
350
	 * @dataProvider instanceProvider
351
	 */
352
	public function testGetReference( ReferenceList $references ) {
353
		$this->assertNull( $references->getReference( '~=[,,_,,]:3' ) );
354
355
		/**
356
		 * @var Reference $reference
357
		 */
358
		foreach ( $references as $reference ) {
359
			$this->assertTrue( $reference->equals( $references->getReference( $reference->getHash() ) ) );
360
		}
361
	}
362
363
	/**
364
	 * @dataProvider instanceProvider
365
	 */
366
	public function testRemoveReferenceHash( ReferenceList $references ) {
367
		$references->removeReferenceHash( '~=[,,_,,]:3' );
368
369
		$hashes = array();
370
371
		/**
372
		 * @var Reference $reference
373
		 */
374
		foreach ( $references as $reference ) {
375
			$hashes[] = $reference->getHash();
376
		}
377
378
		foreach ( $hashes as $hash ) {
379
			$references->removeReferenceHash( $hash );
380
		}
381
382
		$this->assertEquals( 0, count( $references ) );
383
	}
384
385
	public function testRemoveReferenceHashRemovesIdenticalObjects() {
386
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
387
		$references = new ReferenceList( array( $reference, $reference ) );
388
389
		$references->removeReferenceHash( $reference->getHash() );
390
391
		$this->assertTrue( $references->isEmpty() );
392
	}
393
394
	public function testRemoveReferenceHashDoesNotRemoveCopies() {
395
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
396
		$references = new ReferenceList( array( $reference, clone $reference ) );
397
398
		$references->removeReferenceHash( $reference->getHash() );
399
400
		$this->assertFalse( $references->isEmpty() );
401
		$this->assertTrue( $references->hasReference( $reference ) );
402
		$this->assertNotSame( $reference, $references->getReference( $reference->getHash() ) );
403
	}
404
405
	public function testRemoveReferenceHashUpdatesIndexes() {
406
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
407
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
408
		$references = new ReferenceList( array( $reference1, $reference2 ) );
409
410
		$references->removeReferenceHash( $reference1->getHash() );
411
412
		$this->assertSame( 0, $references->indexOf( $reference2 ) );
413
	}
414
415
	public function testGivenOneSnak_addNewReferenceAddsSnak() {
416
		$references = new ReferenceList();
417
		$snak = new PropertyNoValueSnak( 1 );
418
419
		$references->addNewReference( $snak );
420
		$this->assertTrue( $references->hasReference( new Reference( array( $snak ) ) ) );
421
	}
422
423
	public function testGivenMultipleSnaks_addNewReferenceAddsThem() {
424
		$references = new ReferenceList();
425
		$snak1 = new PropertyNoValueSnak( 1 );
426
		$snak2 = new PropertyNoValueSnak( 3 );
427
		$snak3 = new PropertyNoValueSnak( 2 );
428
429
		$references->addNewReference( $snak1, $snak2, $snak3 );
430
431
		$expectedSnaks = array( $snak1, $snak2, $snak3 );
432
		$this->assertTrue( $references->hasReference( new Reference( $expectedSnaks ) ) );
433
	}
434
435
	public function testGivenAnArrayOfSnaks_addNewReferenceAddsThem() {
436
		$references = new ReferenceList();
437
		$snaks = array(
438
			new PropertyNoValueSnak( 1 ),
439
			new PropertyNoValueSnak( 3 ),
440
			new PropertyNoValueSnak( 2 )
441
		);
442
443
		$references->addNewReference( $snaks );
444
		$this->assertTrue( $references->hasReference( new Reference( $snaks ) ) );
445
	}
446
447
	public function testAddNewReferenceDoesNotIgnoreIdenticalObjects() {
448
		$list = new ReferenceList();
449
		$snak = new PropertyNoValueSnak( 1 );
450
		$list->addNewReference( $snak );
451
		$list->addNewReference( $snak );
452
		$this->assertCount( 2, $list );
453
	}
454
455
	public function testAddNewReferenceDoesNotIgnoreCopies() {
456
		$list = new ReferenceList();
457
		$snak = new PropertyNoValueSnak( 1 );
458
		$list->addNewReference( $snak );
459
		$list->addNewReference( clone $snak );
460
		$this->assertCount( 2, $list );
461
	}
462
463
	public function testGivenNoneSnak_addNewReferenceThrowsException() {
464
		$references = new ReferenceList();
465
466
		$this->setExpectedException( 'InvalidArgumentException' );
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
467
		$references->addNewReference( new PropertyNoValueSnak( 1 ), null );
468
	}
469
470
	public function testEmptySerializationStability() {
471
		$list = new ReferenceList();
472
		$this->assertSame( 'a:0:{}', $list->serialize() );
473
	}
474
475
	public function testSerializationStability() {
476
		$list = new ReferenceList();
477
		$list->addNewReference( new PropertyNoValueSnak( 1 ) );
478
		$this->assertSame(
479
			"a:1:{i:0;O:28:\"Wikibase\\DataModel\\Reference\":1:{s:35:\"\x00Wikibase\\DataModel\\"
480
			. "Reference\x00snaks\";C:32:\"Wikibase\\DataModel\\Snak\\SnakList\":102:{a:2:{s:4:\""
481
			. 'data";a:1:{i:0;C:43:"Wikibase\\DataModel\\Snak\\PropertyNoValueSnak":4:{i:1;}}s:5'
482
			. ':"index";i:0;}}}}',
483
			$list->serialize()
484
		);
485
	}
486
487
	public function testSerializeUnserializeRoundtrip() {
488
		$original = new ReferenceList();
489
		$original->addNewReference( new PropertyNoValueSnak( 1 ) );
490
491
		/** @var ReferenceList $clone */
492
		$clone = unserialize( serialize( $original ) );
493
494
		$this->assertTrue( $original->equals( $clone ) );
495
		$this->assertSame( $original->getValueHash(), $clone->getValueHash() );
496
		$this->assertSame( $original->serialize(), $clone->serialize() );
497
	}
498
499
	public function testUnserializeCreatesNonIdenticalClones() {
500
		$original = new ReferenceList();
501
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
502
		$original->addReference( $reference );
503
504
		/** @var ReferenceList $clone */
505
		$clone = unserialize( serialize( $original ) );
506
		$clone->addReference( $reference );
507
508
		$this->assertCount( 2, $clone );
509
	}
510
511
	public function testGivenEmptyList_isEmpty() {
512
		$references = new ReferenceList();
513
		$this->assertTrue( $references->isEmpty() );
514
	}
515
516
	public function testGivenNonEmptyList_isNotEmpty() {
517
		$references = new ReferenceList();
518
		$references->addNewReference( new PropertyNoValueSnak( 1 ) );
519
520
		$this->assertFalse( $references->isEmpty() );
521
	}
522
523
}
524