From ffe0f0f21290ff6469da5c723172b9afc6aeba7d Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 5 Mar 2024 19:39:58 +0100 Subject: [PATCH] Failing test case: Valinor cannot understand `array{k: T|list}` In this test, Valinor is being challenged to understand de-serialization of a given hashmap when given a type `array{a-key: T|list}`. Specifically, at the time of this writing, Valinor only picks `T` during de-serialization, and seems to completely ignore the `list` portion of the data. This kind of de-serialization is relevant when dealing with XML structures, where an element could be singular or plural depending on context: ```xml 123 456 789 ``` Initially discovered by @Tigerman55 --- .../Fixture/SimpleObjectWithConstructor.php | 12 ++++ .../Integration/Mapping/UnionMappingTest.php | 72 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/Integration/Mapping/Fixture/SimpleObjectWithConstructor.php diff --git a/tests/Integration/Mapping/Fixture/SimpleObjectWithConstructor.php b/tests/Integration/Mapping/Fixture/SimpleObjectWithConstructor.php new file mode 100644 index 00000000..98b352ea --- /dev/null +++ b/tests/Integration/Mapping/Fixture/SimpleObjectWithConstructor.php @@ -0,0 +1,12 @@ +} $expectedMap + */ + public function test_union_of_object_and_list_types_in_hashmap_key(mixed $input, array $expectedMap): void + { + try { + self::assertEquals( + $expectedMap, + $this->mapperBuilder() + ->mapper() + ->map( + "array{key:" . SimpleObjectWithConstructor::class . "|list<" . SimpleObjectWithConstructor::class . ">}", + $input + ) + ); + } catch (MappingError $error) { + var_dump($input); + var_dump($expectedMap); + $this->mappingFail($error); + } + } + + /** + * @return non-empty-array< + * non-empty-string, + * array{mixed, array{key: SimpleObjectWithConstructor|list}} + * > + */ + public static function expectedDeSerializationForUnionHashmapTypes(): array + { + return [ + 'single hashmap scalar value gets de-serialized into a hashmap containing a single value' => [ + ['key' => 'single-value'], + ['key' => new SimpleObjectWithConstructor('single-value')], + ], + 'single hashmap value gets de-serialized into a hashmap containing a single value' => [ + ['key' => ['value' => 'single-value']], + ['key' => new SimpleObjectWithConstructor('single-value')], + ], + 'multiple hashmap scalar values get de-serialized into a hashmap containing a a list of values' => [ + [ + 'key' => [ + 'multi-value-1', + 'multi-value-2', + ], + ], + [ + 'key' => [ + new SimpleObjectWithConstructor('multi-value-1'), + new SimpleObjectWithConstructor('multi-value-2'), + ], + ], + ], + 'multiple hashmap values get de-serialized into a hashmap containing a a list of values' => [ + [ + 'key' => [ + ['value' => 'multi-value-1'], + ['value' => 'multi-value-2'], + ], + ], + [ + 'key' => [ + new SimpleObjectWithConstructor('multi-value-1'), + new SimpleObjectWithConstructor('multi-value-2'), + ], + ], + ], + ]; + } }