diff --git a/src/compiler/default_compiler_draft4.h b/src/compiler/default_compiler_draft4.h index 3d425dad1..de3f0c602 100644 --- a/src/compiler/default_compiler_draft4.h +++ b/src/compiler/default_compiler_draft4.h @@ -9,7 +9,6 @@ #include // std::sort, std::any_of, std::all_of, std::find_if, std::none_of #include // assert #include // std::set -#include // std::ostringstream #include // std::move #include "compile_helpers.h" @@ -20,10 +19,8 @@ static auto parse_regex(const std::string &pattern, -> sourcemeta::core::Regex { const auto result{sourcemeta::core::to_regex(pattern)}; if (!result.has_value()) { - std::ostringstream message; - message << "Invalid regular expression: " << pattern; - throw sourcemeta::blaze::CompilerError(base, to_pointer(schema_location), - message.str()); + throw sourcemeta::blaze::CompilerInvalidRegexError( + base, to_pointer(schema_location), pattern); } return result.value(); diff --git a/src/compiler/include/sourcemeta/blaze/compiler_error.h b/src/compiler/include/sourcemeta/blaze/compiler_error.h index 63006366b..c3e00fdde 100644 --- a/src/compiler/include/sourcemeta/blaze/compiler_error.h +++ b/src/compiler/include/sourcemeta/blaze/compiler_error.h @@ -27,11 +27,20 @@ namespace sourcemeta::blaze { class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerError : public std::exception { public: CompilerError(sourcemeta::core::URI base, - sourcemeta::core::Pointer schema_location, std::string message) + sourcemeta::core::Pointer schema_location, const char *message) : base_{std::move(base)}, schema_location_{std::move(schema_location)}, - message_{std::move(message)} {} + message_{message} {} + CompilerError(sourcemeta::core::URI base, + sourcemeta::core::Pointer schema_location, + std::string message) = delete; + CompilerError(sourcemeta::core::URI base, + sourcemeta::core::Pointer schema_location, + std::string &&message) = delete; + CompilerError(sourcemeta::core::URI base, + sourcemeta::core::Pointer schema_location, + std::string_view message) = delete; [[nodiscard]] auto what() const noexcept -> const char * override { - return this->message_.c_str(); + return this->message_; } [[nodiscard]] auto base() const noexcept -> const sourcemeta::core::URI & { @@ -46,7 +55,40 @@ class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerError : public std::exception { private: sourcemeta::core::URI base_; sourcemeta::core::Pointer schema_location_; - std::string message_; + const char *message_; +}; + +/// @ingroup jsonschema +/// An error that represents an invalid regular expression during compilation +class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerInvalidRegexError + : public std::exception { +public: + CompilerInvalidRegexError(sourcemeta::core::URI base, + sourcemeta::core::Pointer schema_location, + std::string regex) + : base_{std::move(base)}, schema_location_{std::move(schema_location)}, + regex_{std::move(regex)} {} + [[nodiscard]] auto what() const noexcept -> const char * override { + return "Invalid regular expression"; + } + + [[nodiscard]] auto base() const noexcept -> const sourcemeta::core::URI & { + return this->base_; + } + + [[nodiscard]] auto location() const noexcept + -> const sourcemeta::core::Pointer & { + return this->schema_location_; + } + + [[nodiscard]] auto regex() const noexcept -> const std::string & { + return this->regex_; + } + +private: + sourcemeta::core::URI base_; + sourcemeta::core::Pointer schema_location_; + std::string regex_; }; /// @ingroup jsonschema @@ -84,11 +126,17 @@ class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerInvalidEntryPoint : public std::exception { public: CompilerInvalidEntryPoint(const std::string_view entrypoint, - const std::string_view message) + const char *message) : identifier_{entrypoint}, message_{message} {} + CompilerInvalidEntryPoint(const std::string_view entrypoint, + std::string message) = delete; + CompilerInvalidEntryPoint(const std::string_view entrypoint, + std::string &&message) = delete; + CompilerInvalidEntryPoint(const std::string_view entrypoint, + std::string_view message) = delete; [[nodiscard]] auto what() const noexcept -> const char * override { - return this->message_.c_str(); + return this->message_; } [[nodiscard]] auto identifier() const noexcept -> const std::string & { @@ -97,7 +145,7 @@ class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerInvalidEntryPoint private: std::string identifier_; - std::string message_; + const char *message_; }; #if defined(_MSC_VER) diff --git a/src/evaluator/include/sourcemeta/blaze/evaluator_error.h b/src/evaluator/include/sourcemeta/blaze/evaluator_error.h index 640b93df8..3b951c522 100644 --- a/src/evaluator/include/sourcemeta/blaze/evaluator_error.h +++ b/src/evaluator/include/sourcemeta/blaze/evaluator_error.h @@ -5,9 +5,9 @@ #include #endif -#include // std::exception -#include // std::string -#include // std::move +#include // std::exception +#include // std::string +#include // std::string_view namespace sourcemeta::blaze { @@ -23,13 +23,16 @@ namespace sourcemeta::blaze { class SOURCEMETA_BLAZE_EVALUATOR_EXPORT EvaluationError : public std::exception { public: - EvaluationError(std::string message) : message_{std::move(message)} {} + EvaluationError(const char *message) : message_{message} {} + EvaluationError(std::string message) = delete; + EvaluationError(std::string &&message) = delete; + EvaluationError(std::string_view message) = delete; [[nodiscard]] auto what() const noexcept -> const char * override { - return this->message_.c_str(); + return this->message_; } private: - std::string message_; + const char *message_; }; #if defined(_MSC_VER) diff --git a/src/linter/include/sourcemeta/blaze/linter_error.h b/src/linter/include/sourcemeta/blaze/linter_error.h index 9ee38f5ab..d5e6c44e4 100644 --- a/src/linter/include/sourcemeta/blaze/linter_error.h +++ b/src/linter/include/sourcemeta/blaze/linter_error.h @@ -34,12 +34,17 @@ class SOURCEMETA_BLAZE_LINTER_EXPORT LinterMissingNameError class SOURCEMETA_BLAZE_LINTER_EXPORT LinterInvalidNameError : public std::exception { public: - LinterInvalidNameError(const std::string_view identifier, - const std::string_view message) + LinterInvalidNameError(const std::string_view identifier, const char *message) : identifier_{identifier}, message_{message} {} + LinterInvalidNameError(const std::string_view identifier, + std::string message) = delete; + LinterInvalidNameError(const std::string_view identifier, + std::string &&message) = delete; + LinterInvalidNameError(const std::string_view identifier, + std::string_view message) = delete; [[nodiscard]] auto what() const noexcept -> const char * override { - return this->message_.c_str(); + return this->message_; } [[nodiscard]] auto identifier() const noexcept -> const std::string & { @@ -48,7 +53,34 @@ class SOURCEMETA_BLAZE_LINTER_EXPORT LinterInvalidNameError private: std::string identifier_; - std::string message_; + const char *message_; +}; + +/// @ingroup linter +/// An error that represents a schema rule name that does not match +/// the required pattern +class SOURCEMETA_BLAZE_LINTER_EXPORT LinterInvalidNamePatternError + : public std::exception { +public: + LinterInvalidNamePatternError(const std::string_view identifier, + const std::string_view regex) + : identifier_{identifier}, regex_{regex} {} + + [[nodiscard]] auto what() const noexcept -> const char * override { + return "The schema rule name does not match the required pattern"; + } + + [[nodiscard]] auto identifier() const noexcept -> const std::string & { + return this->identifier_; + } + + [[nodiscard]] auto regex() const noexcept -> const std::string & { + return this->regex_; + } + +private: + std::string identifier_; + std::string regex_; }; #if defined(_MSC_VER) diff --git a/src/linter/schema.cc b/src/linter/schema.cc index a18e92e7b..9dacfaa0e 100644 --- a/src/linter/schema.cc +++ b/src/linter/schema.cc @@ -25,9 +25,7 @@ static auto validate_name(const std::string_view name) -> void { } if (!sourcemeta::core::matches(pattern.value(), std::string{name})) { - std::string message{"The schema rule name must match "}; - message += NAME_PATTERN; - throw LinterInvalidNameError(name, message); + throw LinterInvalidNamePatternError(name, NAME_PATTERN); } } diff --git a/src/test/include/sourcemeta/blaze/test_error.h b/src/test/include/sourcemeta/blaze/test_error.h index 7fdaae218..c9e120aa3 100644 --- a/src/test/include/sourcemeta/blaze/test_error.h +++ b/src/test/include/sourcemeta/blaze/test_error.h @@ -7,10 +7,11 @@ #include -#include // std::uint64_t -#include // std::runtime_error -#include // std::string -#include // std::move +#include // std::uint64_t +#include // std::exception +#include // std::string +#include // std::string_view +#include // std::move namespace sourcemeta::blaze { @@ -23,12 +24,22 @@ namespace sourcemeta::blaze { /// @ingroup test /// An error that occurs when parsing a test file -class SOURCEMETA_BLAZE_TEST_EXPORT TestParseError : public std::runtime_error { +class SOURCEMETA_BLAZE_TEST_EXPORT TestParseError : public std::exception { public: - TestParseError(const std::string &message, sourcemeta::core::Pointer location, + TestParseError(const char *message, sourcemeta::core::Pointer location, std::uint64_t line, std::uint64_t column) - : std::runtime_error{message}, location_{std::move(location)}, - line_{line}, column_{column} {} + : message_{message}, location_{std::move(location)}, line_{line}, + column_{column} {} + TestParseError(std::string message, sourcemeta::core::Pointer location, + std::uint64_t line, std::uint64_t column) = delete; + TestParseError(std::string &&message, sourcemeta::core::Pointer location, + std::uint64_t line, std::uint64_t column) = delete; + TestParseError(std::string_view message, sourcemeta::core::Pointer location, + std::uint64_t line, std::uint64_t column) = delete; + + [[nodiscard]] auto what() const noexcept -> const char * override { + return this->message_; + } [[nodiscard]] auto location() const noexcept -> const sourcemeta::core::Pointer & { @@ -44,6 +55,7 @@ class SOURCEMETA_BLAZE_TEST_EXPORT TestParseError : public std::runtime_error { } private: + const char *message_; sourcemeta::core::Pointer location_; std::uint64_t line_; std::uint64_t column_; diff --git a/test/evaluator/evaluator_draft4_test.cc b/test/evaluator/evaluator_draft4_test.cc index 7277c96aa..5ea87dafb 100644 --- a/test/evaluator/evaluator_draft4_test.cc +++ b/test/evaluator/evaluator_draft4_test.cc @@ -1049,8 +1049,15 @@ TEST(Evaluator_draft4, ref_14) { const sourcemeta::core::JSON instance{true}; sourcemeta::blaze::Evaluator evaluator; - EXPECT_THROW(evaluator.validate(compiled_schema, instance), - sourcemeta::blaze::EvaluationError); + try { + evaluator.validate(compiled_schema, instance); + FAIL(); + } catch (const sourcemeta::blaze::EvaluationError &error) { + EXPECT_STREQ(error.what(), "The evaluation path depth limit was reached " + "likely due to infinite recursion"); + } catch (...) { + FAIL(); + } } TEST(Evaluator_draft4, ref_15) { @@ -2027,14 +2034,14 @@ TEST(Evaluator_draft4, pattern_4) { sourcemeta::blaze::default_schema_compiler); // The pattern might succeed in some standard library implementations SUCCEED(); - } catch (const sourcemeta::blaze::CompilerError &error) { - EXPECT_STREQ(error.what(), - "Invalid regular expression: ^[a-zA-Z0-9\\/\\_]{1,32}$"); + } catch (const sourcemeta::blaze::CompilerInvalidRegexError &error) { + EXPECT_STREQ(error.what(), "Invalid regular expression"); + EXPECT_EQ(error.regex(), "^[a-zA-Z0-9\\/\\_]{1,32}$"); EXPECT_EQ(error.location(), sourcemeta::core::Pointer({"pattern"})); EXPECT_EQ(error.base().recompose(), ""); SUCCEED(); - } catch (const std::exception &) { - FAIL() << "The compile function was expected to throw a schema error"; + } catch (...) { + FAIL(); } } @@ -2054,15 +2061,15 @@ TEST(Evaluator_draft4, pattern_5) { sourcemeta::blaze::default_schema_compiler); // The pattern might succeed in some standard library implementations SUCCEED(); - } catch (const sourcemeta::blaze::CompilerError &error) { - EXPECT_STREQ(error.what(), - "Invalid regular expression: ^[a-zA-Z0-9\\/\\_]{1,32}$"); + } catch (const sourcemeta::blaze::CompilerInvalidRegexError &error) { + EXPECT_STREQ(error.what(), "Invalid regular expression"); + EXPECT_EQ(error.regex(), "^[a-zA-Z0-9\\/\\_]{1,32}$"); EXPECT_EQ(error.location(), sourcemeta::core::Pointer({"properties", "foo", "pattern"})); EXPECT_EQ(error.base().recompose(), ""); SUCCEED(); - } catch (const std::exception &) { - FAIL() << "The compile function was expected to throw a schema error"; + } catch (...) { + FAIL(); } } @@ -2083,14 +2090,14 @@ TEST(Evaluator_draft4, pattern_6) { sourcemeta::blaze::default_schema_compiler); // The pattern might succeed in some standard library implementations SUCCEED(); - } catch (const sourcemeta::blaze::CompilerError &error) { - EXPECT_STREQ(error.what(), - "Invalid regular expression: ^[a-zA-Z0-9\\/\\_]{1,32}$"); + } catch (const sourcemeta::blaze::CompilerInvalidRegexError &error) { + EXPECT_STREQ(error.what(), "Invalid regular expression"); + EXPECT_EQ(error.regex(), "^[a-zA-Z0-9\\/\\_]{1,32}$"); EXPECT_EQ(error.location(), sourcemeta::core::Pointer({"pattern"})); EXPECT_EQ(error.base().recompose(), "https://nested.com"); SUCCEED(); - } catch (const std::exception &) { - FAIL() << "The compile function was expected to throw a schema error"; + } catch (...) { + FAIL(); } } @@ -2391,15 +2398,15 @@ TEST(Evaluator_draft4, patternProperties_9) { sourcemeta::blaze::default_schema_compiler); // The pattern might succeed in some standard library implementations SUCCEED(); - } catch (const sourcemeta::blaze::CompilerError &error) { - EXPECT_STREQ(error.what(), - "Invalid regular expression: ^[a-zA-Z0-9\\_\\.\\-]*$"); + } catch (const sourcemeta::blaze::CompilerInvalidRegexError &error) { + EXPECT_STREQ(error.what(), "Invalid regular expression"); + EXPECT_EQ(error.regex(), "^[a-zA-Z0-9\\_\\.\\-]*$"); EXPECT_EQ(error.location(), sourcemeta::core::Pointer({"patternProperties"})); EXPECT_EQ(error.base().recompose(), ""); SUCCEED(); - } catch (const std::exception &) { - FAIL() << "The compile function was expected to throw a schema error"; + } catch (...) { + FAIL(); } } diff --git a/test/linter/linter_schema_test.cc b/test/linter/linter_schema_test.cc index 51bf7838b..1a04c9e9f 100644 --- a/test/linter/linter_schema_test.cc +++ b/test/linter/linter_schema_test.cc @@ -299,12 +299,19 @@ TEST(Linter, schema_rule_non_string_title_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNameError &error) { + EXPECT_EQ(error.identifier(), "123"); + EXPECT_STREQ(error.what(), "The schema rule title is not a string"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_uppercase_title_throws) { @@ -314,12 +321,21 @@ TEST(Linter, schema_rule_uppercase_title_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNamePatternError &error) { + EXPECT_EQ(error.identifier(), "Test/Rule"); + EXPECT_STREQ(error.what(), + "The schema rule name does not match the required pattern"); + EXPECT_EQ(error.regex(), "^[a-z0-9_/]+$"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_space_in_title_throws) { @@ -329,12 +345,21 @@ TEST(Linter, schema_rule_space_in_title_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNamePatternError &error) { + EXPECT_EQ(error.identifier(), "test rule"); + EXPECT_STREQ(error.what(), + "The schema rule name does not match the required pattern"); + EXPECT_EQ(error.regex(), "^[a-z0-9_/]+$"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_empty_title_throws) { @@ -344,12 +369,19 @@ TEST(Linter, schema_rule_empty_title_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNameError &error) { + EXPECT_EQ(error.identifier(), ""); + EXPECT_STREQ(error.what(), "The schema rule name must not be empty"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_valid_title_with_digits_and_underscores) { @@ -399,10 +431,14 @@ TEST(Linter, schema_rule_invalid_name_error_preserves_name) { rule_schema, sourcemeta::core::schema_walker, sourcemeta::core::schema_resolver, sourcemeta::blaze::default_schema_compiler); - FAIL() << "Expected LinterInvalidNameError"; - } catch (const sourcemeta::blaze::LinterInvalidNameError &error) { + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNamePatternError &error) { EXPECT_EQ(error.identifier(), "Bad Name!"); - EXPECT_STREQ(error.what(), "The schema rule name must match ^[a-z0-9_/]+$"); + EXPECT_STREQ(error.what(), + "The schema rule name does not match the required pattern"); + EXPECT_EQ(error.regex(), "^[a-z0-9_/]+$"); + } catch (...) { + FAIL(); } } @@ -418,9 +454,11 @@ TEST(Linter, schema_rule_missing_title_error_message) { rule_schema, sourcemeta::core::schema_walker, sourcemeta::core::schema_resolver, sourcemeta::blaze::default_schema_compiler); - FAIL() << "Expected LinterMissingNameError"; + FAIL(); } catch (const sourcemeta::blaze::LinterMissingNameError &error) { EXPECT_STREQ(error.what(), "The schema rule is missing a title"); + } catch (...) { + FAIL(); } } @@ -431,12 +469,21 @@ TEST(Linter, schema_rule_title_with_hyphen_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNamePatternError &error) { + EXPECT_EQ(error.identifier(), "my-rule"); + EXPECT_STREQ(error.what(), + "The schema rule name does not match the required pattern"); + EXPECT_EQ(error.regex(), "^[a-z0-9_/]+$"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_title_with_dot_throws) { @@ -446,12 +493,21 @@ TEST(Linter, schema_rule_title_with_dot_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNamePatternError &error) { + EXPECT_EQ(error.identifier(), "my.rule"); + EXPECT_STREQ(error.what(), + "The schema rule name does not match the required pattern"); + EXPECT_EQ(error.regex(), "^[a-z0-9_/]+$"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_title_only_digits) { @@ -880,12 +936,21 @@ TEST(Linter, schema_rule_title_with_special_chars_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNamePatternError &error) { + EXPECT_EQ(error.identifier(), "test@rule#1"); + EXPECT_STREQ(error.what(), + "The schema rule name does not match the required pattern"); + EXPECT_EQ(error.regex(), "^[a-z0-9_/]+$"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_title_boolean_throws) { @@ -895,12 +960,19 @@ TEST(Linter, schema_rule_title_boolean_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNameError &error) { + EXPECT_EQ(error.identifier(), "true"); + EXPECT_STREQ(error.what(), "The schema rule title is not a string"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_title_null_throws) { @@ -910,12 +982,19 @@ TEST(Linter, schema_rule_title_null_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNameError &error) { + EXPECT_EQ(error.identifier(), "null"); + EXPECT_STREQ(error.what(), "The schema rule title is not a string"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_title_array_throws) { @@ -925,12 +1004,19 @@ TEST(Linter, schema_rule_title_array_throws) { "type": "object" })JSON")}; - sourcemeta::core::SchemaTransformer bundle; - EXPECT_THROW(bundle.add( - rule_schema, sourcemeta::core::schema_walker, - sourcemeta::core::schema_resolver, - sourcemeta::blaze::default_schema_compiler), - sourcemeta::blaze::LinterInvalidNameError); + try { + sourcemeta::core::SchemaTransformer bundle; + bundle.add( + rule_schema, sourcemeta::core::schema_walker, + sourcemeta::core::schema_resolver, + sourcemeta::blaze::default_schema_compiler); + FAIL(); + } catch (const sourcemeta::blaze::LinterInvalidNameError &error) { + EXPECT_EQ(error.identifier(), "[\"foo\"]"); + EXPECT_STREQ(error.what(), "The schema rule title is not a string"); + } catch (...) { + FAIL(); + } } TEST(Linter, schema_rule_property_names_pattern_fail) {