| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #include <jvalidate/validation_visitor.h>
- #include <gmock/gmock.h>
- #include <gtest/gtest.h>
- #include <json/value.h>
- #include <jvalidate/adapters/jsoncpp.h>
- #include <jvalidate/constraint/general_constraint.h>
- #include <jvalidate/detail/pointer.h>
- #include <jvalidate/enum.h>
- #include <jvalidate/regex.h>
- #include <jvalidate/schema.h>
- #include <jvalidate/validator.h>
- #include "matchers.h"
- using enum jvalidate::schema::Version;
- using jvalidate::Status;
- using enum jvalidate::adapter::Type;
- using jvalidate::adapter::JsonCppAdapter;
- using testing::Eq;
- namespace jvalidate {
- class ValidationVisitorTest : public testing::Test {
- protected:
- template <typename JSON = Json::Value const>
- auto visit(jvalidate::detail::Pointer ptr, auto const & cons, JSON & json,
- jvalidate::ValidationResult * result = nullptr, bool annotate_everything = false) {
- JsonCppAdapter const adapter(json);
- ValidationVisitor visitor(node_, adapter, cfg_, regex_, format_, extension_, result);
- if (annotate_everything) {
- visitor.tracking_ = StoreResults::ForAnything;
- }
- visitor.schema_path_ = ptr;
- return visitor.visit(cons, adapter);
- }
- template <typename JSON = Json::Value const>
- auto visit(jvalidate::Not<jvalidate::detail::Pointer> auto const & cons, JSON & json,
- jvalidate::ValidationResult * result = nullptr, bool annotate_everything = false) {
- return visit({}, cons, json, result, annotate_everything);
- }
- void config(jvalidate::ValidationConfig cfg) { cfg_ = cfg; }
- void format(FormatValidator::UserDefinedFormats && fmts) {
- format_ = {std::move(fmts), jvalidate::StdRegexEngine::is_regex};
- }
- private:
- jvalidate::schema::Node node_;
- jvalidate::StdRegexEngine regex_;
- jvalidate::FormatValidator format_{jvalidate::StdRegexEngine::is_regex};
- jvalidate::ValidationConfig cfg_;
- jvalidate::detail::StubExtensionVisitor extension_;
- };
- TEST_F(ValidationVisitorTest, StubExtensionIsNoop) {
- constraint::ExtensionConstraint cons;
- EXPECT_THAT(visit(cons, {}), Eq(Status::Noop));
- }
- TEST_F(ValidationVisitorTest, StubExtensionAnnotates) {
- constraint::ExtensionConstraint cons;
- ValidationResult result;
- visit("/extension"_jptr, cons, {}, &result);
- EXPECT_THAT(result, AnnotationAt("extension", "unsupported extension"));
- }
- TEST_F(ValidationVisitorTest, TypeMatchesType) {
- constraint::TypeConstraint cons{{Integer}};
- EXPECT_THAT(visit(cons, "5"_json), Eq(Status::Accept));
- }
- TEST_F(ValidationVisitorTest, TypeNumberMatchesInteger) {
- constraint::TypeConstraint cons{{Number}};
- EXPECT_THAT(visit(cons, "5"_json), Eq(Status::Accept));
- }
- TEST_F(ValidationVisitorTest, TypeIntegerMatchesWholeDecimal) {
- constraint::TypeConstraint cons{{Integer}};
- // JsonCppAdapter follows the convention of implicitly treating whole doubles
- // that fit in int64s as integer type, but the specification allows for much
- // wider integers than that as far as TypeConstraint is concerned.
- EXPECT_THAT(visit(cons, "10000000000000000000.0"_json), Eq(Status::Accept));
- }
- TEST_F(ValidationVisitorTest, TypeIntegerDoesNotMatchFractional) {
- constraint::TypeConstraint cons{{Integer}};
- EXPECT_THAT(visit(cons, "5.2"_json), Eq(Status::Reject));
- }
- TEST_F(ValidationVisitorTest, ConstConstraintCanPerformStrictOrLooseEquality) {
- constraint::ConstConstraint cons{JsonCppAdapter("\"true\""_json).freeze()};
- config({.strict_equality = false});
- EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Accept));
- config({.strict_equality = true});
- EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Reject));
- }
- TEST_F(ValidationVisitorTest, EnumConstraintCanPerformStrictOrLooseEquality) {
- constraint::EnumConstraint cons;
- cons.enumeration.push_back(JsonCppAdapter("\"true\""_json).freeze());
- config({.strict_equality = false});
- EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Accept));
- config({.strict_equality = true});
- EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Reject));
- }
- TEST_F(ValidationVisitorTest, EnumConstraintAnnotatesMatchingIndex) {
- constraint::EnumConstraint cons;
- cons.enumeration.push_back(JsonCppAdapter("\"true\""_json).freeze());
- cons.enumeration.push_back(JsonCppAdapter("true"_json).freeze());
- ValidationResult result;
- visit("/enum"_jptr, cons, "true"_json, &result, true);
- EXPECT_THAT(result, ErrorAt("enum", "1"));
- }
- TEST_F(ValidationVisitorTest, UnknownFormatIsAccept) {
- constraint::FormatConstraint cons{"bogus", Draft2020_12, true};
- config({.validate_format = true});
- ValidationResult result;
- EXPECT_THAT(visit("/format"_jptr, cons, "\"Hello\""_json, &result), Eq(Status::Accept));
- }
- TEST_F(ValidationVisitorTest, UnimplementedFormatIsError) {
- constraint::FormatConstraint cons{"bogus", Draft2020_12, true};
- config({.validate_format = true});
- format({{"bogus", nullptr}});
- ValidationResult result;
- EXPECT_THAT(visit("/format"_jptr, cons, "\"Hello\""_json, &result), Eq(Status::Reject));
- EXPECT_THAT(result, ErrorAt("format", "unimplemented format 'bogus'"));
- }
- }
- #if !defined(JVALIDATE_MONOTEST)
- int main(int argc, char ** argv) {
- testing::InitGoogleMock(&argc, argv);
- return RUN_ALL_TESTS();
- }
- #endif
|