From 2db95e084f12a1d137d2b08b078fa349b9d6eeb6 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Tue, 28 Jan 2025 14:36:13 -0400 Subject: [PATCH] Remove `anchors()` from the public JSON Schema interface Signed-off-by: Juan Cruz Viotti --- src/core/jsonschema/CMakeLists.txt | 4 +- src/core/jsonschema/anchor.cc | 101 -------------- src/core/jsonschema/frame.cc | 102 ++++++++++++-- .../include/sourcemeta/core/jsonschema.h | 1 - .../sourcemeta/core/jsonschema_anchor.h | 64 --------- test/jsonschema/CMakeLists.txt | 5 - .../jsonschema_anchor_2019_09_test.cc | 125 ------------------ .../jsonschema_anchor_2020_12_test.cc | 119 ----------------- .../jsonschema_anchor_draft4_test.cc | 85 ------------ .../jsonschema_anchor_draft6_test.cc | 85 ------------ .../jsonschema_anchor_draft7_test.cc | 85 ------------ 11 files changed, 94 insertions(+), 682 deletions(-) delete mode 100644 src/core/jsonschema/anchor.cc delete mode 100644 src/core/jsonschema/include/sourcemeta/core/jsonschema_anchor.h delete mode 100644 test/jsonschema/jsonschema_anchor_2019_09_test.cc delete mode 100644 test/jsonschema/jsonschema_anchor_2020_12_test.cc delete mode 100644 test/jsonschema/jsonschema_anchor_draft4_test.cc delete mode 100644 test/jsonschema/jsonschema_anchor_draft6_test.cc delete mode 100644 test/jsonschema/jsonschema_anchor_draft7_test.cc diff --git a/src/core/jsonschema/CMakeLists.txt b/src/core/jsonschema/CMakeLists.txt index 403cd15a5..637c6acfc 100644 --- a/src/core/jsonschema/CMakeLists.txt +++ b/src/core/jsonschema/CMakeLists.txt @@ -4,11 +4,11 @@ include(./official_resolver.cmake) sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME jsonschema FOLDER "Core/JSON Schema" - PRIVATE_HEADERS anchor.h bundle.h resolver.h + PRIVATE_HEADERS bundle.h resolver.h walker.h reference.h frame.h error.h unevaluated.h keywords.h transform.h SOURCES jsonschema.cc default_walker.cc frame.cc - anchor.cc resolver.cc walker.cc bundle.cc + resolver.cc walker.cc bundle.cc unevaluated.cc relativize.cc unidentify.cc transform_rule.cc transformer.cc "${CMAKE_CURRENT_BINARY_DIR}/official_resolver.cc") diff --git a/src/core/jsonschema/anchor.cc b/src/core/jsonschema/anchor.cc deleted file mode 100644 index 115290210..000000000 --- a/src/core/jsonschema/anchor.cc +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include - -#include // assert -#include // std::move - -namespace sourcemeta::core { - -auto anchors(const JSON &schema, const SchemaResolver &resolver, - const std::optional &default_dialect) - -> std::map { - const std::map vocabularies{ - sourcemeta::core::vocabularies(schema, resolver, default_dialect)}; - return anchors(schema, vocabularies); -} - -auto anchors(const JSON &schema, - const std::map &vocabularies) - -> std::map { - std::map result; - - // 2020-12 - if (schema.is_object() && - vocabularies.contains( - "https://json-schema.org/draft/2020-12/vocab/core")) { - if (schema.defines("$dynamicAnchor")) { - const auto &anchor{schema.at("$dynamicAnchor")}; - assert(anchor.is_string()); - result.insert({anchor.to_string(), AnchorType::Dynamic}); - } - - if (schema.defines("$anchor")) { - const auto &anchor{schema.at("$anchor")}; - assert(anchor.is_string()); - const auto anchor_string{anchor.to_string()}; - const auto success = result.insert({anchor_string, AnchorType::Static}); - assert(success.second || result.contains(anchor_string)); - if (!success.second) { - result[anchor_string] = AnchorType::All; - } - } - } - - // 2019-09 - if (schema.is_object() && - vocabularies.contains( - "https://json-schema.org/draft/2019-09/vocab/core")) { - if (schema.defines("$recursiveAnchor")) { - const auto &anchor{schema.at("$recursiveAnchor")}; - assert(anchor.is_boolean()); - if (anchor.to_boolean()) { - // We store a 2019-09 recursive anchor as an empty anchor - result.insert({"", AnchorType::Dynamic}); - } - } - - if (schema.defines("$anchor")) { - const auto &anchor{schema.at("$anchor")}; - assert(anchor.is_string()); - const auto anchor_string{anchor.to_string()}; - const auto success = result.insert({anchor_string, AnchorType::Static}); - assert(success.second || result.contains(anchor_string)); - if (!success.second) { - result[anchor_string] = AnchorType::All; - } - } - } - - // Draft 7 and 6 - // Old `$id` anchor form - if (schema.is_object() && - (vocabularies.contains("http://json-schema.org/draft-07/schema#") || - vocabularies.contains("http://json-schema.org/draft-06/schema#"))) { - if (schema.defines("$id")) { - assert(schema.at("$id").is_string()); - const URI identifier(schema.at("$id").to_string()); - if (identifier.is_fragment_only()) { - result.insert( - {std::string{identifier.fragment().value()}, AnchorType::Static}); - } - } - } - - // Draft 4 - // Old `id` anchor form - if (schema.is_object() && - vocabularies.contains("http://json-schema.org/draft-04/schema#")) { - if (schema.defines("id")) { - assert(schema.at("id").is_string()); - const URI identifier(schema.at("id").to_string()); - if (identifier.is_fragment_only()) { - result.insert( - {std::string{identifier.fragment().value()}, AnchorType::Static}); - } - } - } - - return result; -} - -} // namespace sourcemeta::core diff --git a/src/core/jsonschema/frame.cc b/src/core/jsonschema/frame.cc index 21f0948a1..cffe597a0 100644 --- a/src/core/jsonschema/frame.cc +++ b/src/core/jsonschema/frame.cc @@ -13,6 +13,92 @@ #include // std::pair, std::move #include // std::vector +enum class AnchorType : std::uint8_t { Static, Dynamic, All }; + +static auto find_anchors(const sourcemeta::core::JSON &schema, + const std::map &vocabularies) + -> std::map { + std::map result; + + // 2020-12 + if (schema.is_object() && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/core")) { + if (schema.defines("$dynamicAnchor")) { + const auto &anchor{schema.at("$dynamicAnchor")}; + assert(anchor.is_string()); + result.insert({anchor.to_string(), AnchorType::Dynamic}); + } + + if (schema.defines("$anchor")) { + const auto &anchor{schema.at("$anchor")}; + assert(anchor.is_string()); + const auto anchor_string{anchor.to_string()}; + const auto success = result.insert({anchor_string, AnchorType::Static}); + assert(success.second || result.contains(anchor_string)); + if (!success.second) { + result[anchor_string] = AnchorType::All; + } + } + } + + // 2019-09 + if (schema.is_object() && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/core")) { + if (schema.defines("$recursiveAnchor")) { + const auto &anchor{schema.at("$recursiveAnchor")}; + assert(anchor.is_boolean()); + if (anchor.to_boolean()) { + // We store a 2019-09 recursive anchor as an empty anchor + result.insert({"", AnchorType::Dynamic}); + } + } + + if (schema.defines("$anchor")) { + const auto &anchor{schema.at("$anchor")}; + assert(anchor.is_string()); + const auto anchor_string{anchor.to_string()}; + const auto success = result.insert({anchor_string, AnchorType::Static}); + assert(success.second || result.contains(anchor_string)); + if (!success.second) { + result[anchor_string] = AnchorType::All; + } + } + } + + // Draft 7 and 6 + // Old `$id` anchor form + if (schema.is_object() && + (vocabularies.contains("http://json-schema.org/draft-07/schema#") || + vocabularies.contains("http://json-schema.org/draft-06/schema#"))) { + if (schema.defines("$id")) { + assert(schema.at("$id").is_string()); + const sourcemeta::core::URI identifier(schema.at("$id").to_string()); + if (identifier.is_fragment_only()) { + result.insert( + {std::string{identifier.fragment().value()}, AnchorType::Static}); + } + } + } + + // Draft 4 + // Old `id` anchor form + if (schema.is_object() && + vocabularies.contains("http://json-schema.org/draft-04/schema#")) { + if (schema.defines("id")) { + assert(schema.at("id").is_string()); + const sourcemeta::core::URI identifier(schema.at("id").to_string()); + if (identifier.is_fragment_only()) { + result.insert( + {std::string{identifier.fragment().value()}, AnchorType::Static}); + } + } + } + + return result; +} + static auto find_nearest_bases( const std::map> &bases, const sourcemeta::core::Pointer &pointer, @@ -254,8 +340,8 @@ auto internal_analyse(const sourcemeta::core::JSON &schema, } // Handle schema anchors - for (const auto &[name, type] : sourcemeta::core::anchors( - entry.common.value, entry.common.vocabularies)) { + for (const auto &[name, type] : + find_anchors(entry.common.value, entry.common.vocabularies)) { const auto bases{ find_nearest_bases(base_uris, entry.common.pointer, entry.id)}; @@ -263,8 +349,7 @@ auto internal_analyse(const sourcemeta::core::JSON &schema, const auto anchor_uri{sourcemeta::core::URI::from_fragment(name)}; const auto relative_anchor_uri{anchor_uri.recompose()}; - if (type == sourcemeta::core::AnchorType::Static || - type == sourcemeta::core::AnchorType::All) { + if (type == AnchorType::Static || type == AnchorType::All) { store(frame, ReferenceType::Static, Frame::LocationType::Anchor, relative_anchor_uri, root_id, "", entry.common.pointer, entry.common.pointer.resolve_from(bases.second), @@ -272,8 +357,7 @@ auto internal_analyse(const sourcemeta::core::JSON &schema, entry.common.base_dialect.value()); } - if (type == sourcemeta::core::AnchorType::Dynamic || - type == sourcemeta::core::AnchorType::All) { + if (type == AnchorType::Dynamic || type == AnchorType::All) { store(frame, ReferenceType::Dynamic, Frame::LocationType::Anchor, relative_anchor_uri, root_id, "", entry.common.pointer, entry.common.pointer.resolve_from(bases.second), @@ -310,8 +394,7 @@ auto internal_analyse(const sourcemeta::core::JSON &schema, continue; } - if (type == sourcemeta::core::AnchorType::Static || - type == sourcemeta::core::AnchorType::All) { + if (type == AnchorType::Static || type == AnchorType::All) { store(frame, sourcemeta::core::ReferenceType::Static, Frame::LocationType::Anchor, anchor_uri, root_id, base_string, entry.common.pointer, @@ -320,8 +403,7 @@ auto internal_analyse(const sourcemeta::core::JSON &schema, entry.common.base_dialect.value()); } - if (type == sourcemeta::core::AnchorType::Dynamic || - type == sourcemeta::core::AnchorType::All) { + if (type == AnchorType::Dynamic || type == AnchorType::All) { store(frame, sourcemeta::core::ReferenceType::Dynamic, Frame::LocationType::Anchor, anchor_uri, root_id, base_string, entry.common.pointer, diff --git a/src/core/jsonschema/include/sourcemeta/core/jsonschema.h b/src/core/jsonschema/include/sourcemeta/core/jsonschema.h index c8bfad80f..7007e5055 100644 --- a/src/core/jsonschema/include/sourcemeta/core/jsonschema.h +++ b/src/core/jsonschema/include/sourcemeta/core/jsonschema.h @@ -6,7 +6,6 @@ #endif #include -#include #include #include #include diff --git a/src/core/jsonschema/include/sourcemeta/core/jsonschema_anchor.h b/src/core/jsonschema/include/sourcemeta/core/jsonschema_anchor.h deleted file mode 100644 index 1d117831d..000000000 --- a/src/core/jsonschema/include/sourcemeta/core/jsonschema_anchor.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SOURCEMETA_CORE_JSONSCHEMA_ANCHOR_H_ -#define SOURCEMETA_CORE_JSONSCHEMA_ANCHOR_H_ - -#ifndef SOURCEMETA_CORE_JSONSCHEMA_EXPORT -#include -#endif - -#include -#include - -#include // std::uint8_t -#include // std::map -#include // std::optional -#include // std::string - -namespace sourcemeta::core { - -/// @ingroup jsonschema -/// The anchor type -enum class AnchorType : std::uint8_t { Static, Dynamic, All }; - -/// @ingroup jsonschema -/// -/// This function returns the anchors of the given schema, if any. This function -/// also supports the old pre 2019-09 `id` and `$id` anchor form. A given -/// subschema might have more than two anchors if, for example, declares both -/// `$anchor` and `$dynamicAnchor` (in 2020-12). For example: -/// -/// ```cpp -/// #include -/// #include -/// #include -/// -/// const sourcemeta::core::JSON document = -/// sourcemeta::core::parse_json(R"JSON({ -/// "$schema": "https://json-schema.org/draft/2020-12/schema", -/// "$id": "https://sourcemeta.com/example-schema", -/// "$anchor": "foo" -/// })JSON"); -/// -/// const auto anchors{sourcemeta::core::anchors( -/// document, sourcemeta::core::official_resolver)}; -/// assert(anchors.size() == 1); -/// assert(anchors.contains("foo")); -/// // This is a static anchor -/// assert(anchors.at("foo") == sourcemeta::core::AnchorType::Static); -/// ``` -SOURCEMETA_CORE_JSONSCHEMA_EXPORT -auto anchors(const JSON &schema, const SchemaResolver &resolver, - const std::optional &default_dialect = std::nullopt) - -> std::map; - -/// @ingroup jsonschema -/// -/// This function is a shortcut to sourcemeta::core::anchors if you have -/// already computed the vocabularies that the given schema makes use of. -SOURCEMETA_CORE_JSONSCHEMA_EXPORT -auto anchors(const JSON &schema, - const std::map &vocabularies) - -> std::map; - -} // namespace sourcemeta::core - -#endif diff --git a/test/jsonschema/CMakeLists.txt b/test/jsonschema/CMakeLists.txt index 1bb3e6076..18315c895 100644 --- a/test/jsonschema/CMakeLists.txt +++ b/test/jsonschema/CMakeLists.txt @@ -2,11 +2,6 @@ sourcemeta_googletest(NAMESPACE sourcemeta PROJECT core NAME jsonschema FOLDER "Core/JSON Schema" SOURCES jsonschema_test_utils.h - jsonschema_anchor_2020_12_test.cc - jsonschema_anchor_2019_09_test.cc - jsonschema_anchor_draft7_test.cc - jsonschema_anchor_draft6_test.cc - jsonschema_anchor_draft4_test.cc jsonschema_identify_2020_12_test.cc jsonschema_identify_2019_09_test.cc jsonschema_identify_draft7_test.cc diff --git a/test/jsonschema/jsonschema_anchor_2019_09_test.cc b/test/jsonschema/jsonschema_anchor_2019_09_test.cc deleted file mode 100644 index 09b4b9185..000000000 --- a/test/jsonschema/jsonschema_anchor_2019_09_test.cc +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include - -TEST(JSONSchema_anchor_2019_09, boolean_schema) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json("true"); - const auto anchors{sourcemeta::core::anchors( - document, sourcemeta::core::official_resolver, - "https://json-schema.org/draft/2019-09/schema")}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_2019_09, top_level_no_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_2019_09, top_level_static_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$anchor": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_2019_09, top_level_dynamic_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$dynamicAnchor": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_2019_09, top_level_recursive_anchor_false) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$recursiveAnchor": false - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_2019_09, top_level_recursive_anchor_true) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$recursiveAnchor": true - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("")); - EXPECT_EQ(anchors.at(""), sourcemeta::core::AnchorType::Dynamic); -} - -TEST(JSONSchema_anchor_2019_09, top_level_recursive_anchor_true_and_empty) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$recursiveAnchor": true, - "$anchor": "" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("")); - EXPECT_EQ(anchors.at(""), sourcemeta::core::AnchorType::All); -} - -TEST(JSONSchema_anchor_2019_09, nested_static_with_default_dialect) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$anchor": "foo" - })JSON"); - - const auto anchors{sourcemeta::core::anchors( - document, sourcemeta::core::official_resolver, - "https://json-schema.org/draft/2019-09/schema")}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_2019_09, vocabularies_shortcut) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$anchor": "foo" - })JSON"); - - const std::map vocabularies{sourcemeta::core::vocabularies( - document, sourcemeta::core::official_resolver)}; - - const auto anchors{sourcemeta::core::anchors(document, vocabularies)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_2019_09, old_id_anchor_not_recognized) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} diff --git a/test/jsonschema/jsonschema_anchor_2020_12_test.cc b/test/jsonschema/jsonschema_anchor_2020_12_test.cc deleted file mode 100644 index 4563ac770..000000000 --- a/test/jsonschema/jsonschema_anchor_2020_12_test.cc +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include - -TEST(JSONSchema_anchor_2020_12, boolean_schema) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json("true"); - const auto anchors{sourcemeta::core::anchors( - document, sourcemeta::core::official_resolver, - "https://json-schema.org/draft/2020-12/schema")}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_2020_12, top_level_no_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_2020_12, top_level_static_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$anchor": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_2020_12, top_level_dynamic_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$dynamicAnchor": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Dynamic); -} - -TEST(JSONSchema_anchor_2020_12, top_level_static_and_dynamic_anchor_different) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$anchor": "bar", - "$dynamicAnchor": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 2); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_TRUE(anchors.contains("bar")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Dynamic); - EXPECT_EQ(anchors.at("bar"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_2020_12, top_level_static_and_dynamic_anchor_same) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$anchor": "foo", - "$dynamicAnchor": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::All); -} - -TEST(JSONSchema_anchor_2020_12, nested_static_with_default_dialect) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$anchor": "foo" - })JSON"); - - const auto anchors{sourcemeta::core::anchors( - document, sourcemeta::core::official_resolver, - "https://json-schema.org/draft/2020-12/schema")}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_2020_12, vocabularies_shortcut) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$anchor": "foo", - "$dynamicAnchor": "bar" - })JSON"); - - const std::map vocabularies{sourcemeta::core::vocabularies( - document, sourcemeta::core::official_resolver)}; - - const auto anchors{sourcemeta::core::anchors(document, vocabularies)}; - EXPECT_EQ(anchors.size(), 2); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_TRUE(anchors.contains("bar")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); - EXPECT_EQ(anchors.at("bar"), sourcemeta::core::AnchorType::Dynamic); -} - -TEST(JSONSchema_anchor_2020_12, old_id_anchor_not_recognized) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} diff --git a/test/jsonschema/jsonschema_anchor_draft4_test.cc b/test/jsonschema/jsonschema_anchor_draft4_test.cc deleted file mode 100644 index c3f2ba3d1..000000000 --- a/test/jsonschema/jsonschema_anchor_draft4_test.cc +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#include -#include - -TEST(JSONSchema_anchor_draft4, boolean_schema) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json("true"); - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver, - "http://json-schema.org/draft-04/schema#")}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft4, top_level_no_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft4, top_level_static_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft4, nested_static_with_default_dialect) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver, - "http://json-schema.org/draft-04/schema#")}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft4, vocabularies_shortcut) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "#foo" - })JSON"); - - const std::map vocabularies{sourcemeta::core::vocabularies( - document, sourcemeta::core::official_resolver)}; - - const auto anchors{sourcemeta::core::anchors(document, vocabularies)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft4, non_fragment_relative_id) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft4, not_only_fragment) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "foo#bar" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} diff --git a/test/jsonschema/jsonschema_anchor_draft6_test.cc b/test/jsonschema/jsonschema_anchor_draft6_test.cc deleted file mode 100644 index 628bcfac1..000000000 --- a/test/jsonschema/jsonschema_anchor_draft6_test.cc +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#include -#include - -TEST(JSONSchema_anchor_draft6, boolean_schema) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json("true"); - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver, - "http://json-schema.org/draft-06/schema#")}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft6, top_level_no_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft6, top_level_static_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft6, nested_static_with_default_dialect) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver, - "http://json-schema.org/draft-06/schema#")}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft6, vocabularies_shortcut) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "#foo" - })JSON"); - - const std::map vocabularies{sourcemeta::core::vocabularies( - document, sourcemeta::core::official_resolver)}; - - const auto anchors{sourcemeta::core::anchors(document, vocabularies)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft6, non_fragment_relative_id) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft6, not_only_fragment) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "foo#bar" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} diff --git a/test/jsonschema/jsonschema_anchor_draft7_test.cc b/test/jsonschema/jsonschema_anchor_draft7_test.cc deleted file mode 100644 index c44da4d33..000000000 --- a/test/jsonschema/jsonschema_anchor_draft7_test.cc +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#include -#include - -TEST(JSONSchema_anchor_draft7, boolean_schema) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json("true"); - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver, - "http://json-schema.org/draft-07/schema#")}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft7, top_level_no_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft7, top_level_static_anchor) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft7, nested_static_with_default_dialect) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$id": "#foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver, - "http://json-schema.org/draft-07/schema#")}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft7, vocabularies_shortcut) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "#foo" - })JSON"); - - const std::map vocabularies{sourcemeta::core::vocabularies( - document, sourcemeta::core::official_resolver)}; - - const auto anchors{sourcemeta::core::anchors(document, vocabularies)}; - EXPECT_EQ(anchors.size(), 1); - EXPECT_TRUE(anchors.contains("foo")); - EXPECT_EQ(anchors.at("foo"), sourcemeta::core::AnchorType::Static); -} - -TEST(JSONSchema_anchor_draft7, non_fragment_relative_id) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "foo" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -} - -TEST(JSONSchema_anchor_draft7, not_only_fragment) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "foo#bar" - })JSON"); - - const auto anchors{ - sourcemeta::core::anchors(document, sourcemeta::core::official_resolver)}; - EXPECT_TRUE(anchors.empty()); -}