Innmind /
Immutable
| 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
Loading history...
|
|||||
| 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. Loading history...
|
|||||
| 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. Loading history...
|
|||||
| 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. Loading history...
|
|||||
| 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 |