From a8c899a57813694f1f317d98ede41a170af7b22d Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 1 Dec 2025 14:39:36 -0400 Subject: [PATCH] Implement a `SchemaConfig::applies_to` helper Signed-off-by: Juan Cruz Viotti --- src/extension/schemaconfig/CMakeLists.txt | 2 +- .../include/sourcemeta/core/schemaconfig.h | 5 + .../schemaconfig/{find.cc => schemaconfig.cc} | 11 +- test/schemaconfig/CMakeLists.txt | 1 + .../schemaconfig_applies_to_test.cc | 102 ++++++++++++++++++ 5 files changed, 119 insertions(+), 2 deletions(-) rename src/extension/schemaconfig/{find.cc => schemaconfig.cc} (69%) create mode 100644 test/schemaconfig/schemaconfig_applies_to_test.cc diff --git a/src/extension/schemaconfig/CMakeLists.txt b/src/extension/schemaconfig/CMakeLists.txt index 444236763..d27f4190a 100644 --- a/src/extension/schemaconfig/CMakeLists.txt +++ b/src/extension/schemaconfig/CMakeLists.txt @@ -1,5 +1,5 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME schemaconfig - PRIVATE_HEADERS error.h SOURCES parse.cc find.cc) + PRIVATE_HEADERS error.h SOURCES parse.cc schemaconfig.cc) if(SOURCEMETA_CORE_INSTALL) sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME schemaconfig) diff --git a/src/extension/schemaconfig/include/sourcemeta/core/schemaconfig.h b/src/extension/schemaconfig/include/sourcemeta/core/schemaconfig.h index 8ae6bda60..ade4e89aa 100644 --- a/src/extension/schemaconfig/include/sourcemeta/core/schemaconfig.h +++ b/src/extension/schemaconfig/include/sourcemeta/core/schemaconfig.h @@ -49,6 +49,11 @@ struct SOURCEMETA_CORE_SCHEMACONFIG_EXPORT SchemaConfig { std::unordered_map resolve; JSON extra = JSON::make_object(); + /// Check if the given path represents a schema described by this + /// configuration + [[nodiscard]] + auto applies_to(const std::filesystem::path &path) const -> bool; + /// Parse a configuration file from its contents [[nodiscard]] static auto from_json(const JSON &value, diff --git a/src/extension/schemaconfig/find.cc b/src/extension/schemaconfig/schemaconfig.cc similarity index 69% rename from src/extension/schemaconfig/find.cc rename to src/extension/schemaconfig/schemaconfig.cc index 717227f26..4a428d2c2 100644 --- a/src/extension/schemaconfig/find.cc +++ b/src/extension/schemaconfig/schemaconfig.cc @@ -1,7 +1,9 @@ #include #include -#include // assert +#include // std::ranges::any_of +#include // assert +#include // std::string namespace sourcemeta::core { @@ -31,4 +33,11 @@ auto SchemaConfig::find(const std::filesystem::path &path) return std::nullopt; } +auto SchemaConfig::applies_to(const std::filesystem::path &path) const -> bool { + const std::string filename{path.filename().string()}; + return std::ranges::any_of(this->extension, [&filename](const auto &suffix) { + return filename.ends_with(suffix); + }); +} + } // namespace sourcemeta::core diff --git a/test/schemaconfig/CMakeLists.txt b/test/schemaconfig/CMakeLists.txt index 5c107e958..7f482ee74 100644 --- a/test/schemaconfig/CMakeLists.txt +++ b/test/schemaconfig/CMakeLists.txt @@ -1,5 +1,6 @@ sourcemeta_googletest(NAMESPACE sourcemeta PROJECT core NAME schemaconfig SOURCES + schemaconfig_applies_to_test.cc schemaconfig_find_test.cc schemaconfig_from_json_test.cc schemaconfig_read_json_test.cc) diff --git a/test/schemaconfig/schemaconfig_applies_to_test.cc b/test/schemaconfig/schemaconfig_applies_to_test.cc new file mode 100644 index 000000000..28d988e3c --- /dev/null +++ b/test/schemaconfig/schemaconfig_applies_to_test.cc @@ -0,0 +1,102 @@ +#include + +#include +#include + +TEST(SchemaConfig_applies_to, default_extensions) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com" + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_TRUE(config.applies_to("foo.json")); + EXPECT_TRUE(config.applies_to("bar.yaml")); + EXPECT_TRUE(config.applies_to("baz.yml")); + EXPECT_FALSE(config.applies_to("qux.schema")); + EXPECT_FALSE(config.applies_to("no_extension")); +} + +TEST(SchemaConfig_applies_to, single_extension_match) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com", + "extension": ".json" + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_TRUE(config.applies_to("foo.json")); + EXPECT_TRUE(config.applies_to("/path/to/schema.json")); +} + +TEST(SchemaConfig_applies_to, single_extension_no_match) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com", + "extension": ".json" + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_FALSE(config.applies_to("foo.yaml")); + EXPECT_FALSE(config.applies_to("foo.schema")); + EXPECT_FALSE(config.applies_to("no_extension")); +} + +TEST(SchemaConfig_applies_to, multiple_extensions_match) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com", + "extension": [ ".json", ".yaml", ".yml" ] + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_TRUE(config.applies_to("foo.json")); + EXPECT_TRUE(config.applies_to("bar.yaml")); + EXPECT_TRUE(config.applies_to("baz.yml")); +} + +TEST(SchemaConfig_applies_to, multiple_extensions_no_match) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com", + "extension": [ ".json", ".yaml" ] + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_FALSE(config.applies_to("foo.schema")); + EXPECT_FALSE(config.applies_to("bar.txt")); + EXPECT_FALSE(config.applies_to("no_extension")); +} + +TEST(SchemaConfig_applies_to, double_extension_match) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com", + "extension": ".json" + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_TRUE(config.applies_to("foo.schema.json")); + EXPECT_TRUE(config.applies_to("/path/to/bar.test.json")); +} + +TEST(SchemaConfig_applies_to, compound_extension_match) { + const auto input{sourcemeta::core::parse_json(R"JSON({ + "baseUri": "https://example.com", + "extension": ".schema.json" + })JSON")}; + + const auto config{ + sourcemeta::core::SchemaConfig::from_json(input, TEST_DIRECTORY)}; + + EXPECT_TRUE(config.applies_to("foo.schema.json")); + EXPECT_TRUE(config.applies_to("/path/to/bar.schema.json")); + EXPECT_FALSE(config.applies_to("baz.json")); + EXPECT_FALSE(config.applies_to("qux.schema.yaml")); +}