#include #include #include #include #include #include #include #include #include #include #include using jvalidate::Status; using testing::Eq; 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; } struct IsKeyOfConstraint : jvalidate::extension::ConstraintBase { IsKeyOfConstraint(std::string_view ptr) : ptr(ptr) { EXPECT_M(ptr.find('/') != std::string_view::npos, "IsKeyOfConstraint requires a value-relative-pointer, not a key-relative-pointer"); } jvalidate::detail::RelativePointer ptr; }; template class Visitor : public jvalidate::extension::Visitor, IsKeyOfConstraint> { public: Visitor(A const & root_document) : root_document_(root_document) {} template Status visit(IsKeyOfConstraint const & cons, A2 const & document, auto const & validator) const { auto const & object = std::get<1>(cons.ptr.inspect(validator.where_, root_document_)).as_object(); if (object.find(document.as_string()) != object.end()) { return Status::Accept; } return Status::Reject; } private: A const & root_document_; }; TEST(ExtensionConstraint, CanExtend) { jvalidate::schema::Node schema; jvalidate::detail::StdRegexEngine re; auto json = R"({ "nodes": { "A": {}, "B": {} }, "edges": [ { "source": "A", "destination": "B" } ] })"_json; using Adapter = jvalidate::adapter::JsonCppAdapter; Adapter document = json; jvalidate::ValidationVisitor validator(schema, {}, re, Visitor(document), nullptr); jvalidate::constraint::ExtensionConstraint cons{std::make_unique("1/nodes")}; EXPECT_THAT(validator.visit(cons, Adapter(json["edges"][0]["source"])), Eq(Status::Accept)); EXPECT_THAT(validator.visit(cons, Adapter(json["edges"][0]["destination"])), Eq(Status::Accept)); } int main(int argc, char ** argv) { testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); }