|
|
@@ -0,0 +1,86 @@
|
|
|
+#include <jvalidate/constraint/extension_constraint.h>
|
|
|
+#include <jvalidate/detail/expect.h>
|
|
|
+#include <jvalidate/extension.h>
|
|
|
+
|
|
|
+#include <gmock/gmock.h>
|
|
|
+#include <gtest/gtest.h>
|
|
|
+
|
|
|
+#include <json/reader.h>
|
|
|
+#include <json/value.h>
|
|
|
+
|
|
|
+#include <jvalidate/adapters/jsoncpp.h>
|
|
|
+#include <jvalidate/detail/relative_pointer.h>
|
|
|
+#include <jvalidate/status.h>
|
|
|
+#include <jvalidate/validator.h>
|
|
|
+
|
|
|
+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<Json::CharReader> 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> {
|
|
|
+ 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 <jvalidate::Adapter A>
|
|
|
+class Visitor : public jvalidate::extension::Visitor<Visitor<A>, IsKeyOfConstraint> {
|
|
|
+public:
|
|
|
+ Visitor(A const & root_document) : root_document_(root_document) {}
|
|
|
+
|
|
|
+ template <jvalidate::Adapter A2>
|
|
|
+ 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<Json::Value>;
|
|
|
+ Adapter document = json;
|
|
|
+
|
|
|
+ jvalidate::ValidationVisitor validator(schema, {}, re, Visitor(document), nullptr);
|
|
|
+ jvalidate::constraint::ExtensionConstraint cons{std::make_unique<IsKeyOfConstraint>("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();
|
|
|
+}
|