From 831c9167d394d4b050b06473ee812d606103e33c Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Thu, 26 Sep 2024 19:19:47 -0400 Subject: [PATCH] Allow older JSON Schema dialects (#809) Signed-off-by: Juan Cruz Viotti --- src/compiler/compiler.cc | 13 +-- test/compiler/compiler_test.cc | 197 ++++++++++++++++++++++++++++++--- 2 files changed, 185 insertions(+), 25 deletions(-) diff --git a/src/compiler/compiler.cc b/src/compiler/compiler.cc index db2a2de9..89970177 100644 --- a/src/compiler/compiler.cc +++ b/src/compiler/compiler.cc @@ -101,17 +101,6 @@ auto compile(sourcemeta::jsontoolkit::JSON &schema, const std::optional &default_dialect) -> void { canonicalize(schema, walker, resolver, default_dialect); - const auto mapper_resolver{make_resolver(resolver)}; - const auto base_dialect{sourcemeta::jsontoolkit::base_dialect( - schema, mapper_resolver, default_dialect) - .get()}; - - // TODO: Use a custom error here - if (!base_dialect.has_value() || - base_dialect.value() != "https://json-schema.org/draft/2020-12/schema") { - throw std::domain_error("Only JSON Schema 2020-12 is supported"); - } - sourcemeta::alterschema::Bundle mapper; // Enums @@ -135,7 +124,7 @@ auto compile(sourcemeta::jsontoolkit::JSON &schema, // Numbers mapper.add(); - mapper.apply(schema, walker, mapper_resolver, + mapper.apply(schema, walker, make_resolver(resolver), sourcemeta::jsontoolkit::empty_pointer, default_dialect); // The "any" encoding is always the last resort diff --git a/test/compiler/compiler_test.cc b/test/compiler/compiler_test.cc index 92313bc3..0f3c6c77 100644 --- a/test/compiler/compiler_test.cc +++ b/test/compiler/compiler_test.cc @@ -5,21 +5,170 @@ #include -TEST(JSONBinPack_Compiler, unsupported_draft) { - sourcemeta::jsontoolkit::JSON schema = sourcemeta::jsontoolkit::parse(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "boolean" +TEST(JSONBinPack_Compiler, dialect_2020_12) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema" })JSON"); - EXPECT_THROW(sourcemeta::jsonbinpack::compile( - schema, sourcemeta::jsontoolkit::default_schema_walker, - sourcemeta::jsontoolkit::official_resolver, - "https://json-schema.org/draft/2020-12/schema"), - std::domain_error); + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_2019_09) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_draft7) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_draft6) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); } -TEST(JSONBinPack_Compiler, unknown_draft_default) { - sourcemeta::jsontoolkit::JSON schema = sourcemeta::jsontoolkit::parse(R"JSON({ +TEST(JSONBinPack_Compiler, dialect_draft4) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_draft3) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_draft2) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-02/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_draft1) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-01/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, dialect_draft0) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-00/schema#" + })JSON"); + + sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver); + + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", + "name": "ANY_PACKED_TYPE_TAG_BYTE_PREFIX", + "options": {} + })JSON"); + + EXPECT_EQ(schema, expected); +} + +TEST(JSONBinPack_Compiler, unknown_dialect_default) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ "type": "integer" })JSON"); @@ -28,8 +177,7 @@ TEST(JSONBinPack_Compiler, unknown_draft_default) { sourcemeta::jsontoolkit::official_resolver, "https://json-schema.org/draft/2020-12/schema"); - const sourcemeta::jsontoolkit::JSON expected = - sourcemeta::jsontoolkit::parse(R"JSON({ + const auto expected = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "https://jsonbinpack.sourcemeta.com/schemas/encoding/v1.json", "name": "ARBITRARY_MULTIPLE_ZIGZAG_VARINT", "options": { @@ -39,3 +187,26 @@ TEST(JSONBinPack_Compiler, unknown_draft_default) { EXPECT_EQ(schema, expected); } + +TEST(JSONBinPack_Compiler, unknown_dialect_without_default) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "type": "integer" + })JSON"); + + EXPECT_THROW(sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver), + sourcemeta::jsontoolkit::SchemaError); +} + +TEST(JSONBinPack_Compiler, invalid_dialect) { + auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://foo.com", + "type": "integer" + })JSON"); + + EXPECT_THROW(sourcemeta::jsonbinpack::compile( + schema, sourcemeta::jsontoolkit::default_schema_walker, + sourcemeta::jsontoolkit::official_resolver), + sourcemeta::jsontoolkit::SchemaResolutionError); +}