Passed
Push — equalHashArrays ( ea52b8 )
by no
02:53
created

SnakListTest::testEquals()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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