Skip to content

Commit 435a92c

Browse files
authored
Fix contains with minContains not tracking evaluation (#479)
We incorrectly compile away `contains` when `minContains: 0` even if we do actually need to track evaluation for other reasons (i.e. `unevaluatedItems`). See: json-schema-org/JSON-Schema-Test-Suite#765 Signed-off-by: Juan Cruz Viotti <[email protected]>
1 parent c0beb60 commit 435a92c

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

src/compiler/default_compiler_2019_09.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ auto compiler_2019_09_applicator_contains_with_options(
149149
schema_context, dynamic_context, ValueNone{})};
150150
}
151151

152-
if (minimum == 0 && !maximum.has_value()) {
152+
if (minimum == 0 && !maximum.has_value() && !track_evaluation) {
153153
return {};
154154
}
155155

test/evaluator/evaluator_2020_12_test.cc

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,6 +2038,86 @@ TEST(Evaluator_2020_12, unevaluatedItems_5_exhaustive) {
20382038
"expected to validate against this subschema");
20392039
}
20402040

2041+
TEST(Evaluator_2020_12, unevaluatedItems_6) {
2042+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
2043+
"$schema": "https://json-schema.org/draft/2020-12/schema",
2044+
"contains": { "type": "string" },
2045+
"minContains": 0,
2046+
"unevaluatedItems": false
2047+
})JSON")};
2048+
2049+
const sourcemeta::core::JSON instance{
2050+
sourcemeta::core::parse_json("[\"foo\"]")};
2051+
2052+
EVALUATE_WITH_TRACE_FAST_SUCCESS(schema, instance, 3);
2053+
2054+
EVALUATE_TRACE_PRE(0, LoopContains, "/contains", "#/contains", "");
2055+
EVALUATE_TRACE_PRE(1, AssertionTypeStrict, "/contains/type",
2056+
"#/contains/type", "/0");
2057+
EVALUATE_TRACE_PRE(2, LoopItemsUnevaluated, "/unevaluatedItems",
2058+
"#/unevaluatedItems", "");
2059+
2060+
EVALUATE_TRACE_POST_SUCCESS(0, AssertionTypeStrict, "/contains/type",
2061+
"#/contains/type", "/0");
2062+
EVALUATE_TRACE_POST_SUCCESS(1, LoopContains, "/contains", "#/contains", "");
2063+
EVALUATE_TRACE_POST_SUCCESS(2, LoopItemsUnevaluated, "/unevaluatedItems",
2064+
"#/unevaluatedItems", "");
2065+
2066+
EVALUATE_TRACE_POST_DESCRIBE(instance, 0,
2067+
"The value was expected to be of type string");
2068+
EVALUATE_TRACE_POST_DESCRIBE(
2069+
instance, 1,
2070+
"The array value was expected to contain at least 0 items that validate "
2071+
"against the given subschema");
2072+
EVALUATE_TRACE_POST_DESCRIBE(
2073+
instance, 2,
2074+
"The array items not covered by other array keywords, if any, were "
2075+
"expected to validate against this subschema");
2076+
}
2077+
2078+
TEST(Evaluator_2020_12, unevaluatedItems_6_exhaustive) {
2079+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
2080+
"$schema": "https://json-schema.org/draft/2020-12/schema",
2081+
"contains": { "type": "string" },
2082+
"minContains": 0,
2083+
"unevaluatedItems": false
2084+
})JSON")};
2085+
2086+
const sourcemeta::core::JSON instance{
2087+
sourcemeta::core::parse_json("[\"foo\"]")};
2088+
2089+
EVALUATE_WITH_TRACE_EXHAUSTIVE_SUCCESS(schema, instance, 4);
2090+
2091+
EVALUATE_TRACE_PRE(0, LoopContains, "/contains", "#/contains", "");
2092+
EVALUATE_TRACE_PRE(1, AssertionTypeStrict, "/contains/type",
2093+
"#/contains/type", "/0");
2094+
EVALUATE_TRACE_PRE_ANNOTATION(2, "/contains", "#/contains", "");
2095+
EVALUATE_TRACE_PRE(3, LoopItemsUnevaluated, "/unevaluatedItems",
2096+
"#/unevaluatedItems", "");
2097+
2098+
EVALUATE_TRACE_POST_SUCCESS(0, AssertionTypeStrict, "/contains/type",
2099+
"#/contains/type", "/0");
2100+
EVALUATE_TRACE_POST_ANNOTATION(1, "/contains", "#/contains", "", 0);
2101+
EVALUATE_TRACE_POST_SUCCESS(2, LoopContains, "/contains", "#/contains", "");
2102+
EVALUATE_TRACE_POST_SUCCESS(3, LoopItemsUnevaluated, "/unevaluatedItems",
2103+
"#/unevaluatedItems", "");
2104+
2105+
EVALUATE_TRACE_POST_DESCRIBE(instance, 0,
2106+
"The value was expected to be of type string");
2107+
EVALUATE_TRACE_POST_DESCRIBE(
2108+
instance, 1,
2109+
"The item at index 0 of the array value successfully validated against "
2110+
"the containment check subschema");
2111+
EVALUATE_TRACE_POST_DESCRIBE(
2112+
instance, 2,
2113+
"The array value was expected to contain at least 0 items that validate "
2114+
"against the given subschema");
2115+
EVALUATE_TRACE_POST_DESCRIBE(
2116+
instance, 3,
2117+
"The array items not covered by other array keywords, if any, were "
2118+
"expected to validate against this subschema");
2119+
}
2120+
20412121
TEST(Evaluator_2020_12, unevaluatedProperties_1) {
20422122
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
20432123
"$schema": "https://json-schema.org/draft/2020-12/schema",

0 commit comments

Comments
 (0)