validation_visitor_test.cxx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include <jvalidate/validation_visitor.h>
  2. #include <utility>
  3. #include <gmock/gmock.h>
  4. #include <gtest/gtest.h>
  5. #include <json/value.h>
  6. #include <jvalidate/adapters/jsoncpp.h>
  7. #include <jvalidate/constraint/extension_constraint.h>
  8. #include <jvalidate/constraint/general_constraint.h>
  9. #include <jvalidate/constraint/string_constraint.h>
  10. #include <jvalidate/detail/pointer.h>
  11. #include <jvalidate/enum.h>
  12. #include <jvalidate/forward.h>
  13. #include <jvalidate/regex.h>
  14. #include <jvalidate/schema.h>
  15. #include <jvalidate/status.h>
  16. #include <jvalidate/validation_config.h>
  17. #include <jvalidate/validation_result.h>
  18. #include <jvalidate/validator.h>
  19. #include "./matchers.h"
  20. using enum jvalidate::schema::Version;
  21. using jvalidate::Status;
  22. using enum jvalidate::adapter::Type;
  23. using jvalidate::adapter::JsonCppAdapter;
  24. using testing::Eq;
  25. namespace jvalidate {
  26. class ValidationVisitorTest : public testing::Test {
  27. protected:
  28. auto visit(jvalidate::detail::Pointer ptr, auto const & cons, Json::Value const & json,
  29. jvalidate::ValidationResult * result = nullptr, bool annotate_everything = false) {
  30. JsonCppAdapter const adapter(json);
  31. ValidationVisitor visitor(node_, adapter, cfg_, regex_, extension_, result);
  32. if (annotate_everything) {
  33. visitor.tracking_ = StoreResults::ForAnything;
  34. }
  35. visitor.schema_path_ = std::move(ptr);
  36. return visitor.visit(cons, adapter);
  37. }
  38. auto visit(jvalidate::Not<jvalidate::detail::Pointer> auto const & cons, Json::Value const & json,
  39. jvalidate::ValidationResult * result = nullptr, bool annotate_everything = false) {
  40. return visit({}, cons, json, result, annotate_everything);
  41. }
  42. void config(jvalidate::ValidationConfig cfg) { cfg_ = cfg; }
  43. private:
  44. jvalidate::schema::Node node_;
  45. jvalidate::StdRegexEngine regex_;
  46. jvalidate::ValidationConfig cfg_;
  47. jvalidate::detail::StubExtensionVisitor extension_;
  48. };
  49. TEST_F(ValidationVisitorTest, StubExtensionIsNoop) {
  50. constraint::ExtensionConstraint cons;
  51. EXPECT_THAT(visit(cons, {}), Eq(Status::Noop));
  52. }
  53. TEST_F(ValidationVisitorTest, StubExtensionAnnotates) {
  54. constraint::ExtensionConstraint cons;
  55. ValidationResult result;
  56. visit("/extension"_jptr, cons, {}, &result);
  57. EXPECT_THAT(result, AnnotationAt("extension", "unsupported extension"));
  58. }
  59. TEST_F(ValidationVisitorTest, TypeMatchesType) {
  60. constraint::TypeConstraint cons{{Integer}};
  61. EXPECT_THAT(visit(cons, "5"_json), Eq(Status::Accept));
  62. }
  63. TEST_F(ValidationVisitorTest, TypeNumberMatchesInteger) {
  64. constraint::TypeConstraint cons{{Number}};
  65. EXPECT_THAT(visit(cons, "5"_json), Eq(Status::Accept));
  66. }
  67. TEST_F(ValidationVisitorTest, TypeIntegerMatchesWholeDecimal) {
  68. constraint::TypeConstraint cons{{Integer}};
  69. // JsonCppAdapter follows the convention of implicitly treating whole doubles
  70. // that fit in int64s as integer type, but the specification allows for much
  71. // wider integers than that as far as TypeConstraint is concerned.
  72. EXPECT_THAT(visit(cons, "10000000000000000000.0"_json), Eq(Status::Accept));
  73. }
  74. TEST_F(ValidationVisitorTest, TypeIntegerDoesNotMatchFractional) {
  75. constraint::TypeConstraint cons{{Integer}};
  76. EXPECT_THAT(visit(cons, "5.2"_json), Eq(Status::Reject));
  77. }
  78. TEST_F(ValidationVisitorTest, ConstConstraintCanPerformStrictOrLooseEquality) {
  79. constraint::ConstConstraint cons{JsonCppAdapter("\"true\""_json).freeze()};
  80. config({.strict_equality = false});
  81. EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Accept));
  82. config({.strict_equality = true});
  83. EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Reject));
  84. }
  85. TEST_F(ValidationVisitorTest, EnumConstraintCanPerformStrictOrLooseEquality) {
  86. constraint::EnumConstraint cons;
  87. cons.enumeration.push_back(JsonCppAdapter("\"true\""_json).freeze());
  88. config({.strict_equality = false});
  89. EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Accept));
  90. config({.strict_equality = true});
  91. EXPECT_THAT(visit(cons, "true"_json), Eq(Status::Reject));
  92. }
  93. TEST_F(ValidationVisitorTest, EnumConstraintAnnotatesMatchingIndex) {
  94. constraint::EnumConstraint cons;
  95. cons.enumeration.push_back(JsonCppAdapter("\"true\""_json).freeze());
  96. cons.enumeration.push_back(JsonCppAdapter("true"_json).freeze());
  97. ValidationResult result;
  98. visit("/enum"_jptr, cons, "true"_json, &result, true);
  99. EXPECT_THAT(result, ErrorAt("enum", "1"));
  100. }
  101. TEST_F(ValidationVisitorTest, UnimplementedFormatIsError) {
  102. constraint::FormatConstraint cons{.format = "bogus", .is_assertion = true};
  103. config({.validate_format = true});
  104. ValidationResult result;
  105. EXPECT_THAT(visit("/format"_jptr, cons, "\"Hello\""_json, &result), Eq(Status::Reject));
  106. EXPECT_THAT(result, ErrorAt("format", "bogus is unimplemented"));
  107. }
  108. }
  109. #if !defined(JVALIDATE_MONOTEST)
  110. int main(int argc, char ** argv) {
  111. testing::InitGoogleMock(&argc, argv);
  112. return RUN_ALL_TESTS();
  113. }
  114. #endif