Completed
Pull Request — master (#117)
by Jeroen De
12:06 queued 09:54
created

tests/unit/Differ/OrderedListDifferTest.php (6 issues)

Severity

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
declare( strict_types = 1 );
4
5
namespace Diff\Tests\Differ;
6
7
use Diff\Comparer\CallbackComparer;
8
use Diff\Differ\Differ;
9
use Diff\Differ\OrderedListDiffer;
10
use Diff\DiffOp\DiffOpAdd;
11
use Diff\DiffOp\DiffOpRemove;
12
use Diff\Tests\DiffTestCase;
13
14
/**
15
 * @covers \Diff\Differ\OrderedListDiffer
16
 *
17
 * @since 0.9
18
 *
19
 * @group Diff
20
 * @group Differ
21
 *
22
 * @license BSD-3-Clause
23
 * @author Jeroen De Dauw < [email protected] >
24
 * @author Tobias Gritschacher < [email protected] >
25
 */
26
class OrderedListDifferTest extends DiffTestCase {
27
28
	/**
29
	 * Returns those that both work for native and strict mode.
30
	 */
31
	private function getCommonArgLists() {
32
		$argLists = array();
33
34
		$old = array();
35
		$new = array();
36
		$expected = array();
37
38
		$argLists[] = array( $old, $new, $expected,
39
			'There should be no difference between empty arrays' );
40
41
		$old = array( 42 );
42
		$new = array( 42 );
43
		$expected = array();
44
45
		$argLists[] = array( $old, $new, $expected,
46
			'There should be no difference between arrays with the same element' );
47
48
		$old = array( 42, 'ohi', 4.2, false );
49
		$new = array( 42, 'ohi', 4.2, false );
50
		$expected = array();
51
52
		$argLists[] = array( $old, $new, $expected,
53
			'There should be no difference between arrays with the same elements' );
54
55
		$old = array( 42, 'ohi', 4.2, false );
56
		$new = array( false, 4.2, 'ohi', 42 );
57
		$expected = array(
58
			new DiffOpAdd( false ),
59
			new DiffOpAdd( 4.2 ),
60
			new DiffOpAdd( 'ohi' ),
61
			new DiffOpAdd( 42 ),
62
			new DiffOpRemove( 42 ),
63
			new DiffOpRemove( 'ohi' ),
64
			new DiffOpRemove( 4.2 ),
65
			new DiffOpRemove( false )
66
		);
67
68
		$argLists[] = array( $old, $new, $expected,
69
			'Changing the order of all four elements should result in four add operations and four remove operations' );
70
71
		$old = array( 42, 'ohi', 4.2, false );
72
		$new = array( 4.2, 'ohi', 42, false );
73
		$expected = array(
74
			new DiffOpAdd( 4.2 ),
75
			new DiffOpAdd( 42 ),
76
			new DiffOpRemove( 42 ),
77
			new DiffOpRemove( 4.2 ),
78
		);
79
80
		$argLists[] = array( $old, $new, $expected,
81
			'Changing the order of two of four elements should result in two add operations and two remove operations' );
82
83
		$old = array();
84
		$new = array( 42 );
85
		$expected = array( new DiffOpAdd( 42 ) );
86
87
		$argLists[] = array( $old, $new, $expected,
88
			'An array with a single element should be an add operation different from an empty array' );
89
90
		$old = array( 42 );
91
		$new = array();
92
		$expected = array( new DiffOpRemove( 42 ) );
93
94
		$argLists[] = array( $old, $new, $expected,
95
			'An empty array should be a remove operation different from an array with one element' );
96
97
		$old = array( 1 );
98
		$new = array( 2 );
99
		$expected = array( new DiffOpRemove( 1 ), new DiffOpAdd( 2 ) );
100
101
		$argLists[] = array( $old, $new, $expected,
102
			'Two arrays with a single different element should differ by an add and a remove op' );
103
104
		$old = array( 9001, 42, 1, 0 );
105
		$new = array( 9001, 42, 2, 0 );
106
		$expected = array( new DiffOpRemove( 1 ), new DiffOpAdd( 2 ) );
107
108
		$argLists[] = array( $old, $new, $expected,
109
			'Two arrays with a single different element should differ by an add and a remove op
110
			 when the order of the identical elements stays the same' );
111
112
		$old = array( 'a', 'b', 'c' );
113
		$new = array( 'c', 'b', 'a', 'd' );
114
		$expected = array(
115
			new DiffOpRemove( 'a' ),
116
			new DiffOpRemove( 'c' ),
117
			new DiffOpAdd( 'c' ),
118
			new DiffOpAdd( 'a' ),
119
			new DiffOpAdd( 'd' )
120
		);
121
122
		$argLists[] = array( $old, $new, $expected,
123
			'Changing the position of two elements and adding one new element should result
124
			in two remove ops and three add ops' );
125
126
		$old = array( 'a', 'b', 'c', 'd' );
127
		$new = array( 'b', 'a', 'c' );
128
		$expected = array(
129
			new DiffOpRemove( 'a' ),
130
			new DiffOpRemove( 'b' ),
131
			new DiffOpRemove( 'd' ),
132
			new DiffOpAdd( 'b' ),
133
			new DiffOpAdd( 'a' )
134
		);
135
136
		$argLists[] = array( $old, $new, $expected,
137
			'Changing the position of two elements and removing the last element should result
138
			in three remove ops and two add ops' );
139
140
		$old = array( 'a', 'b', 'c' );
141
		$new = array( 'b', 'c' );
142
		$expected = array(
143
			new DiffOpRemove( 'a' ),
144
			new DiffOpRemove( 'b' ),
145
			new DiffOpRemove( 'c' ),
146
			new DiffOpAdd( 'b' ),
147
			new DiffOpAdd( 'c' )
148
		);
149
150
		$argLists[] = array( $old, $new, $expected,
151
			'Removing the first element results in remove ops for all elements and add ops for the remaining elements,
152
			 because the position of all remaining elements has changed' );
153
154
		return $argLists;
155
	}
156
157
	public function toDiffProvider() {
158
		$argLists = $this->getCommonArgLists();
159
160
		$old = array( 42, 42 );
161
		$new = array( 42 );
162
		$expected = array( new DiffOpRemove( 42 ) );
163
164
		$argLists[] = array( $old, $new, $expected,
165
			'[42, 42] to [42] should [rem(42)]' );
166
167
		$old = array( 42 );
168
		$new = array( 42, 42 );
169
		$expected = array( new DiffOpAdd( 42 ) );
170
171
		$argLists[] = array( $old, $new, $expected,
172
			'[42] to [42, 42] should [add(42)]' );
173
174
		$old = array( '42' );
175
		$new = array( 42 );
176
		$expected = array( new DiffOpRemove( '42' ), new DiffOpAdd( 42 ) );
177
178
		$argLists[] = array( $old, $new, $expected,
179
			'["42"] to [42] should [rem("42"), add(42)]' );
180
181
		$old = array( array( 1 ) );
182
		$new = array( array( 2 ) );
183
		$expected = array( new DiffOpRemove( array( 1 ) ), new DiffOpAdd( array( 2 ) ) );
184
185
		$argLists[] = array( $old, $new, $expected,
186
			'[[1]] to [[2]] should [rem([1]), add([2])]' );
187
188
		$old = array( array( 2 ) );
189
		$new = array( array( 2 ) );
190
		$expected = array();
191
192
		$argLists[] = array( $old, $new, $expected,
193
			'[[2]] to [[2]] should result in an empty diff' );
194
195
		// test "soft" object comparison
196
		$obj1 = new \stdClass();
197
		$obj2 = new \stdClass();
198
		$objX = new \stdClass();
199
200
		$obj1->test = 'Test';
201
		$obj2->test = 'Test';
202
		$objX->xest = 'Test';
203
204
		$old = array( $obj1 );
205
		$new = array( $obj2 );
206
		$expected = array( );
207
208
		$argLists[] = array( $old, $new, $expected,
209
			'Two arrays containing equivalent objects should result in an empty diff' );
210
211
		$old = array( $obj1 );
212
		$new = array( $objX );
213
		$expected = array( new DiffOpRemove( $obj1 ), new DiffOpAdd( $objX )  );
214
215
		$argLists[] = array( $old, $new, $expected,
216
			'Two arrays containing different objects of the same type should result in an add and a remove op.' );
217
218
		return $argLists;
219
	}
220
221
	/**
222
	 * @dataProvider toDiffProvider
223
	 */
224
	public function testDoDiff( $old, $new, $expected, $message = '' ) {
225
		$callback = function( $foo, $bar ) {
226
			return is_object( $foo ) ? $foo == $bar : $foo === $bar;
227
		};
228
229
		$this->doTestDiff(
230
			new OrderedListDiffer( new CallbackComparer( $callback ) ),
231
			$old,
232
			$new,
233
			$expected,
234
			$message
235
		);
236
	}
237
238
	private function doTestDiff( Differ $differ, $old, $new, $expected, $message ) {
239
		$actual = $differ->doDiff( $old, $new );
240
241
		$this->assertArrayEquals( $expected, $actual, false, false, $message );
242
	}
243
244
	public function testCallbackComparisonReturningFalse() {
245
		$differ = new OrderedListDiffer( new CallbackComparer( function( $foo, $bar ) {
0 ignored issues
show
The parameter $foo 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 $bar 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...
246
			return false;
247
		} ) );
248
249
		$actual = $differ->doDiff( array( 1, '2' ), array( 1, '2', 'foo' ) );
250
251
		$expected = array(
252
			new DiffOpAdd( 1 ),
253
			new DiffOpAdd( '2' ),
254
			new DiffOpAdd( 'foo' ),
255
			new DiffOpRemove( 1 ),
256
			new DiffOpRemove( '2' ),
257
		);
258
259
		$this->assertArrayEquals(
260
			$expected, $actual, false, false,
261
			'All elements should be removed and added when comparison callback always returns false'
262
		);
263
	}
264
265
	public function testCallbackComparisonReturningTrue() {
266
		$differ = new OrderedListDiffer( new CallbackComparer( function( $foo, $bar ) {
0 ignored issues
show
The parameter $foo 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 $bar 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...
267
			return true;
268
		} ) );
269
270
		$actual = $differ->doDiff( array( 1, '2', 'baz' ), array( 1, 'foo', '2' ) );
271
272
		$expected = array();
273
274
		$this->assertArrayEquals(
275
			$expected, $actual, false, false,
276
			'No elements should be removed or added when comparison callback always returns true'
277
		);
278
	}
279
280
	public function testCallbackComparisonReturningNyanCat() {
281
		$differ = new OrderedListDiffer( new CallbackComparer( function( $foo, $bar ) {
0 ignored issues
show
The parameter $foo 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 $bar 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...
282
			return '~=[,,_,,]:3';
283
		} ) );
284
285
		$this->expectException( 'RuntimeException' );
286
287
		$differ->doDiff( array( 1, '2', 'baz' ), array( 1, 'foo', '2' ) );
288
	}
289
290
}
291