Completed
Pull Request — master (#617)
by Bene
05:59 queued 03:04
created

testGivenOneSnak_addNewReferenceAddsSnak()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4285
cc 1
eloc 5
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
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
196
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
197
		$reference3 = new Reference( array( new PropertyNoValueSnak( 3 ) ) );
198
199
		$references = new ReferenceList( array( $reference1, $reference2 ) );
200
201
		$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...
202
		$references->addReference( $reference3, -1 );
203
	}
204
205
	public function testGivenEmptyReference_addReferenceDoesNotAdd() {
206
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
207
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
208
		$emptyReference = new Reference( array() );
209
210
		$references = new ReferenceList( array( $reference1, $reference2 ) );
211
		$references->addReference( $emptyReference );
212
213
		$expectedList = new ReferenceList( array( $reference1, $reference2 ) );
214
		$this->assertSameReferenceOrder( $expectedList, $references );
215
	}
216
217
	public function testGivenEmptyReferenceAndIndex_addReferenceDoesNotAdd() {
218
		$reference1 = new Reference( array( new PropertyNoValueSnak( 1 ) ) );
219
		$reference2 = new Reference( array( new PropertyNoValueSnak( 2 ) ) );
220
		$emptyReference = new Reference( array() );
221
222
		$references = new ReferenceList( array( $reference1, $reference2 ) );
223
		$references->addReference( $emptyReference, 0 );
224
225
		$expectedList = new ReferenceList( array( $reference1, $reference2 ) );
226
		$this->assertSameReferenceOrder( $expectedList, $references );
227
	}
228
229
	/**
230
	 * @dataProvider instanceProvider
231
	 * @param ReferenceList $array
232
	 */
233
	public function testIndexOf( ReferenceList $array ) {
234
		$this->assertFalse( $array->indexOf( new Reference() ) );
235
236
		$i = 0;
237
		foreach ( $array as $reference ) {
238
			$this->assertEquals( $i++, $array->indexOf( $reference ) );
239
		}
240
	}
241
242
	/**
243
	 * @dataProvider instanceProvider
244
	 * @param ReferenceList $array
245
	 */
246
	public function testEquals( ReferenceList $array ) {
247
		$this->assertTrue( $array->equals( $array ) );
248
		$this->assertFalse( $array->equals( 42 ) );
249
	}
250
251
	/**
252
	 * @dataProvider instanceProvider
253
	 * @param ReferenceList $array
254
	 */
255
	public function testGetHashReturnsString( ReferenceList $array ) {
256
		$this->assertInternalType( 'string', $array->getValueHash() );
257
	}
258
259
	/**
260
	 * @dataProvider instanceProvider
261
	 * @param ReferenceList $array
262
	 */
263
	public function testGetHashValueIsTheSameForClone( ReferenceList $array ) {
264
		$copy = unserialize( serialize( $array ) );
265
		$this->assertEquals( $array->getValueHash(), $copy->getValueHash() );
266
	}
267
268
	/**
269
	 * @dataProvider instanceProvider
270
	 * @param ReferenceList $references
271
	 */
272
	public function testHasReferenceHash( ReferenceList $references ) {
273
		$this->assertFalse( $references->hasReferenceHash( '~=[,,_,,]:3' ) );
274
275
		/**
276
		 * @var Hashable $reference
277
		 */
278
		foreach ( $references as $reference ) {
279
			$this->assertTrue( $references->hasReferenceHash( $reference->getHash() ) );
280
		}
281
	}
282
283
	/**
284
	 * @dataProvider instanceProvider
285
	 * @param ReferenceList $references
286
	 */
287
	public function testGetReference( ReferenceList $references ) {
288
		$this->assertNull( $references->getReference( '~=[,,_,,]:3' ) );
289
290
		/**
291
		 * @var Reference $reference
292
		 */
293
		foreach ( $references as $reference ) {
294
			$this->assertTrue( $reference->equals( $references->getReference( $reference->getHash() ) ) );
295
		}
296
	}
297
298
	/**
299
	 * @dataProvider instanceProvider
300
	 * @param ReferenceList $references
301
	 */
302
	public function testRemoveReferenceHash( ReferenceList $references ) {
303
		$references->removeReferenceHash( '~=[,,_,,]:3' );
304
305
		$hashes = array();
306
307
		/**
308
		 * @var Reference $reference
309
		 */
310
		foreach ( $references as $reference ) {
311
			$hashes[] = $reference->getHash();
312
		}
313
314
		foreach ( $hashes as $hash ) {
315
			$references->removeReferenceHash( $hash );
316
		}
317
318
		$this->assertEquals( 0, count( $references ) );
319
	}
320
321
	public function testGivenOneSnak_addNewReferenceAddsSnak() {
322
		$references = new ReferenceList();
323
		$snak = new PropertyNoValueSnak( 1 );
324
325
		$references->addNewReference( $snak );
326
		$this->assertTrue( $references->hasReference( new Reference( array( $snak ) ) ) );
327
	}
328
329
	public function testGivenMultipleSnaks_addNewReferenceAddsThem() {
330
		$references = new ReferenceList();
331
		$snak1 = new PropertyNoValueSnak( 1 );
332
		$snak2 = new PropertyNoValueSnak( 3 );
333
		$snak3 = new PropertyNoValueSnak( 2 );
334
335
		$references->addNewReference( $snak1, $snak2, $snak3 );
336
337
		$expectedSnaks = array( $snak1, $snak2, $snak3 );
338
		$this->assertTrue( $references->hasReference( new Reference( $expectedSnaks ) ) );
339
	}
340
341
	public function testGivenAnArrayOfSnaks_addNewReferenceAddsThem() {
342
		$references = new ReferenceList();
343
		$snaks = array(
344
			new PropertyNoValueSnak( 1 ),
345
			new PropertyNoValueSnak( 3 ),
346
			new PropertyNoValueSnak( 2 )
347
		);
348
349
		$references->addNewReference( $snaks );
350
		$this->assertTrue( $references->hasReference( new Reference( $snaks ) ) );
351
	}
352
353
	public function testGivenNoneSnak_addNewReferenceThrowsException() {
354
		$references = new ReferenceList();
355
356
		$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...
357
		$references->addNewReference( new PropertyNoValueSnak( 1 ), null );
358
	}
359
360
	public function testSerializeRoundtrip() {
361
		$references = new ReferenceList();
362
363
		$references->addReference( new Reference() );
364
365
		$references->addReference( new Reference( array(
366
			new PropertyNoValueSnak( 2 ),
367
			new PropertyNoValueSnak( 3 ),
368
		) ) );
369
370
		$serialized = serialize( $references );
371
		$this->assertTrue( $references->equals( unserialize( $serialized ) ) );
372
	}
373
374
	public function testGivenEmptyList_isEmpty() {
375
		$references = new ReferenceList();
376
		$this->assertTrue( $references->isEmpty() );
377
	}
378
379
	public function testGivenNonEmptyList_isNotEmpty() {
380
		$references = new ReferenceList();
381
		$references->addNewReference( new PropertyNoValueSnak( 1 ) );
382
383
		$this->assertFalse( $references->isEmpty() );
384
	}
385
386
}
387