Passed
Push — equalHashArrays ( ea52b8...32bc1b )
by no
07:38 queued 03:50
created

SnakListTest   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 308
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 6
dl 0
loc 308
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A testGivenAssociativeArray_constructorPreservesArrayKeys() 0 4 1
A testHasSnak() 0 14 2
B testRemoveSnak() 0 27 3
A testAddSnak() 0 19 2
B orderByPropertyProvider() 0 93 3
A testOrderByProperty() 0 17 2
A getInstanceClass() 0 3 1
A elementInstancesProvider() 0 11 1
A constructorProvider() 0 21 1
A testGivenInvalidConstructorArguments_constructorThrowsException() 0 3 1
A invalidConstructorArgumentsProvider() 0 16 1
A testComparableInterface() 0 3 1
A testEquals() 0 3 1
B equalsProvider() 0 32 1
1
<?php
2
3
namespace Wikibase\DataModel\Tests\Snak;
4
5
use Comparable;
6
use DataValues\StringValue;
7
use InvalidArgumentException;
8
use Wikibase\DataModel\Entity\PropertyId;
9
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
10
use Wikibase\DataModel\Snak\PropertyValueSnak;
11
use Wikibase\DataModel\Snak\Snak;
12
use Wikibase\DataModel\Snak\SnakList;
13
use Wikibase\DataModel\Tests\HashArray\HashArrayTest;
14
15
/**
16
 * @covers Wikibase\DataModel\Snak\SnakList
17
 * @uses DataValues\StringValue
18
 * @uses Wikibase\DataModel\Entity\PropertyId
19
 * @uses Wikibase\DataModel\Snak\PropertyNoValueSnak
20
 * @uses Wikibase\DataModel\Snak\PropertyValueSnak
21
 * @uses Wikibase\DataModel\Snak\Snak
22
 * @uses Wikibase\DataModel\Snak\SnakList
23
 * @uses Wikibase\DataModel\HashArray
24
 * @uses Wikibase\DataModel\Snak\SnakObject
25
 * @uses Wikibase\DataModel\Internal\MapValueHasher
26
 * @uses Wikibase\DataModel\Entity\EntityId
27
 *
28
 * @license GPL-2.0+
29
 * @author Jeroen De Dauw < [email protected] >
30
 * @author Addshore
31
 * @author Thiemo Mättig
32
 */
33
class SnakListTest extends HashArrayTest {
34
35
	/**
36
	 * @see HashArrayTest::getInstanceClass
37
	 */
38
	public function getInstanceClass() {
39
		return 'Wikibase\DataModel\Snak\SnakList';
40
	}
41
42
	public function elementInstancesProvider() {
43
		$id42 = new PropertyId( 'P42' );
44
45
		$argLists = [];
46
47
		$argLists[] = [ [ new PropertyNoValueSnak( $id42 ) ] ];
48
		$argLists[] = [ [ new PropertyNoValueSnak( new PropertyId( 'P9001' ) ) ] ];
49
		$argLists[] = [ [ new PropertyValueSnak( $id42, new StringValue( 'a' ) ) ] ];
50
51
		return $argLists;
52
	}
53
54
	public function constructorProvider() {
55
		$id42 = new PropertyId( 'P42' );
56
		$id9001 = new PropertyId( 'P9001' );
57
58
		return [
59
			[],
60
			[ [] ],
61
			[ [
62
				new PropertyNoValueSnak( $id42 )
63
			] ],
64
			[ [
65
				new PropertyNoValueSnak( $id42 ),
66
				new PropertyNoValueSnak( $id9001 ),
67
			] ],
68
			[ [
69
				new PropertyNoValueSnak( $id42 ),
70
				new PropertyNoValueSnak( $id9001 ),
71
				new PropertyValueSnak( $id42, new StringValue( 'a' ) ),
72
			] ],
73
		];
74
	}
75
76
	/**
77
	 * @dataProvider invalidConstructorArgumentsProvider
78
	 * @expectedException InvalidArgumentException
79
	 */
80
	public function testGivenInvalidConstructorArguments_constructorThrowsException( $input ) {
81
		new SnakList( $input );
82
	}
83
84
	public function invalidConstructorArgumentsProvider() {
85
		$id1 = new PropertyId( 'P1' );
86
87
		return [
88
			[ false ],
89
			[ 1 ],
90
			[ 0.1 ],
91
			[ 'string' ],
92
			[ $id1 ],
93
			[ new PropertyNoValueSnak( $id1 ) ],
94
			[ new PropertyValueSnak( $id1, new StringValue( 'a' ) ) ],
95
			[ [ null ] ],
96
			[ [ $id1 ] ],
97
			[ [ new SnakList() ] ],
98
		];
99
	}
100
101
	public function testGivenAssociativeArray_constructorPreservesArrayKeys() {
102
		$snakList = new SnakList( [ 'key' => new PropertyNoValueSnak( 1 ) ] );
103
		$this->assertSame( [ 'key' ], array_keys( iterator_to_array( $snakList ) ) );
104
	}
105
106
	/**
107
	 * @dataProvider instanceProvider
108
	 * @param SnakList $array
109
	 */
110
	public function testHasSnak( SnakList $array ) {
111
		/**
112
		 * @var Snak $hashable
113
		 */
114
		foreach ( iterator_to_array( $array ) as $hashable ) {
115
			$this->assertTrue( $array->hasSnak( $hashable ) );
116
			$this->assertTrue( $array->hasSnakHash( $hashable->getHash() ) );
117
			$array->removeSnak( $hashable );
118
			$this->assertFalse( $array->hasSnak( $hashable ) );
119
			$this->assertFalse( $array->hasSnakHash( $hashable->getHash() ) );
120
		}
121
122
		$this->assertTrue( true );
123
	}
124
125
	/**
126
	 * @dataProvider instanceProvider
127
	 * @param SnakList $array
128
	 */
129
	public function testRemoveSnak( SnakList $array ) {
130
		$elementCount = $array->count();
131
132
		/**
133
		 * @var Snak $element
134
		 */
135
		foreach ( iterator_to_array( $array ) as $element ) {
136
			$this->assertTrue( $array->hasSnak( $element ) );
137
138
			if ( $elementCount % 2 === 0 ) {
139
				$array->removeSnak( $element );
140
			}
141
			else {
142
				$array->removeSnakHash( $element->getHash() );
143
			}
144
145
			$this->assertFalse( $array->hasSnak( $element ) );
146
			$this->assertEquals( --$elementCount, $array->count() );
147
		}
148
149
		$element = new PropertyNoValueSnak( new PropertyId( 'P42' ) );
150
151
		$array->removeSnak( $element );
152
		$array->removeSnakHash( $element->getHash() );
153
154
		$this->assertTrue( true );
155
	}
156
157
	/**
158
	 * @dataProvider instanceProvider
159
	 * @param SnakList $array
160
	 */
161
	public function testAddSnak( SnakList $array ) {
162
		$elementCount = $array->count();
163
164
		$elements = $this->elementInstancesProvider();
165
		$element = array_shift( $elements );
166
		$element = $element[0][0];
167
168
		if ( !$array->hasSnak( $element ) ) {
169
			++$elementCount;
170
		}
171
172
		$this->assertEquals( !$array->hasSnak( $element ), $array->addSnak( $element ) );
173
174
		$this->assertEquals( $elementCount, $array->count() );
175
176
		$this->assertFalse( $array->addSnak( $element ) );
177
178
		$this->assertEquals( $elementCount, $array->count() );
179
	}
180
181
	public function orderByPropertyProvider() {
182
		$class = $this->getInstanceClass();
183
184
		$id1 = new PropertyId( 'P1' );
185
		$id2 = new PropertyId( 'P2' );
186
		$id3 = new PropertyId( 'P3' );
187
188
		/**
189
		 * List of test data containing snaks to initialize SnakList objects. The first list of
190
		 * snaks represents the snak list to be used as test input while the second represents the
191
		 * expected result.
192
		 * @var array
193
		 */
194
		$rawArguments = [
195
			'Default order' => [
196
				[],
197
				[],
198
			],
199
			'Unknown id in order' => [
200
				[],
201
				[],
202
				[ 'P1' ]
203
			],
204
			[
205
				[ new PropertyNoValueSnak( $id1 ) ],
206
				[ new PropertyNoValueSnak( $id1 ) ],
207
			],
208
			[
209
				[
210
					new PropertyNoValueSnak( $id2 ),
211
					new PropertyNoValueSnak( $id1 ),
212
				],
213
				[
214
					new PropertyNoValueSnak( $id2 ),
215
					new PropertyNoValueSnak( $id1 ),
216
				],
217
			],
218
			[
219
				[
220
					new PropertyNoValueSnak( $id1 ),
221
					new PropertyNoValueSnak( $id2 ),
222
					new PropertyValueSnak( $id1, new StringValue( 'a' ) ),
223
				],
224
				[
225
					new PropertyNoValueSnak( $id1 ),
226
					new PropertyValueSnak( $id1, new StringValue( 'a' ) ),
227
					new PropertyNoValueSnak( $id2 ),
228
				],
229
			],
230
			'With additional order' => [
231
				[
232
					new PropertyNoValueSnak( $id3 ),
233
					new PropertyNoValueSnak( $id2 ),
234
					new PropertyValueSnak( $id1, new StringValue( 'a' ) ),
235
				],
236
				[
237
					new PropertyNoValueSnak( $id2 ),
238
					new PropertyNoValueSnak( $id3 ),
239
					new PropertyValueSnak( $id1, new StringValue( 'a' ) ),
240
				],
241
				[ 'P2' ]
242
			],
243
			[
244
				[
245
					new PropertyNoValueSnak( $id3 ),
246
					new PropertyNoValueSnak( $id2 ),
247
					new PropertyNoValueSnak( $id2 ),
248
					new PropertyValueSnak( $id1, new StringValue( 'a' ) ),
249
					new PropertyNoValueSnak( $id1 ),
250
				],
251
				[
252
					new PropertyValueSnak( $id1, new StringValue( 'a' ) ),
253
					new PropertyNoValueSnak( $id1 ),
254
					new PropertyNoValueSnak( $id3 ),
255
					new PropertyNoValueSnak( $id2 ),
256
					new PropertyNoValueSnak( $id2 ),
257
				],
258
				[ 'P1' ]
259
			],
260
		];
261
262
		$arguments = [];
263
264
		foreach ( $rawArguments as $key => $rawArgument ) {
265
			$arguments[$key] = [
266
				new $class( $rawArgument[0] ),
267
				new $class( $rawArgument[1] ),
268
				array_key_exists( 2, $rawArgument ) ? $rawArgument[2] : []
269
			];
270
		}
271
272
		return $arguments;
273
	}
274
275
	/**
276
	 * @dataProvider orderByPropertyProvider
277
	 */
278
	public function testOrderByProperty( SnakList $snakList, SnakList $expected, array $order = [] ) {
279
		$initialSnakList = new SnakList( array_values( iterator_to_array( $snakList ) ) );
280
281
		$snakList->orderByProperty( $order );
282
283
		// Instantiate new SnakList resetting the snaks' array keys. This allows comparing the
284
		// reordered SnakList to the expected SnakList.
285
		$orderedSnakList = new SnakList( array_values( iterator_to_array( $snakList ) ) );
286
287
		$this->assertEquals( $expected, $orderedSnakList );
288
289
		if ( $orderedSnakList->equals( $initialSnakList ) ) {
290
			$this->assertSame( $initialSnakList->getHash(), $snakList->getHash() );
291
		} else {
292
			$this->assertNotSame( $initialSnakList->getHash(), $snakList->getHash() );
293
		}
294
	}
295
296
	public function testComparableInterface() {
297
		$this->assertInstanceOf( Comparable::class, new SnakList() );
298
	}
299
300
	/**
301
	 * @dataProvider equalsProvider
302
	 */
303
	public function testEquals( SnakList $list1, SnakList $list2, $expected ) {
304
		$this->assertSame( $expected, $list1->equals( $list2 ) );
305
	}
306
307
	public function equalsProvider() {
308
		$empty = new SnakList();
309
		$oneSnak = new SnakList( [ new PropertyNoValueSnak( 1 ) ] );
310
311
		return [
312
			'empty object is equal to itself' => [
313
				$empty,
314
				$empty,
315
				true
316
			],
317
			'non-empty object is equal to itself' => [
318
				$oneSnak,
319
				$oneSnak,
320
				true
321
			],
322
			'different empty objects are equal' => [
323
				$empty,
324
				new SnakList(),
325
				true
326
			],
327
			'different objects with same content are equal' => [
328
				$oneSnak,
329
				new SnakList( [ new PropertyNoValueSnak( 1 ) ] ),
330
				true
331
			],
332
			'different objects with different content are not equal' => [
333
				$oneSnak,
334
				new SnakList( [ new PropertyNoValueSnak( 2 ) ] ),
335
				false
336
			],
337
		];
338
	}
339
340
}
341