summaryrefslogtreecommitdiff
path: root/graphics/asymptote/LspCpp/third_party/rapidjson/test/unittest/schematest.cpp
diff options
context:
space:
mode:
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.cpp659
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