diff options
Diffstat (limited to 'graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp')
-rw-r--r-- | graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp | 659 |
1 files changed, 641 insertions, 18 deletions
diff --git a/graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp b/graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp index 92c1b72384..3f511b3e17 100644 --- a/graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp +++ b/graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp @@ -112,6 +112,13 @@ TEST(SchemaValidator, Hasher) { #define VALIDATE(schema, json, expected) \ {\ + VALIDATE_(schema, json, expected, true) \ +} + +#define VALIDATE_(schema, json, expected, expected2) \ +{\ + EXPECT_TRUE(expected2 == schema.GetError().ObjectEmpty());\ + EXPECT_TRUE(schema.IsSupportedSpecification());\ SchemaValidator validator(schema);\ Document d;\ /*printf("\n%s\n", json);*/\ @@ -149,6 +156,8 @@ TEST(SchemaValidator, Hasher) { #define INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, \ flags, SchemaValidatorType, PointerType) \ {\ + EXPECT_TRUE(schema.GetError().ObjectEmpty());\ + EXPECT_TRUE(schema.IsSupportedSpecification());\ SchemaValidatorType validator(schema);\ validator.SetValidateFlags(flags);\ Document d;\ @@ -188,6 +197,20 @@ TEST(SchemaValidator, Hasher) { }\ } +// Use for checking whether a compiled schema document contains errors +#define SCHEMAERROR(schema, error) \ +{\ + Document e;\ + e.Parse(error);\ + if (schema.GetError() != e) {\ + StringBuffer sb;\ + Writer<StringBuffer> w(sb);\ + schema.GetError().Accept(w);\ + printf("GetError() Expected: %s Actual: %s\n", error, sb.GetString());\ + ADD_FAILURE();\ + }\ +} + TEST(SchemaValidator, Typeless) { Document sd; sd.Parse("{}"); @@ -223,7 +246,7 @@ TEST(SchemaValidator, Enum_Typed) { "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}"); } -TEST(SchemaValidator, Enum_Typless) { +TEST(SchemaValidator, Enum_Typeless) { Document sd; sd.Parse("{ \"enum\": [\"red\", \"amber\", \"green\", null, 42] }"); SchemaDocument s(sd); @@ -333,7 +356,7 @@ TEST(SchemaValidator, OneOf) { " ]" "}}"); INVALIDATE(s, "15", "", "oneOf", "", - "{ \"oneOf\": { \"errorCode\": 22, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"errors\": [{}, {}]}}"); + "{ \"oneOf\": { \"errorCode\": 22, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"matches\": [0,1]}}"); } TEST(SchemaValidator, Not) { @@ -502,12 +525,13 @@ TEST(SchemaValidator, String_Pattern) { TEST(SchemaValidator, String_Pattern_Invalid) { Document sd; - sd.Parse("{\"type\":\"string\",\"pattern\":\"a{0}\"}"); // TODO: report regex is invalid somehow + sd.Parse("{\"type\":\"string\",\"pattern\":\"a{0}\"}"); SchemaDocument s(sd); + SCHEMAERROR(s, "{\"RegexInvalid\":{\"errorCode\":9,\"instanceRef\":\"#/pattern\",\"value\":\"a{0}\"}}"); - VALIDATE(s, "\"\"", true); - VALIDATE(s, "\"a\"", true); - VALIDATE(s, "\"aa\"", true); + VALIDATE_(s, "\"\"", true, false); + VALIDATE_(s, "\"a\"", true, false); + VALIDATE_(s, "\"aa\"", true, false); } #endif @@ -1886,12 +1910,6 @@ TEST(SchemaValidator, SchemaPointer) { " }," " \"f\": {" " \"type\": \"boolean\"" - " }," - " \"cyclic_source\": {" - " \"$ref\": \"#/definitions/Resp_200/properties/cyclic_target\"" - " }," - " \"cyclic_target\": {" - " \"$ref\": \"#/definitions/Resp_200/properties/cyclic_source\"" " }" " }," " \"type\": \"object\"" @@ -2135,9 +2153,13 @@ public: } virtual const SchemaDocumentType* GetRemoteDocument(const char* uri, SizeType length) { + //printf("GetRemoteDocument : %s\n", uri); for (size_t i = 0; i < kCount; i++) - if (typename SchemaDocumentType::SValue(uri, length) == sd_[i]->GetURI()) + if (typename SchemaDocumentType::GValue(uri, length) == sd_[i]->GetURI()) { + //printf("Matched document"); return sd_[i]; + } + //printf("No matched document"); return 0; } @@ -2390,7 +2412,9 @@ TEST(SchemaValidator, Issue728_AllOfRef) { Document sd; sd.Parse("{\"allOf\": [{\"$ref\": \"#/abc\"}]}"); SchemaDocument s(sd); - VALIDATE(s, "{\"key1\": \"abc\", \"key2\": \"def\"}", true); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/allOf/0\",\"value\":\"#/abc\"}}"); + + VALIDATE_(s, "{\"key1\": \"abc\", \"key2\": \"def\"}", true, false); } TEST(SchemaValidator, Issue1017_allOfHandler) { @@ -2625,7 +2649,7 @@ TEST(SchemaValidator, Ref_remote_issue1210) { SchemaDocumentProvider(SchemaDocument** collection) : collection(collection) { } virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) { int i = 0; - while (collection[i] && SchemaDocument::SValue(uri, length) != collection[i]->GetURI()) ++i; + while (collection[i] && SchemaDocument::GValue(uri, length) != collection[i]->GetURI()) ++i; return collection[i]; } }; @@ -2656,7 +2680,7 @@ TEST(SchemaValidator, ContinueOnErrors) { ASSERT_FALSE(sd.HasParseError()); SchemaDocument s(sd); VALIDATE(s, "{\"version\": 1.0, \"address\": {\"number\": 24, \"street1\": \"The Woodlands\", \"street3\": \"Ham\", \"city\": \"Romsey\", \"area\": \"Kent\", \"country\": \"UK\", \"postcode\": \"SO51 0GP\"}, \"phones\": [\"0111-222333\", \"0777-666888\"], \"names\": [\"Fred\", \"Bloggs\"]}", true); - INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#", + INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"Narnia\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#", "{ \"multipleOf\": {" " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01" " }," @@ -2691,6 +2715,9 @@ TEST(SchemaValidator, ContinueOnErrors) { " }," " \"required\": {" " \"missing\": [\"street1\"], \"errorCode\": 15, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"" + " }," + " \"oneOf\": {" + " \"matches\": [0, 1], \"errorCode\": 22, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/address_type/properties/area\"" " }" "}", kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); @@ -2917,7 +2944,7 @@ TEST(SchemaValidator, ContinueOnErrors_RogueString) { // Test that when kValidateContinueOnErrorFlag is set, an incorrect simple type with a sub-schema is handled correctly. // This tests that we don't blow up when there is a type mismatch but there is a sub-schema present -TEST(SchemaValidator, ContinueOnErrors_Issue2) { +TEST(SchemaValidator, ContinueOnErrors_BadSimpleType) { Document sd; sd.Parse("{\"type\":\"string\", \"anyOf\":[{\"maxLength\":2}]}"); ASSERT_FALSE(sd.HasParseError()); @@ -2943,10 +2970,606 @@ TEST(SchemaValidator, ContinueOnErrors_Issue2) { kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); } -TEST(SchemaValidator, Schema_UnknownError) { + +TEST(SchemaValidator, UnknownValidationError) { ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null")); } +// The first occurrence of a duplicate keyword is taken +TEST(SchemaValidator, DuplicateKeyword) { + Document sd; + sd.Parse("{ \"title\": \"test\",\"type\": \"number\", \"type\": \"string\" }"); + EXPECT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + VALIDATE(s, "42", true); + INVALIDATE(s, "\"Life, the universe, and everything\"", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); +} + + +// SchemaDocument tests + +// Specification (schema draft, open api version) +TEST(SchemaValidator, Schema_SupportedNotObject) { + Document sd; + sd.Parse("true"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedNoSpec) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedNoSpecStatic) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + Specification spec = SchemaDocumentType::GetSpecification(sd); + ASSERT_FALSE(spec.IsSupported()); + ASSERT_TRUE(spec.draft == kDraftNone); + ASSERT_TRUE(spec.oapi == kVersionNone); +} + +TEST(SchemaValidator, Schema_SupportedDraft5Static) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-05/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + Specification spec = SchemaDocumentType::GetSpecification(sd); + ASSERT_TRUE(spec.IsSupported()); + ASSERT_TRUE(spec.draft == kDraft05); + ASSERT_TRUE(spec.oapi == kVersionNone); +} + +TEST(SchemaValidator, Schema_SupportedDraft4) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraft4NoFrag) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-04/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraft5) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-05/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft05); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraft5NoFrag) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-05/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft05); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_IgnoreDraftEmbedded) { + Document sd; + sd.Parse("{\"root\": {\"$schema\":\"http://json-schema.org/draft-05/schema#\", \"type\": \"integer\"}}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, SchemaDocument::PointerType("/root")); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraftOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kDraft04)); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_UnknownDraftOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kDraftUnknown)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraftUnknown); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraftOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kDraft03)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft03); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownDraft) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-xxx/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraftUnknown); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownDraftNotString) { + Document sd; + sd.Parse("{\"$schema\": 4, \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraftUnknown); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft3) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-03/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft03); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft6) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-06/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft06); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft7) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-07/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft07); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft2019_09) { + Document sd; + sd.Parse("{\"$schema\":\"https://json-schema.org/draft/2019-09/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2019_09); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft2020_12) { + Document sd; + sd.Parse("{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2020_12); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_SupportedVersion20Static) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"swagger\":\"2.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + Specification spec = SchemaDocumentType::GetSpecification(sd); + ASSERT_TRUE(spec.IsSupported()); + ASSERT_TRUE(spec.draft == kDraft04); + ASSERT_TRUE(spec.oapi == kVersion20); +} + +TEST(SchemaValidator, Schema_SupportedVersion20) { + Document sd; + sd.Parse("{\"swagger\":\"2.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion20); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedVersion30x) { + Document sd; + sd.Parse("{\"openapi\":\"3.0.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion30); + ASSERT_TRUE(s.GetSpecification().draft == kDraft05); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedVersionOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion20)); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion20); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_UnknownVersionOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersionUnknown)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedVersionOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion31)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion31); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2020_12); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownVersion) { + Document sd; + sd.Parse("{\"openapi\":\"1.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownVersionShort) { + Document sd; + sd.Parse("{\"openapi\":\"3.0.\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownVersionNotString) { + Document sd; + sd.Parse("{\"swagger\": 2}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedVersion31) { + Document sd; + sd.Parse("{\"openapi\":\"3.1.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion31); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2020_12); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_DraftAndVersion) { + Document sd; + sd.Parse("{\"swagger\": \"2.0\", \"$schema\": \"http://json-schema.org/draft-04/schema#\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + SCHEMAERROR(s, "{\"SpecIllegal\":{\"errorCode\":12,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_StartUnknown) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, SchemaDocument::PointerType("/nowhere")); + SCHEMAERROR(s, "{\"StartUnknown\":{\"errorCode\":1,\"instanceRef\":\"#\", \"value\":\"#/nowhere\"}}"); +} + +TEST(SchemaValidator, Schema_MultipleErrors) { + Document sd; + sd.Parse("{\"swagger\": \"foo\", \"$schema\": \"bar\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + SCHEMAERROR(s, "{ \"SpecUnknown\": {\"errorCode\":10,\"instanceRef\":\"#\"}," + " \"SpecIllegal\": {\"errorCode\":12,\"instanceRef\":\"#\"}" + "}"); +} + +// $ref is a non-JSON pointer fragment - not allowed when OpenAPI +TEST(SchemaValidator, Schema_RefPlainNameOpenApi) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"swagger\": \"2.0\", \"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myStr\": {\"type\": \"string\", \"id\": \"#myStrId\"}, \"myInt2\": {\"type\": \"integer\", \"id\": \"#myId\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefPlainName\":{\"errorCode\":2,\"instanceRef\":\"#/properties/myInt1\",\"value\":\"#myId\"}}"); +} + +// $ref is a non-JSON pointer fragment - not allowed when remote document +TEST(SchemaValidator, Schema_RefPlainNameRemote) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + RemoteSchemaDocumentProvider<SchemaDocumentType> provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#plainname\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefPlainName\":{\"errorCode\":2,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#plainname\"}}"); +} + +// $ref is an empty string +TEST(SchemaValidator, Schema_RefEmptyString) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefInvalid\":{\"errorCode\":3,\"instanceRef\":\"#/properties/myInt1\"}}"); +} + +// $ref is remote but no provider +TEST(SchemaValidator, Schema_RefNoRemoteProvider) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#plainname\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, 0); + SCHEMAERROR(s, "{\"RefNoRemoteProvider\":{\"errorCode\":7,\"instanceRef\":\"#/properties/myInt\"}}"); +} + +// $ref is remote but no schema returned +TEST(SchemaValidator, Schema_RefNoRemoteSchema) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + RemoteSchemaDocumentProvider<SchemaDocumentType> provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/will-not-resolve.json\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefNoRemoteSchema\":{\"errorCode\":8,\"instanceRef\":\"#/properties/myInt\",\"value\":\"http://localhost:1234/will-not-resolve.json\"}}"); +} + +// $ref pointer is invalid +TEST(SchemaValidator, Schema_RefPointerInvalid) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"#/&&&&&\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefPointerInvalid\":{\"errorCode\":4,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#/&&&&&\",\"offset\":2}}"); +} + +// $ref is remote and pointer is invalid +TEST(SchemaValidator, Schema_RefPointerInvalidRemote) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + RemoteSchemaDocumentProvider<SchemaDocumentType> provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/abc&&&&&\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefPointerInvalid\":{\"errorCode\":4,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#/abc&&&&&\",\"offset\":5}}"); +} + +// $ref is unknown non-pointer +TEST(SchemaValidator, Schema_RefUnknownPlainName) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"#plainname\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#plainname\"}}"); +} + +/// $ref is unknown pointer +TEST(SchemaValidator, Schema_RefUnknownPointer) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"#/a/b\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#/a/b\"}}"); +} + +// $ref is remote and unknown pointer +TEST(SchemaValidator, Schema_RefUnknownPointerRemote) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + RemoteSchemaDocumentProvider<SchemaDocumentType> provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/a/b\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/properties/myInt\",\"value\":\"http://localhost:1234/subSchemas.json#/a/b\"}}"); +} + +// $ref is cyclical +TEST(SchemaValidator, Schema_RefCyclical) { + typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {" + " \"cyclic_source\": {" + " \"$ref\": \"#/properties/cyclic_target\"" + " }," + " \"cyclic_target\": {" + " \"$ref\": \"#/properties/cyclic_source\"" + " }" + "}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefCyclical\":{\"errorCode\":6,\"instanceRef\":\"#/properties/cyclic_target\",\"value\":\"#/properties/cyclic_source\"}}"); +} + +TEST(SchemaValidator, Schema_ReadOnlyAndWriteOnly) { + Document sd; + sd.Parse("{\"type\": \"integer\", \"readOnly\": true, \"writeOnly\": true}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s1(sd, 0, 0, 0, 0, 0, Specification(kDraft04)); + EXPECT_TRUE(s1.GetError().ObjectEmpty()); + SchemaDocument s2(sd, 0, 0, 0, 0, 0, Specification(kVersion30)); + SCHEMAERROR(s2, "{\"ReadOnlyAndWriteOnly\":{\"errorCode\":13,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, ReadOnlyWhenWriting) { + Document sd; + sd.Parse( + "{" + " \"type\":\"object\"," + " \"properties\": {" + " \"rprop\" : {" + " \"type\": \"string\"," + " \"readOnly\": true" + " }" + " }" + "}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion20)); + VALIDATE(s, "{ \"rprop\": \"hello\" }", true); + INVALIDATE_(s, "{ \"rprop\": \"hello\" }", "/properties/rprop", "readOnly", "/rprop", + "{ \"readOnly\": {" + " \"errorCode\": 26, \"instanceRef\": \"#/rprop\", \"schemaRef\": \"#/properties/rprop\"" + " }" + "}", + kValidateDefaultFlags | kValidateWriteFlag, SchemaValidator, Pointer); +} + +TEST(SchemaValidator, WriteOnlyWhenReading) { + Document sd; + sd.Parse( + "{" + " \"type\":\"object\"," + " \"properties\": {" + " \"wprop\" : {" + " \"type\": \"boolean\"," + " \"writeOnly\": true" + " }" + " }" + "}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion30)); + VALIDATE(s, "{ \"wprop\": true }", true); + INVALIDATE_(s, "{ \"wprop\": true }", "/properties/wprop", "writeOnly", "/wprop", + "{ \"writeOnly\": {" + " \"errorCode\": 27, \"instanceRef\": \"#/wprop\", \"schemaRef\": \"#/properties/wprop\"" + " }" + "}", + kValidateDefaultFlags | kValidateReadFlag, SchemaValidator, Pointer); +} + +TEST(SchemaValidator, NullableTrue) { + Document sd; + sd.Parse("{\"type\": \"string\", \"nullable\": true}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, kVersion20); + + VALIDATE(s, "\"hello\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); + INVALIDATE(s, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"boolean\"" + "}}"); + + SchemaDocument s30(sd, 0, 0, 0, 0, 0, kVersion30); + + VALIDATE(s30, "\"hello\"", true); + VALIDATE(s30, "null", true); + INVALIDATE(s30, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"null\", \"string\"], \"actual\": \"boolean\"" + "}}"); +} + +TEST(SchemaValidator, NullableFalse) { + Document sd; + sd.Parse("{\"type\": \"string\", \"nullable\": false}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, kVersion20); + + VALIDATE(s, "\"hello\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); + INVALIDATE(s, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"boolean\"" + "}}"); + + SchemaDocument s30(sd, 0, 0, 0, 0, 0, kVersion30); + + VALIDATE(s30, "\"hello\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); + INVALIDATE(s30, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"boolean\"" + "}}"); +} + #if defined(_MSC_VER) || defined(__clang__) RAPIDJSON_DIAG_POP #endif |