1 | <?php |
||||
2 | declare(strict_types = 1); |
||||
3 | |||||
4 | namespace Tests\Innmind\Immutable; |
||||
5 | |||||
6 | use Innmind\Immutable\{ |
||||
7 | Map, |
||||
8 | Pair, |
||||
9 | Str, |
||||
10 | Set, |
||||
11 | Sequence, |
||||
12 | }; |
||||
13 | use PHPUnit\Framework\TestCase; |
||||
14 | |||||
15 | class MapTest extends TestCase |
||||
16 | { |
||||
17 | public function testInterface() |
||||
18 | { |
||||
19 | $m = Map::of(); |
||||
20 | |||||
21 | $this->assertInstanceOf(\Countable::class, $m); |
||||
22 | } |
||||
23 | |||||
24 | public function testOf() |
||||
25 | { |
||||
26 | $map = Map::of() |
||||
27 | (1, 1.1) |
||||
28 | (2, 2.1); |
||||
29 | |||||
30 | $this->assertTrue( |
||||
31 | $map->equals( |
||||
32 | Map::of() |
||||
33 | ->put(1, 1.1) |
||||
34 | ->put(2, 2.1), |
||||
35 | ), |
||||
36 | ); |
||||
37 | } |
||||
38 | |||||
39 | public function testEmptyOf() |
||||
40 | { |
||||
41 | $this->assertTrue(Map::of()->equals(Map::of())); |
||||
42 | } |
||||
43 | |||||
44 | public function testPut() |
||||
45 | { |
||||
46 | $m = Map::of(); |
||||
47 | |||||
48 | $this->assertSame(0, $m->size()); |
||||
49 | $m2 = $m->put(42, 42); |
||||
50 | $this->assertNotSame($m, $m2); |
||||
51 | $this->assertSame(0, $m->size()); |
||||
52 | $this->assertSame(1, $m2->size()); |
||||
53 | |||||
54 | $m = Map::of(); |
||||
55 | $m = $m |
||||
56 | ->put(23, 24) |
||||
57 | ->put(41, 42) |
||||
58 | ->put(65, 66) |
||||
59 | ->put(89, 90) |
||||
60 | ->put(65, 1); |
||||
61 | |||||
62 | $this->assertSame(24, $this->get($m, 23)); |
||||
63 | $this->assertSame(42, $this->get($m, 41)); |
||||
64 | $this->assertSame(1, $this->get($m, 65)); |
||||
65 | $this->assertSame(90, $this->get($m, 89)); |
||||
66 | $this->assertSame(4, $m->size()); |
||||
67 | } |
||||
68 | |||||
69 | public function testTupleLikeInjection() |
||||
70 | { |
||||
71 | $map = Map::of() |
||||
72 | (1, 2) |
||||
73 | (3, 4); |
||||
74 | $expected = Map::of() |
||||
75 | ->put(1, 2) |
||||
76 | ->put(3, 4); |
||||
77 | |||||
78 | $this->assertTrue($map->equals($expected)); |
||||
79 | } |
||||
80 | |||||
81 | public function testGet() |
||||
82 | { |
||||
83 | $m = Map::of(); |
||||
84 | $m = $m->put(23, 24); |
||||
85 | |||||
86 | $this->assertSame(24, $this->get($m, 23)); |
||||
87 | } |
||||
88 | |||||
89 | public function testReturnNothingWhenGettingUnknownKey() |
||||
90 | { |
||||
91 | $this->assertNull($this->get(Map::of(), 24)); |
||||
92 | } |
||||
93 | |||||
94 | public function testContains() |
||||
95 | { |
||||
96 | $m = Map::of(); |
||||
97 | $m = $m->put(23, 24); |
||||
98 | |||||
99 | $this->assertFalse($m->contains(24)); |
||||
100 | $this->assertTrue($m->contains(23)); |
||||
101 | } |
||||
102 | |||||
103 | public function testClear() |
||||
104 | { |
||||
105 | $m = Map::of(); |
||||
106 | $m = $m->put(24, 42.0); |
||||
107 | |||||
108 | $m2 = $m->clear(); |
||||
109 | $this->assertNotSame($m, $m2); |
||||
110 | $this->assertInstanceOf(Map::class, $m2); |
||||
111 | $this->assertSame(1, $m->size()); |
||||
112 | $this->assertSame(0, $m2->size()); |
||||
113 | } |
||||
114 | |||||
115 | public function testEquals() |
||||
116 | { |
||||
117 | $m = Map::of()->put(24, 42); |
||||
118 | $m2 = Map::of()->put(24, 42); |
||||
119 | |||||
120 | $this->assertTrue($m->equals($m2)); |
||||
121 | $this->assertFalse($m->equals($m2->put(65, 66))); |
||||
122 | $this->assertFalse($m->equals($m2->put(24, 24))); |
||||
123 | $this->assertFalse( |
||||
124 | Map::of() |
||||
125 | ->put('foo_res', 'res') |
||||
126 | ->put('foo_bar_res', 'res') |
||||
127 | ->equals( |
||||
128 | Map::of() |
||||
129 | ->put('foo_res', 'res') |
||||
130 | ->put('bar_res', 'res'), |
||||
131 | ), |
||||
132 | ); |
||||
133 | |||||
134 | $m = Map::of() |
||||
135 | ->put(24, 42) |
||||
136 | ->put(42, 24); |
||||
137 | $m2 = Map::of() |
||||
138 | ->put(42, 24) |
||||
139 | ->put(24, 42); |
||||
140 | |||||
141 | $this->assertTrue($m->equals($m2)); |
||||
142 | |||||
143 | $this->assertTrue(Map::of()->equals(Map::of())); |
||||
144 | } |
||||
145 | |||||
146 | public function testFilter() |
||||
147 | { |
||||
148 | $m = Map::of() |
||||
149 | ->put(0, 1) |
||||
150 | ->put(1, 2) |
||||
151 | ->put(2, 3) |
||||
152 | ->put(4, 5); |
||||
153 | |||||
154 | $m2 = $m->filter(static function(int $key, int $value) { |
||||
155 | return ($key + $value) % 3 === 0; |
||||
156 | }); |
||||
157 | |||||
158 | $this->assertNotSame($m, $m2); |
||||
159 | $this->assertInstanceOf(Map::class, $m2); |
||||
160 | $this->assertSame(4, $m->size()); |
||||
161 | $this->assertSame(2, $m2->size()); |
||||
162 | $this->assertTrue($m2->contains(1)); |
||||
163 | $this->assertTrue($m2->contains(4)); |
||||
164 | $this->assertFalse($m2->contains(0)); |
||||
165 | $this->assertFalse($m2->contains(2)); |
||||
166 | } |
||||
167 | |||||
168 | public function testForeach() |
||||
169 | { |
||||
170 | $m = Map::of() |
||||
171 | ->put(0, 1) |
||||
172 | ->put(1, 2) |
||||
173 | ->put(2, 3) |
||||
174 | ->put(3, 4); |
||||
175 | $count = 0; |
||||
176 | |||||
177 | $m->foreach(function(int $key, int $value) use (&$count) { |
||||
178 | $this->assertSame($count, $key); |
||||
179 | $this->assertSame($value, $key + 1); |
||||
180 | ++$count; |
||||
181 | }); |
||||
182 | $this->assertSame(4, $count); |
||||
183 | } |
||||
184 | |||||
185 | public function testGroupEmptyMap() |
||||
186 | { |
||||
187 | $this->assertTrue( |
||||
188 | Map::of() |
||||
189 | ->groupBy(static function() {}) |
||||
190 | ->equals(Map::of()), |
||||
191 | ); |
||||
192 | } |
||||
193 | |||||
194 | public function testGroupBy() |
||||
195 | { |
||||
196 | $m = Map::of() |
||||
197 | ->put(0, 1) |
||||
198 | ->put(1, 2) |
||||
199 | ->put(2, 3) |
||||
200 | ->put(4, 5); |
||||
201 | |||||
202 | $m2 = $m->groupBy(static function(int $key, int $value) { |
||||
203 | return ($key + $value) % 3; |
||||
204 | }); |
||||
205 | $this->assertNotSame($m, $m2); |
||||
206 | $this->assertInstanceOf(Map::class, $m2); |
||||
207 | $this->assertTrue($m2->contains(0)); |
||||
208 | $this->assertTrue($m2->contains(1)); |
||||
209 | $this->assertTrue($m2->contains(2)); |
||||
210 | $this->assertSame(2, $this->get($m2, 0)->size()); |
||||
211 | $this->assertSame(1, $this->get($m2, 1)->size()); |
||||
212 | $this->assertSame(1, $this->get($m2, 2)->size()); |
||||
213 | $this->assertSame(1, $this->get($this->get($m2, 1), 0)); |
||||
214 | $this->assertSame(2, $this->get($this->get($m2, 0), 1)); |
||||
215 | $this->assertSame(3, $this->get($this->get($m2, 2), 2)); |
||||
216 | $this->assertSame(5, $this->get($this->get($m2, 0), 4)); |
||||
217 | } |
||||
218 | |||||
219 | public function testKeys() |
||||
220 | { |
||||
221 | $m = Map::of() |
||||
222 | ->put(0, 1) |
||||
223 | ->put(1, 2) |
||||
224 | ->put(2, 3) |
||||
225 | ->put(4, 5); |
||||
226 | |||||
227 | $k = $m->keys(); |
||||
228 | $this->assertInstanceOf(Set::class, $k); |
||||
229 | $this->assertSame([0, 1, 2, 4], $k->toList()); |
||||
230 | $this->assertTrue($k->equals($m->keys())); |
||||
231 | } |
||||
232 | |||||
233 | public function testValues() |
||||
234 | { |
||||
235 | $m = Map::of() |
||||
236 | ->put(0, 1) |
||||
237 | ->put(1, 2) |
||||
238 | ->put(2, 3) |
||||
239 | ->put(4, 5) |
||||
240 | ->put(5, 5); |
||||
241 | |||||
242 | $v = $m->values(); |
||||
243 | $this->assertInstanceOf(Sequence::class, $v); |
||||
244 | $this->assertSame([1, 2, 3, 5, 5], $v->toList()); |
||||
245 | $this->assertTrue($v->equals($m->values())); |
||||
246 | } |
||||
247 | |||||
248 | public function testMap() |
||||
249 | { |
||||
250 | $m = Map::of() |
||||
251 | ->put(0, 1) |
||||
252 | ->put(1, 2) |
||||
253 | ->put(2, 3) |
||||
254 | ->put(4, 5); |
||||
255 | |||||
256 | $m2 = $m->map(static function(int $key, int $value) { |
||||
257 | return $value**2; |
||||
258 | }); |
||||
259 | $this->assertNotSame($m, $m2); |
||||
260 | $this->assertInstanceOf(Map::class, $m2); |
||||
261 | $this->assertSame([0, 1, 2, 4], $m->keys()->toList()); |
||||
262 | $this->assertSame([1, 2, 3, 5], $m->values()->toList()); |
||||
263 | $this->assertSame([0, 1, 2, 4], $m2->keys()->toList()); |
||||
264 | $this->assertSame([1, 4, 9, 25], $m2->values()->toList()); |
||||
265 | } |
||||
266 | |||||
267 | public function testFlatMap() |
||||
268 | { |
||||
269 | $map = Map::of()(0, 1)(2, 3)(4, 5); |
||||
270 | $map2 = $map->flatMap(static fn($key, $value) => Map::of()($value, $key)); |
||||
271 | |||||
272 | $this->assertNotSame($map, $map2); |
||||
273 | $this->assertSame([0, 2, 4], $map->keys()->toList()); |
||||
274 | $this->assertSame([1, 3, 5], $map->values()->toList()); |
||||
275 | $this->assertSame([1, 3, 5], $map2->keys()->toList()); |
||||
276 | $this->assertSame([0, 2, 4], $map2->values()->toList()); |
||||
277 | } |
||||
278 | |||||
279 | public function testRemove() |
||||
280 | { |
||||
281 | $m = Map::of() |
||||
282 | ->put(0, 1) |
||||
283 | ->put(1, 2) |
||||
284 | ->put(2, 3) |
||||
285 | ->put(3, 4) |
||||
286 | ->put(4, 5); |
||||
287 | |||||
288 | $m2 = $m->remove(12); |
||||
289 | $this->assertTrue($m->equals($m2)); |
||||
290 | $this->assertSame([0, 1, 2, 3, 4], $m->keys()->toList()); |
||||
291 | $this->assertSame([1, 2, 3, 4, 5], $m->values()->toList()); |
||||
292 | |||||
293 | $m2 = $m->remove(3); |
||||
294 | $this->assertNotSame($m, $m2); |
||||
295 | $this->assertInstanceOf(Map::class, $m2); |
||||
296 | $this->assertSame([0, 1, 2, 3, 4], $m->keys()->toList()); |
||||
297 | $this->assertSame([1, 2, 3, 4, 5], $m->values()->toList()); |
||||
298 | $this->assertSame([0, 1, 2, 4], $m2->keys()->toList()); |
||||
299 | $this->assertSame([1, 2, 3, 5], $m2->values()->toList()); |
||||
300 | |||||
301 | $m2 = $m->remove(4); |
||||
302 | $this->assertNotSame($m, $m2); |
||||
303 | $this->assertInstanceOf(Map::class, $m2); |
||||
304 | $this->assertSame([0, 1, 2, 3, 4], $m->keys()->toList()); |
||||
305 | $this->assertSame([1, 2, 3, 4, 5], $m->values()->toList()); |
||||
306 | $this->assertSame([0, 1, 2, 3], $m2->keys()->toList()); |
||||
307 | $this->assertSame([1, 2, 3, 4], $m2->values()->toList()); |
||||
308 | |||||
309 | $m2 = $m->remove(0); |
||||
310 | $this->assertNotSame($m, $m2); |
||||
311 | $this->assertInstanceOf(Map::class, $m2); |
||||
312 | $this->assertSame([0, 1, 2, 3, 4], $m->keys()->toList()); |
||||
313 | $this->assertSame([1, 2, 3, 4, 5], $m->values()->toList()); |
||||
314 | $this->assertSame([1, 2, 3, 4], $m2->keys()->toList()); |
||||
315 | $this->assertSame([2, 3, 4, 5], $m2->values()->toList()); |
||||
316 | } |
||||
317 | |||||
318 | public function testMerge() |
||||
319 | { |
||||
320 | $m = Map::of() |
||||
321 | ->put($s = new \stdClass, 24) |
||||
322 | ->put($s2 = new \stdClass, 42); |
||||
323 | $m2 = Map::of() |
||||
324 | ->put($s3 = new \stdClass, 24) |
||||
325 | ->put($s2, 66) |
||||
326 | ->put($s4 = new \stdClass, 42); |
||||
327 | |||||
328 | $m3 = $m->merge($m2); |
||||
329 | $this->assertNotSame($m, $m3); |
||||
330 | $this->assertNotSame($m2, $m3); |
||||
331 | $this->assertInstanceOf(Map::class, $m3); |
||||
332 | $this->assertSame(4, $m3->size()); |
||||
333 | $this->assertSame([$s, $s2], $m->keys()->toList()); |
||||
334 | $this->assertSame([24, 42], $m->values()->toList()); |
||||
335 | $this->assertSame([$s3, $s2, $s4], $m2->keys()->toList()); |
||||
336 | $this->assertSame([24, 66, 42], $m2->values()->toList()); |
||||
337 | $this->assertSame([$s, $s2, $s3, $s4], $m3->keys()->toList()); |
||||
338 | $this->assertSame([24, 66, 24, 42], $m3->values()->toList()); |
||||
339 | $this->assertFalse($m3->equals($m2->merge($m))); |
||||
340 | } |
||||
341 | |||||
342 | public function testPartition() |
||||
343 | { |
||||
344 | $m = Map::of() |
||||
345 | ->put(0, 1) |
||||
346 | ->put(1, 2) |
||||
347 | ->put(2, 3) |
||||
348 | ->put(3, 4) |
||||
349 | ->put(4, 5); |
||||
350 | |||||
351 | $p = $m->partition(static function(int $i, int $v) { |
||||
352 | return ($i + $v) % 3 === 0; |
||||
353 | }); |
||||
354 | |||||
355 | $this->assertInstanceOf(Map::class, $p); |
||||
356 | $this->assertNotSame($p, $m); |
||||
357 | $this->assertSame( |
||||
358 | [true, false], |
||||
359 | $p->keys()->toList(), |
||||
360 | ); |
||||
361 | $this->assertSame( |
||||
362 | [1, 4], |
||||
363 | $this->get($p, true)->keys()->toList(), |
||||
364 | ); |
||||
365 | $this->assertSame( |
||||
366 | [2, 5], |
||||
367 | $this->get($p, true)->values()->toList(), |
||||
368 | ); |
||||
369 | $this->assertSame( |
||||
370 | [0, 2, 3], |
||||
371 | $this->get($p, false)->keys()->toList(), |
||||
372 | ); |
||||
373 | $this->assertSame( |
||||
374 | [1, 3, 4], |
||||
375 | $this->get($p, false)->values()->toList(), |
||||
376 | ); |
||||
377 | } |
||||
378 | |||||
379 | public function testReduce() |
||||
380 | { |
||||
381 | $m = Map::of()->put(4, 4); |
||||
382 | |||||
383 | $v = $m->reduce( |
||||
384 | 42, |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
385 | static function(float $carry, int $key, int $value): float { |
||||
386 | return $carry / ($key * $value); |
||||
387 | }, |
||||
388 | ); |
||||
389 | |||||
390 | $this->assertSame(2.625, $v); |
||||
391 | $this->assertSame([4], $m->keys()->toList()); |
||||
392 | $this->assertSame([4], $m->values()->toList()); |
||||
393 | } |
||||
394 | |||||
395 | public function testMatches() |
||||
396 | { |
||||
397 | $map = Map::of() |
||||
398 | (1, 2) |
||||
399 | (3, 4); |
||||
400 | |||||
401 | $this->assertTrue($map->matches(static fn($key, $value) => $value % 2 === 0)); |
||||
402 | $this->assertFalse($map->matches(static fn($key, $value) => $key % 2 === 0)); |
||||
0 ignored issues
–
show
The parameter
$value is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
403 | $this->assertFalse(Map::of([1, 2], [3, 3])->matches( |
||||
404 | static fn($key, $value) => $value % 2 === 0, |
||||
405 | )); |
||||
406 | } |
||||
407 | |||||
408 | public function testAny() |
||||
409 | { |
||||
410 | $map = Map::of() |
||||
411 | (1, 2) |
||||
412 | (3, 4); |
||||
413 | |||||
414 | $this->assertTrue($map->any(static fn($key, $value) => $value === 4)); |
||||
415 | $this->assertTrue($map->any(static fn($key, $value) => $key === 1)); |
||||
0 ignored issues
–
show
The parameter
$value is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
416 | $this->assertFalse($map->any(static fn($key, $value) => $key === 0)); |
||||
0 ignored issues
–
show
The parameter
$value is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
417 | $this->assertFalse($map->any(static fn($key, $value) => $value === 1)); |
||||
418 | } |
||||
419 | |||||
420 | public function testFind() |
||||
421 | { |
||||
422 | $map = Map::of([1, 2], [3, 4], [5, 6]); |
||||
423 | |||||
424 | $this->assertSame( |
||||
425 | 4, |
||||
426 | $map |
||||
427 | ->find(static fn($k) => $k === 3) |
||||
428 | ->map(static fn($pair) => $pair->value()) |
||||
429 | ->match( |
||||
430 | static fn($value) => $value, |
||||
431 | static fn() => null, |
||||
432 | ), |
||||
433 | ); |
||||
434 | } |
||||
435 | |||||
436 | private function get($map, $index) |
||||
437 | { |
||||
438 | return $map->get($index)->match( |
||||
439 | static fn($value) => $value, |
||||
440 | static fn() => null, |
||||
441 | ); |
||||
442 | } |
||||
443 | } |
||||
444 |