Explorar o código

test/refactor: begin developing annotation tests

Sam Jaffe hai 1 ano
pai
achega
f33b6308af

+ 6 - 1
Makefile

@@ -22,7 +22,7 @@ HEADERS := $(shell find $(INCLUDE_DIR) -name *.h)
 TEST_HEADERS := $(wildcard $(TEST_DIR)*.h)
 TEST_SOURCES := $(wildcard $(TEST_DIR)*.cxx)
 TEST_OBJECTS := $(patsubst %.cxx, .build/%.o, $(TEST_SOURCES))
-TEST_BINARIES := .build/bin/selfvalidate
+TEST_BINARIES := .build/bin/selfvalidate .build/bin/annotation_test
 
 EXCLUDED_TESTS := format* content ecmascript_regex zeroTerminatedFloats
 EXCLUDED_TESTS := $(shell printf ":*optional_%s" $(EXCLUDED_TESTS) | cut -c2-)
@@ -41,6 +41,7 @@ test: $(TEST_BINARIES)
 run-test: test
 run-test:
 	.build/bin/selfvalidate --gtest_filter=-$(EXCLUDED_TESTS) $(CLEAN_ANSI)
+	.build/bin/annotation_test $(CLEAN_ANSI)
 
 .build/tests/%.o: tests/%.cxx $(HEADERS) $(TEST_HEADERS)
 	@ mkdir -p .build/tests
@@ -50,3 +51,7 @@ run-test:
 .build/bin/selfvalidate: .build/tests/selfvalidate_test.o
 	@ mkdir -p .build/bin
 	$(CXX) $< -o $@ $(LD_FLAGS) -ljsoncpp -lgmock -lcurl -lgtest
+
+.build/bin/annotation_test: .build/tests/annotation_test.o
+	@ mkdir -p .build/bin
+	$(CXX) $< -o $@ $(LD_FLAGS) -ljsoncpp -lgmock -lgtest

+ 18 - 0
include/jvalidate/validation_result.h

@@ -32,6 +32,24 @@ public:
     return os;
   }
 
+  bool has_annotation(detail::Pointer const & where, detail::Pointer const & schema_path) const {
+    return annotation(where, schema_path) != nullptr;
+  }
+
+  bool has_annotation(detail::Pointer const & where) const { return annotations_.contains(where); }
+
+  std::string const * annotation(detail::Pointer const & where,
+                                 detail::Pointer const & schema_path) const {
+    if (not annotations_.contains(where)) {
+      return nullptr;
+    }
+    auto const & anno = annotations_.at(where);
+    if (not anno.contains(schema_path)) {
+      return nullptr;
+    }
+    return &anno.at(schema_path);
+  }
+
 private:
   void annotate(ValidationResult && result) {
     for (auto const & [where, errors] : result.annotations_) {

+ 72 - 0
tests/annotation_test.cxx

@@ -0,0 +1,72 @@
+#include "gmock/gmock-matchers.h"
+#include <string_view>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <jvalidate/adapter.h>
+#include <jvalidate/adapters/jsoncpp.h>
+#include <jvalidate/detail/pointer.h>
+#include <jvalidate/enum.h>
+#include <jvalidate/schema.h>
+#include <jvalidate/status.h>
+#include <jvalidate/uri.h>
+#include <jvalidate/validation_result.h>
+#include <jvalidate/validator.h>
+
+#include <json/reader.h>
+#include <json/value.h>
+
+using enum jvalidate::schema::Version;
+
+auto operator""_jptr(char const * data, size_t len) {
+  return jvalidate::detail::Pointer(std::string_view{data, len});
+}
+
+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;
+}
+
+MATCHER_P(HasAnnotationsFor, doc_path, "") { return arg.has_annotation(doc_path); }
+
+MATCHER_P2(HasAnnotationAt, doc_path, schema_path, "") {
+  return arg.has_annotation(doc_path, schema_path);
+}
+
+MATCHER_P3(AnnotationAt, doc_path, schema_path, matcher, "") {
+  auto const * anno = arg.annotation(doc_path, schema_path);
+  if (not anno) {
+    return false;
+  }
+  return testing::ExplainMatchResult(matcher, *anno, result_listener);
+}
+
+TEST(Annotation, AttachesFormattingAnnotation) {
+  jvalidate::Schema const schema(R"({
+    "format": "uri"
+  })"_json,
+                                 Draft2020_12);
+
+  auto const instance = R"("http://json-schema.org")"_json;
+
+  jvalidate::ValidationResult result;
+  bool const valid = jvalidate::Validator(schema).validate(instance, &result);
+
+  EXPECT_TRUE(valid);
+  EXPECT_THAT(result, AnnotationAt(""_jptr, "/format"_jptr, "format 'uri'"));
+}
+
+int main(int argc, char ** argv) {
+  testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}

+ 34 - 0
tests/custom_filter.h

@@ -0,0 +1,34 @@
+#pragma once
+
+#include <algorithm>
+#include <regex>
+#include <string>
+#include <vector>
+
+class Glob {
+private:
+  std::regex re_;
+
+public:
+  explicit Glob(std::string glob) {
+    for (size_t i = glob.find('.'); i != std::string::npos; i = glob.find('.', i + 2)) {
+      glob.insert(glob.begin() + i, '\\');
+    }
+    for (size_t i = glob.find('*'); i != std::string::npos; i = glob.find('*', i + 2)) {
+      glob.insert(glob.begin() + i, '.');
+    }
+    re_ = std::regex(glob);
+  }
+
+  bool operator==(std::string const & str) const { return std::regex_search(str, re_); }
+};
+
+struct RecursiveTestFilter {
+  std::vector<Glob> whitelist;
+  std::vector<Glob> blacklist;
+
+  bool accepts(std::string const & str) const {
+    return std::count(blacklist.begin(), blacklist.end(), str) == 0 and
+           (whitelist.empty() or std::count(whitelist.begin(), whitelist.end(), str) > 0);
+  }
+};

+ 2 - 29
tests/selfvalidate_test.cxx

@@ -22,40 +22,13 @@
 #include <json/value.h>
 #include <json/writer.h>
 
+#include "./custom_filter.h"
 #include "./json_schema_test_suite.h"
 
 using jvalidate::schema::Version;
 
 using testing::TestWithParam;
 
-class Glob {
-private:
-  std::regex re_;
-
-public:
-  explicit Glob(std::string glob) {
-    for (size_t i = glob.find('.'); i != std::string::npos; i = glob.find('.', i + 2)) {
-      glob.insert(glob.begin() + i, '\\');
-    }
-    for (size_t i = glob.find('*'); i != std::string::npos; i = glob.find('*', i + 2)) {
-      glob.insert(glob.begin() + i, '.');
-    }
-    re_ = std::regex(glob);
-  }
-
-  bool operator==(std::string const & str) const { return std::regex_search(str, re_); }
-};
-
-struct RecursiveTestFilter {
-  std::vector<Glob> whitelist;
-  std::vector<Glob> blacklist;
-
-  bool accepts(std::string const & str) const {
-    return std::count(blacklist.begin(), blacklist.end(), str) == 0 and
-      (whitelist.empty() or std::count(whitelist.begin(), whitelist.end(), str) > 0);
-  }
-};
-
 bool load_stream(std::istream & in, Json::Value & out) {
   Json::CharReaderBuilder builder;
   std::string error;
@@ -124,7 +97,7 @@ protected:
         tokens[i - 1] += tokens[i];
         tokens.erase(tokens.begin() + i);
       }
-      for (auto &tok : tokens) {
+      for (auto & tok : tokens) {
         into.emplace_back(tok);
       }
     };