| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- #include <gmock/gmock.h>
- #include <gtest/gtest.h>
- #include <jvalidate/adapter.h>
- #include <jvalidate/adapters/jsoncpp.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 <sstream>
- #include "matchers.h"
- using enum jvalidate::schema::Version;
- using testing::Not;
- static auto validate(Json::Value const & schema_doc, Json::Value const & instance_doc,
- jvalidate::schema::Version version = Draft2020_12) {
- jvalidate::Schema const schema(schema_doc, version);
- jvalidate::ValidationResult result;
- (void)jvalidate::Validator(schema).validate(instance_doc, &result);
- return result;
- }
- TEST(AnnotationTest, AttachesFormattingAnnotation) {
- auto const schema = R"({
- "format": "uri"
- })"_json;
- auto const instance = R"("http://json-schema.org")"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, AnnotationAt("format", "uri"));
- }
- TEST(AnnotationTest, AnnotatesAtRootSafely) {
- auto const schema = R"(false)"_json;
- auto const instance = R"(4)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt("", "always false"));
- }
- TEST(AnnotationTest, AnnotatesErrors) {
- auto const schema = R"({
- "minimum": 5
- })"_json;
- auto const instance = R"(4)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt("minimum", "4 < 5"));
- }
- TEST(AnnotationTest, AnnotatesDescription) {
- auto const schema = R"({
- "description": "lorem ipsum",
- "minimum": 5
- })"_json;
- auto const instance = R"(4)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, AnnotationAt("description", "lorem ipsum"));
- }
- TEST(AnnotationTest, CanRecordAnnotationsAsList) {
- auto const schema = R"({
- "items": false
- })"_json;
- auto const instance = R"([ 0, 1 ])"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, AnnotationAt("items", std::vector<std::string>{"0", "1"}));
- }
- TEST(AnnotationTest, OnlyErrors) {
- auto const schema = R"({
- "items": false
- })"_json;
- auto const instance = R"([ 0, 1 ])"_json;
- jvalidate::ValidationResult result = validate(schema, instance).only_errors();
- EXPECT_THAT(result, Not(HasAnnotationAt(""_jptr, ""_jptr)));
- }
- TEST(AnnotationTest, DoesNotAnnotatesValid) {
- auto const schema = R"({
- "minimum": 5
- })"_json;
- auto const instance = R"(6)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, Not(HasAnnotationsFor(""_jptr)));
- }
- TEST(AnnotationTest, NotSchemaFlipsAnnotationRule) {
- auto const schema = R"({
- "not": { "minimum": 5 }
- })"_json;
- auto const instance = R"(6)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt(""_jptr, "/not"_jptr, "minimum", "6 >= 5"));
- }
- TEST(AnnotationTest, NotSchemaPropogatesDeeply) {
- auto const schema = R"({
- "not": {
- "properties": {
- "A": {
- "enum": [ 1, 3, 4 ]
- }
- }
- }
- })"_json;
- auto const instance = R"({"A": 3})"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt("/A"_jptr, "/not/properties/A"_jptr, "enum", "1"));
- }
- TEST(AnnotationTest, PathFollowsSchemaNotConstraintModel) {
- auto const schema = R"({
- "$comment": "disallow is implemented in the form of NotConstraint[TypeConstraint]",
- "disallow": "string"
- })"_json;
- auto const instance = R"("hello")"_json;
- jvalidate::ValidationResult result = validate(schema, instance, Draft03);
- EXPECT_THAT(result, ErrorAt("disallow", "string is in types [string]"));
- }
- TEST(AnnotationTest, AttachesAlwaysFalseSensibly) {
- auto const schema = R"({
- "properties": {
- "A": false
- }
- })"_json;
- auto const instance = R"({
- "A": null
- })"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt("/A"_jptr, "/properties/A"_jptr, "", "always false"));
- }
- TEST(AnnotationTest, IfThenCanGiveABecauseReason) {
- auto const schema = R"({
- "if": {
- "properties": {
- "A": { "const": true }
- },
- "required": [ "A" ]
- },
- "then": {
- "properties": {
- "B": { "multipleOf": 3 }
- }
- },
- "else": {
- "properties": {
- "B": { "multipleOf": 5 }
- }
- }
- })"_json;
- auto const instance = R"({
- "A": true,
- "B": 4
- })"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result,
- ErrorAt(""_jptr, "/if"_jptr, "required", "contains all required properties A"));
- EXPECT_THAT(result, ErrorAt("/A"_jptr, "/if/properties/A"_jptr, "const", "matches value"));
- EXPECT_THAT(result, ErrorAt("/B"_jptr, "/then/properties/B"_jptr, "multipleOf",
- "4 is not a multiple of 3"));
- }
- TEST(AnnotationTest, IfElseCanGiveABecauseReason) {
- auto const schema = R"({
- "if": {
- "properties": {
- "A": { "const": true }
- },
- "required": [ "A" ]
- },
- "then": {
- "properties": {
- "B": { "multipleOf": 3 }
- }
- },
- "else": {
- "properties": {
- "B": { "multipleOf": 5 }
- }
- }
- })"_json;
- auto const instance = R"({
- "A": false,
- "B": 4
- })"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result,
- ErrorAt(""_jptr, "/if"_jptr, "required", "contains all required properties A"));
- EXPECT_THAT(result, ErrorAt("/A"_jptr, "/if/properties/A"_jptr, "const", "true was expected"));
- EXPECT_THAT(result, ErrorAt("/B"_jptr, "/else/properties/B"_jptr, "multipleOf",
- "4 is not a multiple of 5"));
- }
- TEST(AnnotationTest, OneOfGivesAllReasonsOnTooMany) {
- auto const schema = R"({
- "oneOf": [
- { "minimum": 5 },
- { "multipleOf": 3 },
- { "maximum": 2 }
- ]
- })"_json;
- auto const instance = R"(6)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt(""_jptr, ""_jptr, "oneOf", "validates multiple subschemas [ 0, 1 ]"));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/0"_jptr, "minimum", "6 >= 5"));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/1"_jptr, "multipleOf", "6 is a multiple of 3"));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/2"_jptr, "maximum", "6 > 2"));
- }
- TEST(AnnotationTest, OneOfGivesAllReasonsOnNoMatches) {
- auto const schema = R"({
- "oneOf": [
- { "minimum": 5 },
- { "multipleOf": 3 },
- { "maximum": 2 }
- ]
- })"_json;
- auto const instance = R"(4)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, ErrorAt(""_jptr, ""_jptr, "oneOf", "validates no subschemas"));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/0"_jptr, "minimum", "4 < 5"));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/1"_jptr, "multipleOf", "4 is not a multiple of 3"));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/2"_jptr, "maximum", "4 > 2"));
- }
- TEST(AnnotationTest, OneOfGivesAllReasonsOnMatch) {
- auto const schema = R"({
- "oneOf": [
- { "minimum": 5 },
- { "multipleOf": 3 },
- { "maximum": 2 }
- ]
- })"_json;
- auto const instance = R"(3)"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- EXPECT_THAT(result, Not(HasAnnotationAt(""_jptr, ""_jptr)));
- EXPECT_THAT(result, ErrorAt(""_jptr, "/oneOf/1"_jptr, "multipleOf", "3 is a multiple of 3"));
- }
- TEST(ValidationResultJsonTest, OutputsFormattedJSON) {
- auto const schema = R"({
- "items": false
- })"_json;
- auto const instance = R"([ 0, 1 ])"_json;
- jvalidate::ValidationResult result = validate(schema, instance);
- std::stringstream ss;
- ss << result;
- EXPECT_THAT(ss.str(), R"({
- "valid": false,
- "details": [
- {
- "valid": false,
- "evaluationPath": "",
- "instanceLocation": "",
- "annotations": {
- "items": [
- "0",
- "1"
- ]
- }
- },
- {
- "valid": false,
- "evaluationPath": "/items",
- "instanceLocation": "/0",
- "errors": {
- "": "always false"
- }
- },
- {
- "valid": false,
- "evaluationPath": "/items",
- "instanceLocation": "/1",
- "errors": {
- "": "always false"
- }
- }
- ]
- })");
- }
- #if !defined(JVALIDATE_MONOTEST)
- int main(int argc, char ** argv) {
- testing::InitGoogleMock(&argc, argv);
- return RUN_ALL_TESTS();
- }
- #endif
|