extension_test.cxx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include <jvalidate/extension.h>
  2. #include <string_view>
  3. #include <gmock/gmock.h>
  4. #include <gtest/gtest.h>
  5. #include <json/value.h>
  6. #include <jvalidate/adapters/jsoncpp.h> // IWYU pragma: keep
  7. #include <jvalidate/constraint/extension_constraint.h>
  8. #include <jvalidate/detail/expect.h>
  9. #include <jvalidate/detail/relative_pointer.h>
  10. #include <jvalidate/forward.h>
  11. #include <jvalidate/status.h>
  12. #include <jvalidate/validator.h>
  13. #include "matchers.h"
  14. using enum jvalidate::schema::Version;
  15. using jvalidate::Status;
  16. using jvalidate::constraint::ExtensionConstraint;
  17. using testing::Not;
  18. struct IsKeyOfConstraint : jvalidate::extension::ConstraintBase<IsKeyOfConstraint> {
  19. explicit IsKeyOfConstraint(std::string_view ptr) : ptr(ptr) {
  20. EXPECT_M(ptr.find('/') != std::string_view::npos,
  21. "IsKeyOfConstraint requires a value-relative-pointer, not a key-relative-pointer");
  22. }
  23. jvalidate::detail::RelativePointer ptr;
  24. };
  25. class Visitor : public jvalidate::extension::Visitor<Visitor, IsKeyOfConstraint> {
  26. public:
  27. template <jvalidate::Adapter A2>
  28. Status visit(IsKeyOfConstraint const & cons, A2 const & document, auto const & validator) const {
  29. validator.annotate(cons.ptr);
  30. auto const & object =
  31. std::get<1>(cons.ptr.inspect(validator.where(), validator.root())).as_object();
  32. if (object.find(document.as_string()) != object.end()) {
  33. return Status::Accept;
  34. }
  35. return Status::Reject;
  36. }
  37. };
  38. namespace {
  39. auto validate(Json::Value const & schema_doc, Json::Value const & instance_doc,
  40. jvalidate::schema::Version version = Draft2020_12) {
  41. using A = jvalidate::adapter::AdapterFor<Json::Value const>;
  42. jvalidate::ConstraintFactory<A> factory{{"is_key_of", [](auto const & context) {
  43. return ExtensionConstraint::make<IsKeyOfConstraint>(
  44. context.schema.as_string());
  45. }}};
  46. jvalidate::Schema const schema(schema_doc, version, factory);
  47. jvalidate::ValidationResult result;
  48. (void)jvalidate::Validator(schema, Visitor()).validate(instance_doc, &result);
  49. return result;
  50. }
  51. }
  52. TEST(ExtensionConstraintTest, CanReportSuccess) {
  53. auto schema = R"({
  54. "properties": {
  55. "nodes": {
  56. "type": "object"
  57. },
  58. "edges": {
  59. "items": {
  60. "properties": {
  61. "destination": {
  62. "is_key_of": "3/nodes",
  63. "type": "string"
  64. },
  65. "source": {
  66. "is_key_of": "3/nodes",
  67. "type": "string"
  68. }
  69. },
  70. "type": "object"
  71. },
  72. "type": "array"
  73. }
  74. },
  75. "type": "object"
  76. })"_json;
  77. auto instance = R"({
  78. "nodes": {
  79. "A": {},
  80. "B": {}
  81. },
  82. "edges": [
  83. { "source": "A", "destination": "B" }
  84. ]
  85. })"_json;
  86. jvalidate::ValidationResult result = validate(schema, instance);
  87. EXPECT_THAT(result, Valid());
  88. }
  89. TEST(ExtensionConstraintTest, CanReportFailure) {
  90. auto schema = R"({
  91. "properties": {
  92. "nodes": {
  93. "type": "object"
  94. },
  95. "edges": {
  96. "items": {
  97. "properties": {
  98. "destination": {
  99. "is_key_of": "3/nodes",
  100. "type": "string"
  101. },
  102. "source": {
  103. "is_key_of": "3/nodes",
  104. "type": "string"
  105. }
  106. },
  107. "type": "object"
  108. },
  109. "type": "array"
  110. }
  111. },
  112. "type": "object"
  113. })"_json;
  114. auto instance = R"({
  115. "nodes": {
  116. "A": {},
  117. "B": {}
  118. },
  119. "edges": [
  120. { "source": "A", "destination": "C" }
  121. ]
  122. })"_json;
  123. jvalidate::ValidationResult result = validate(schema, instance);
  124. EXPECT_THAT(result, Not(Valid()));
  125. }
  126. #if !defined(JVALIDATE_MONOTEST)
  127. int main(int argc, char ** argv) {
  128. testing::InitGoogleMock(&argc, argv);
  129. return RUN_ALL_TESTS();
  130. }
  131. #endif