Completed
Push — master ( fcf711...00bb57 )
by
unknown
02:50
created

tests/phpunit/Patcher/MapPatcherTest.php (4 issues)

parameters are used.

Unused Code Minor

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Diff\Tests\Patcher;
4
5
use Diff\Comparer\CallbackComparer;
6
use Diff\DiffOp\Diff\Diff;
7
use Diff\DiffOp\DiffOpAdd;
8
use Diff\DiffOp\DiffOpChange;
9
use Diff\DiffOp\DiffOpRemove;
10
use Diff\Patcher\MapPatcher;
11
use Diff\Patcher\Patcher;
12
use Diff\Tests\DiffTestCase;
13
14
/**
15
 * @covers Diff\Patcher\MapPatcher
16
 * @covers Diff\Patcher\ThrowingPatcher
17
 *
18
 * @group Diff
19
 * @group DiffPatcher
20
 * @group MapPatcherTest
21
 *
22
 * @licence GNU GPL v2+
23
 * @author Jeroen De Dauw < [email protected] >
24
 * @author Daniel Kinzler
25
 */
26
class MapPatcherTest extends DiffTestCase {
27
28
	public function patchProvider() {
29
		$argLists = array();
30
31
		$patcher = new MapPatcher();
32
		$base = array();
33
		$diff = new Diff();
34
		$expected = array();
35
36
		$argLists['all empty'] = array( $patcher, $base, $diff, $expected );
37
38
39
		$patcher = new MapPatcher();
40
		$base = array( 'foo', 'bar' => array( 'baz' ) );
41
		$diff = new Diff();
42
		$expected = array( 'foo', 'bar' => array( 'baz' ) );
43
44
		$argLists['empty patch'] = array( $patcher, $base, $diff, $expected );
45
46
47
		$patcher = new MapPatcher();
48
		$base = array( 'foo', 'bar' => array( 'baz' ) );
49
		$diff = new Diff( array( 'bah' => new DiffOpAdd( 'blah' ) ) );
50
		$expected = array( 'foo', 'bar' => array( 'baz' ), 'bah' => 'blah' );
51
52
		$argLists['add'] = array( $patcher, $base, $diff, $expected );
53
54
55
		$patcher = new MapPatcher();
56
		$base = array( 'foo', 'bar' => array( 'baz' ) );
57
		$diff = new Diff( array( 'bah' => new DiffOpAdd( 'blah' ) ) );
58
		$expected = array( 'foo', 'bar' => array( 'baz' ), 'bah' => 'blah' );
59
60
		$argLists['add2'] = array( $patcher, $base, $diff, $expected ); //FIXME: dupe?
61
62
63
		$patcher = new MapPatcher();
64
		$base = array();
65
		$diff = new Diff( array(
66
			'foo' => new DiffOpAdd( 'bar' ),
67
			'bah' => new DiffOpAdd( 'blah' )
68
		) );
69
		$expected = array(
70
			'foo' => 'bar',
71
			'bah' => 'blah'
72
		);
73
74
		$argLists['add to empty base'] = array( $patcher, $base, $diff, $expected );
75
76
77
		$patcher = new MapPatcher();
78
		$base = array(
79
			'enwiki' => array(
80
				'name'   => 'Nyan Cat',
81
				'badges' => array( 'FA' )
82
			)
83
		);
84
		$diff = new Diff( array(
85
			'nlwiki' => new Diff( array(
86
				'name'   => new DiffOpAdd( 'Nyan Cat' ),
87
				'badges' => new Diff( array(
88
					new DiffOpAdd( 'J approves' ),
89
				), false ),
90
			), true ),
91
		), true );
92
		$expected = array(
93
			'enwiki' => array(
94
				'name'   => 'Nyan Cat',
95
				'badges' => array( 'FA' )
96
			),
97
98
			'nlwiki' => array(
99
				'name'   => 'Nyan Cat',
100
				'badges' => array( 'J approves' )
101
			)
102
		);
103
104
		$argLists['add to non-existent key'] = array( $patcher, $base, $diff, $expected );
105
106
107
		$patcher = new MapPatcher();
108
		$base = array(
109
			'foo' => 'bar',
110
			'nyan' => 'cat',
111
			'bah' => 'blah',
112
		);
113
		$diff = new Diff( array(
114
			'foo' => new DiffOpRemove( 'bar' ),
115
			'bah' => new DiffOpRemove( 'blah' ),
116
		) );
117
		$expected = array(
118
			'nyan' => 'cat'
119
		);
120
121
		$argLists['remove'] = array( $patcher, $base, $diff, $expected );
122
123
124
		$patcher = new MapPatcher();
125
		$base = array(
126
			'foo' => 'bar',
127
			'nyan' => 'cat',
128
			'spam' => 'blah',
129
			'bah' => 'blah',
130
		);
131
		$diff = new Diff( array(
132
			'foo' => new DiffOpChange( 'bar', 'baz' ),
133
			'bah' => new DiffOpRemove( 'blah' ),
134
			'oh' => new DiffOpAdd( 'noez' ),
135
		) );
136
		$expected = array(
137
			'foo' => 'baz',
138
			'nyan' => 'cat',
139
			'spam' => 'blah',
140
			'oh' => 'noez',
141
		);
142
143
		$argLists['change/add/remove'] = array( $patcher, $base, $diff, $expected );
144
145
146
		$patcher = new MapPatcher();
147
		$base = array(
148
			'foo' => 'bar',
149
		);
150
		$diff = new Diff( array(
151
			'baz' => new Diff( array( new DiffOpAdd( 'ny' ), new DiffOpAdd( 'an' ) ), false ),
152
		) );
153
		$expected = array(
154
			'foo' => 'bar',
155
			'baz' => array( 'ny', 'an' ),
156
		);
157
158
		$argLists['add to substructure'] = array( $patcher, $base, $diff, $expected );
159
160
161
		// ---- conflicts ----
162
163
		$patcher = new MapPatcher();
164
		$base = array();
165
		$diff = new Diff( array(
166
			'baz' => new DiffOpRemove( 'X' ),
167
		) );
168
		$expected = $base;
169
170
		$argLists['conflict: remove missing'] = array( $patcher, $base, $diff, $expected );
171
172
173
		$patcher = new MapPatcher();
174
		$base = array( 'baz' => 'Y' );
175
		$diff = new Diff( array(
176
			'baz' => new DiffOpRemove( 'X' ),
177
		) );
178
		$expected = $base;
179
180
		$argLists['conflict: remove mismatching value'] = array( $patcher, $base, $diff, $expected );
181
182
183
		$patcher = new MapPatcher();
184
		$base = array( 'baz' => 'Y' );
185
		$diff = new Diff( array(
186
			'baz' => new DiffOpAdd( 'X' ),
187
		) );
188
		$expected = $base;
189
190
		$argLists['conflict: add existing'] = array( $patcher, $base, $diff, $expected );
191
192
193
		$patcher = new MapPatcher();
194
		$base = array( 'baz' => 'Y' );
195
		$diff = new Diff( array(
196
			'baz' => new DiffOpChange( 'X', 'Z' ),
197
		) );
198
		$expected = $base;
199
200
		$argLists['conflict: change mismatching value'] = array( $patcher, $base, $diff, $expected );
201
202
203
		$patcher = new MapPatcher();
204
		$base = array(
205
			'foo' => 'bar',
206
			'nyan' => 'cat',
207
			'spam' => 'blah',
208
			'bah' => 'blah',
209
		);
210
		$diff = new Diff( array(
211
			'foo' => new DiffOpChange( 'bar', 'var' ),
212
			'nyan' => new DiffOpRemove( 'fat' ),
213
			'bah' => new DiffOpChange( 'blubb', 'clubb' ),
214
			'yea' => new DiffOpAdd( 'stuff' ),
215
		) );
216
		$expected = array(
217
			'foo' => 'var',
218
			'nyan' => 'cat',
219
			'spam' => 'blah',
220
			'bah' => 'blah',
221
			'yea' => 'stuff',
222
		);
223
224
		$argLists['some mixed conflicts'] = array( $patcher, $base, $diff, $expected );
225
226
		return $argLists;
227
	}
228
229
	/**
230
	 * @dataProvider patchProvider
231
	 *
232
	 * @param Patcher $patcher
233
	 * @param array $base
234
	 * @param Diff $diff
235
	 * @param array $expected
236
	 */
237
	public function testPatch( Patcher $patcher, array $base, Diff $diff, array $expected ) {
238
		$actual = $patcher->patch( $base, $diff );
239
240
		$this->assertArrayEquals( $expected, $actual, true, true );
241
	}
242
243
	public function getApplicableDiffProvider() {
244
		// Diff, current object, expected
245
		$argLists = array();
246
247
		$diff = new Diff( array(), true );
248
		$currentObject = array();
249
		$expected = clone $diff;
250
251
		$argLists[] = array( $diff, $currentObject, $expected, 'Empty diff should remain empty on empty base' );
252
253
254
		$diff = new Diff( array(), true );
255
256
		$currentObject = array( 'foo' => 0, 'bar' => 1 );
257
258
		$expected = clone $diff;
259
260
		$argLists[] = array( $diff, $currentObject, $expected, 'Empty diff should remain empty on non-empty base' );
261
262
263
		$diff = new Diff( array(
264
			'foo' => new DiffOpChange( 0, 42 ),
265
			'bar' => new DiffOpChange( 1, 9001 ),
266
		), true );
267
268
		$currentObject = array( 'foo' => 0, 'bar' => 1 );
269
270
		$expected = clone $diff;
271
272
		$argLists[] = array( $diff, $currentObject, $expected, 'Diff should not be altered on matching base' );
273
274
275
		$diff = new Diff( array(
276
			'foo' => new DiffOpChange( 0, 42 ),
277
			'bar' => new DiffOpChange( 1, 9001 ),
278
		), true );
279
		$currentObject = array();
280
281
		$expected = new Diff( array(), true );
282
283
		$argLists[] = array( $diff, $currentObject, $expected, 'Diff with only change ops should be empty on empty base' );
284
285
286
		$diff = new Diff( array(
287
			'foo' => new DiffOpChange( 0, 42 ),
288
			'bar' => new DiffOpChange( 1, 9001 ),
289
		), true );
290
291
		$currentObject = array( 'foo' => 'something else', 'bar' => 1, 'baz' => 'o_O' );
292
293
		$expected = new Diff( array(
294
			'bar' => new DiffOpChange( 1, 9001 ),
295
		), true );
296
297
		$argLists[] = array( $diff, $currentObject, $expected, 'Only change ops present in the base should be retained' );
298
299
300
		$diff = new Diff( array(
301
			'bar' => new DiffOpRemove( 9001 ),
302
		), true );
303
304
		$currentObject = array();
305
306
		$expected = new Diff( array(), true );
307
308
		$argLists[] = array( $diff, $currentObject, $expected, 'Remove ops should be removed on empty base' );
309
310
311
		$diff = new Diff( array(
312
			'foo' => new DiffOpAdd( 42 ),
313
			'bar' => new DiffOpRemove( 9001 ),
314
		), true );
315
316
		$currentObject = array( 'foo' => 'bar' );
317
318
		$expected = new Diff( array(), true );
319
320
		$argLists[] = array(
321
			$diff,
322
			$currentObject,
323
			$expected,
324
			'Mismatching add ops and remove ops not present in base should be removed'
325
		);
326
327
328
		$diff = new Diff( array(
329
			'foo' => new DiffOpAdd( 42 ),
330
			'bar' => new DiffOpRemove( 9001 ),
331
		), true );
332
333
		$currentObject = array( 'foo' => 42, 'bar' => 9001 );
334
335
		$expected = new Diff( array(
336
			'bar' => new DiffOpRemove( 9001 ),
337
		), true );
338
339
		$argLists[] = array( $diff, $currentObject, $expected, 'Remove ops present in base should be retained' );
340
341
342
		$diff = new Diff( array(
343
			'foo' => new DiffOpAdd( 42 ),
344
			'bar' => new DiffOpRemove( 9001 ),
345
		), true );
346
347
		$currentObject = array();
348
349
		$expected = new Diff( array(
350
			'foo' => new DiffOpAdd( 42 ),
351
		), true );
352
353
		$argLists[] = array(
354
			$diff,
355
			$currentObject,
356
			$expected,
357
			'Add ops not present in the base should be retained (MapDiff)'
358
		);
359
360
361
		$diff = new Diff( array(
362
			'foo' => new Diff( array( 'bar' => new DiffOpChange( 0, 1 ) ), true ),
363
			'le-non-existing-element' => new Diff( array( 'bar' => new DiffOpChange( 0, 1 ) ), true ),
364
			'spam' => new Diff( array( new DiffOpAdd( 42 ) ), false ),
365
			new DiffOpAdd( 9001 ),
366
		), true );
367
368
		$currentObject = array(
369
			'foo' => array( 'bar' => 0, 'baz' => 'O_o' ),
370
			'spam' => array( 23, 'ohi' )
371
		);
372
373
		$expected = new Diff( array(
374
			'foo' => new Diff( array( 'bar' => new DiffOpChange( 0, 1 ) ), true ),
375
			'spam' => new Diff( array( new DiffOpAdd( 42 ) ), false ),
376
			new DiffOpAdd( 9001 ),
377
		), true );
378
379
		$argLists[] = array( $diff, $currentObject, $expected, 'Recursion should work properly' );
380
381
		return $argLists;
382
	}
383
384
	/**
385
	 * @dataProvider getApplicableDiffProvider
386
	 *
387
	 * @param Diff $diff
388
	 * @param array $currentObject
389
	 * @param Diff $expected
390
	 * @param string|null $message
391
	 */
392
	public function testGetApplicableDiff( Diff $diff, array $currentObject, Diff $expected, $message = null ) {
393
		$patcher = new MapPatcher();
394
		$actual = $patcher->getApplicableDiff( $currentObject, $diff );
395
396
		$this->assertEquals( $expected->getOperations(), $actual->getOperations(), $message );
397
	}
398
399
	public function testSetValueComparerToAlwaysFalse() {
400
		$patcher = new MapPatcher();
401
402
		$patcher->setValueComparer( new CallbackComparer( function( $firstValue, $secondValue ) {
0 ignored issues
show
The parameter $firstValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $secondValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
403
			return false;
404
		} ) );
405
406
		$baseMap = array(
407
			'foo' => 42,
408
			'bar' => 9001,
409
		);
410
411
		$patch = new Diff( array(
412
			'foo' => new DiffOpChange( 42, 1337 ),
413
			'bar' => new DiffOpChange( 9001, 1337 ),
414
		) );
415
416
		$patchedMap = $patcher->patch( $baseMap, $patch );
417
418
		$this->assertEquals( $baseMap, $patchedMap );
419
	}
420
421
	public function testSetValueComparerToAlwaysTrue() {
422
		$patcher = new MapPatcher();
423
424
		$patcher->setValueComparer( new CallbackComparer( function( $firstValue, $secondValue ) {
0 ignored issues
show
The parameter $firstValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $secondValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
425
			return true;
426
		} ) );
427
428
		$baseMap = array(
429
			'foo' => 42,
430
			'bar' => 9001,
431
		);
432
433
		$patch = new Diff( array(
434
			'foo' => new DiffOpChange( 3, 1337 ),
435
			'bar' => new DiffOpChange( 3, 1337 ),
436
		) );
437
438
		$expectedMap = array(
439
			'foo' => 1337,
440
			'bar' => 1337,
441
		);
442
443
		$patchedMap = $patcher->patch( $baseMap, $patch );
444
445
		$this->assertEquals( $expectedMap, $patchedMap );
446
	}
447
448
	public function testErrorOnUnknownDiffOpType() {
449
		$patcher = new MapPatcher();
450
451
		$diffOp = $this->getMock( 'Diff\DiffOp\DiffOp' );
452
453
		$diffOp->expects( $this->any() )
454
			->method( 'getType' )
455
			->will( $this->returnValue( 'diff' ) );
456
457
		$diff = new Diff( array( $diffOp ), true );
458
459
		$patcher->patch( array(), $diff );
460
461
		$patcher->throwErrors();
462
		$this->setExpectedException( 'Diff\Patcher\PatcherException' );
463
464
		$patcher->patch( array(), $diff );
465
	}
466
467
}
468