From c778dcd716e9eef3eedf2d8642dd8609b8f112c0 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Tue, 3 Feb 2026 14:16:07 -0400 Subject: [PATCH 1/2] [WIP] Implement support for custom reachability checks Signed-off-by: Juan Cruz Viotti --- benchmark/jsonschema.cc | 21 +- src/core/jsonschema/frame.cc | 66 +- test/jsonschema/CMakeLists.txt | 4 + .../jsonschema_frame_2019_09_test.cc | 203 +++ .../jsonschema_frame_2020_12_test.cc | 1342 ++++++++++++++++- .../jsonschema_frame_draft0_test.cc | 51 + .../jsonschema_frame_draft1_test.cc | 51 + .../jsonschema_frame_draft2_test.cc | 51 + .../jsonschema_frame_draft3_test.cc | 58 + .../jsonschema_frame_draft4_test.cc | 118 ++ .../jsonschema_frame_draft6_test.cc | 75 + .../jsonschema_frame_draft7_test.cc | 64 + 12 files changed, 2070 insertions(+), 34 deletions(-) diff --git a/benchmark/jsonschema.cc b/benchmark/jsonschema.cc index f5e12ac8a..4a7dcb87a 100644 --- a/benchmark/jsonschema.cc +++ b/benchmark/jsonschema.cc @@ -88,19 +88,22 @@ static void Schema_Frame_KrakenD_Reachable(benchmark::State &state) { frame.analyse(schema, sourcemeta::core::schema_walker, sourcemeta::core::schema_resolver); - const auto &base{frame.traverse(frame.root())->get()}; - for (auto _ : state) { for (const auto &entry : frame.locations()) { if (entry.second.type == - sourcemeta::core::SchemaFrame::LocationType::Pointer) { - continue; + sourcemeta::core::SchemaFrame::LocationType::Resource) { + for (const auto &subentry : frame.locations()) { + if (subentry.second.type == + sourcemeta::core::SchemaFrame::LocationType::Pointer) { + continue; + } + + auto result{frame.is_reachable(entry.second, subentry.second, + sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver)}; + benchmark::DoNotOptimize(result); + } } - - auto result{frame.is_reachable(base, entry.second, - sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver)}; - benchmark::DoNotOptimize(result); } } } diff --git a/src/core/jsonschema/frame.cc b/src/core/jsonschema/frame.cc index 6ba5493ea..43f527e3a 100644 --- a/src/core/jsonschema/frame.cc +++ b/src/core/jsonschema/frame.cc @@ -1457,7 +1457,14 @@ auto SchemaFrame::populate_reachability(const Location &base, } for (const auto &pointer_reference : has_non_pointer_location) { - const bool is_reachable = has_non_orphan.contains(pointer_reference); + const auto &pointer{pointer_reference.get()}; + bool is_reachable{false}; + if (pointer == base.pointer) { + is_reachable = true; + } else if (pointer.starts_with(base.pointer)) { + is_reachable = has_non_orphan.contains(pointer_reference); + } + cache.emplace(pointer_reference, is_reachable); if (!is_reachable) { unreachable_pointers.push_back(pointer_reference); @@ -1474,12 +1481,20 @@ auto SchemaFrame::populate_reachability(const Location &base, continue; } - const auto any_non_orphan{ - std::ranges::any_of(locations, [](const Location *location) { - return location->type != LocationType::Pointer && !location->orphan; - })}; - cache.emplace(pointer_reference, any_non_orphan); - if (!any_non_orphan) { + const auto &pointer{pointer_reference.get()}; + bool is_reachable{false}; + if (pointer == base.pointer) { + is_reachable = true; + } else if (pointer.starts_with(base.pointer)) { + is_reachable = + std::ranges::any_of(locations, [](const Location *location) { + return location->type != LocationType::Pointer && + !location->orphan; + }); + } + + cache.emplace(pointer_reference, is_reachable); + if (!is_reachable) { unreachable_pointers.push_back(pointer_reference); } } @@ -1567,7 +1582,8 @@ auto SchemaFrame::populate_reachability(const Location &base, PotentialReach entry{.pointer = pointer_reference, .potential_sources = {}}; WeakPointer ancestor = pointer; - while (!ancestor.empty()) { + bool first_iteration{true}; + while (first_iteration || !ancestor.empty()) { auto destination_iterator = references_by_destination.find(std::cref(ancestor)); if (destination_iterator != references_by_destination.end()) { @@ -1619,7 +1635,12 @@ auto SchemaFrame::populate_reachability(const Location &base, .source_pointer = source_pointer, .crosses = crosses}); } } + + if (ancestor.empty()) { + break; + } ancestor = ancestor.initial(); + first_iteration = false; } if (!entry.potential_sources.empty()) { @@ -1651,13 +1672,10 @@ auto SchemaFrame::populate_reachability(const Location &base, } const auto &source_parent{potential_source.source_pointer->initial()}; - bool source_parent_reachable{source_parent.empty()}; - if (!source_parent_reachable) { - const auto reachability_iterator{ - cache.find(std::cref(source_parent))}; - source_parent_reachable = reachability_iterator != cache.end() && - reachability_iterator->second; - } + const auto reachability_iterator{cache.find(std::cref(source_parent))}; + const bool source_parent_reachable{reachability_iterator != + cache.end() && + reachability_iterator->second}; if (source_parent_reachable) { became_reachable = true; @@ -1666,7 +1684,25 @@ auto SchemaFrame::populate_reachability(const Location &base, } if (became_reachable) { + const auto &reached_pointer{read_iterator->pointer.get()}; cache[read_iterator->pointer] = true; + for (auto &[cache_pointer, cache_reachable] : cache) { + if (!cache_reachable && + cache_pointer.get().starts_with(reached_pointer)) { + const auto locations_it = + this->pointer_to_location_.find(cache_pointer); + if (locations_it != this->pointer_to_location_.end()) { + const bool has_non_orphan{std::ranges::any_of( + locations_it->second, [](const Location *location) { + return location->type != LocationType::Pointer && + !location->orphan; + })}; + if (has_non_orphan) { + cache_reachable = true; + } + } + } + } changed = true; } else { if (write_iterator != read_iterator) { diff --git a/test/jsonschema/CMakeLists.txt b/test/jsonschema/CMakeLists.txt index be834ac85..5f76abf2b 100644 --- a/test/jsonschema/CMakeLists.txt +++ b/test/jsonschema/CMakeLists.txt @@ -96,6 +96,10 @@ target_link_libraries(sourcemeta_core_jsonschema_unit target_link_libraries(sourcemeta_core_jsonschema_unit PRIVATE sourcemeta::core::uri) +if(MSVC) + target_compile_options(sourcemeta_core_jsonschema_unit PRIVATE /bigobj) +endif() + # JSON Schema Referencing Suite # See https://github.com/python-jsonschema/referencing-suite sourcemeta_googletest(NAMESPACE sourcemeta PROJECT core NAME jsonschema_referencing_suite diff --git a/test/jsonschema/jsonschema_frame_2019_09_test.cc b/test/jsonschema/jsonschema_frame_2019_09_test.cc index b2e0a6a4c..a588f276a 100644 --- a/test/jsonschema/jsonschema_frame_2019_09_test.cc +++ b/test/jsonschema/jsonschema_frame_2019_09_test.cc @@ -112,6 +112,12 @@ TEST(JSONSchema_frame_2019_09, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", + "https://example.com"); } TEST(JSONSchema_frame_2019_09, empty_schema) { @@ -272,6 +278,26 @@ TEST(JSONSchema_frame_2019_09, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_2019_09, one_level_applicators_with_identifiers) { @@ -382,6 +408,29 @@ TEST(JSONSchema_frame_2019_09, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/test/qux#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#/properties/foo", + "https://www.sourcemeta.com/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#test", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#/properties/foo", + "https://www.sourcemeta.com/test/qux#/properties/foo"); } TEST(JSONSchema_frame_2019_09, subschema_absolute_identifier) { @@ -457,6 +506,16 @@ TEST(JSONSchema_frame_2019_09, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_2019_09, nested_schemas) { @@ -682,6 +741,52 @@ TEST(JSONSchema_frame_2019_09, nested_schemas) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/baz#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo#test", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz", + "https://www.sourcemeta.com/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz#extra", + "https://www.sourcemeta.com/baz"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/qux", + "https://www.sourcemeta.com/qux"); } TEST(JSONSchema_frame_2019_09, id_override) { @@ -1346,6 +1451,10 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_no_recursive_anchor_anonymous) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", "#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", + "#/additionalItems"); } TEST(JSONSchema_frame_2019_09, recursive_ref_no_recursive_anchor) { @@ -1408,6 +1517,13 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_no_recursive_anchor) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/additionalItems", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/additionalItems", + "https://www.sourcemeta.com/schema#/additionalItems"); } TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_false_anonymous) { @@ -1463,6 +1579,10 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_false_anonymous) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", "#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", + "#/additionalItems"); } TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_false) { @@ -1531,6 +1651,13 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_false) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/additionalItems", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/additionalItems", + "https://www.sourcemeta.com/schema#/additionalItems"); } TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_true_anonymous) { @@ -1593,6 +1720,11 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_true_anonymous) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", "#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "", "#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", + "#/additionalItems"); } TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_true) { @@ -1670,6 +1802,16 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_recursive_anchor_true) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Dynamic, "https://www.sourcemeta.com/schema", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Dynamic, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/additionalItems", + "https://www.sourcemeta.com/schema#/additionalItems"); } TEST(JSONSchema_frame_2019_09, @@ -1755,6 +1897,10 @@ TEST(JSONSchema_frame_2019_09, EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalItems", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_2019_09, @@ -1849,6 +1995,12 @@ TEST(JSONSchema_frame_2019_09, frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "https://example.com", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_2019_09, recursive_ref_nested_recursive_anchor_true) { @@ -1928,6 +2080,16 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_nested_recursive_anchor_true) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Dynamic, "https://www.sourcemeta.com/schema", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Dynamic, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/additionalItems"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/additionalItems", + "https://www.sourcemeta.com/schema#/additionalItems"); } TEST(JSONSchema_frame_2019_09, recursive_ref_multiple_recursive_anchor_true) { @@ -2045,6 +2207,16 @@ TEST(JSONSchema_frame_2019_09, recursive_ref_multiple_recursive_anchor_true) { frame, Dynamic, "https://www.sourcemeta.com/schema", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Dynamic, "https://www.sourcemeta.com/nested", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/nested"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/nested", + "https://www.sourcemeta.com/nested"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, + "https://www.sourcemeta.com/nested", + "https://www.sourcemeta.com/nested"); } TEST(JSONSchema_frame_2019_09, recursive_anchor_conflict) { @@ -2170,6 +2342,10 @@ TEST(JSONSchema_frame_2019_09, recursive_anchor_on_relative_id) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "middle", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "middle"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "middle", "middle"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "middle", "middle"); } TEST(JSONSchema_frame_2019_09, ref_with_id) { @@ -2241,6 +2417,13 @@ TEST(JSONSchema_frame_2019_09, ref_with_id) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/string", + "https://www.sourcemeta.com/schema#/$defs/string"); } TEST(JSONSchema_frame_2019_09, ref_from_definitions) { @@ -2333,6 +2516,26 @@ TEST(JSONSchema_frame_2019_09, ref_from_definitions) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/definitions/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/definitions/middle"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/middle", + "https://www.sourcemeta.com/schema#/definitions/middle"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/string", + "https://www.sourcemeta.com/schema#/definitions/middle"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/definitions/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/middle", + "https://www.sourcemeta.com/schema#/definitions/string"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/string", + "https://www.sourcemeta.com/schema#/definitions/string"); } TEST(JSONSchema_frame_2019_09, relative_base_uri_without_ref) { diff --git a/test/jsonschema/jsonschema_frame_2020_12_test.cc b/test/jsonschema/jsonschema_frame_2020_12_test.cc index 972332af5..2e74cfe76 100644 --- a/test/jsonschema/jsonschema_frame_2020_12_test.cc +++ b/test/jsonschema/jsonschema_frame_2020_12_test.cc @@ -112,6 +112,12 @@ TEST(JSONSchema_frame_2020_12, anonymous_with_nested_schema_resource) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", + "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_2020_12, empty_schema) { @@ -272,6 +278,26 @@ TEST(JSONSchema_frame_2020_12, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_2020_12, one_level_applicators_with_identifiers) { @@ -381,6 +407,38 @@ TEST(JSONSchema_frame_2020_12, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/test/qux#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#test", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux#/items", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#/properties/foo", + "https://www.sourcemeta.com/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#test", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#/items", + "https://www.sourcemeta.com/test/qux#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test/qux#/properties/foo", + "https://www.sourcemeta.com/test/qux#/properties/foo"); } TEST(JSONSchema_frame_2020_12, subschema_absolute_identifier) { @@ -448,6 +506,16 @@ TEST(JSONSchema_frame_2020_12, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_2020_12, nested_schemas) { @@ -673,6 +741,88 @@ TEST(JSONSchema_frame_2020_12, nested_schemas) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/baz#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo#test", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz#extra", + "https://www.sourcemeta.com/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo#test", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/qux", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz", + "https://www.sourcemeta.com/qux"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz#extra", + "https://www.sourcemeta.com/qux"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/qux", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz#extra", + "https://www.sourcemeta.com/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/qux", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz", + "https://www.sourcemeta.com/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/baz#extra", + "https://www.sourcemeta.com/baz"); } TEST(JSONSchema_frame_2020_12, id_override) { @@ -986,6 +1136,50 @@ TEST(JSONSchema_frame_2020_12, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#foo", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.test.com", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test#bar", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://www.test.com", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/items", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com#baz", + "https://www.test.com"); } TEST(JSONSchema_frame_2020_12, dynamic_refs_with_id) { @@ -1238,6 +1432,161 @@ TEST(JSONSchema_frame_2020_12, dynamic_refs_with_id) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/unknown", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/anchor", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/dynamic", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/extra", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/unknown", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#baz", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/dynamic", + "https://www.sourcemeta.com/schema#/properties/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#baz", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/schema#/properties/baz"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/qux", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/anchor"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/anchor"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/anchor", + "https://www.sourcemeta.com/schema#/properties/anchor"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/anchor"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#baz", + "https://www.sourcemeta.com/schema#/properties/anchor"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/schema#/properties/anchor"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/dynamic"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/dynamic"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/dynamic"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/dynamic", + "https://www.sourcemeta.com/schema#/properties/dynamic"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#dynamic", + "https://www.sourcemeta.com/schema#/properties/dynamic"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/extra"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/extra"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/extra"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/extra", + "https://www.sourcemeta.com/schema#/properties/extra"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/dynamic", + "https://www.sourcemeta.com/schema#/properties/extra"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#dynamic", + "https://www.sourcemeta.com/schema#/properties/extra"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/unknown"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/unknown"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/unknown"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/unknown", + "https://www.sourcemeta.com/schema#/properties/unknown"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/schema#/properties/unknown"); } TEST(JSONSchema_frame_2020_12, dynamic_refs_with_no_id) { @@ -1448,6 +1797,86 @@ TEST(JSONSchema_frame_2020_12, dynamic_refs_with_no_id) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/unknown", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/bar", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/baz", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/dynamic", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/bar", + "#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/baz", + "#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#baz", "#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://www.example.com", + "#/properties/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/baz", + "#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#baz", "#/properties/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://www.example.com", + "#/properties/baz"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "https://www.example.com"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "https://www.example.com"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/baz", + "https://www.example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com", + "https://www.example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/qux", + "https://www.example.com"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/anchor"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/anchor", + "#/properties/anchor"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/baz", + "#/properties/anchor"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#baz", "#/properties/anchor"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/anchor"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "#/properties/dynamic"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/dynamic", + "#/properties/dynamic"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#dynamic", + "#/properties/dynamic"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/dynamic"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/extra"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/extra", + "#/properties/extra"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/dynamic", + "#/properties/extra"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#dynamic", + "#/properties/extra"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/extra"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "#/properties/unknown"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/unknown", + "#/properties/unknown"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/unknown"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://www.example.com", + "#/properties/unknown"); } TEST(JSONSchema_frame_2020_12, ref_to_dynamic_anchor) { @@ -1545,6 +1974,32 @@ TEST(JSONSchema_frame_2020_12, ref_to_dynamic_anchor) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#foo", + "https://www.sourcemeta.com/schema#/properties/bar"); } TEST(JSONSchema_frame_2020_12, different_dynamic_and_refs_in_same_object) { @@ -1643,6 +2098,26 @@ TEST(JSONSchema_frame_2020_12, different_dynamic_and_refs_in_same_object) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); } TEST(JSONSchema_frame_2020_12, same_dynamic_and_refs_in_same_object) { @@ -1742,6 +2217,26 @@ TEST(JSONSchema_frame_2020_12, same_dynamic_and_refs_in_same_object) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); } TEST(JSONSchema_frame_2020_12, dynamic_anchor_with_id) { @@ -1904,6 +2399,41 @@ TEST(JSONSchema_frame_2020_12, dynamic_anchor_with_id) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#test", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Dynamic, "https://www.sourcemeta.com/schema#test", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/bar#test", + "https://www.sourcemeta.com/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, + "https://www.sourcemeta.com/bar#test", + "https://www.sourcemeta.com/bar"); } TEST(JSONSchema_frame_2020_12, dynamic_anchor_without_id) { @@ -1973,6 +2503,12 @@ TEST(JSONSchema_frame_2020_12, dynamic_anchor_without_id) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#test", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#test", "#/properties/foo"); } TEST(JSONSchema_frame_2020_12, @@ -2047,6 +2583,12 @@ TEST(JSONSchema_frame_2020_12, EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#test", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/test", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/test", + "#/$defs/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#test", "#/$defs/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#test", "#/$defs/test"); } TEST(JSONSchema_frame_2020_12, dynamic_ref_to_single_dynamic_anchor_external) { @@ -2136,6 +2678,19 @@ TEST(JSONSchema_frame_2020_12, dynamic_ref_to_single_dynamic_anchor_external) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/test", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/test", + "#/$defs/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#test", "#/$defs/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#test", "#/$defs/test"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/foo", + "#/$defs/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/foo", "#/$defs/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/test", + "#/$defs/foo"); } TEST(JSONSchema_frame_2020_12, dynamic_anchor_same_on_schema_resource) { @@ -2208,6 +2763,10 @@ TEST(JSONSchema_frame_2020_12, no_id_recursive_empty_pointer) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); } TEST(JSONSchema_frame_2020_12, ref_metaschema) { @@ -2348,6 +2907,13 @@ TEST(JSONSchema_frame_2020_12, ref_with_id) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/string", + "https://www.sourcemeta.com/schema#/$defs/string"); } TEST(JSONSchema_frame_2020_12, ref_from_definitions) { @@ -2440,6 +3006,26 @@ TEST(JSONSchema_frame_2020_12, ref_from_definitions) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/definitions/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/definitions/middle"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/middle", + "https://www.sourcemeta.com/schema#/definitions/middle"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/string", + "https://www.sourcemeta.com/schema#/definitions/middle"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/definitions/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/middle", + "https://www.sourcemeta.com/schema#/definitions/string"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/definitions/string", + "https://www.sourcemeta.com/schema#/definitions/string"); } TEST(JSONSchema_frame_2020_12, relative_base_uri_without_ref) { @@ -2552,6 +3138,20 @@ TEST(JSONSchema_frame_2020_12, relative_base_uri_with_ref) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/$defs/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "common", + "common#/allOf/0"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/allOf/0", + "common#/allOf/0"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/$defs/foo", + "common#/allOf/0"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "common", + "common#/$defs/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "common#/allOf/0", + "common#/$defs/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/$defs/foo", + "common#/$defs/foo"); } TEST(JSONSchema_frame_2020_12, relative_base_with_relative_path_ref) { @@ -2669,6 +3269,13 @@ TEST(JSONSchema_frame_2020_12, idempotent_with_refs) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/string", + "https://www.sourcemeta.com/schema#/$defs/string"); } TEST(JSONSchema_frame_2020_12, allof_refs) { @@ -2743,6 +3350,14 @@ TEST(JSONSchema_frame_2020_12, allof_refs) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/allOf/0", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/allOf/1", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/allOf/0"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/allOf/0", "#/allOf/0"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/allOf/1", "#/allOf/0"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/allOf/1"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/allOf/0", "#/allOf/1"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/allOf/1", "#/allOf/1"); } TEST(JSONSchema_frame_2020_12, properties_with_refs) { @@ -2859,6 +3474,70 @@ TEST(JSONSchema_frame_2020_12, properties_with_refs) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/baz/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz/items", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz/items", + "https://www.sourcemeta.com/schema#/properties/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/baz"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz/items", + "https://www.sourcemeta.com/schema#/properties/baz"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/baz/items"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/baz/items"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/baz/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz", + "https://www.sourcemeta.com/schema#/properties/baz/items"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/baz/items", + "https://www.sourcemeta.com/schema#/properties/baz/items"); } TEST(JSONSchema_frame_2020_12, property_ref_defs) { @@ -2986,20 +3665,131 @@ TEST(JSONSchema_frame_2020_12, property_ref_defs) { frame, Static, "https://www.sourcemeta.com/schema", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", - frame.root()); - EXPECT_FRAME_LOCATION_REACHABLE( + frame.root()); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + frame.root()); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper", + frame.root()); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper/items", + frame.root()); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/$defs/" + "helper/items/additionalProperties", + frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper/items", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper/items", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/properties/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper", + "https://www.sourcemeta.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper/items", + "https://www.sourcemeta.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/$defs/helper"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/helper/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/$defs/helper/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", - frame.root()); - EXPECT_FRAME_LOCATION_REACHABLE( + "https://www.sourcemeta.com/schema#/$defs/helper/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper", - frame.root()); + "https://www.sourcemeta.com/schema#/$defs/helper/items"); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper/items", - frame.root()); - EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, - "https://www.sourcemeta.com/schema#/$defs/" - "helper/items/additionalProperties", - frame.root()); + "https://www.sourcemeta.com/schema#/$defs/helper/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/$defs/helper/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper", + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/helper/items", + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/$defs/helper/items/" + "additionalProperties"); } TEST(JSONSchema_frame_2020_12, property_cross_ref) { @@ -3118,6 +3908,83 @@ TEST(JSONSchema_frame_2020_12, property_cross_ref) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar/items", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar/items", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/properties/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar/items"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar/items", + "https://www.sourcemeta.com/schema#/properties/bar/items"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/properties/bar/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar/items", + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties", + "https://www.sourcemeta.com/schema#/properties/bar/items/" + "additionalProperties"); } TEST(JSONSchema_frame_2020_12, dynamic_ref_multiple_targets) { @@ -3252,6 +4119,25 @@ TEST(JSONSchema_frame_2020_12, dynamic_ref_multiple_targets) { "https://www.example.com#test", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Dynamic, "https://www.example.com/foo#test", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.example.com", + "https://www.example.com#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.example.com#/properties/foo", + "https://www.example.com#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.example.com#/properties/bar", + "https://www.example.com#/properties/foo"); + + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com", + "https://www.example.com#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.example.com#/properties/foo", + "https://www.example.com#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.example.com#/properties/bar", + "https://www.example.com#/properties/bar"); } TEST(JSONSchema_frame_2020_12, cross_id_anonymous_nested) { @@ -3357,6 +4243,19 @@ TEST(JSONSchema_frame_2020_12, cross_id_anonymous_nested) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/schema"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/schema", + "#/$defs/schema"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/schema/items", + "#/$defs/schema"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "#/$defs/schema/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/schema", + "#/$defs/schema/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/schema/items", + "#/$defs/schema/items"); } TEST(JSONSchema_frame_2020_12, relative_id_with_absolute_default_id) { @@ -3627,6 +4526,11 @@ TEST(JSONSchema_frame_2020_12, single_nested_anonymous_with_nested_resource) { frame, Static, "https://www.sourcemeta.com/schema", "#/wrapper"); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#test", "#/wrapper"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/wrapper", + "#/wrapper/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/wrapper/items", + "#/wrapper/items"); } TEST(JSONSchema_frame_2020_12, multiple_nested_cross_ref) { @@ -3760,6 +4664,20 @@ TEST(JSONSchema_frame_2020_12, multiple_nested_cross_ref) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#foo", "#/wrapper"); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#bar", "#/wrapper"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/wrapper", + "#/common/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/test", + "#/common/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/with-id", + "#/common/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/wrapper", + "#/common/with-id"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/common/test", + "#/common/with-id"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/with-id", + "#/common/with-id"); } TEST(JSONSchema_frame_2020_12, multiple_nested_cross_ref_missing_target) { @@ -3822,6 +4740,11 @@ TEST(JSONSchema_frame_2020_12, multiple_nested_cross_ref_missing_target) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/wrapper", "#/wrapper"); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/test", "#/wrapper"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/wrapper", + "#/common/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/test", + "#/common/test"); } TEST(JSONSchema_frame_2020_12, multiple_nested_no_base_dialect) { @@ -3969,6 +4892,11 @@ TEST(JSONSchema_frame_2020_12, multiple_nested_with_default_id) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/wrapper", "#/wrapper"); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/test", "#/wrapper"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/wrapper", + "#/common/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/common/test", + "#/common/test"); } TEST(JSONSchema_frame_2020_12, anchor_with_invalid_type) { @@ -4247,6 +5175,26 @@ TEST(JSONSchema_frame_2020_12, ref_to_ref_chain) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/$defs/child", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/parent"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/parent", + "https://www.sourcemeta.com/schema#/$defs/parent"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/child", + "https://www.sourcemeta.com/schema#/$defs/parent"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/child"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/parent", + "https://www.sourcemeta.com/schema#/$defs/child"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/$defs/child", + "https://www.sourcemeta.com/schema#/$defs/child"); } TEST(JSONSchema_frame_2020_12, nested_defs_unreferenced) { @@ -4332,6 +5280,28 @@ TEST(JSONSchema_frame_2020_12, nested_defs_unreferenced) { frame, Static, "https://www.sourcemeta.com/schema#/properties/foo/$defs/unused", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/properties/foo/$defs/unused", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo/$defs/unused"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo/$defs/unused"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://www.sourcemeta.com/schema#/properties/foo/$defs/unused", + "https://www.sourcemeta.com/schema#/properties/foo/$defs/unused"); } TEST(JSONSchema_frame_2020_12, circular_ref_through_defs) { @@ -4422,6 +5392,26 @@ TEST(JSONSchema_frame_2020_12, circular_ref_through_defs) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/schema#/$defs/b", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/$defs/a", + "https://www.sourcemeta.com/schema#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/$defs/b", + "https://www.sourcemeta.com/schema#/$defs/a"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/$defs/a", + "https://www.sourcemeta.com/schema#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/$defs/b", + "https://www.sourcemeta.com/schema#/$defs/b"); } TEST(JSONSchema_frame_2020_12, nested_invalid_schema_keyword) { @@ -4696,6 +5686,37 @@ TEST(JSONSchema_frame_2020_12, ref_to_orphan_chain) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/a", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/a", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/a"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", "#/$defs/a"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/b"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/b"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", "#/$defs/b"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/c"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/c"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/c"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/c"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", "#/$defs/c"); } TEST(JSONSchema_frame_2020_12, orphan_chain_unreferenced) { @@ -4775,6 +5796,21 @@ TEST(JSONSchema_frame_2020_12, orphan_chain_unreferenced) { EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/a", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/b", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/c", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", "#/$defs/a"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/b"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", "#/$defs/b"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/c"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/c"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/c"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/c", "#/$defs/c"); } TEST(JSONSchema_frame_2020_12, circular_orphan_refs) { @@ -4844,6 +5880,14 @@ TEST(JSONSchema_frame_2020_12, circular_orphan_refs) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/a", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/b", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/a"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/a"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/a", "#/$defs/b"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/b", "#/$defs/b"); } TEST(JSONSchema_frame_2020_12, ref_from_deep_nesting) { @@ -4951,6 +5995,26 @@ TEST(JSONSchema_frame_2020_12, ref_from_deep_nesting) { frame, Static, "#/properties/x/properties/y/properties/z", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "", "#/properties/x/properties/y/properties/z"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/properties/x", + "#/properties/x/properties/y/properties/z"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/properties/x/properties/y", + "#/properties/x/properties/y/properties/z"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "#/properties/x/properties/y/properties/z", + "#/properties/x/properties/y/properties/z"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/properties/x/properties/y/properties/z"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/x", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); } TEST(JSONSchema_frame_2020_12, orphan_refs_reachable_target) { @@ -5039,6 +6103,30 @@ TEST(JSONSchema_frame_2020_12, orphan_refs_reachable_target) { frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/orphan", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/orphan", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/orphan", + "#/$defs/string"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/orphan"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/orphan"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/orphan"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/orphan", + "#/$defs/orphan"); } TEST(JSONSchema_frame_2020_12, root_dynamic_anchor) { @@ -5182,6 +6270,18 @@ TEST(JSONSchema_frame_2020_12, dynamic_ref_to_static_anchor) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#target", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); } TEST(JSONSchema_frame_2020_12, dynamic_ref_to_pointer) { @@ -5258,6 +6358,18 @@ TEST(JSONSchema_frame_2020_12, dynamic_ref_to_pointer) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); } TEST(JSONSchema_frame_2020_12, dynamic_ref_to_dynamic_anchor) { @@ -5350,6 +6462,23 @@ TEST(JSONSchema_frame_2020_12, dynamic_ref_to_dynamic_anchor) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#target", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#target", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#target", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#target", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#target", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); } TEST(JSONSchema_frame_2020_12, static_ref_to_dynamic_anchor) { @@ -5475,6 +6604,61 @@ TEST(JSONSchema_frame_2020_12, static_ref_to_dynamic_anchor) { EXPECT_FRAME_LOCATION_NON_REACHABLE( frame, Static, "#/$defs/string/additionalProperties/$defs/nested", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#target", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#target", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties", "#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties/$defs/nested", + "#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#target", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#target", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties", "#/$defs/string"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties/$defs/nested", + "#/$defs/string"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "#/$defs/string/additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/properties/foo", + "#/$defs/string/additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string/additionalProperties"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "#/$defs/string/additionalProperties", + "#/$defs/string/additionalProperties"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties/$defs/nested", + "#/$defs/string/additionalProperties"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "", "#/$defs/string/additionalProperties/$defs/nested"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/properties/foo", + "#/$defs/string/additionalProperties/$defs/nested"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/$defs/string", + "#/$defs/string/additionalProperties/$defs/nested"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties", + "#/$defs/string/additionalProperties/$defs/nested"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "#/$defs/string/additionalProperties/$defs/nested", + "#/$defs/string/additionalProperties/$defs/nested"); } TEST(JSONSchema_frame_2020_12, unreferenced_dynamic_anchor) { @@ -5548,6 +6732,12 @@ TEST(JSONSchema_frame_2020_12, unreferenced_dynamic_anchor) { EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Dynamic, "#unused", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/string", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#unused", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, "#unused", "#/$defs/string"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/$defs/string", + "#/$defs/string"); } TEST(JSONSchema_frame_2020_12, property_named_defs) { @@ -5645,10 +6835,59 @@ TEST(JSONSchema_frame_2020_12, property_named_defs) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://example.com/schema#/$defs/helper", frame.root()); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/$defs", + frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://example.com/schema#/$defs/helper/properties/definitions", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com/schema", + "https://example.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com/schema#/$defs/helper", + "https://example.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/$defs", + "https://example.com/schema#/$defs/helper"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/definitions", + "https://example.com/schema#/$defs/helper"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com/schema", + "https://example.com/schema#/$defs/helper/properties/$defs"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com/schema#/$defs/helper", + "https://example.com/schema#/$defs/helper/properties/$defs"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/$defs", + "https://example.com/schema#/$defs/helper/properties/$defs"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/definitions", + "https://example.com/schema#/$defs/helper/properties/$defs"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com/schema", + "https://example.com/schema#/$defs/helper/properties/definitions"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com/schema#/$defs/helper", + "https://example.com/schema#/$defs/helper/properties/definitions"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/$defs", + "https://example.com/schema#/$defs/helper/properties/definitions"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, + "https://example.com/schema#/$defs/helper/properties/definitions", + "https://example.com/schema#/$defs/helper/properties/definitions"); } TEST(JSONSchema_frame_2020_12, nested_schema_with_dynamic_anchor_and_refs) { @@ -5849,6 +7088,68 @@ TEST(JSONSchema_frame_2020_12, nested_schema_with_dynamic_anchor_and_refs) { frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/$defs/schema/$defs/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "__sourcemeta-core-wrap__"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "__sourcemeta-core-wrap__", + "__sourcemeta-core-wrap__"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#meta", + "__sourcemeta-core-wrap__"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, + "__sourcemeta-core-wrap__#meta", + "__sourcemeta-core-wrap__"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/foo", + "__sourcemeta-core-wrap__"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/bar", + "__sourcemeta-core-wrap__"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/baz", + "__sourcemeta-core-wrap__"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "__sourcemeta-core-wrap__#/$defs/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "__sourcemeta-core-wrap__", + "__sourcemeta-core-wrap__#/$defs/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/foo", + "__sourcemeta-core-wrap__#/$defs/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/bar", + "__sourcemeta-core-wrap__#/$defs/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/baz", + "__sourcemeta-core-wrap__#/$defs/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "__sourcemeta-core-wrap__#/$defs/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "__sourcemeta-core-wrap__", + "__sourcemeta-core-wrap__#/$defs/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/foo", + "__sourcemeta-core-wrap__#/$defs/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/bar", + "__sourcemeta-core-wrap__#/$defs/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/baz", + "__sourcemeta-core-wrap__#/$defs/bar"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", + "__sourcemeta-core-wrap__#/$defs/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "__sourcemeta-core-wrap__", + "__sourcemeta-core-wrap__#/$defs/baz"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/foo", + "__sourcemeta-core-wrap__#/$defs/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/bar", + "__sourcemeta-core-wrap__#/$defs/baz"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "__sourcemeta-core-wrap__#/$defs/baz", + "__sourcemeta-core-wrap__#/$defs/baz"); } TEST(JSONSchema_frame_2020_12, @@ -5953,6 +7254,18 @@ TEST(JSONSchema_frame_2020_12, frame, Static, "https://example.com/unreferenced#meta", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Dynamic, "https://example.com/unreferenced#meta", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://example.com/root", + "https://example.com/unreferenced"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com/unreferenced", + "https://example.com/unreferenced"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com/unreferenced#meta", + "https://example.com/unreferenced"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Dynamic, + "https://example.com/unreferenced#meta", + "https://example.com/unreferenced"); } TEST(JSONSchema_frame_2020_12, @@ -6051,4 +7364,13 @@ TEST(JSONSchema_frame_2020_12, frame, Static, "https://example.com/unreferenced", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE( frame, Static, "https://example.com/unreferenced#meta", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://example.com/root", + "https://example.com/unreferenced"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com/unreferenced", + "https://example.com/unreferenced"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com/unreferenced#meta", + "https://example.com/unreferenced"); } diff --git a/test/jsonschema/jsonschema_frame_draft0_test.cc b/test/jsonschema/jsonschema_frame_draft0_test.cc index ffc6f2172..96d164fcd 100644 --- a/test/jsonschema/jsonschema_frame_draft0_test.cc +++ b/test/jsonschema/jsonschema_frame_draft0_test.cc @@ -91,6 +91,10 @@ TEST(JSONSchema_frame_draft0, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_draft0, empty_schema) { @@ -251,6 +255,20 @@ TEST(JSONSchema_frame_draft0, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft0, one_level_applicators_with_identifiers) { @@ -324,6 +342,13 @@ TEST(JSONSchema_frame_draft0, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft0, subschema_absolute_identifier) { @@ -399,6 +424,13 @@ TEST(JSONSchema_frame_draft0, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft0, id_override) { @@ -574,6 +606,25 @@ TEST(JSONSchema_frame_draft0, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.example.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com/test", + "https://www.example.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); } TEST(JSONSchema_frame_draft0, ref_metaschema) { diff --git a/test/jsonschema/jsonschema_frame_draft1_test.cc b/test/jsonschema/jsonschema_frame_draft1_test.cc index bd66c8d77..3f092f730 100644 --- a/test/jsonschema/jsonschema_frame_draft1_test.cc +++ b/test/jsonschema/jsonschema_frame_draft1_test.cc @@ -91,6 +91,10 @@ TEST(JSONSchema_frame_draft1, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_draft1, empty_schema) { @@ -251,6 +255,20 @@ TEST(JSONSchema_frame_draft1, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft1, one_level_applicators_with_identifiers) { @@ -324,6 +342,13 @@ TEST(JSONSchema_frame_draft1, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft1, subschema_absolute_identifier) { @@ -399,6 +424,13 @@ TEST(JSONSchema_frame_draft1, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft1, id_override) { @@ -574,6 +606,25 @@ TEST(JSONSchema_frame_draft1, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.example.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com/test", + "https://www.example.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); } TEST(JSONSchema_frame_draft1, ref_metaschema) { diff --git a/test/jsonschema/jsonschema_frame_draft2_test.cc b/test/jsonschema/jsonschema_frame_draft2_test.cc index dc9addca2..006d49dcb 100644 --- a/test/jsonschema/jsonschema_frame_draft2_test.cc +++ b/test/jsonschema/jsonschema_frame_draft2_test.cc @@ -91,6 +91,10 @@ TEST(JSONSchema_frame_draft2, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_draft2, empty_schema) { @@ -251,6 +255,20 @@ TEST(JSONSchema_frame_draft2, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft2, one_level_applicators_with_identifiers) { @@ -324,6 +342,13 @@ TEST(JSONSchema_frame_draft2, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft2, subschema_absolute_identifier) { @@ -399,6 +424,13 @@ TEST(JSONSchema_frame_draft2, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft2, id_override) { @@ -574,6 +606,25 @@ TEST(JSONSchema_frame_draft2, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.example.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com/test", + "https://www.example.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); } TEST(JSONSchema_frame_draft2, ref_metaschema) { diff --git a/test/jsonschema/jsonschema_frame_draft3_test.cc b/test/jsonschema/jsonschema_frame_draft3_test.cc index 1d8a46b88..160ddef97 100644 --- a/test/jsonschema/jsonschema_frame_draft3_test.cc +++ b/test/jsonschema/jsonschema_frame_draft3_test.cc @@ -91,6 +91,10 @@ TEST(JSONSchema_frame_draft3, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); } TEST(JSONSchema_frame_draft3, empty_schema) { @@ -251,6 +255,20 @@ TEST(JSONSchema_frame_draft3, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft3, one_level_applicators_with_identifiers) { @@ -324,6 +342,13 @@ TEST(JSONSchema_frame_draft3, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft3, subschema_absolute_identifier) { @@ -399,6 +424,13 @@ TEST(JSONSchema_frame_draft3, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft3, id_override) { @@ -574,6 +606,25 @@ TEST(JSONSchema_frame_draft3, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.example.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com/test", + "https://www.example.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); } TEST(JSONSchema_frame_draft3, ref_metaschema) { @@ -764,4 +815,11 @@ TEST(JSONSchema_frame_draft3, nested_relative_ref_with_id) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://example.com#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com", + "https://example.com#/additionalProperties"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com#/additionalProperties", + "https://example.com#/additionalProperties"); } diff --git a/test/jsonschema/jsonschema_frame_draft4_test.cc b/test/jsonschema/jsonschema_frame_draft4_test.cc index f73917b13..c728af810 100644 --- a/test/jsonschema/jsonschema_frame_draft4_test.cc +++ b/test/jsonschema/jsonschema_frame_draft4_test.cc @@ -101,6 +101,12 @@ TEST(JSONSchema_frame_draft4, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", + "https://example.com"); } TEST(JSONSchema_frame_draft4, empty_schema) { @@ -261,6 +267,20 @@ TEST(JSONSchema_frame_draft4, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft4, one_level_applicators_with_identifiers) { @@ -334,6 +354,13 @@ TEST(JSONSchema_frame_draft4, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft4, subschema_absolute_identifier) { @@ -409,6 +436,16 @@ TEST(JSONSchema_frame_draft4, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft4, id_override) { @@ -584,6 +621,25 @@ TEST(JSONSchema_frame_draft4, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.example.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.example.com/test", + "https://www.example.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); } TEST(JSONSchema_frame_draft4, ref_metaschema) { @@ -704,6 +760,19 @@ TEST(JSONSchema_frame_draft4, location_independent_identifier_anonymous) { EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/definitions/bar", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/foo", + "#/definitions/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/definitions/bar", + "#/definitions/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/bar", + "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/foo", + "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#foo", "#/definitions/bar"); } TEST(JSONSchema_frame_draft4, ref_with_id) { @@ -844,6 +913,26 @@ TEST(JSONSchema_frame_draft4, EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/bar"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/bar", + "https://www.sourcemeta.com/schema#/properties/bar"); } TEST(JSONSchema_frame_draft4, relative_base_uri_without_ref) { @@ -955,6 +1044,24 @@ TEST(JSONSchema_frame_draft4, relative_base_uri_with_ref) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/definitions/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "common", + "common#/allOf/0"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/allOf/0", + "common#/allOf/0"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#foo", + "common#/allOf/0"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/definitions/foo", + "common#/allOf/0"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "common", + "common#/definitions/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "common#/allOf/0", + "common#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#/definitions/foo", + "common#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "common#foo", + "common#/definitions/foo"); } TEST(JSONSchema_frame_draft4, ref_with_invalid_type) { @@ -1061,6 +1168,10 @@ TEST(JSONSchema_frame_draft4, ref_invalidates_sibling_subschemas_and_refs) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); } TEST(JSONSchema_frame_draft4, top_level_relative_ref_with_id) { @@ -1160,6 +1271,13 @@ TEST(JSONSchema_frame_draft4, nested_relative_ref_with_id) { frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://example.com#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://example.com", + "https://example.com#/additionalProperties"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://example.com#/additionalProperties", + "https://example.com#/additionalProperties"); } TEST(JSONSchema_frame_draft4, invalid_id_not_string) { diff --git a/test/jsonschema/jsonschema_frame_draft6_test.cc b/test/jsonschema/jsonschema_frame_draft6_test.cc index c77a225a0..1730621cc 100644 --- a/test/jsonschema/jsonschema_frame_draft6_test.cc +++ b/test/jsonschema/jsonschema_frame_draft6_test.cc @@ -101,6 +101,12 @@ TEST(JSONSchema_frame_draft6, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", + "https://example.com"); } TEST(JSONSchema_frame_draft6, empty_schema) { @@ -261,6 +267,20 @@ TEST(JSONSchema_frame_draft6, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft6, one_level_applicators_with_identifiers) { @@ -334,6 +354,16 @@ TEST(JSONSchema_frame_draft6, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft6, subschema_absolute_identifier) { @@ -409,6 +439,16 @@ TEST(JSONSchema_frame_draft6, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft6, id_override) { @@ -584,6 +624,23 @@ TEST(JSONSchema_frame_draft6, explicit_argument_id_different) { frame, Static, "https://www.example.com#/properties/one", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.example.com#/properties/two", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test", + "https://www.sourcemeta.com/test"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "https://www.test.com", + "https://www.sourcemeta.com/test"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.test.com"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/test", "https://www.test.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.test.com", + "https://www.test.com"); } TEST(JSONSchema_frame_draft6, ref_metaschema) { @@ -704,6 +761,20 @@ TEST(JSONSchema_frame_draft6, location_independent_identifier_anonymous) { EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/definitions/bar", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/foo", + "#/definitions/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/definitions/bar", + "#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#foo", "#/definitions/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/foo", + "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/bar", + "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#foo", "#/definitions/bar"); } TEST(JSONSchema_frame_draft6, ref_with_id) { @@ -965,6 +1036,10 @@ TEST(JSONSchema_frame_draft6, ref_invalidates_sibling_subschemas_and_refs) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); } TEST(JSONSchema_frame_draft6, top_level_relative_ref_with_id) { diff --git a/test/jsonschema/jsonschema_frame_draft7_test.cc b/test/jsonschema/jsonschema_frame_draft7_test.cc index 4be97ae35..6e52bee2b 100644 --- a/test/jsonschema/jsonschema_frame_draft7_test.cc +++ b/test/jsonschema/jsonschema_frame_draft7_test.cc @@ -101,6 +101,12 @@ TEST(JSONSchema_frame_draft7, anonymous_with_nested_schema_resource) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://example.com", + "https://example.com"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/additionalProperties", + "https://example.com"); } TEST(JSONSchema_frame_draft7, empty_schema) { @@ -261,6 +267,26 @@ TEST(JSONSchema_frame_draft7, one_level_applicators_without_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/items"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/items"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/schema#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE( + frame, Static, "https://www.sourcemeta.com/schema#/properties/foo", + "https://www.sourcemeta.com/schema#/properties/foo"); } TEST(JSONSchema_frame_draft7, one_level_applicators_with_identifiers) { @@ -334,6 +360,16 @@ TEST(JSONSchema_frame_draft7, one_level_applicators_with_identifiers) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "https://www.sourcemeta.com/test/qux#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/test/qux#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft7, subschema_absolute_identifier) { @@ -409,6 +445,16 @@ TEST(JSONSchema_frame_draft7, subschema_absolute_identifier) { frame, Static, "https://www.sourcemeta.com/foo", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE( frame, Static, "https://www.sourcemeta.com/schema#/items", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/foo", + "https://www.sourcemeta.com/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, + "https://www.sourcemeta.com/schema#/items", + "https://www.sourcemeta.com/foo"); } TEST(JSONSchema_frame_draft7, id_override) { @@ -704,6 +750,20 @@ TEST(JSONSchema_frame_draft7, location_independent_identifier_anonymous) { EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/definitions/bar", frame.root()); EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/foo", + "#/definitions/foo"); + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "#/definitions/bar", + "#/definitions/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#foo", "#/definitions/foo"); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/foo", + "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/definitions/bar", + "#/definitions/bar"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#foo", "#/definitions/bar"); } TEST(JSONSchema_frame_draft7, ref_with_id) { @@ -1080,6 +1140,10 @@ TEST(JSONSchema_frame_draft7, ref_invalidates_sibling_subschemas_and_refs) { EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "", frame.root()); EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", frame.root()); + + EXPECT_FRAME_LOCATION_NON_REACHABLE(frame, Static, "", "#/properties/foo"); + EXPECT_FRAME_LOCATION_REACHABLE(frame, Static, "#/properties/foo", + "#/properties/foo"); } TEST(JSONSchema_frame_draft7, top_level_relative_ref_with_id) { From bc9f8bff2b93703eca8fa0979c5785cc8d8b9792 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Tue, 3 Feb 2026 16:25:04 -0400 Subject: [PATCH 2/2] Optimise Signed-off-by: Juan Cruz Viotti --- src/core/jsonschema/frame.cc | 40 +++++++++++++++--------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/core/jsonschema/frame.cc b/src/core/jsonschema/frame.cc index 43f527e3a..af9e53527 100644 --- a/src/core/jsonschema/frame.cc +++ b/src/core/jsonschema/frame.cc @@ -1435,14 +1435,14 @@ auto SchemaFrame::populate_reachability(const Location &base, // --------------------------------------------------------------------------- std::vector> unreachable_pointers; + std::unordered_set, + WeakPointer::Hasher, WeakPointer::Comparator> + pointers_with_non_orphan; if (this->pointer_to_location_.empty()) { std::unordered_set, WeakPointer::Hasher, WeakPointer::Comparator> has_non_pointer_location; - std::unordered_set, - WeakPointer::Hasher, WeakPointer::Comparator> - has_non_orphan; for (const auto &entry : this->locations_) { auto [iterator, inserted] = this->pointer_to_location_.try_emplace( @@ -1451,7 +1451,7 @@ auto SchemaFrame::populate_reachability(const Location &base, if (entry.second.type != LocationType::Pointer) { has_non_pointer_location.insert(iterator->first); if (!entry.second.orphan) { - has_non_orphan.insert(iterator->first); + pointers_with_non_orphan.insert(iterator->first); } } } @@ -1462,7 +1462,7 @@ auto SchemaFrame::populate_reachability(const Location &base, if (pointer == base.pointer) { is_reachable = true; } else if (pointer.starts_with(base.pointer)) { - is_reachable = has_non_orphan.contains(pointer_reference); + is_reachable = pointers_with_non_orphan.contains(pointer_reference); } cache.emplace(pointer_reference, is_reachable); @@ -1481,16 +1481,20 @@ auto SchemaFrame::populate_reachability(const Location &base, continue; } + const bool has_non_orphan{ + std::ranges::any_of(locations, [](const Location *location) { + return location->type != LocationType::Pointer && !location->orphan; + })}; + if (has_non_orphan) { + pointers_with_non_orphan.insert(pointer_reference); + } + const auto &pointer{pointer_reference.get()}; bool is_reachable{false}; if (pointer == base.pointer) { is_reachable = true; } else if (pointer.starts_with(base.pointer)) { - is_reachable = - std::ranges::any_of(locations, [](const Location *location) { - return location->type != LocationType::Pointer && - !location->orphan; - }); + is_reachable = has_non_orphan; } cache.emplace(pointer_reference, is_reachable); @@ -1688,19 +1692,9 @@ auto SchemaFrame::populate_reachability(const Location &base, cache[read_iterator->pointer] = true; for (auto &[cache_pointer, cache_reachable] : cache) { if (!cache_reachable && - cache_pointer.get().starts_with(reached_pointer)) { - const auto locations_it = - this->pointer_to_location_.find(cache_pointer); - if (locations_it != this->pointer_to_location_.end()) { - const bool has_non_orphan{std::ranges::any_of( - locations_it->second, [](const Location *location) { - return location->type != LocationType::Pointer && - !location->orphan; - })}; - if (has_non_orphan) { - cache_reachable = true; - } - } + cache_pointer.get().starts_with(reached_pointer) && + pointers_with_non_orphan.contains(cache_pointer)) { + cache_reachable = true; } } changed = true;