|
8 | 8 |
|
9 | 9 | #define EXPECT_OUTPUT(traces, index, expected_type, expected_name, \ |
10 | 10 | expected_instance_location, expected_evaluate_path, \ |
11 | | - expected_keyword_location) \ |
| 11 | + expected_keyword_location, expected_annotation) \ |
12 | 12 | EXPECT_TRUE(traces.size() > index); \ |
13 | 13 | EXPECT_EQ(traces.at((index)).type, \ |
14 | 14 | sourcemeta::blaze::TraceOutput::EntryType::expected_type); \ |
|
17 | 17 | expected_instance_location); \ |
18 | 18 | EXPECT_EQ(sourcemeta::core::to_string(traces.at((index)).evaluate_path), \ |
19 | 19 | expected_evaluate_path); \ |
20 | | - EXPECT_EQ(traces.at((index)).keyword_location, (expected_keyword_location)); |
| 20 | + EXPECT_EQ(traces.at((index)).keyword_location, (expected_keyword_location)); \ |
| 21 | + if (std::optional<sourcemeta::core::JSON>{expected_annotation} \ |
| 22 | + .has_value()) { \ |
| 23 | + EXPECT_TRUE(traces.at((index)).annotation.has_value()); \ |
| 24 | + EXPECT_EQ( \ |
| 25 | + traces.at((index)).annotation.value(), \ |
| 26 | + std::optional<sourcemeta::core::JSON>{expected_annotation}.value()); \ |
| 27 | + } else { \ |
| 28 | + EXPECT_FALSE(traces.at((index)).annotation.has_value()); \ |
| 29 | + } |
21 | 30 |
|
22 | 31 | TEST(Compiler_output_trace, pass_1) { |
23 | 32 | const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({ |
@@ -51,13 +60,64 @@ TEST(Compiler_output_trace, pass_1) { |
51 | 60 | EXPECT_EQ(traces.size(), 4); |
52 | 61 |
|
53 | 62 | EXPECT_OUTPUT(traces, 0, Push, "LoopPropertiesMatchClosed", "", "/properties", |
54 | | - "#/properties"); |
| 63 | + "#/properties", std::nullopt); |
55 | 64 | EXPECT_OUTPUT(traces, 1, Push, "AssertionTypeStrict", "/foo", |
56 | | - "/properties/foo/type", "#/properties/foo/type"); |
| 65 | + "/properties/foo/type", "#/properties/foo/type", std::nullopt); |
57 | 66 | EXPECT_OUTPUT(traces, 2, Pass, "AssertionTypeStrict", "/foo", |
58 | | - "/properties/foo/type", "#/properties/foo/type"); |
| 67 | + "/properties/foo/type", "#/properties/foo/type", std::nullopt); |
59 | 68 | EXPECT_OUTPUT(traces, 3, Pass, "LoopPropertiesMatchClosed", "", "/properties", |
60 | | - "#/properties"); |
| 69 | + "#/properties", std::nullopt); |
| 70 | +} |
| 71 | + |
| 72 | +TEST(Compiler_output_trace, pass_annotations) { |
| 73 | + const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({ |
| 74 | + "$schema": "https://json-schema.org/draft/2020-12/schema", |
| 75 | + "title": "Foo Bar", |
| 76 | + "additionalProperties": false, |
| 77 | + "properties": { |
| 78 | + "foo": true, |
| 79 | + "bar": true |
| 80 | + } |
| 81 | + })JSON")}; |
| 82 | + |
| 83 | + const auto schema_template{sourcemeta::blaze::compile( |
| 84 | + schema, sourcemeta::core::schema_official_walker, |
| 85 | + sourcemeta::core::schema_official_resolver, |
| 86 | + sourcemeta::blaze::default_schema_compiler, |
| 87 | + sourcemeta::blaze::Mode::Exhaustive)}; |
| 88 | + |
| 89 | + const sourcemeta::core::JSON instance{sourcemeta::core::parse_json(R"JSON({ |
| 90 | + "foo": "bar", |
| 91 | + "bar": "baz" |
| 92 | + })JSON")}; |
| 93 | + |
| 94 | + sourcemeta::blaze::TraceOutput output; |
| 95 | + sourcemeta::blaze::Evaluator evaluator; |
| 96 | + const auto result{ |
| 97 | + evaluator.validate(schema_template, instance, std::ref(output))}; |
| 98 | + |
| 99 | + EXPECT_TRUE(result); |
| 100 | + std::vector<sourcemeta::blaze::TraceOutput::Entry> traces{output.cbegin(), |
| 101 | + output.cend()}; |
| 102 | + |
| 103 | + EXPECT_EQ(traces.size(), 7); |
| 104 | + |
| 105 | + EXPECT_OUTPUT(traces, 0, Annotation, "AnnotationEmit", "", "/title", |
| 106 | + "#/title", sourcemeta::core::JSON{"Foo Bar"}); |
| 107 | + EXPECT_OUTPUT(traces, 1, Push, "LoopPropertiesMatch", "", "/properties", |
| 108 | + "#/properties", std::nullopt); |
| 109 | + EXPECT_OUTPUT(traces, 2, Annotation, "AnnotationEmit", "", "/properties", |
| 110 | + "#/properties", sourcemeta::core::JSON{"foo"}); |
| 111 | + EXPECT_OUTPUT(traces, 3, Annotation, "AnnotationEmit", "", "/properties", |
| 112 | + "#/properties", sourcemeta::core::JSON{"bar"}); |
| 113 | + EXPECT_OUTPUT(traces, 4, Pass, "LoopPropertiesMatch", "", "/properties", |
| 114 | + "#/properties", std::nullopt); |
| 115 | + EXPECT_OUTPUT(traces, 5, Push, "LoopPropertiesExcept", "", |
| 116 | + "/additionalProperties", "#/additionalProperties", |
| 117 | + std::nullopt); |
| 118 | + EXPECT_OUTPUT(traces, 6, Pass, "LoopPropertiesExcept", "", |
| 119 | + "/additionalProperties", "#/additionalProperties", |
| 120 | + std::nullopt); |
61 | 121 | } |
62 | 122 |
|
63 | 123 | TEST(Compiler_output_trace, pass_with_matching_prefix_1) { |
@@ -98,11 +158,13 @@ TEST(Compiler_output_trace, pass_with_matching_prefix_1) { |
98 | 158 | EXPECT_EQ(traces.size(), 4); |
99 | 159 |
|
100 | 160 | EXPECT_OUTPUT(traces, 0, Push, "LoopPropertiesMatchClosed", "", "/properties", |
101 | | - "#/$defs/helper/properties"); |
| 161 | + "#/$defs/helper/properties", std::nullopt); |
102 | 162 | EXPECT_OUTPUT(traces, 1, Push, "AssertionTypeStrict", "/foo", |
103 | | - "/properties/foo/type", "#/$defs/helper/properties/foo/type"); |
| 163 | + "/properties/foo/type", "#/$defs/helper/properties/foo/type", |
| 164 | + std::nullopt); |
104 | 165 | EXPECT_OUTPUT(traces, 2, Pass, "AssertionTypeStrict", "/foo", |
105 | | - "/properties/foo/type", "#/$defs/helper/properties/foo/type"); |
| 166 | + "/properties/foo/type", "#/$defs/helper/properties/foo/type", |
| 167 | + std::nullopt); |
106 | 168 | EXPECT_OUTPUT(traces, 3, Pass, "LoopPropertiesMatchClosed", "", "/properties", |
107 | | - "#/$defs/helper/properties"); |
| 169 | + "#/$defs/helper/properties", std::nullopt); |
108 | 170 | } |
0 commit comments