1515 EXPECT_EQ (sourcemeta::core::to_string(traces.at((index)).evaluate_path), \
1616 expected_evaluate_path);
1717
18+ #define EXPECT_ANNOTATION_COUNT (output, expected_count ) \
19+ EXPECT_EQ (output.annotations().size(), (expected_count));
20+
21+ #define EXPECT_ANNOTATION_ENTRY (output, expected_instance_location, \
22+ expected_evaluate_path, expected_entry_count) \
23+ { \
24+ const auto instance_location{ \
25+ sourcemeta::core::to_pointer (expected_instance_location)}; \
26+ const auto evaluate_path{ \
27+ sourcemeta::core::to_pointer (expected_evaluate_path)}; \
28+ EXPECT_TRUE (output.annotations ().contains ( \
29+ {sourcemeta::core::to_weak_pointer (instance_location), \
30+ sourcemeta::core::to_weak_pointer (evaluate_path)})); \
31+ EXPECT_EQ (output.annotations () \
32+ .at ({sourcemeta::core::to_weak_pointer (instance_location), \
33+ sourcemeta::core::to_weak_pointer (evaluate_path)}) \
34+ .size (), \
35+ (expected_entry_count)); \
36+ }
37+
38+ #define EXPECT_ANNOTATION_VALUE (output, expected_instance_location, \
39+ expected_evaluate_path, expected_entry_index, \
40+ expected_value) \
41+ { \
42+ const auto instance_location{ \
43+ sourcemeta::core::to_pointer (expected_instance_location)}; \
44+ const auto evaluate_path{ \
45+ sourcemeta::core::to_pointer (expected_evaluate_path)}; \
46+ EXPECT_EQ (output.annotations () \
47+ .at ({sourcemeta::core::to_weak_pointer (instance_location), \
48+ sourcemeta::core::to_weak_pointer (evaluate_path)}) \
49+ .at (expected_entry_index), \
50+ (expected_value)); \
51+ }
52+
1853TEST (Compiler_output_simple, success_string_1) {
1954 const sourcemeta::core::JSON schema{sourcemeta::core::parse_json (R"JSON( {
2055 "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -37,6 +72,8 @@ TEST(Compiler_output_simple, success_string_1) {
3772 std::vector<sourcemeta::blaze::SimpleOutput::Entry> traces{output.cbegin (),
3873 output.cend ()};
3974 EXPECT_TRUE (traces.empty ());
75+
76+ EXPECT_ANNOTATION_COUNT (output, 0 );
4077}
4178
4279TEST (Compiler_output_simple, fail_meaningless_if_1) {
@@ -82,6 +119,8 @@ TEST(Compiler_output_simple, fail_meaningless_if_1) {
82119 EXPECT_OUTPUT (
83120 traces, 1 , " /foo" , " /properties/foo/unevaluatedProperties" ,
84121 " The object value was not expected to define unevaluated properties" );
122+
123+ EXPECT_ANNOTATION_COUNT (output, 0 );
85124}
86125
87126TEST (Compiler_output_simple, success_dynamic_anchor_1) {
@@ -112,6 +151,8 @@ TEST(Compiler_output_simple, success_dynamic_anchor_1) {
112151 std::vector<sourcemeta::blaze::SimpleOutput::Entry> traces{output.cbegin (),
113152 output.cend ()};
114153 EXPECT_TRUE (traces.empty ());
154+
155+ EXPECT_ANNOTATION_COUNT (output, 0 );
115156}
116157
117158TEST (Compiler_output_simple, success_oneof_1) {
@@ -139,6 +180,8 @@ TEST(Compiler_output_simple, success_oneof_1) {
139180 std::vector<sourcemeta::blaze::SimpleOutput::Entry> traces{output.cbegin (),
140181 output.cend ()};
141182 EXPECT_TRUE (traces.empty ());
183+
184+ EXPECT_ANNOTATION_COUNT (output, 0 );
142185}
143186
144187TEST (Compiler_output_simple, fail_string) {
@@ -167,6 +210,8 @@ TEST(Compiler_output_simple, fail_string) {
167210 EXPECT_OUTPUT (
168211 traces, 0 , " " , " /type" ,
169212 " The value was expected to be of type string but it was of type integer" );
213+
214+ EXPECT_ANNOTATION_COUNT (output, 0 );
170215}
171216
172217TEST (Compiler_output_simple, fail_string_over_ref) {
@@ -200,6 +245,7 @@ TEST(Compiler_output_simple, fail_string_over_ref) {
200245 EXPECT_OUTPUT (
201246 traces, 0 , " " , " /$ref/type" ,
202247 " The value was expected to be of type string but it was of type integer" );
248+ EXPECT_ANNOTATION_COUNT (output, 0 );
203249}
204250
205251TEST (Compiler_output_simple, fail_string_with_matching_base) {
@@ -235,6 +281,7 @@ TEST(Compiler_output_simple, fail_string_with_matching_base) {
235281 EXPECT_OUTPUT (
236282 traces, 0 , " " , " /type" ,
237283 " The value was expected to be of type string but it was of type integer" );
284+ EXPECT_ANNOTATION_COUNT (output, 0 );
238285}
239286
240287TEST (Compiler_output_simple, fail_string_with_non_matching_base) {
@@ -269,6 +316,7 @@ TEST(Compiler_output_simple, fail_string_with_non_matching_base) {
269316 EXPECT_OUTPUT (
270317 traces, 0 , " " , " /$ref/type" ,
271318 " The value was expected to be of type string but it was of type integer" );
319+ EXPECT_ANNOTATION_COUNT (output, 0 );
272320}
273321
274322TEST (Compiler_output_simple, fail_oneof_1) {
@@ -300,6 +348,7 @@ TEST(Compiler_output_simple, fail_oneof_1) {
300348 EXPECT_OUTPUT (traces, 0 , " " , " /oneOf" ,
301349 " The string value was expected to validate against one and "
302350 " only one of the 2 given subschemas" );
351+ EXPECT_ANNOTATION_COUNT (output, 0 );
303352}
304353
305354TEST (Compiler_output_simple, fail_not_1) {
@@ -330,6 +379,7 @@ TEST(Compiler_output_simple, fail_not_1) {
330379 EXPECT_OUTPUT (traces, 0 , " " , " /not" ,
331380 " The string value was expected to not validate against the "
332381 " given subschema, but it did" );
382+ EXPECT_ANNOTATION_COUNT (output, 0 );
333383}
334384
335385TEST (Compiler_output_simple, fail_not_not_1) {
@@ -362,6 +412,7 @@ TEST(Compiler_output_simple, fail_not_not_1) {
362412 EXPECT_OUTPUT (traces, 0 , " " , " /not" ,
363413 " The integer value was expected to not validate against the "
364414 " given subschema, but it did" );
415+ EXPECT_ANNOTATION_COUNT (output, 0 );
365416}
366417
367418TEST (Compiler_output_simple, fail_anyof_1) {
@@ -400,6 +451,7 @@ TEST(Compiler_output_simple, fail_anyof_1) {
400451 EXPECT_OUTPUT (
401452 traces, 0 , " " , " /allOf/1/type" ,
402453 " The value was expected to be of type integer but it was of type object" );
454+ EXPECT_ANNOTATION_COUNT (output, 0 );
403455}
404456
405457TEST (Compiler_output_simple, fail_anyof_2) {
@@ -433,4 +485,150 @@ TEST(Compiler_output_simple, fail_anyof_2) {
433485 EXPECT_OUTPUT (traces, 0 , " " , " /anyOf" ,
434486 " The object value was expected to validate against at least "
435487 " one of the 2 given subschemas" );
488+ EXPECT_ANNOTATION_COUNT (output, 0 );
489+ }
490+
491+ TEST (Compiler_output_simple, annotations_success_1) {
492+ const sourcemeta::core::JSON schema{sourcemeta::core::parse_json (R"JSON( {
493+ "$schema": "https://json-schema.org/draft/2020-12/schema",
494+ "title": "My Schema",
495+ "properties": {
496+ "foo": {
497+ "title": "Foo",
498+ "deprecated": true,
499+ "$ref": "#/$defs/test"
500+ },
501+ "bar": true
502+ },
503+ "$defs": {
504+ "test": {
505+ "title": "Test"
506+ }
507+ }
508+ })JSON" )};
509+
510+ const auto schema_template{sourcemeta::blaze::compile (
511+ schema, sourcemeta::core::schema_official_walker,
512+ sourcemeta::core::schema_official_resolver,
513+ sourcemeta::blaze::default_schema_compiler,
514+ sourcemeta::blaze::Mode::Exhaustive)};
515+
516+ const auto instance{sourcemeta::core::parse_json (R"JSON( {
517+ "foo": "bar",
518+ "bar": "baz"
519+ })JSON" )};
520+
521+ sourcemeta::blaze::SimpleOutput output{instance};
522+ sourcemeta::blaze::Evaluator evaluator;
523+ const auto result{
524+ evaluator.validate (schema_template, instance, std::ref (output))};
525+ EXPECT_TRUE (result);
526+
527+ EXPECT_ANNOTATION_COUNT (output, 5 );
528+
529+ EXPECT_ANNOTATION_ENTRY (output, " " , " /properties" , 2 );
530+ EXPECT_ANNOTATION_VALUE (output, " " , " /properties" , 0 ,
531+ sourcemeta::core::JSON{" bar" });
532+ EXPECT_ANNOTATION_VALUE (output, " " , " /properties" , 1 ,
533+ sourcemeta::core::JSON{" foo" });
534+
535+ EXPECT_ANNOTATION_ENTRY (output, " " , " /title" , 1 );
536+ EXPECT_ANNOTATION_VALUE (output, " " , " /title" , 0 ,
537+ sourcemeta::core::JSON{" My Schema" });
538+
539+ EXPECT_ANNOTATION_ENTRY (output, " /foo" , " /properties/foo/$ref/title" , 1 );
540+ EXPECT_ANNOTATION_VALUE (output, " /foo" , " /properties/foo/$ref/title" , 0 ,
541+ sourcemeta::core::JSON{" Test" });
542+
543+ EXPECT_ANNOTATION_ENTRY (output, " /foo" , " /properties/foo/title" , 1 );
544+ EXPECT_ANNOTATION_VALUE (output, " /foo" , " /properties/foo/title" , 0 ,
545+ sourcemeta::core::JSON{" Foo" });
546+
547+ EXPECT_ANNOTATION_ENTRY (output, " /foo" , " /properties/foo/deprecated" , 1 );
548+ EXPECT_ANNOTATION_VALUE (output, " /foo" , " /properties/foo/deprecated" , 0 ,
549+ sourcemeta::core::JSON{true });
550+ }
551+
552+ TEST (Compiler_output_simple, annotations_success_2) {
553+ const sourcemeta::core::JSON schema{sourcemeta::core::parse_json (R"JSON( {
554+ "$schema": "https://json-schema.org/draft/2020-12/schema",
555+ "anyOf": [
556+ { "title": "First branch" },
557+ { "type": "string", "title": "Second branch" },
558+ { "title": "Third branch" }
559+ ]
560+ })JSON" )};
561+
562+ const auto schema_template{sourcemeta::blaze::compile (
563+ schema, sourcemeta::core::schema_official_walker,
564+ sourcemeta::core::schema_official_resolver,
565+ sourcemeta::blaze::default_schema_compiler,
566+ sourcemeta::blaze::Mode::Exhaustive)};
567+
568+ const sourcemeta::core::JSON instance{5 };
569+
570+ sourcemeta::blaze::SimpleOutput output{instance};
571+ sourcemeta::blaze::Evaluator evaluator;
572+ const auto result{
573+ evaluator.validate (schema_template, instance, std::ref (output))};
574+ EXPECT_TRUE (result);
575+
576+ EXPECT_ANNOTATION_COUNT (output, 2 );
577+
578+ EXPECT_ANNOTATION_ENTRY (output, " " , " /anyOf/0/title" , 1 );
579+ EXPECT_ANNOTATION_VALUE (output, " " , " /anyOf/0/title" , 0 ,
580+ sourcemeta::core::JSON{" First branch" });
581+
582+ EXPECT_ANNOTATION_ENTRY (output, " " , " /anyOf/2/title" , 1 );
583+ EXPECT_ANNOTATION_VALUE (output, " " , " /anyOf/2/title" , 0 ,
584+ sourcemeta::core::JSON{" Third branch" });
585+ }
586+
587+ TEST (Compiler_output_simple, annotations_success_3) {
588+ const sourcemeta::core::JSON schema{sourcemeta::core::parse_json (R"JSON( {
589+ "$schema": "https://json-schema.org/draft/2020-12/schema",
590+ "not": {
591+ "title": "First branch",
592+ "type": "string"
593+ }
594+ })JSON" )};
595+
596+ const auto schema_template{sourcemeta::blaze::compile (
597+ schema, sourcemeta::core::schema_official_walker,
598+ sourcemeta::core::schema_official_resolver,
599+ sourcemeta::blaze::default_schema_compiler,
600+ sourcemeta::blaze::Mode::Exhaustive)};
601+
602+ const sourcemeta::core::JSON instance{5 };
603+
604+ sourcemeta::blaze::SimpleOutput output{instance};
605+ sourcemeta::blaze::Evaluator evaluator;
606+ const auto result{
607+ evaluator.validate (schema_template, instance, std::ref (output))};
608+ EXPECT_TRUE (result);
609+
610+ EXPECT_ANNOTATION_COUNT (output, 0 );
611+ }
612+
613+ TEST (Compiler_output_simple, annotations_failure_1) {
614+ const sourcemeta::core::JSON schema{sourcemeta::core::parse_json (R"JSON( {
615+ "$schema": "https://json-schema.org/draft/2020-12/schema",
616+ "title": "Foo",
617+ "type": "string"
618+ })JSON" )};
619+
620+ const auto schema_template{sourcemeta::blaze::compile (
621+ schema, sourcemeta::core::schema_official_walker,
622+ sourcemeta::core::schema_official_resolver,
623+ sourcemeta::blaze::default_schema_compiler,
624+ sourcemeta::blaze::Mode::Exhaustive)};
625+
626+ const sourcemeta::core::JSON instance{5 };
627+
628+ sourcemeta::blaze::SimpleOutput output{instance};
629+ sourcemeta::blaze::Evaluator evaluator;
630+ const auto result{
631+ evaluator.validate (schema_template, instance, std::ref (output))};
632+ EXPECT_FALSE (result);
633+ EXPECT_ANNOTATION_COUNT (output, 0 );
436634}
0 commit comments