Passed
Push — refIdentity ( 075981 )
by no
03:49
created

ReferenceListTest::testIndexOf_checksForIdentity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 1
eloc 8
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\DataModel\Tests;
4
5
use Hashable;
6
use InvalidArgumentException;
7
use Wikibase\DataModel\Entity\PropertyId;
8
use Wikibase\DataModel\Reference;
9
use Wikibase\DataModel\ReferenceList;
10
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
11
use Wikibase\DataModel\Snak\SnakList;
12
13
/**
14
 * @covers Wikibase\DataModel\ReferenceList
15
 *
16
 * @group Wikibase
17
 * @group WikibaseDataModel
18
 * @group WikibaseReference
19
 *
20
 * @licence GNU GPL v2+
21
 * @author Jeroen De Dauw < [email protected] >
22
 * @author Thiemo Mättig
23
 */
24
class ReferenceListTest extends \PHPUnit_Framework_TestCase {
25
26
	public function instanceProvider() {
27
		$instances = array();
28
29
		foreach ( $this->getConstructorArg() as $arg ) {
30
			$instances[] = array( new ReferenceList( $arg ) );
31
		}
32
33
		return $instances;
34
	}
35
36
	public function getElementInstances() {
37
		return array(
38
			new Reference(),
39
			new Reference( array( new PropertyNoValueSnak( 2 ) ) ),
40
			new Reference( array( new PropertyNoValueSnak( 3 ) ) ),
41
		);
42
	}
43
44
	public function getConstructorArg() {
45
		return array(
46
			array(),
47
			$this->getElementInstances(),
48
		);
49
	}
50
51
	public function testCanConstructWithReferenceListObject() {
52
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
53
		$original = new ReferenceList( array( $reference ) );
54
		$copy = new ReferenceList( $original );
55
56
		$this->assertSame( 1, $copy->count() );
57
		$this->assertNotNull( $copy->getReference( $reference->getHash() ) );
58
	}
59
60
	/**
61
	 * @dataProvider invalidConstructorArgumentsProvider
62
	 * @expectedException InvalidArgumentException
63
	 */
64
	public function testGivenInvalidConstructorArguments_constructorThrowsException( $input ) {
65
		new ReferenceList( $input );
66
	}
67
68
	public function invalidConstructorArgumentsProvider() {
69
		$id1 = new PropertyId( 'P1' );
70
71
		return array(
72
			array( null ),
73
			array( false ),
74
			array( 1 ),
75
			array( 0.1 ),
76
			array( 'string' ),
77
			array( $id1 ),
78
			array( new PropertyNoValueSnak( $id1 ) ),
79
			array( new Reference() ),
80
			array( new SnakList( array( new PropertyNoValueSnak( $id1 ) ) ) ),
81
			array( array( new PropertyNoValueSnak( $id1 ) ) ),
82
			array( array( new ReferenceList() ) ),
83
			array( array( new SnakList() ) ),
84
		);
85
	}
86
87
	/**
88
	 * @dataProvider instanceProvider
89
	 * @param ReferenceList $array
90
	 */
91
	public function testHasReferenceBeforeRemoveButNotAfter( ReferenceList $array ) {
92
		if ( $array->count() === 0 ) {
93
			$this->assertTrue( true );
94
			return;
95
		}
96
97
		/**
98
		 * @var Reference $hashable
99
		 */
100
		foreach ( iterator_to_array( $array ) as $hashable ) {
101
			$this->assertTrue( $array->hasReference( $hashable ) );
102
			$array->removeReference( $hashable );
103
			$this->assertFalse( $array->hasReference( $hashable ) );
104
		}
105
	}
106
107
	public function testGivenCloneOfReferenceInList_hasReferenceReturnsTrue() {
108
		$list = new ReferenceList();
109
110
		$reference = new Reference( array( new PropertyNoValueSnak( 42 ) ) );
111
		$sameReference = unserialize( serialize( $reference ) );
112
113
		$list->addReference( $reference );
114
115
		$this->assertTrue(
116
			$list->hasReference( $sameReference ),
117
			'hasReference should return true when a reference with the same value is present, even when its another instance'
118
		);
119
	}
120
121
	/**
122
	 * @dataProvider instanceProvider
123
	 * @param ReferenceList $array
124
	 */
125
	public function testRemoveReference( ReferenceList $array ) {
126
		$elementCount = count( $array );
127
128
		/**
129
		 * @var Reference $element
130
		 */
131
		foreach ( iterator_to_array( $array ) as $element ) {
132
			$this->assertTrue( $array->hasReference( $element ) );
133
134
			$array->removeReference( $element );
135
136
			$this->assertFalse( $array->hasReference( $element ) );
137
			$this->assertEquals( --$elementCount, count( $array ) );
138
		}
139
140
		$elements = $this->getElementInstances();
141
		$element = array_shift( $elements );
142
143
		$array->removeReference( $element );
0 ignored issues
show
Bug introduced by
It seems like $element defined by array_shift($elements) on line 141 can be null; however, Wikibase\DataModel\Refer...List::removeReference() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
144
		$array->removeReference( $element );
0 ignored issues
show
Bug introduced by
It seems like $element defined by array_shift($elements) on line 141 can be null; however, Wikibase\DataModel\Refer...List::removeReference() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
145
146
		$this->assertTrue( true );
147
	}
148
149
	public function testAddReferenceOnEmptyList() {
150
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
151
152
		$references = new ReferenceList();
153
		$references->addReference( $reference );
154
155
		$this->assertCount( 1, $references );
156
157
		$expectedList = new ReferenceList( array( $reference ) );
158
		$this->assertSameReferenceOrder( $expectedList, $references );
159
	}
160
161
	private function assertSameReferenceOrder( ReferenceList $expectedList, ReferenceList $references ) {
162
		$this->assertEquals(
163
			iterator_to_array( $expectedList ),
164
			iterator_to_array( $references )
165
		);
166
	}
167
168
	public function testAddReferenceOnNonEmptyList() {
169
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
170
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
171
		$reference3 = new Reference( array( new PropertyNoValueSnak( 3 ) ) );
172
173
		$references = new ReferenceList( array( $reference1, $reference2 ) );
174
		$references->addReference( $reference3 );
175
176
		$this->assertCount( 3, $references );
177
178
		$expectedList = new ReferenceList( array( $reference1, $reference2, $reference3 ) );
179
		$this->assertSameReferenceOrder( $expectedList, $references );
180
	}
181
182
	public function testAddReferenceAtIndexZero() {
183
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
184
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
185
		$reference3 = new Reference( array( new PropertyNoValueSnak( 3 ) ) );
186
187
		$references = new ReferenceList( array( $reference1, $reference2 ) );
188
		$references->addReference( $reference3, 0 );
189
190
		$expectedList = new ReferenceList( array( $reference3, $reference1, $reference2 ) );
191
		$this->assertSameReferenceOrder( $expectedList, $references );
192
	}
193
194
	public function testAddReferenceAtNegativeIndex() {
195
		$reference = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
196
		$referenceList = new ReferenceList();
197
198
		$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...
199
		$referenceList->addReference( $reference, -1 );
200
	}
201
202
	public function testGivenEmptyReference_addReferenceDoesNotAdd() {
203
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
204
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
205
		$emptyReference = new Reference( array() );
206
207
		$references = new ReferenceList( array( $reference1, $reference2 ) );
208
		$references->addReference( $emptyReference );
209
210
		$expectedList = new ReferenceList( array( $reference1, $reference2 ) );
211
		$this->assertSameReferenceOrder( $expectedList, $references );
212
	}
213
214
	public function testGivenEmptyReferenceAndIndex_addReferenceDoesNotAdd() {
215
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
216
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
217
		$emptyReference = new Reference( array() );
218
219
		$references = new ReferenceList( array( $reference1, $reference2 ) );
220
		$references->addReference( $emptyReference, 0 );
221
222
		$expectedList = new ReferenceList( array( $reference1, $reference2 ) );
223
		$this->assertSameReferenceOrder( $expectedList, $references );
224
	}
225
226
	/**
227
	 * @dataProvider instanceProvider
228
	 * @param ReferenceList $array
229
	 */
230
	public function testIndexOf( ReferenceList $array ) {
231
		$this->assertFalse( $array->indexOf( new Reference() ) );
232
233
		$i = 0;
234
		foreach ( $array as $reference ) {
235
			$this->assertEquals( $i++, $array->indexOf( $reference ) );
236
		}
237
	}
238
239
	public function testIndexOf_checksForIdentity() {
240
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
241
		$reference2 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
242
		$referenceList = new ReferenceList( array( $reference1 ) );
243
244
		$this->assertNotSame( $reference1, $reference2, 'post condition' );
245
		$this->assertTrue( $reference1->equals( $reference2 ), 'post condition' );
246
		$this->assertSame( 0, $referenceList->indexOf( $reference1 ), 'identity' );
247
		$this->assertFalse( $referenceList->indexOf( $reference2 ), 'not equality' );
248
	}
249
250
	/**
251
	 * @dataProvider instanceProvider
252
	 * @param ReferenceList $array
253
	 */
254
	public function testEquals( ReferenceList $array ) {
255
		$this->assertTrue( $array->equals( $array ) );
256
		$this->assertFalse( $array->equals( 42 ) );
257
	}
258
259
	/**
260
	 * @dataProvider instanceProvider
261
	 * @param ReferenceList $array
262
	 */
263
	public function testGetHashReturnsString( ReferenceList $array ) {
264
		$this->assertInternalType( 'string', $array->getValueHash() );
265
	}
266
267
	/**
268
	 * @dataProvider instanceProvider
269
	 * @param ReferenceList $array
270
	 */
271
	public function testGetHashValueIsTheSameForClone( ReferenceList $array ) {
272
		$copy = unserialize( serialize( $array ) );
273
		$this->assertEquals( $array->getValueHash(), $copy->getValueHash() );
274
	}
275
276
	/**
277
	 * @dataProvider instanceProvider
278
	 * @param ReferenceList $references
279
	 */
280
	public function testHasReferenceHash( ReferenceList $references ) {
281
		$this->assertFalse( $references->hasReferenceHash( '~=[,,_,,]:3' ) );
282
283
		/**
284
		 * @var Hashable $reference
285
		 */
286
		foreach ( $references as $reference ) {
287
			$this->assertTrue( $references->hasReferenceHash( $reference->getHash() ) );
288
		}
289
	}
290
291
	/**
292
	 * @dataProvider instanceProvider
293
	 * @param ReferenceList $references
294
	 */
295
	public function testGetReference( ReferenceList $references ) {
296
		$this->assertNull( $references->getReference( '~=[,,_,,]:3' ) );
297
298
		/**
299
		 * @var Reference $reference
300
		 */
301
		foreach ( $references as $reference ) {
302
			$this->assertTrue( $reference->equals( $references->getReference( $reference->getHash() ) ) );
303
		}
304
	}
305
306
	/**
307
	 * @dataProvider instanceProvider
308
	 * @param ReferenceList $references
309
	 */
310
	public function testRemoveReferenceHash( ReferenceList $references ) {
311
		$references->removeReferenceHash( '~=[,,_,,]:3' );
312
313
		$hashes = array();
314
315
		/**
316
		 * @var Reference $reference
317
		 */
318
		foreach ( $references as $reference ) {
319
			$hashes[] = $reference->getHash();
320
		}
321
322
		foreach ( $hashes as $hash ) {
323
			$references->removeReferenceHash( $hash );
324
		}
325
326
		$this->assertEquals( 0, count( $references ) );
327
	}
328
329
	public function testGivenOneSnak_addNewReferenceAddsSnak() {
330
		$references = new ReferenceList();
331
		$snak = new PropertyNoValueSnak( 1 );
332
333
		$references->addNewReference( $snak );
334
		$this->assertTrue( $references->hasReference( new Reference( array( $snak ) ) ) );
335
	}
336
337
	public function testGivenMultipleSnaks_addNewReferenceAddsThem() {
338
		$references = new ReferenceList();
339
		$snak1 = new PropertyNoValueSnak( 1 );
340
		$snak2 = new PropertyNoValueSnak( 3 );
341
		$snak3 = new PropertyNoValueSnak( 2 );
342
343
		$references->addNewReference( $snak1, $snak2, $snak3 );
344
345
		$expectedSnaks = array( $snak1, $snak2, $snak3 );
346
		$this->assertTrue( $references->hasReference( new Reference( $expectedSnaks ) ) );
347
	}
348
349
	public function testGivenAnArrayOfSnaks_addNewReferenceAddsThem() {
350
		$references = new ReferenceList();
351
		$snaks = array(
352
			new PropertyNoValueSnak( 1 ),
353
			new PropertyNoValueSnak( 3 ),
354
			new PropertyNoValueSnak( 2 )
355
		);
356
357
		$references->addNewReference( $snaks );
358
		$this->assertTrue( $references->hasReference( new Reference( $snaks ) ) );
359
	}
360
361
	public function testGivenNoneSnak_addNewReferenceThrowsException() {
362
		$references = new ReferenceList();
363
364
		$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...
365
		$references->addNewReference( new PropertyNoValueSnak( 1 ), null );
366
	}
367
368
	public function testSerializeRoundtrip() {
369
		$references = new ReferenceList();
370
371
		$references->addReference( new Reference() );
372
373
		$references->addReference( new Reference( array(
374
			new PropertyNoValueSnak( 2 ),
375
			new PropertyNoValueSnak( 3 ),
376
		) ) );
377
378
		$serialized = serialize( $references );
379
		$this->assertTrue( $references->equals( unserialize( $serialized ) ) );
380
	}
381
382
	public function testGivenEmptyList_isEmpty() {
383
		$references = new ReferenceList();
384
		$this->assertTrue( $references->isEmpty() );
385
	}
386
387
	public function testGivenNonEmptyList_isNotEmpty() {
388
		$references = new ReferenceList();
389
		$references->addNewReference( new PropertyNoValueSnak( 1 ) );
390
391
		$this->assertFalse( $references->isEmpty() );
392
	}
393
394
}
395