| 2096 | ], |
| 2097 | ) |
| 2098 | def test_struct_array_union(self, tag1, tag2, tag3, unknown): |
| 2099 | class Test1(Struct, tag=tag1, array_like=True): |
| 2100 | a: int |
| 2101 | b: int |
| 2102 | c: int = 0 |
| 2103 | |
| 2104 | class Test2(Struct, tag=tag2, array_like=True): |
| 2105 | x: int |
| 2106 | y: int |
| 2107 | |
| 2108 | class Test3(Struct, tag=tag3, array_like=True): |
| 2109 | pass |
| 2110 | |
| 2111 | typ = Union[Test1, Test2, Test3] |
| 2112 | |
| 2113 | # Decoding works |
| 2114 | assert roundtrip([tag1, 1, 2], typ) == Test1(1, 2) |
| 2115 | assert roundtrip([tag2, 3, 4], typ) == Test2(3, 4) |
| 2116 | assert roundtrip([tag3], typ) == Test3() |
| 2117 | |
| 2118 | # Optional & Extra fields still respected |
| 2119 | assert roundtrip([tag1, 1, 2, 3], typ) == Test1(1, 2, 3) |
| 2120 | assert roundtrip([tag1, 1, 2, 3, 4], typ) == Test1(1, 2, 3) |
| 2121 | |
| 2122 | # Missing required field |
| 2123 | with pytest.raises(ValidationError) as rec: |
| 2124 | roundtrip([tag1, 1], typ) |
| 2125 | assert "Expected `array` of at least length 3, got 2" in str(rec.value) |
| 2126 | |
| 2127 | # Type error has correct field index |
| 2128 | with pytest.raises(ValidationError) as rec: |
| 2129 | roundtrip([tag1, 1, "bad", 2], typ) |
| 2130 | assert "Expected `int`, got `str` - at `$[2]`" == str(rec.value) |
| 2131 | |
| 2132 | # Tag missing |
| 2133 | with pytest.raises(ValidationError) as rec: |
| 2134 | roundtrip([], typ) |
| 2135 | assert "Expected `array` of at least length 1, got 0" == str(rec.value) |
| 2136 | |
| 2137 | # Tag wrong type |
| 2138 | with pytest.raises(ValidationError) as rec: |
| 2139 | roundtrip([123.456, 2, 3, 4], typ) |
| 2140 | assert f"Expected `{type(tag1).__name__}`" in str(rec.value) |
| 2141 | assert "`$[0]`" in str(rec.value) |
| 2142 | |
| 2143 | # Tag unknown |
| 2144 | with pytest.raises(ValidationError) as rec: |
| 2145 | roundtrip([unknown, 1, 2, 3], typ) |
| 2146 | assert f"Invalid value {unknown!r} - at `$[0]`" == str(rec.value) |
| 2147 | |
| 2148 | @pytest.mark.parametrize("tags", [(1, 2), (-10000, 10000), ("A", "B")]) |
| 2149 | @pytest.mark.parametrize("array_like", [False, True]) |