Commit 1a59ab50 authored by miloyip's avatar miloyip

Add invalid schema keyword

parent a326c681
...@@ -40,6 +40,12 @@ RAPIDJSON_DIAG_PUSH ...@@ -40,6 +40,12 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(effc++)
#endif #endif
#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
RAPIDJSON_MULTILINEMACRO_BEGIN\
context.invalidKeyword = keyword;\
return false;\
RAPIDJSON_MULTILINEMACRO_END
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -198,6 +204,7 @@ struct SchemaValidationContext { ...@@ -198,6 +204,7 @@ struct SchemaValidationContext {
allocator(a), allocator(a),
schema(s), schema(s),
valueSchema(), valueSchema(),
invalidKeyword(),
hasher(), hasher(),
patternPropertiesSchemas(), patternPropertiesSchemas(),
notValidator(), notValidator(),
...@@ -223,6 +230,7 @@ struct SchemaValidationContext { ...@@ -223,6 +230,7 @@ struct SchemaValidationContext {
CrtAllocator* allocator; // For allocating memory for context CrtAllocator* allocator; // For allocating memory for context
const SchemaType* schema; const SchemaType* schema;
const SchemaType* valueSchema; const SchemaType* valueSchema;
const char* invalidKeyword;
HasherType* hasher; HasherType* hasher;
SchemaValidatorArray allOfValidators; SchemaValidatorArray allOfValidators;
SchemaValidatorArray anyOfValidators; SchemaValidatorArray anyOfValidators;
...@@ -528,7 +536,7 @@ public: ...@@ -528,7 +536,7 @@ public:
else if (additionalItems_) else if (additionalItems_)
context.valueSchema = GetTypeless(); context.valueSchema = GetTypeless();
else else
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("items");
} }
else else
context.valueSchema = GetTypeless(); context.valueSchema = GetTypeless();
...@@ -554,14 +562,14 @@ public: ...@@ -554,14 +562,14 @@ public:
if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
if (!patternValid) if (!patternValid)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("patternProperties");
} }
else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
if (!patternValid || !otherValid) if (!patternValid || !otherValid)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("patternProperties");
} }
else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("patternProperties");
} }
if (enum_) { if (enum_) {
...@@ -569,20 +577,20 @@ public: ...@@ -569,20 +577,20 @@ public:
for (SizeType i = 0; i < enumCount_; i++) for (SizeType i = 0; i < enumCount_; i++)
if (enum_[i] == h) if (enum_[i] == h)
goto foundEnum; goto foundEnum;
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("enum");
foundEnum:; foundEnum:;
} }
if (allOf_.schemas) if (allOf_.schemas)
for (SizeType i = 0; i < allOf_.count; i++) for (SizeType i = 0; i < allOf_.count; i++)
if (!context.allOfValidators.validators[i]->IsValid()) if (!context.allOfValidators.validators[i]->IsValid())
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("allOf");
if (anyOf_.schemas) { if (anyOf_.schemas) {
for (SizeType i = 0; i < anyOf_.count; i++) for (SizeType i = 0; i < anyOf_.count; i++)
if (context.anyOfValidators.validators[i]->IsValid()) if (context.anyOfValidators.validators[i]->IsValid())
goto foundAny; goto foundAny;
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("anyOf");
foundAny:; foundAny:;
} }
...@@ -591,86 +599,88 @@ public: ...@@ -591,86 +599,88 @@ public:
for (SizeType i = 0; i < oneOf_.count; i++) for (SizeType i = 0; i < oneOf_.count; i++)
if (context.oneOfValidators.validators[i]->IsValid()) { if (context.oneOfValidators.validators[i]->IsValid()) {
if (oneValid) if (oneValid)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("oneOf");
else else
oneValid = true; oneValid = true;
} }
if (!oneValid) if (!oneValid)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("oneOf");
} }
if (not_ && context.notValidator->IsValid()) if (not_ && context.notValidator->IsValid())
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("not");
if (ref_ && !context.refValidator->IsValid())
RAPIDJSON_INVALID_KEYWORD_RETURN("$ref");
return !ref_ || context.refValidator->IsValid(); return true;
} }
bool Null(Context& context) const { bool Null(Context& context) const {
CreateParallelValidator(context); if (!(type_ & (1 << kNullSchemaType)))
return (type_ & (1 << kNullSchemaType)); RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return CreateParallelValidator(context);
} }
bool Bool(Context& context, bool) const { bool Bool(Context& context, bool) const {
CreateParallelValidator(context); if (!(type_ & (1 << kBooleanSchemaType)))
return (type_ & (1 << kBooleanSchemaType)); RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return CreateParallelValidator(context);
} }
bool Int(Context& context, int i) const { bool Int(Context& context, int i) const {
CreateParallelValidator(context); if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false; return CheckDouble(context, i) && CreateParallelValidator(context);
return CheckDouble(i);
} }
bool Uint(Context& context, unsigned u) const { bool Uint(Context& context, unsigned u) const {
CreateParallelValidator(context); if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false; return CheckDouble(context, u) && CreateParallelValidator(context);
return CheckDouble(u);
} }
bool Int64(Context& context, int64_t i) const { bool Int64(Context& context, int64_t i) const {
CreateParallelValidator(context); if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false; return CheckDouble(context, i) && CreateParallelValidator(context);
return CheckDouble(i);
} }
bool Uint64(Context& context, uint64_t u) const { bool Uint64(Context& context, uint64_t u) const {
CreateParallelValidator(context); if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
if ((type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false; return CheckDouble(context, u) && CreateParallelValidator(context);
return CheckDouble(u);
} }
bool Double(Context& context, double d) const { bool Double(Context& context, double d) const {
CreateParallelValidator(context); if (!(type_ & (1 << kNumberSchemaType)))
if ((type_ & (1 << kNumberSchemaType)) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false; return CheckDouble(context, d) && CreateParallelValidator(context);
return CheckDouble(d);
} }
bool String(Context& context, const Ch* str, SizeType length, bool) const { bool String(Context& context, const Ch* str, SizeType length, bool) const {
(void)str; if (!(type_ & (1 << kStringSchemaType)))
CreateParallelValidator(context); RAPIDJSON_INVALID_KEYWORD_RETURN("type");
if ((type_ & (1 << kStringSchemaType)) == 0)
return false;
//if (length < minLength_ || length > maxLength_)
// return false;
if (minLength_ != 0 || maxLength_ != SizeType(~0)) { if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
SizeType count; SizeType count;
if (internal::CountStringCodePoint<EncodingType>(str, length, &count) && (count < minLength_ || count > maxLength_)) if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
return false; if (count < minLength_)
RAPIDJSON_INVALID_KEYWORD_RETURN("minLength");
if (count > maxLength_)
RAPIDJSON_INVALID_KEYWORD_RETURN("maxLength");
} }
}
if (pattern_ && !IsPatternMatch(pattern_, str, length))
RAPIDJSON_INVALID_KEYWORD_RETURN("pattern");
return !pattern_ || IsPatternMatch(pattern_, str, length); return CreateParallelValidator(context);
} }
bool StartObject(Context& context) const { bool StartObject(Context& context) const {
CreateParallelValidator(context); if (!(type_ & (1 << kObjectSchemaType)))
if ((type_ & (1 << kObjectSchemaType)) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false;
context.objectRequiredCount = 0; context.objectRequiredCount = 0;
if (hasDependencies_) { if (hasDependencies_) {
...@@ -685,7 +695,7 @@ public: ...@@ -685,7 +695,7 @@ public:
std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
} }
return true; return CreateParallelValidator(context);
} }
bool Key(Context& context, const Ch* str, SizeType len, bool) const { bool Key(Context& context, const Ch* str, SizeType len, bool) const {
...@@ -731,12 +741,21 @@ public: ...@@ -731,12 +741,21 @@ public:
return true; return true;
} }
return context.patternPropertiesSchemaCount != 0; // patternProperties are not additional properties if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
RAPIDJSON_INVALID_KEYWORD_RETURN("additionalProperties");
return true;
} }
bool EndObject(Context& context, SizeType memberCount) const { bool EndObject(Context& context, SizeType memberCount) const {
if (context.objectRequiredCount != requiredCount_ || memberCount < minProperties_ || memberCount > maxProperties_) if (context.objectRequiredCount != requiredCount_)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("required");
if (memberCount < minProperties_)
RAPIDJSON_INVALID_KEYWORD_RETURN("minProperties");
if (memberCount > maxProperties_)
RAPIDJSON_INVALID_KEYWORD_RETURN("maxProperties");
if (hasDependencies_) { if (hasDependencies_) {
for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
...@@ -744,11 +763,11 @@ public: ...@@ -744,11 +763,11 @@ public:
if (properties_[sourceIndex].dependencies) { if (properties_[sourceIndex].dependencies) {
for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
if (properties_[sourceIndex].dependencies[targetIndex] && !context.objectDependencies[targetIndex]) if (properties_[sourceIndex].dependencies[targetIndex] && !context.objectDependencies[targetIndex])
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("dependencies");
} }
else if (properties_[sourceIndex].dependenciesSchema) else if (properties_[sourceIndex].dependenciesSchema)
if (!context.dependencyValidators.validators[sourceIndex]->IsValid()) if (!context.dependencyValidators.validators[sourceIndex]->IsValid())
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("dependencies");
} }
} }
...@@ -756,21 +775,28 @@ public: ...@@ -756,21 +775,28 @@ public:
} }
bool StartArray(Context& context) const { bool StartArray(Context& context) const {
CreateParallelValidator(context); if (!(type_ & (1 << kArraySchemaType)))
if ((type_ & (1 << kArraySchemaType)) == 0) RAPIDJSON_INVALID_KEYWORD_RETURN("type");
return false;
if (uniqueItems_) if (uniqueItems_)
context.arrayElementHashCodes.SetArray(); context.arrayElementHashCodes.SetArray();
context.arrayElementIndex = 0; context.arrayElementIndex = 0;
context.inArray = true; context.inArray = true;
return true;
return CreateParallelValidator(context);
} }
bool EndArray(Context& context, SizeType elementCount) const { bool EndArray(Context& context, SizeType elementCount) const {
context.inArray = false; context.inArray = false;
return elementCount >= minItems_ && elementCount <= maxItems_;
if (elementCount < minItems_)
RAPIDJSON_INVALID_KEYWORD_RETURN("minItems");
if (elementCount > maxItems_)
RAPIDJSON_INVALID_KEYWORD_RETURN("maxItems");
return true;
} }
private: private:
...@@ -879,14 +905,22 @@ private: ...@@ -879,14 +905,22 @@ private:
else if (type == "number" ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); else if (type == "number" ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
} }
void CreateParallelValidator(Context& context) const { bool CreateParallelValidator(Context& context) const {
if (enum_ || context.arrayUniqueness) if (enum_ || context.arrayUniqueness)
context.hasher = new HasherType; context.hasher = new HasherType;
if (allOf_.schemas) CreateSchemaValidators(context, context.allOfValidators, allOf_);
if (anyOf_.schemas) CreateSchemaValidators(context, context.anyOfValidators, anyOf_); if (allOf_.schemas)
if (oneOf_.schemas) CreateSchemaValidators(context, context.oneOfValidators, oneOf_); CreateSchemaValidators(context, context.allOfValidators, allOf_);
if (anyOf_.schemas)
CreateSchemaValidators(context, context.anyOfValidators, anyOf_);
if (oneOf_.schemas)
CreateSchemaValidators(context, context.oneOfValidators, oneOf_);
if (not_ && !context.notValidator) if (not_ && !context.notValidator)
context.notValidator = context.factory->CreateSchemaValidator(*not_); context.notValidator = context.factory->CreateSchemaValidator(*not_);
if (ref_ && !context.refValidator) if (ref_ && !context.refValidator)
context.refValidator = context.factory->CreateSchemaValidator(*ref_); context.refValidator = context.factory->CreateSchemaValidator(*ref_);
...@@ -896,6 +930,7 @@ private: ...@@ -896,6 +930,7 @@ private:
for (SizeType i = 0; i < propertyCount_; i++) for (SizeType i = 0; i < propertyCount_; i++)
context.dependencyValidators.validators[i] = properties_[i].dependenciesSchema ? context.factory->CreateSchemaValidator(*properties_[i].dependenciesSchema) : 0; context.dependencyValidators.validators[i] = properties_[i].dependenciesSchema ? context.factory->CreateSchemaValidator(*properties_[i].dependenciesSchema) : 0;
} }
return true;
} }
void CreateSchemaValidators(Context& context, typename Context::SchemaValidatorArray& validators, const SchemaArray& schemas) const { void CreateSchemaValidators(Context& context, typename Context::SchemaValidatorArray& validators, const SchemaArray& schemas) const {
...@@ -928,15 +963,19 @@ private: ...@@ -928,15 +963,19 @@ private:
return false; return false;
} }
bool CheckDouble(double d) const { bool CheckDouble(Context& context, double d) const {
if (exclusiveMinimum_ ? d <= minimum_ : d < minimum_) return false; if (exclusiveMinimum_ ? d <= minimum_ : d < minimum_)
if (exclusiveMaximum_ ? d >= maximum_ : d > maximum_) return false; RAPIDJSON_INVALID_KEYWORD_RETURN("minimum");
if (exclusiveMaximum_ ? d >= maximum_ : d > maximum_)
RAPIDJSON_INVALID_KEYWORD_RETURN("maximum");
if (hasMultipleOf_) { if (hasMultipleOf_) {
double a = std::abs(d), b = std::abs(multipleOf_); double a = std::abs(d), b = std::abs(multipleOf_);
double q = std::floor(a / b); double q = std::floor(a / b);
double r = a - q * b; double r = a - q * b;
if (r > 0.0) if (r > 0.0)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("multipleOf");
} }
return true; return true;
} }
...@@ -1222,6 +1261,10 @@ public: ...@@ -1222,6 +1261,10 @@ public:
return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
} }
const char* GetInvalidSchemaKeyword() const {
return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
}
PointerType GetInvalidDocumentPointer() const { PointerType GetInvalidDocumentPointer() const {
return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch)); return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
} }
...@@ -1370,12 +1413,6 @@ private: ...@@ -1370,12 +1413,6 @@ private:
if (!CurrentSchema().EndValue(CurrentContext())) if (!CurrentSchema().EndValue(CurrentContext()))
return false; return false;
// *documentStack_.template Push<Ch>() = '\0';
// documentStack_.template Pop<Ch>(1);
// printf("document: %s\n", documentStack_.template Bottom<Ch>());
while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
;
uint64_t h = CurrentContext().arrayUniqueness ? CurrentContext().hasher->GetHashCode() : 0; uint64_t h = CurrentContext().arrayUniqueness ? CurrentContext().hasher->GetHashCode() : 0;
PopSchema(); PopSchema();
...@@ -1385,11 +1422,17 @@ private: ...@@ -1385,11 +1422,17 @@ private:
if (context.valueUniqueness) { if (context.valueUniqueness) {
for (typename Context::HashCodeArray::ConstValueIterator itr = context.arrayElementHashCodes.Begin(); itr != context.arrayElementHashCodes.End(); ++itr) for (typename Context::HashCodeArray::ConstValueIterator itr = context.arrayElementHashCodes.Begin(); itr != context.arrayElementHashCodes.End(); ++itr)
if (itr->GetUint64() == h) if (itr->GetUint64() == h)
return false; RAPIDJSON_INVALID_KEYWORD_RETURN("uniqueItems");
context.arrayElementHashCodes.PushBack(h, *context.allocator); context.arrayElementHashCodes.PushBack(h, *context.allocator);
} }
} }
// *documentStack_.template Push<Ch>() = '\0';
// documentStack_.template Pop<Ch>(1);
// printf("document: %s\n", documentStack_.template Bottom<Ch>());
while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
;
return true; return true;
} }
...@@ -1421,6 +1464,7 @@ private: ...@@ -1421,6 +1464,7 @@ private:
void PopSchema() { schemaStack_.template Pop<Context>(1)->~Context(); } void PopSchema() { schemaStack_.template Pop<Context>(1)->~Context(); }
const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; } const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
Context& CurrentContext() { return *schemaStack_.template Top<Context>(); } Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
static const size_t kDefaultSchemaStackCapacity = 1024; static const size_t kDefaultSchemaStackCapacity = 1024;
static const size_t kDefaultDocumentStackCapacity = 256; static const size_t kDefaultDocumentStackCapacity = 256;
......
...@@ -99,17 +99,18 @@ TEST(SchemaValidator, Hasher) { ...@@ -99,17 +99,18 @@ TEST(SchemaValidator, Hasher) {
EXPECT_FALSE(d.HasParseError());\ EXPECT_FALSE(d.HasParseError());\
EXPECT_TRUE(expected == d.Accept(validator));\ EXPECT_TRUE(expected == d.Accept(validator));\
EXPECT_TRUE(expected == validator.IsValid());\ EXPECT_TRUE(expected == validator.IsValid());\
/*if (!validator.IsValid()) {\ if (expected && !validator.IsValid()) {\
StringBuffer sb;\ StringBuffer sb;\
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\ validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\
printf("Error schema: %s\n", sb.GetString());\ printf("Invalid schema: %s\n", sb.GetString());\
printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());\
sb.Clear();\ sb.Clear();\
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);\ validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);\
printf("Error document: %s\n", sb.GetString());\ printf("Invalid document: %s\n", sb.GetString());\
}*/\ }\
} }
#define VALIDATE_ERROR(schema, json, invalidSchemaPointer, invalidDocumentPointer) \ #define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer) \
{\ {\
SchemaValidator validator(schema);\ SchemaValidator validator(schema);\
Document d;\ Document d;\
...@@ -124,6 +125,10 @@ TEST(SchemaValidator, Hasher) { ...@@ -124,6 +125,10 @@ TEST(SchemaValidator, Hasher) {
printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\ printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\
ADD_FAILURE();\ ADD_FAILURE();\
}\ }\
if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\
printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\
ADD_FAILURE();\
}\
if (validator.GetInvalidDocumentPointer() != Pointer(invalidDocumentPointer)) {\ if (validator.GetInvalidDocumentPointer() != Pointer(invalidDocumentPointer)) {\
StringBuffer sb;\ StringBuffer sb;\
validator.GetInvalidDocumentPointer().Stringify(sb);\ validator.GetInvalidDocumentPointer().Stringify(sb);\
...@@ -149,7 +154,7 @@ TEST(SchemaValidator, MultiType) { ...@@ -149,7 +154,7 @@ TEST(SchemaValidator, MultiType) {
VALIDATE(s, "42", true); VALIDATE(s, "42", true);
VALIDATE(s, "\"Life, the universe, and everything\"", true); VALIDATE(s, "\"Life, the universe, and everything\"", true);
VALIDATE_ERROR(s, "[\"Life\", \"the universe\", \"and everything\"]", "", ""); INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "");
} }
TEST(SchemaValidator, Enum_Typed) { TEST(SchemaValidator, Enum_Typed) {
...@@ -158,7 +163,7 @@ TEST(SchemaValidator, Enum_Typed) { ...@@ -158,7 +163,7 @@ TEST(SchemaValidator, Enum_Typed) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "\"red\"", true); VALIDATE(s, "\"red\"", true);
VALIDATE(s, "\"blue\"", false); INVALIDATE(s, "\"blue\"", "", "enum", "");
} }
TEST(SchemaValidator, Enum_Typless) { TEST(SchemaValidator, Enum_Typless) {
...@@ -169,7 +174,7 @@ TEST(SchemaValidator, Enum_Typless) { ...@@ -169,7 +174,7 @@ TEST(SchemaValidator, Enum_Typless) {
VALIDATE(s, "\"red\"", true); VALIDATE(s, "\"red\"", true);
VALIDATE(s, "null", true); VALIDATE(s, "null", true);
VALIDATE(s, "42", true); VALIDATE(s, "42", true);
VALIDATE(s, "0", false); INVALIDATE(s, "0", "", "enum", "");
} }
TEST(SchemaValidator, Enum_InvalidType) { TEST(SchemaValidator, Enum_InvalidType) {
...@@ -178,7 +183,7 @@ TEST(SchemaValidator, Enum_InvalidType) { ...@@ -178,7 +183,7 @@ TEST(SchemaValidator, Enum_InvalidType) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "\"red\"", true); VALIDATE(s, "\"red\"", true);
VALIDATE(s, "null", false); INVALIDATE(s, "null", "", "type", "");
} }
TEST(SchemaValidator, AllOf) { TEST(SchemaValidator, AllOf) {
...@@ -188,7 +193,7 @@ TEST(SchemaValidator, AllOf) { ...@@ -188,7 +193,7 @@ TEST(SchemaValidator, AllOf) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "\"ok\"", true); VALIDATE(s, "\"ok\"", true);
VALIDATE(s, "\"too long\"", false); INVALIDATE(s, "\"too long\"", "", "allOf", "");
} }
{ {
Document sd; Document sd;
...@@ -196,7 +201,7 @@ TEST(SchemaValidator, AllOf) { ...@@ -196,7 +201,7 @@ TEST(SchemaValidator, AllOf) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "\"No way\"", false); VALIDATE(s, "\"No way\"", false);
VALIDATE(s, "-1", false); INVALIDATE(s, "-1", "", "allOf", "");
} }
} }
...@@ -205,9 +210,9 @@ TEST(SchemaValidator, AnyOf) { ...@@ -205,9 +210,9 @@ TEST(SchemaValidator, AnyOf) {
sd.Parse("{\"anyOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }"); sd.Parse("{\"anyOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }");
SchemaDocument s(sd); SchemaDocument s(sd);
//VALIDATE(s, "\"Yes\"", true); VALIDATE(s, "\"Yes\"", true);
//VALIDATE(s, "42", true); VALIDATE(s, "42", true);
VALIDATE(s, "{ \"Not a\": \"string or number\" }", false); INVALIDATE(s, "{ \"Not a\": \"string or number\" }", "", "anyOf", "");
} }
TEST(SchemaValidator, OneOf) { TEST(SchemaValidator, OneOf) {
...@@ -217,8 +222,8 @@ TEST(SchemaValidator, OneOf) { ...@@ -217,8 +222,8 @@ TEST(SchemaValidator, OneOf) {
VALIDATE(s, "10", true); VALIDATE(s, "10", true);
VALIDATE(s, "9", true); VALIDATE(s, "9", true);
VALIDATE(s, "2", false); INVALIDATE(s, "2", "", "oneOf", "");
VALIDATE(s, "15", false); INVALIDATE(s, "15", "", "oneOf", "");
} }
TEST(SchemaValidator, Not) { TEST(SchemaValidator, Not) {
...@@ -227,8 +232,8 @@ TEST(SchemaValidator, Not) { ...@@ -227,8 +232,8 @@ TEST(SchemaValidator, Not) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "42", true); VALIDATE(s, "42", true);
VALIDATE(s, "{ \"key\": \"value\" }", true); // TO FIX VALIDATE(s, "{ \"key\": \"value\" }", true);
VALIDATE(s, "\"I am a string\"", false); INVALIDATE(s, "\"I am a string\"", "", "not", "");
} }
TEST(SchemaValidator, Ref) { TEST(SchemaValidator, Ref) {
...@@ -292,7 +297,7 @@ TEST(SchemaValidator, Ref_AllOf) { ...@@ -292,7 +297,7 @@ TEST(SchemaValidator, Ref_AllOf) {
"}"); "}");
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE_ERROR(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"} }", "/properties/shipping_address", "/shipping_address"); INVALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"} }", "/properties/shipping_address", "allOf", "/shipping_address");
VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\", \"type\": \"business\"} }", true); VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\", \"type\": \"business\"} }", true);
} }
...@@ -302,7 +307,7 @@ TEST(SchemaValidator, String) { ...@@ -302,7 +307,7 @@ TEST(SchemaValidator, String) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "\"I'm a string\"", true); VALIDATE(s, "\"I'm a string\"", true);
VALIDATE(s, "42", false); INVALIDATE(s, "42", "", "type", "");
} }
TEST(SchemaValidator, String_LengthRange) { TEST(SchemaValidator, String_LengthRange) {
...@@ -310,10 +315,10 @@ TEST(SchemaValidator, String_LengthRange) { ...@@ -310,10 +315,10 @@ TEST(SchemaValidator, String_LengthRange) {
sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}"); sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "\"A\"", false); INVALIDATE(s, "\"A\"", "", "minLength", "");
VALIDATE(s, "\"AB\"", true); VALIDATE(s, "\"AB\"", true);
VALIDATE(s, "\"ABC\"", true); VALIDATE(s, "\"ABC\"", true);
VALIDATE(s, "\"ABCD\"", false); INVALIDATE(s, "\"ABCD\"", "", "maxLength", "");
} }
#if RAPIDJSON_SCHEMA_HAS_REGEX #if RAPIDJSON_SCHEMA_HAS_REGEX
...@@ -324,8 +329,8 @@ TEST(SchemaValidator, String_Pattern) { ...@@ -324,8 +329,8 @@ TEST(SchemaValidator, String_Pattern) {
VALIDATE(s, "\"555-1212\"", true); VALIDATE(s, "\"555-1212\"", true);
VALIDATE(s, "\"(888)555-1212\"", true); VALIDATE(s, "\"(888)555-1212\"", true);
VALIDATE(s, "\"(888)555-1212 ext. 532\"", false); INVALIDATE(s, "\"(888)555-1212 ext. 532\"", "", "pattern", "");
VALIDATE(s, "\"(800)FLOWERS\"", false); INVALIDATE(s, "\"(800)FLOWERS\"", "", "pattern", "");
} }
#endif #endif
...@@ -336,8 +341,8 @@ TEST(SchemaValidator, Integer) { ...@@ -336,8 +341,8 @@ TEST(SchemaValidator, Integer) {
VALIDATE(s, "42", true); VALIDATE(s, "42", true);
VALIDATE(s, "-1", true); VALIDATE(s, "-1", true);
VALIDATE(s, "3.1415926", false); INVALIDATE(s, "3.1415926", "", "type", "");
VALIDATE(s, "\"42\"", false); INVALIDATE(s, "\"42\"", "", "type", "");
} }
TEST(SchemaValidator, Integer_Range) { TEST(SchemaValidator, Integer_Range) {
...@@ -345,12 +350,12 @@ TEST(SchemaValidator, Integer_Range) { ...@@ -345,12 +350,12 @@ TEST(SchemaValidator, Integer_Range) {
sd.Parse("{\"type\":\"integer\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}"); sd.Parse("{\"type\":\"integer\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}");
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "-1", false); INVALIDATE(s, "-1", "", "minimum", "");
VALIDATE(s, "0", true); VALIDATE(s, "0", true);
VALIDATE(s, "10", true); VALIDATE(s, "10", true);
VALIDATE(s, "99", true); VALIDATE(s, "99", true);
VALIDATE(s, "100", false); INVALIDATE(s, "100", "", "maximum", "");
VALIDATE(s, "101", false); INVALIDATE(s, "101", "", "maximum", "");
} }
TEST(SchemaValidator, Integer_MultipleOf) { TEST(SchemaValidator, Integer_MultipleOf) {
...@@ -361,7 +366,7 @@ TEST(SchemaValidator, Integer_MultipleOf) { ...@@ -361,7 +366,7 @@ TEST(SchemaValidator, Integer_MultipleOf) {
VALIDATE(s, "0", true); VALIDATE(s, "0", true);
VALIDATE(s, "10", true); VALIDATE(s, "10", true);
VALIDATE(s, "20", true); VALIDATE(s, "20", true);
VALIDATE(s, "23", false); INVALIDATE(s, "23", "", "multipleOf", "");
} }
TEST(SchemaValidator, Number_Range) { TEST(SchemaValidator, Number_Range) {
...@@ -369,12 +374,12 @@ TEST(SchemaValidator, Number_Range) { ...@@ -369,12 +374,12 @@ TEST(SchemaValidator, Number_Range) {
sd.Parse("{\"type\":\"number\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}"); sd.Parse("{\"type\":\"number\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}");
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "-1", false); INVALIDATE(s, "-1", "", "minimum", "");
VALIDATE(s, "0", true); VALIDATE(s, "0", true);
VALIDATE(s, "10", true); VALIDATE(s, "10", true);
VALIDATE(s, "99", true); VALIDATE(s, "99", true);
VALIDATE(s, "100", false); INVALIDATE(s, "100", "", "maximum", "");
VALIDATE(s, "101", false); INVALIDATE(s, "101", "", "maximum", "");
} }
TEST(SchemaValidator, Number_MultipleOf) { TEST(SchemaValidator, Number_MultipleOf) {
...@@ -385,7 +390,7 @@ TEST(SchemaValidator, Number_MultipleOf) { ...@@ -385,7 +390,7 @@ TEST(SchemaValidator, Number_MultipleOf) {
VALIDATE(s, "0", true); VALIDATE(s, "0", true);
VALIDATE(s, "10", true); VALIDATE(s, "10", true);
VALIDATE(s, "20", true); VALIDATE(s, "20", true);
VALIDATE(s, "23", false); INVALIDATE(s, "23", "", "multipleOf", "");
} }
TEST(SchemaValidator, Number_MultipleOfOne) { TEST(SchemaValidator, Number_MultipleOfOne) {
...@@ -395,7 +400,7 @@ TEST(SchemaValidator, Number_MultipleOfOne) { ...@@ -395,7 +400,7 @@ TEST(SchemaValidator, Number_MultipleOfOne) {
VALIDATE(s, "42", true); VALIDATE(s, "42", true);
VALIDATE(s, "42.0", true); VALIDATE(s, "42.0", true);
VALIDATE(s, "3.1415926", false); INVALIDATE(s, "3.1415926", "", "multipleOf", "");
} }
TEST(SchemaValidator, Object) { TEST(SchemaValidator, Object) {
...@@ -405,8 +410,8 @@ TEST(SchemaValidator, Object) { ...@@ -405,8 +410,8 @@ TEST(SchemaValidator, Object) {
VALIDATE(s, "{\"key\":\"value\",\"another_key\":\"another_value\"}", true); VALIDATE(s, "{\"key\":\"value\",\"another_key\":\"another_value\"}", true);
VALIDATE(s, "{\"Sun\":1.9891e30,\"Jupiter\":1.8986e27,\"Saturn\":5.6846e26,\"Neptune\":10.243e25,\"Uranus\":8.6810e25,\"Earth\":5.9736e24,\"Venus\":4.8685e24,\"Mars\":6.4185e23,\"Mercury\":3.3022e23,\"Moon\":7.349e22,\"Pluto\":1.25e22}", true); VALIDATE(s, "{\"Sun\":1.9891e30,\"Jupiter\":1.8986e27,\"Saturn\":5.6846e26,\"Neptune\":10.243e25,\"Uranus\":8.6810e25,\"Earth\":5.9736e24,\"Venus\":4.8685e24,\"Mars\":6.4185e23,\"Mercury\":3.3022e23,\"Moon\":7.349e22,\"Pluto\":1.25e22}", true);
VALIDATE(s, "[\"An\", \"array\", \"not\", \"an\", \"object\"]", false); INVALIDATE(s, "[\"An\", \"array\", \"not\", \"an\", \"object\"]", "", "type", "");
VALIDATE(s, "\"Not an object\"", false); INVALIDATE(s, "\"Not an object\"", "", "type", "");
} }
TEST(SchemaValidator, Object_Properties) { TEST(SchemaValidator, Object_Properties) {
...@@ -424,7 +429,7 @@ TEST(SchemaValidator, Object_Properties) { ...@@ -424,7 +429,7 @@ TEST(SchemaValidator, Object_Properties) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true); VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
VALIDATE(s, "{ \"number\": \"1600\", \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", false); INVALIDATE(s, "{ \"number\": \"1600\", \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", "/properties/number", "type", "/number");
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\" }", true); VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\" }", true);
VALIDATE(s, "{}", true); VALIDATE(s, "{}", true);
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true); VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true);
...@@ -448,7 +453,7 @@ TEST(SchemaValidator, Object_AdditionalPropertiesBoolean) { ...@@ -448,7 +453,7 @@ TEST(SchemaValidator, Object_AdditionalPropertiesBoolean) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true); VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", false); INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", "", "additionalProperties", "/direction");
} }
TEST(SchemaValidator, Object_AdditionalPropertiesObject) { TEST(SchemaValidator, Object_AdditionalPropertiesObject) {
...@@ -469,7 +474,7 @@ TEST(SchemaValidator, Object_AdditionalPropertiesObject) { ...@@ -469,7 +474,7 @@ TEST(SchemaValidator, Object_AdditionalPropertiesObject) {
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true); VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true); VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true);
VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"office_number\": 201 }", false); INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"office_number\": 201 }", "/additionalProperties", "type", "/office_number");
} }
TEST(SchemaValidator, Object_Required) { TEST(SchemaValidator, Object_Required) {
...@@ -489,7 +494,7 @@ TEST(SchemaValidator, Object_Required) { ...@@ -489,7 +494,7 @@ TEST(SchemaValidator, Object_Required) {
VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\" }", true); VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\" }", true);
VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true); VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true);
VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", false); INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "");
} }
...@@ -498,11 +503,11 @@ TEST(SchemaValidator, Object_PropertiesRange) { ...@@ -498,11 +503,11 @@ TEST(SchemaValidator, Object_PropertiesRange) {
sd.Parse("{\"type\":\"object\", \"minProperties\":2, \"maxProperties\":3}"); sd.Parse("{\"type\":\"object\", \"minProperties\":2, \"maxProperties\":3}");
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "{}", false); INVALIDATE(s, "{}", "", "minProperties", "");
VALIDATE(s, "{\"a\":0}", false); INVALIDATE(s, "{\"a\":0}", "", "minProperties", "");
VALIDATE(s, "{\"a\":0,\"b\":1}", true); VALIDATE(s, "{\"a\":0,\"b\":1}", true);
VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2}", true); VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2}", true);
VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", false); INVALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", "", "maxProperties", "");
} }
TEST(SchemaValidator, Object_PropertyDependencies) { TEST(SchemaValidator, Object_PropertyDependencies) {
...@@ -523,7 +528,7 @@ TEST(SchemaValidator, Object_PropertyDependencies) { ...@@ -523,7 +528,7 @@ TEST(SchemaValidator, Object_PropertyDependencies) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555, \"billing_address\": \"555 Debtor's Lane\" }", true); VALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555, \"billing_address\": \"555 Debtor's Lane\" }", true);
VALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555 }", false); INVALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555 }", "", "dependencies", "");
VALIDATE(s, "{ \"name\": \"John Doe\"}", true); VALIDATE(s, "{ \"name\": \"John Doe\"}", true);
VALIDATE(s, "{ \"name\": \"John Doe\", \"billing_address\": \"555 Debtor's Lane\" }", true); VALIDATE(s, "{ \"name\": \"John Doe\", \"billing_address\": \"555 Debtor's Lane\" }", true);
} }
...@@ -549,8 +554,8 @@ TEST(SchemaValidator, Object_SchemaDependencies) { ...@@ -549,8 +554,8 @@ TEST(SchemaValidator, Object_SchemaDependencies) {
"}"); "}");
SchemaDocument s(sd); SchemaDocument s(sd);
//VALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555,\"billing_address\" : \"555 Debtor's Lane\"}", true); VALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555,\"billing_address\" : \"555 Debtor's Lane\"}", true);
VALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555 }", false); INVALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555 }", "", "dependencies", "");
VALIDATE(s, "{\"name\": \"John Doe\", \"billing_address\" : \"555 Debtor's Lane\"}", true); VALIDATE(s, "{\"name\": \"John Doe\", \"billing_address\" : \"555 Debtor's Lane\"}", true);
} }
...@@ -569,8 +574,8 @@ TEST(SchemaValidator, Object_PatternProperties) { ...@@ -569,8 +574,8 @@ TEST(SchemaValidator, Object_PatternProperties) {
VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true); VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true);
VALIDATE(s, "{ \"I_0\": 42 }", true); VALIDATE(s, "{ \"I_0\": 42 }", true);
VALIDATE(s, "{ \"S_0\": 42 }", false); INVALIDATE(s, "{ \"S_0\": 42 }", "", "patternProperties", "/S_0");
VALIDATE(s, "{ \"I_42\": \"This is a string\" }", false); INVALIDATE(s, "{ \"I_42\": \"This is a string\" }", "", "patternProperties", "/I_42");
VALIDATE(s, "{ \"keyword\": \"value\" }", true); VALIDATE(s, "{ \"keyword\": \"value\" }", true);
} }
...@@ -592,7 +597,7 @@ TEST(SchemaValidator, Object_PatternProperties_AdditionalProperties) { ...@@ -592,7 +597,7 @@ TEST(SchemaValidator, Object_PatternProperties_AdditionalProperties) {
VALIDATE(s, "{ \"builtin\": 42 }", true); VALIDATE(s, "{ \"builtin\": 42 }", true);
VALIDATE(s, "{ \"keyword\": \"value\" }", true); VALIDATE(s, "{ \"keyword\": \"value\" }", true);
VALIDATE(s, "{ \"keyword\": 42 }", false); INVALIDATE(s, "{ \"keyword\": 42 }", "/additionalProperties", "type", "/keyword");
} }
#endif #endif
...@@ -603,7 +608,7 @@ TEST(SchemaValidator, Array) { ...@@ -603,7 +608,7 @@ TEST(SchemaValidator, Array) {
VALIDATE(s, "[1, 2, 3, 4, 5]", true); VALIDATE(s, "[1, 2, 3, 4, 5]", true);
VALIDATE(s, "[3, \"different\", { \"types\" : \"of values\" }]", true); VALIDATE(s, "[3, \"different\", { \"types\" : \"of values\" }]", true);
VALIDATE(s, "{\"Not\": \"an array\"}", false); INVALIDATE(s, "{\"Not\": \"an array\"}", "", "type", "");
} }
TEST(SchemaValidator, Array_ItemsList) { TEST(SchemaValidator, Array_ItemsList) {
...@@ -618,7 +623,7 @@ TEST(SchemaValidator, Array_ItemsList) { ...@@ -618,7 +623,7 @@ TEST(SchemaValidator, Array_ItemsList) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "[1, 2, 3, 4, 5]", true); VALIDATE(s, "[1, 2, 3, 4, 5]", true);
VALIDATE(s, "[1, 2, \"3\", 4, 5]", false); INVALIDATE(s, "[1, 2, \"3\", 4, 5]", "", "type", "/2");
VALIDATE(s, "[]", true); VALIDATE(s, "[]", true);
} }
...@@ -647,8 +652,8 @@ TEST(SchemaValidator, Array_ItemsTuple) { ...@@ -647,8 +652,8 @@ TEST(SchemaValidator, Array_ItemsTuple) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true); VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
VALIDATE(s, "[24, \"Sussex\", \"Drive\"]", false); INVALIDATE(s, "[24, \"Sussex\", \"Drive\"]", "/items/2", "enum", "/2");
VALIDATE(s, "[\"Palais de l'Elysee\"]", false); INVALIDATE(s, "[\"Palais de l'Elysee\"]", "/items/0", "type", "/0");
VALIDATE(s, "[10, \"Downing\", \"Street\"]", true); VALIDATE(s, "[10, \"Downing\", \"Street\"]", true);
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true); VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true);
} }
...@@ -680,7 +685,7 @@ TEST(SchemaValidator, Array_AdditionalItmes) { ...@@ -680,7 +685,7 @@ TEST(SchemaValidator, Array_AdditionalItmes) {
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true); VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\"]", true); VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\"]", true);
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", false); INVALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", "", "items", "/4");
} }
TEST(SchemaValidator, Array_ItemsRange) { TEST(SchemaValidator, Array_ItemsRange) {
...@@ -688,11 +693,11 @@ TEST(SchemaValidator, Array_ItemsRange) { ...@@ -688,11 +693,11 @@ TEST(SchemaValidator, Array_ItemsRange) {
sd.Parse("{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}"); sd.Parse("{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}");
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "[]", false); INVALIDATE(s, "[]", "", "minItems", "");
VALIDATE(s, "[1]", false); INVALIDATE(s, "[1]", "", "minItems", "");
VALIDATE(s, "[1, 2]", true); VALIDATE(s, "[1, 2]", true);
VALIDATE(s, "[1, 2, 3]", true); VALIDATE(s, "[1, 2, 3]", true);
VALIDATE(s, "[1, 2, 3, 4]", false); INVALIDATE(s, "[1, 2, 3, 4]", "", "maxItems", "");
} }
TEST(SchemaValidator, Array_UniqueItems) { TEST(SchemaValidator, Array_UniqueItems) {
...@@ -701,7 +706,7 @@ TEST(SchemaValidator, Array_UniqueItems) { ...@@ -701,7 +706,7 @@ TEST(SchemaValidator, Array_UniqueItems) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "[1, 2, 3, 4, 5]", true); VALIDATE(s, "[1, 2, 3, 4, 5]", true);
VALIDATE(s, "[1, 2, 3, 3, 4]", false); INVALIDATE(s, "[1, 2, 3, 3, 4]", "", "uniqueItems", "/3");
VALIDATE(s, "[]", true); VALIDATE(s, "[]", true);
} }
...@@ -712,8 +717,8 @@ TEST(SchemaValidator, Boolean) { ...@@ -712,8 +717,8 @@ TEST(SchemaValidator, Boolean) {
VALIDATE(s, "true", true); VALIDATE(s, "true", true);
VALIDATE(s, "false", true); VALIDATE(s, "false", true);
VALIDATE(s, "\"true\"", false); INVALIDATE(s, "\"true\"", "", "type", "");
VALIDATE(s, "0", false); INVALIDATE(s, "0", "", "type", "");
} }
TEST(SchemaValidator, Null) { TEST(SchemaValidator, Null) {
...@@ -722,9 +727,9 @@ TEST(SchemaValidator, Null) { ...@@ -722,9 +727,9 @@ TEST(SchemaValidator, Null) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "null", true); VALIDATE(s, "null", true);
VALIDATE(s, "false", false); INVALIDATE(s, "false", "", "type", "");
VALIDATE(s, "0", false); INVALIDATE(s, "0", "", "type", "");
VALIDATE(s, "\"\"", false); INVALIDATE(s, "\"\"", "", "type", "");
} }
// Additional tests // Additional tests
...@@ -735,8 +740,8 @@ TEST(SchemaValidator, ObjectInArray) { ...@@ -735,8 +740,8 @@ TEST(SchemaValidator, ObjectInArray) {
SchemaDocument s(sd); SchemaDocument s(sd);
VALIDATE(s, "[\"a\"]", true); VALIDATE(s, "[\"a\"]", true);
VALIDATE(s, "[1]", false); INVALIDATE(s, "[1]", "", "type", "/0");
VALIDATE(s, "[{}]", false); INVALIDATE(s, "[{}]", "", "type", "/0");
} }
TEST(SchemaValidator, MultiTypeInObject) { TEST(SchemaValidator, MultiTypeInObject) {
...@@ -754,7 +759,7 @@ TEST(SchemaValidator, MultiTypeInObject) { ...@@ -754,7 +759,7 @@ TEST(SchemaValidator, MultiTypeInObject) {
VALIDATE(s, "{ \"tel\": 999 }", true); VALIDATE(s, "{ \"tel\": 999 }", true);
VALIDATE(s, "{ \"tel\": \"123-456\" }", true); VALIDATE(s, "{ \"tel\": \"123-456\" }", true);
VALIDATE(s, "{ \"tel\": true }", false); INVALIDATE(s, "{ \"tel\": true }", "/properties/tel", "type", "/tel");
} }
TEST(SchemaValidator, MultiTypeWithObject) { TEST(SchemaValidator, MultiTypeWithObject) {
...@@ -772,7 +777,7 @@ TEST(SchemaValidator, MultiTypeWithObject) { ...@@ -772,7 +777,7 @@ TEST(SchemaValidator, MultiTypeWithObject) {
VALIDATE(s, "\"Hello\"", true); VALIDATE(s, "\"Hello\"", true);
VALIDATE(s, "{ \"tel\": 999 }", true); VALIDATE(s, "{ \"tel\": 999 }", true);
VALIDATE(s, "{ \"tel\": \"fail\" }", false); INVALIDATE(s, "{ \"tel\": \"fail\" }", "/properties/tel", "type", "/tel");
} }
TEST(SchemaValidator, AllOf_Nested) { TEST(SchemaValidator, AllOf_Nested) {
...@@ -789,11 +794,11 @@ TEST(SchemaValidator, AllOf_Nested) { ...@@ -789,11 +794,11 @@ TEST(SchemaValidator, AllOf_Nested) {
VALIDATE(s, "\"ok\"", true); VALIDATE(s, "\"ok\"", true);
VALIDATE(s, "\"OK\"", true); VALIDATE(s, "\"OK\"", true);
VALIDATE(s, "\"okay\"", false); INVALIDATE(s, "\"okay\"", "", "allOf", "");
VALIDATE(s, "\"o\"", false); INVALIDATE(s, "\"o\"", "", "allOf", "");
VALIDATE(s, "\"n\"", false); INVALIDATE(s, "\"n\"", "", "allOf", "");
VALIDATE(s, "\"too long\"", false); INVALIDATE(s, "\"too long\"", "", "allOf", "");
VALIDATE(s, "123", false); INVALIDATE(s, "123", "", "allOf", "");
} }
static char* ReadFile(const char* filename, size_t& length) { static char* ReadFile(const char* filename, size_t& length) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment