#include "gmock/gmock-matchers.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using enum jvalidate::schema::Version; using testing::Not; auto operator""_jptr(char const * data, size_t len) { return jvalidate::detail::Pointer(std::string_view{data, len}); } Json::Value operator""_json(char const * data, size_t len) { Json::Value value; Json::CharReaderBuilder builder; std::unique_ptr reader(builder.newCharReader()); std::string error; if (not reader->parse(data, data + len, &value, &error)) { throw std::runtime_error(error); } return value; } auto validate(Json::Value const & schema_doc, Json::Value const & instance_doc, jvalidate::schema::Version version = Draft2020_12) { jvalidate::Schema const schema(schema_doc, version); jvalidate::ValidationResult result; (void)jvalidate::Validator(schema).validate(instance_doc, &result); return result; } MATCHER_P(HasAnnotationsFor, doc_path, "") { return arg.has_annotation(doc_path); } MATCHER_P2(HasAnnotationAt, doc_path, schema_path, "") { return arg.has_annotation(doc_path, schema_path); } MATCHER_P3(AnnotationAt, doc_path, schema_path, matcher, "") { auto const * anno = arg.annotation(doc_path, schema_path); if (not anno) { return false; } return testing::ExplainMatchResult(matcher, *anno, result_listener); } TEST(Annotation, AttachesFormattingAnnotation) { auto const schema = R"({ "format": "uri" })"_json; auto const instance = R"("http://json-schema.org")"_json; jvalidate::ValidationResult result = validate(schema, instance); EXPECT_THAT(result, AnnotationAt(""_jptr, "/format"_jptr, "format 'uri'")); } TEST(Annotation, AnnotatesErrors) { auto const schema = R"({ "minimum": 5 })"_json; auto const instance = R"(4)"_json; jvalidate::ValidationResult result = validate(schema, instance); EXPECT_THAT(result, AnnotationAt(""_jptr, "/minimum"_jptr, "4 < 5")); } TEST(Annotation, DoesNotAnnotatesValid) { auto const schema = R"({ "minimum": 5 })"_json; auto const instance = R"(6)"_json; jvalidate::ValidationResult result = validate(schema, instance); EXPECT_THAT(result, Not(HasAnnotationsFor(""_jptr))); } TEST(Annotation, NotSchemaFlipsAnnotationRule) { auto const schema = R"({ "not": { "minimum": 5 } })"_json; auto const instance = R"(6)"_json; jvalidate::ValidationResult result = validate(schema, instance); EXPECT_THAT(result, AnnotationAt(""_jptr, "/not/minimum"_jptr, "6 >= 5")); } TEST(Annotation, PathFollowsSchemaNotObject) { auto const schema = R"({ "disallow": "string" })"_json; auto const instance = R"("hello")"_json; jvalidate::ValidationResult result = validate(schema, instance, Draft03); EXPECT_THAT(result, AnnotationAt(""_jptr, "/disallow"_jptr, "type (string) is one of [string]")); } int main(int argc, char ** argv) { testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); }