Completed
Push — 21x ( 0e3ed4...f4f4da )
by adam
17:20 queued 21s
created

MapDiffTest::testGetAdditions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
1
<?php
2
3
namespace Diff\Tests\DiffOp\Diff;
4
5
use Diff\Differ\ListDiffer;
6
use Diff\Differ\MapDiffer;
7
use Diff\DiffOp\Diff\Diff;
8
use Diff\DiffOp\DiffOp;
9
use Diff\DiffOp\DiffOpAdd;
10
use Diff\DiffOp\DiffOpChange;
11
use Diff\DiffOp\DiffOpRemove;
12
use Diff\Tests\DiffOp\DiffOpTest;
13
14
/**
15
 * @covers Diff\DiffOp\Diff\MapDiff
16
 *
17
 * @group Diff
18
 * @group DiffOp
19
 *
20
 * @license GPL-2.0+
21
 * @author Jeroen De Dauw < [email protected] >
22
 */
23
class MapDiffTest extends DiffOpTest {
24
25
	/**
26
	 * @see DiffOpTest::getClass
27
	 *
28
	 * @since 0.1
29
	 *
30
	 * @return string
31
	 */
32
	public function getClass() {
33
		return '\Diff\DiffOp\Diff\MapDiff';
34
	}
35
36
	/**
37
	 * @see DiffOpTest::constructorProvider
38
	 *
39
	 * @since 0.1
40
	 */
41
	public function constructorProvider() {
42
		$operationLists = array();
43
44
		$operationLists[] = array();
45
46
		$operationLists[] = array(
47
			new DiffOpAdd( 42 ),
48
		);
49
50
		$operationLists[] = array(
51
			new DiffOpAdd( 42 ),
52
			new DiffOpChange( 9000, 9001 ),
53
		);
54
55
		$operationLists[] = array(
56
			new DiffOpAdd( 42 ),
57
			new DiffOpRemove( 1 ),
58
			new DiffOpChange( 9000, 9001 ),
59
			new DiffOpChange( 5, 1 ),
60
			new Diff( array(
61
				new DiffOpAdd( 42 ),
62
				new DiffOpRemove( 1 ),
63
			), false ),
64
			new Diff( array(
65
				new DiffOpAdd( 42 ),
66
				new DiffOpRemove( 1 ),
67
				new DiffOpChange( 9000, 9001 ),
68
			), true ),
69
		);
70
71
		$argLists = array();
72
73
		foreach ( $operationLists as $operationList ) {
74
			$argLists[] = array( true, $operationList );
75
			$argLists[] = array( true, $operationList, 'foobar' );
76
		}
77
78
		$argLists[] = array( false, array( 42 ) );
79
		$argLists[] = array( false, array( new MapDiffer() ) );
80
		$argLists[] = array( false, array( '~=[,,_,,]:3' ) );
81
82
		return $argLists;
83
	}
84
85
	public function recursionProvider() {
86
		return array_merge( $this->newFromArraysProvider(), array(
87
			array(
88
				array(
89
					'en' => array( 1, 2, 3 ),
90
				),
91
				array(
92
					'en' => array( 4, 2 ),
93
				),
94
				array(
95
					'en' => 'list',
96
				),
97
			),
98
			array(
99
				array(
100
					'en' => array( 1, 2, 3 ),
101
					'nl' => array( 'hax' ),
102
					'foo' => 'bar',
103
				),
104
				array(
105
					'en' => array( 4, 2 ),
106
					'de' => array( 'hax' ),
107
				),
108
				array(
109
					'en' => 'list',
110
					'de' => 'list',
111
					'nl' => 'list',
112
					'foo' => new DiffOpRemove( 'bar' ),
113
				),
114
			),
115
			array(
116
				array(
117
					'en' => array( 'a' => 1, 'b' => 2, 'c' => 3 ),
118
					'nl' => array( 'a' => 'hax' ),
119
					'foo' => 'bar',
120
					'bar' => array( 1, 2, 3 ),
121
				),
122
				array(
123
					'bar' => array( 4, 2 ),
124
					'en' => array( 'd' => 4, 'b' => 2 ),
125
					'de' => array( 'a' => 'hax' ),
126
				),
127
				array(
128
					'en' => 'map',
129
					'de' => 'map',
130
					'nl' => 'map',
131
					'foo' => new DiffOpRemove( 'bar' ),
132
					'bar' => 'list',
133
				),
134
			),
135
		) );
136
	}
137
138
	/**
139
	 * @dataProvider recursionProvider
140
	 */
141
	public function testRecursion( array $from, array $to, $expected ) {
142
		$mapDiffer = new MapDiffer( true );
143
		$listDiffer = new ListDiffer();
144
145
		$diff = new Diff( $mapDiffer->doDiff( $from, $to ) );
146
147
		foreach ( $expected as $key => &$value ) {
148
			if ( $value === 'list' || $value === 'map' ) {
149
				$differ = $value === 'list' ? $listDiffer : $mapDiffer;
150
151
				$value = new Diff(
152
					$differ->doDiff(
153
						array_key_exists( $key, $from ) ? $from[$key] : array(),
154
						array_key_exists( $key, $to ) ? $to[$key] : array()
155
					),
156
					$value === 'map'
157
				);
158
			}
159
		}
160
161
		$sorter = function( $a, $b ) {
162
			$aa = serialize( $a );
163
			$bb = serialize( $b );
164
165
			if ( $aa == $bb ) {
166
				return 0;
167
			}
168
			else {
169
				return $aa > $bb ? -1 : 1;
170
			}
171
		};
172
173
		uasort( $expected, $sorter );
174
		$diff->uasort( $sorter );
175
		$actual = $diff->getArrayCopy();
176
177
		$this->assertEquals( $expected, $actual );
178
	}
179
180
	public function newFromArraysProvider() {
181
		return array(
182
			array(
183
				array(),
184
				array(),
185
				array(),
186
			),
187
			array(
188
				array( 'en' => 'en' ),
189
				array(),
190
				array(
191
					'en' => new DiffOpRemove( 'en' )
192
				),
193
			),
194
			array(
195
				array(),
196
				array( 'en' => 'en' ),
197
				array(
198
					'en' => new DiffOpAdd( 'en' )
199
				)
200
			),
201
			array(
202
				array( 'en' => 'foo' ),
203
				array( 'en' => 'en' ),
204
				array(
205
					'en' => new DiffOpChange( 'foo', 'en' )
206
				),
207
			),
208
			array(
209
				array( 'en' => 'foo' ),
210
				array( 'en' => 'foo', 'de' => 'bar' ),
211
				array(
212
					'de' => new DiffOpAdd( 'bar' )
213
				)
214
			),
215
			array(
216
				array( 'en' => 'foo' ),
217
				array( 'en' => 'baz', 'de' => 'bar' ),
218
				array(
219
					'de' => new DiffOpAdd( 'bar' ),
220
					'en' => new DiffOpChange( 'foo', 'baz' )
221
				)
222
			),
223
		);
224
	}
225
226
	/**
227
	 * @dataProvider newFromArraysProvider
228
	 */
229
	public function testNewFromArrays( array $from, array $to, array $expected ) {
230
		$differ = new MapDiffer( true );
231
		$diff = new Diff( $differ->doDiff( $from, $to ) );
232
233
		$this->assertInstanceOf( '\Diff\DiffOp\DiffOp', $diff );
234
		$this->assertInstanceOf( '\Diff\DiffOp\Diff\Diff', $diff );
235
		$this->assertInstanceOf( '\ArrayObject', $diff );
236
237
		// Sort to get rid of differences in order, since no promises about order are made.
238
		asort( $expected );
239
		$diff->asort();
240
		$actual = $diff->getArrayCopy();
241
242
		$this->assertEquals( $expected, $actual );
243
244
		$this->assertEquals(
245
			$actual === array(),
246
			$diff->isEmpty()
247
		);
248
	}
249
250
	public function elementInstancesProvider() {
251
		return array(
252
			array( array(
253
			) ),
254
			array( array(
255
				new DiffOpAdd( 'ohi' )
256
			) ),
257
			array( array(
258
				new DiffOpRemove( 'ohi' )
259
			) ),
260
			array( array(
261
				new DiffOpAdd( 'ohi' ),
262
				new DiffOpRemove( 'there' )
263
			) ),
264
			array( array(
265
			) ),
266
			array( array(
267
				new DiffOpAdd( 'ohi' ),
268
				new DiffOpRemove( 'there' ),
269
				new DiffOpChange( 'ohi', 'there' )
270
			) ),
271
			array( array(
272
				'1' => new DiffOpAdd( 'ohi' ),
273
				'33' => new DiffOpRemove( 'there' ),
274
				'7' => new DiffOpChange( 'ohi', 'there' )
275
			) ),
276
		);
277
	}
278
279
	/**
280
	 * @dataProvider elementInstancesProvider
281
	 */
282
	public function testGetAdditions( array $operations ) {
283
		$diff = new Diff( $operations, true );
284
285
		$changes = array();
286
287
		/**
288
		 * @var DiffOp $operation
289
		 */
290
		foreach ( $operations as $operation ) {
291
			if ( $operation->getType() == 'change' ) {
292
				$changes[] = $operation;
293
			}
294
		}
295
296
		$this->assertArrayEquals( $changes, $diff->getChanges() );
297
	}
298
299
	public function testElementsInRecuriveDiff() {
300
		$old = array(
301
			'en' => array( 'en-foo', 'en-bar' ),
302
			'de' => array( 'de-0', 'de-1' ),
303
			'onoez' => array( '~=[,,_,,]:3' ),
304
			'a' => 'b',
305
		);
306
307
		$new = array(
308
			'en' => array( 'en-foo', 'en-baz' ),
309
			'nl' => array( 'nl-0', 'nl-1' ),
310
			'onoez' => array( '~=[,,_,,]:3' ),
311
			'a' => 'b',
312
		);
313
314
		$differ = new MapDiffer( true );
315
		$diff = new Diff( $differ->doDiff( $old, $new ) );
316
317
		$this->assertTrue( $diff->offsetExists( 'en' ) );
318
		$this->assertTrue( $diff->offsetExists( 'de' ) );
319
		$this->assertTrue( $diff->offsetExists( 'nl' ) );
320
		$this->assertFalse( $diff->offsetExists( 'onoez' ) );
321
		$this->assertFalse( $diff->offsetExists( 'a' ) );
322
323
		$this->assertInstanceOf( 'Diff\DiffOp\Diff\Diff', $diff['de'] );
324
		$this->assertInstanceOf( 'Diff\DiffOp\Diff\Diff', $diff['nl'] );
325
		$this->assertInstanceOf( 'Diff\DiffOp\Diff\Diff', $diff['en'] );
326
327
		$this->assertSame( 2, count( $diff['de'] ) );
328
		$this->assertSame( 2, count( $diff['nl'] ) );
329
		$this->assertSame( 2, count( $diff['en'] ) );
330
331
		/**
332
		 * @var Diff $listDiff
333
		 */
334
		$listDiff = $diff['en'];
335
336
		$add = $listDiff->getAdditions();
337
		$add = array_shift( $add );
338
		$this->assertEquals( 'en-baz', $add->getNewValue() );
339
340
		$remove = $listDiff->getRemovals();
341
		$remove = array_shift( $remove );
342
		$this->assertEquals( 'en-bar', $remove->getOldValue() );
343
	}
344
345
	public function testEmptyElementsInRecursiveDiff() {
346
		$old = array(
347
			'en' => array( 'a' => 'en-foo', 'b' => 'en-bar' ),
348
		);
349
350
		$new = array(
351
			'en' => array( 'a' => 'en-foo', 'b' => 'en-bar' ),
352
		);
353
354
		$differ = new MapDiffer( true );
355
		$diff = new Diff( $differ->doDiff( $old, $new ) );
356
357
		$this->assertTrue( $diff->isEmpty() );
358
		$this->assertSame( array(), $diff->getOperations() );
359
	}
360
361
}
362