Merge 92b4d9d1b6 into 491ac44026
This commit is contained in:
commit
9fa740d63e
@ -59,6 +59,12 @@ public:
|
||||
|
||||
virtual void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const = 0;
|
||||
|
||||
virtual void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const
|
||||
{
|
||||
json_patch patch;
|
||||
validate(ptr, instance, patch, e);
|
||||
}
|
||||
|
||||
virtual const json &default_value(const json::json_pointer &, const json &, error_handler &) const
|
||||
{
|
||||
return default_value_;
|
||||
@ -89,6 +95,16 @@ class schema_ref : public schema
|
||||
e.error(ptr, instance, "unresolved or freed schema-reference " + id_);
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const final
|
||||
{
|
||||
auto target = target_.lock();
|
||||
|
||||
if (target)
|
||||
target->validate_inplace(ptr, instance, e);
|
||||
else
|
||||
e.error(ptr, instance, "unresolved or freed schema-reference " + id_);
|
||||
}
|
||||
|
||||
const json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override final
|
||||
{
|
||||
if (!default_value_.is_null())
|
||||
@ -362,6 +378,32 @@ public:
|
||||
|
||||
sch->second->validate(ptr, instance, patch, e);
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr,
|
||||
json &instance,
|
||||
error_handler &e,
|
||||
const json_uri &initial) const
|
||||
{
|
||||
if (!root_) {
|
||||
e.error(ptr, "", "no root schema has yet been set for validating an instance");
|
||||
return;
|
||||
}
|
||||
|
||||
auto file_entry = files_.find(initial.location());
|
||||
if (file_entry == files_.end()) {
|
||||
e.error(ptr, "", "no file found serving requested root-URI. " + initial.location());
|
||||
return;
|
||||
}
|
||||
|
||||
auto &file = file_entry->second;
|
||||
auto sch = file.schemas.find(initial.fragment());
|
||||
if (sch == file.schemas.end()) {
|
||||
e.error(ptr, "", "no schema find for request initial URI: " + initial.to_string());
|
||||
return;
|
||||
}
|
||||
|
||||
sch->second->validate_inplace(ptr, instance, e);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace json_schema
|
||||
@ -404,6 +446,15 @@ class logical_not : public schema
|
||||
e.error(ptr, instance, "the subschema has succeeded, but it is required to not validate");
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const final
|
||||
{
|
||||
first_error_handler esub;
|
||||
subschema_->validate_inplace(ptr, instance, esub);
|
||||
|
||||
if (!esub)
|
||||
e.error(ptr, instance, "the subschema has succeeded, but it is required to not validate");
|
||||
}
|
||||
|
||||
const json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override
|
||||
{
|
||||
return subschema_->default_value(ptr, instance, e);
|
||||
@ -450,6 +501,29 @@ class logical_combination : public schema
|
||||
e.error(ptr, instance, "no subschema has succeeded, but one of them is required to validate");
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const final
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
for (auto &s : subschemata_) {
|
||||
first_error_handler esub;
|
||||
json new_instance(instance);
|
||||
s->validate_inplace(ptr, new_instance, esub);
|
||||
if (!esub) {
|
||||
count++;
|
||||
instance = new_instance;
|
||||
}
|
||||
|
||||
if (is_validate_complete(instance, ptr, e, esub, count))
|
||||
return;
|
||||
}
|
||||
|
||||
// could accumulate esub details for anyOf and oneOf, but not clear how to select which subschema failure to report
|
||||
// or how to report multiple such failures
|
||||
if (count == 0)
|
||||
e.error(ptr, instance, "no subschema has succeeded, but one of them is required to validate");
|
||||
}
|
||||
|
||||
// specialized for each of the logical_combination_types
|
||||
static const std::string key;
|
||||
static bool is_validate_complete(const json &, const json::json_pointer &, error_handler &, const first_error_handler &, size_t);
|
||||
@ -555,6 +629,48 @@ class type_schema : public schema
|
||||
}
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const override final
|
||||
{
|
||||
// depending on the type of instance run the type specific validator - if present
|
||||
auto type = type_[static_cast<uint8_t>(instance.type())];
|
||||
|
||||
if (type)
|
||||
type->validate_inplace(ptr, instance, e);
|
||||
else
|
||||
e.error(ptr, instance, "unexpected instance type");
|
||||
|
||||
if (enum_.first) {
|
||||
bool seen_in_enum = false;
|
||||
for (auto &v : enum_.second)
|
||||
if (instance == v) {
|
||||
seen_in_enum = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!seen_in_enum)
|
||||
e.error(ptr, instance, "instance not found in required enum");
|
||||
}
|
||||
|
||||
if (const_.first &&
|
||||
const_.second != instance)
|
||||
e.error(ptr, instance, "instance not const");
|
||||
|
||||
for (auto l : logic_)
|
||||
l->validate_inplace(ptr, instance, e);
|
||||
|
||||
if (if_) {
|
||||
first_error_handler err;
|
||||
if_->validate_inplace(ptr, instance, err);
|
||||
if (!err) {
|
||||
if (then_)
|
||||
then_->validate_inplace(ptr, instance, e);
|
||||
} else {
|
||||
if (else_)
|
||||
else_->validate_inplace(ptr, instance, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<schema> make_for_default_(
|
||||
std::shared_ptr<::schema> & /* sch */,
|
||||
@ -949,14 +1065,6 @@ class boolean : public schema
|
||||
void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override
|
||||
{
|
||||
if (!true_) { // false schema
|
||||
// empty array
|
||||
// switch (instance.type()) {
|
||||
// case json::value_t::array:
|
||||
// if (instance.size() != 0) // valid false-schema
|
||||
// e.error(ptr, instance, "false-schema required empty array");
|
||||
// return;
|
||||
//}
|
||||
|
||||
e.error(ptr, instance, "instance invalid as per false-schema");
|
||||
}
|
||||
}
|
||||
@ -982,6 +1090,20 @@ public:
|
||||
: schema(root), required_(r) {}
|
||||
};
|
||||
|
||||
json find_patch_add(const json::json_pointer &ptr, const json_patch &patch)
|
||||
{
|
||||
if (!patch.operator json().is_array()) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string path = ptr.to_string();
|
||||
for (const auto &op : patch.operator json()) {
|
||||
if (op.at("path") == path && op.at("op") == "add") {
|
||||
return op.at("value");
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class object : public schema
|
||||
{
|
||||
std::pair<bool, size_t> maxProperties_{false, 0};
|
||||
@ -1006,10 +1128,6 @@ class object : public schema
|
||||
if (minProperties_.first && instance.size() < minProperties_.second)
|
||||
e.error(ptr, instance, "too few properties");
|
||||
|
||||
for (auto &r : required_)
|
||||
if (instance.find(r) == instance.end())
|
||||
e.error(ptr, instance, "required property '" + r + "' not found in object");
|
||||
|
||||
// for each property in instance
|
||||
for (auto &p : instance.items()) {
|
||||
if (propertyNames_)
|
||||
@ -1045,6 +1163,12 @@ class object : public schema
|
||||
for (auto const &prop : properties_) {
|
||||
const auto finding = instance.find(prop.first);
|
||||
if (instance.end() == finding) { // if the prop is not in the instance
|
||||
{
|
||||
json default_value = find_patch_add((ptr / prop.first), patch);
|
||||
if (!default_value.is_null()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const auto &default_value = prop.second->default_value(ptr, instance, e);
|
||||
if (!default_value.is_null()) { // if default value is available
|
||||
patch.add((ptr / prop.first), default_value);
|
||||
@ -1052,6 +1176,14 @@ class object : public schema
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &r : required_) {
|
||||
if (instance.find(r) != instance.end())
|
||||
continue;
|
||||
if (!find_patch_add((ptr / r), patch).is_null())
|
||||
continue;
|
||||
e.error(ptr, instance, "required property '" + r + "' not found in object");
|
||||
}
|
||||
|
||||
for (auto &dep : dependencies_) {
|
||||
auto prop = instance.find(dep.first);
|
||||
if (prop != instance.end()) // if dependency-property is present in instance
|
||||
@ -1059,6 +1191,70 @@ class object : public schema
|
||||
}
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const override
|
||||
{
|
||||
if (maxProperties_.first && instance.size() > maxProperties_.second)
|
||||
e.error(ptr, instance, "too many properties");
|
||||
|
||||
if (minProperties_.first && instance.size() < minProperties_.second)
|
||||
e.error(ptr, instance, "too few properties");
|
||||
|
||||
// reverse search
|
||||
for (auto const &prop : properties_) {
|
||||
const auto finding = instance.find(prop.first);
|
||||
if (instance.end() == finding) { // if the prop is not in the instance
|
||||
const auto &default_value = prop.second->default_value(ptr, instance, e);
|
||||
if (!default_value.is_null()) { // if default value is available
|
||||
instance[prop.first] = default_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for each property in instance
|
||||
json_patch patch;
|
||||
for (auto &p : instance.items()) {
|
||||
if (propertyNames_)
|
||||
propertyNames_->validate(ptr, p.key(), patch, e);
|
||||
|
||||
bool a_prop_or_pattern_matched = false;
|
||||
auto schema_p = properties_.find(p.key());
|
||||
// check if it is in "properties"
|
||||
if (schema_p != properties_.end()) {
|
||||
a_prop_or_pattern_matched = true;
|
||||
schema_p->second->validate_inplace(ptr / p.key(), p.value(), e);
|
||||
}
|
||||
|
||||
#ifndef NO_STD_REGEX
|
||||
// check all matching patternProperties
|
||||
for (auto &schema_pp : patternProperties_)
|
||||
if (REGEX_NAMESPACE::regex_search(p.key(), schema_pp.first)) {
|
||||
a_prop_or_pattern_matched = true;
|
||||
schema_pp.second->validate_inplace(ptr / p.key(), p.value(), e);
|
||||
}
|
||||
#endif
|
||||
|
||||
// check additionalProperties as a last resort
|
||||
if (!a_prop_or_pattern_matched && additionalProperties_) {
|
||||
first_error_handler additional_prop_err;
|
||||
additionalProperties_->validate_inplace(ptr / p.key(), p.value(), additional_prop_err);
|
||||
if (additional_prop_err)
|
||||
e.error(ptr, instance, "validation failed for additional property '" + p.key() + "': " + additional_prop_err.message_);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &r : required_) {
|
||||
if (instance.find(r) != instance.end())
|
||||
continue;
|
||||
e.error(ptr, instance, "required property '" + r + "' not found in object");
|
||||
}
|
||||
|
||||
for (auto &dep : dependencies_) {
|
||||
auto prop = instance.find(dep.first);
|
||||
if (prop != instance.end()) // if dependency-property is present in instance
|
||||
dep.second->validate_inplace(ptr / dep.first, instance, e); // validate
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
object(json &sch,
|
||||
root_schema *root,
|
||||
@ -1205,6 +1401,61 @@ class array : public schema
|
||||
}
|
||||
}
|
||||
|
||||
void validate_inplace(const json::json_pointer &ptr, json &instance, error_handler &e) const override
|
||||
{
|
||||
if (maxItems_.first && instance.size() > maxItems_.second)
|
||||
e.error(ptr, instance, "array has too many items");
|
||||
|
||||
if (minItems_.first && instance.size() < minItems_.second)
|
||||
e.error(ptr, instance, "array has too few items");
|
||||
|
||||
if (uniqueItems_) {
|
||||
for (auto it = instance.begin(); it != instance.end(); ++it) {
|
||||
auto v = std::find(it + 1, instance.end(), *it);
|
||||
if (v != instance.end())
|
||||
e.error(ptr, instance, "items have to be unique for this array");
|
||||
}
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
if (items_schema_)
|
||||
for (auto &i : instance) {
|
||||
items_schema_->validate_inplace(ptr / index, i, e);
|
||||
index++;
|
||||
}
|
||||
else {
|
||||
auto item = items_.cbegin();
|
||||
for (auto &i : instance) {
|
||||
std::shared_ptr<schema> item_validator;
|
||||
if (item == items_.cend())
|
||||
item_validator = additionalItems_;
|
||||
else {
|
||||
item_validator = *item;
|
||||
item++;
|
||||
}
|
||||
|
||||
if (!item_validator)
|
||||
break;
|
||||
|
||||
item_validator->validate_inplace(ptr / index, i, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (contains_) {
|
||||
bool contained = false;
|
||||
for (auto &item : instance) {
|
||||
first_error_handler local_e;
|
||||
contains_->validate_inplace(ptr, item, local_e);
|
||||
if (!local_e) {
|
||||
contained = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!contained)
|
||||
e.error(ptr, instance, "array does not contain required element as per 'contains'");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
array(json &sch, root_schema *root, const std::vector<nlohmann::json_uri> &uris)
|
||||
: schema(root)
|
||||
@ -1450,5 +1701,17 @@ json json_validator::validate(const json &instance, error_handler &err, const js
|
||||
return patch;
|
||||
}
|
||||
|
||||
void json_validator::validate_inplace(json &instance) const
|
||||
{
|
||||
throwing_error_handler err;
|
||||
validate_inplace(instance, err);
|
||||
}
|
||||
|
||||
void json_validator::validate_inplace(json &instance, error_handler &err, const json_uri &initial_uri) const
|
||||
{
|
||||
json::json_pointer ptr;
|
||||
root_->validate_inplace(ptr, instance, err, initial_uri);
|
||||
}
|
||||
|
||||
} // namespace json_schema
|
||||
} // namespace nlohmann
|
||||
|
||||
@ -190,6 +190,14 @@ public:
|
||||
|
||||
// validate a json-document based on the root-schema with a custom error-handler
|
||||
json validate(const json &, error_handler &, const json_uri &initial_uri = json_uri("#")) const;
|
||||
|
||||
// validate a json-document in place based on the root-schema.
|
||||
// Default values of schema are inserted in-place with the given json-document
|
||||
void validate_inplace(json &) const;
|
||||
|
||||
// validate a json-document based on the root-schema with a custom error-handler.
|
||||
// Default values of schema are inserted in-place with the given json-document
|
||||
void validate_inplace(json &, error_handler &, const json_uri &initial_uri = json_uri("#")) const;
|
||||
};
|
||||
|
||||
} // namespace json_schema
|
||||
|
||||
@ -73,3 +73,7 @@ add_test(NAME issue-149-entry-selection COMMAND issue-149-entry-selection)
|
||||
add_executable(issue-189-default-values issue-189-default-values.cpp)
|
||||
target_link_libraries(issue-189-default-values nlohmann_json_schema_validator)
|
||||
add_test(NAME issue-189-default-values COMMAND issue-189-default-values)
|
||||
|
||||
add_executable(issue-232-patch-in-place issue-232-patch-in-place.cpp)
|
||||
target_link_libraries(issue-232-patch-in-place nlohmann_json_schema_validator)
|
||||
add_test(NAME issue-232-patch-in-place COMMAND issue-232-patch-in-place)
|
||||
@ -111,34 +111,49 @@ int main(void)
|
||||
|
||||
validator.set_root_schema(schema);
|
||||
|
||||
for (auto &test_case : test_group["tests"]) {
|
||||
std::cout << " Testing Case " << test_case["description"] << "\n";
|
||||
for (bool inplace : {false, true}) {
|
||||
for (auto &test_case : test_group["tests"]) {
|
||||
std::cout << " Testing Case " << test_case["description"] << "\n";
|
||||
|
||||
bool valid = true;
|
||||
bool valid = true;
|
||||
|
||||
try {
|
||||
validator.validate(test_case["data"]);
|
||||
} catch (const std::out_of_range &e) {
|
||||
valid = false;
|
||||
std::cout << " Test Case Exception (out of range): " << e.what() << "\n";
|
||||
try {
|
||||
json data(test_case["data"]);
|
||||
if (inplace)
|
||||
validator.validate_inplace(data);
|
||||
else
|
||||
validator.validate(data);
|
||||
|
||||
} catch (const std::invalid_argument &e) {
|
||||
valid = false;
|
||||
std::cout << " Test Case Exception (invalid argument): " << e.what() << "\n";
|
||||
} catch (const std::out_of_range &e) {
|
||||
valid = false;
|
||||
std::cout << " Test Case Exception (out of range): " << e.what() << "\n";
|
||||
|
||||
} catch (const std::logic_error &e) {
|
||||
valid = !test_case["valid"]; /* force test-case failure */
|
||||
std::cout << " Not yet implemented: " << e.what() << "\n";
|
||||
} catch (const std::invalid_argument &e) {
|
||||
valid = false;
|
||||
std::cout << " Test Case Exception (invalid argument): " << e.what() << "\n";
|
||||
|
||||
} catch (const std::logic_error &e) {
|
||||
valid = !test_case["valid"]; /* force test-case failure */
|
||||
std::cout << " Not yet implemented: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
bool expected = //
|
||||
test_case.at("valid").is_boolean() //
|
||||
? test_case.at("valid").get<bool>() //
|
||||
: inplace //
|
||||
? test_case.at("/valid/inplace"_json_pointer).get<bool>() //
|
||||
: test_case.at("/valid/not_inplace"_json_pointer).get<bool>(); //
|
||||
std::string inplace_prefix = inplace ? "valid_inplace" : "valid";
|
||||
if (valid == expected)
|
||||
std::cout
|
||||
<< " --> [" << inplace_prefix << "] Test Case exited with " << valid << " as expected.\n";
|
||||
else {
|
||||
group_failed++;
|
||||
std::cout << " --> [" << inplace_prefix << "] Test Case exited with " << valid << " NOT expected.\n";
|
||||
}
|
||||
group_total++;
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
if (valid == test_case["valid"])
|
||||
std::cout << " --> Test Case exited with " << valid << " as expected.\n";
|
||||
else {
|
||||
group_failed++;
|
||||
std::cout << " --> Test Case exited with " << valid << " NOT expected.\n";
|
||||
}
|
||||
group_total++;
|
||||
std::cout << "\n";
|
||||
}
|
||||
total_failed += group_failed;
|
||||
total += group_total;
|
||||
|
||||
@ -18,7 +18,10 @@
|
||||
{
|
||||
"description": "still valid when the invalid default is used",
|
||||
"data": {},
|
||||
"valid": true
|
||||
"valid": {
|
||||
"inplace": false,
|
||||
"not_inplace": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -42,7 +45,10 @@
|
||||
{
|
||||
"description": "still valid when the invalid default is used",
|
||||
"data": {},
|
||||
"valid": true
|
||||
"valid": {
|
||||
"inplace": false,
|
||||
"not_inplace": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -72,7 +78,10 @@
|
||||
{
|
||||
"description": "missing properties are not filled in with the default",
|
||||
"data": {},
|
||||
"valid": true
|
||||
"valid": {
|
||||
"inplace": false,
|
||||
"not_inplace": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -30,7 +30,11 @@ cmake \
|
||||
${EXTRA_ARGS} \
|
||||
${SRC_DIR}
|
||||
|
||||
CPU_COUNT=$(nproc)
|
||||
CPU_COUNT=$( \
|
||||
which nproc &>/dev/null && nproc \
|
||||
|| which getconf &>/dev/null && getconf _NPROCESSORS_ONLN 2>/dev/null \
|
||||
|| echo 1 \
|
||||
)
|
||||
|
||||
# Build and install json-schema-validator
|
||||
cmake --build . -- -j${CPU_COUNT}
|
||||
|
||||
140
test/issue-232-patch-in-place.cpp
Normal file
140
test/issue-232-patch-in-place.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json-schema.hpp>
|
||||
|
||||
using nlohmann::json;
|
||||
using nlohmann::json_uri;
|
||||
using nlohmann::json_schema::json_validator;
|
||||
using namespace std::chrono;
|
||||
|
||||
void add_sub_schema(json &schema, int depth)
|
||||
{
|
||||
schema["type"] = "object";
|
||||
schema["default"] = json::object();
|
||||
schema["properties"] = R"(
|
||||
{
|
||||
"array": {
|
||||
"type": "array",
|
||||
"default": [
|
||||
{"name": "foo"}
|
||||
],
|
||||
"items": {
|
||||
"required": ["name"],
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"enum": "foo"
|
||||
},
|
||||
"code": {
|
||||
"const": 1,
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"enum": "bar"
|
||||
},
|
||||
"code": {
|
||||
"const": 2,
|
||||
"default": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
)"_json;
|
||||
if (--depth >= 0) {
|
||||
json &properties = schema.at("/properties/array/items/oneOf/0/properties"_json_pointer);
|
||||
properties["sub"] = json::object();
|
||||
add_sub_schema(properties.at("sub"), depth);
|
||||
}
|
||||
}
|
||||
|
||||
void add_sub_data(json &data, int depth)
|
||||
{
|
||||
data["array"] = R"(
|
||||
[
|
||||
{
|
||||
"name": "foo",
|
||||
"code": 1
|
||||
}
|
||||
]
|
||||
)"_json;
|
||||
if (--depth >= 0) {
|
||||
json &item = data.at("/array/0"_json_pointer);
|
||||
item["sub"] = json::object();
|
||||
add_sub_schema(item.at("sub"), depth);
|
||||
}
|
||||
}
|
||||
|
||||
static const int DEPTH = 100;
|
||||
static const json get_schema()
|
||||
{
|
||||
static json schema;
|
||||
if (schema.empty()) {
|
||||
schema = R"(
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||
}
|
||||
)"_json;
|
||||
add_sub_schema(schema, DEPTH);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
static void loader(const json_uri &uri, json &schema)
|
||||
{
|
||||
schema = get_schema();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
json_validator validator(loader);
|
||||
|
||||
validator.set_root_schema(get_schema());
|
||||
|
||||
json data = json::object();
|
||||
json expected(data);
|
||||
add_sub_data(expected, DEPTH);
|
||||
|
||||
auto start = high_resolution_clock::now();
|
||||
#if 1
|
||||
validator.validate_inplace(data);
|
||||
#else
|
||||
size_t count = 0;
|
||||
while (true) { // https://github.com/pboettch/json-schema-validator/issues/206#issuecomment-1173404152
|
||||
json patch = validator.validate(data);
|
||||
if (patch.empty()) {
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
data.patch_inplace(patch);
|
||||
}
|
||||
std::cout << "Number of iterations: " << count << std::endl;
|
||||
#endif
|
||||
auto stop = high_resolution_clock::now();
|
||||
auto duration = duration_cast<microseconds>(stop - start);
|
||||
if (duration.count() > 300000) {
|
||||
std::cerr << "To long duration: " << duration.count() << " us" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto diff = json::diff( //
|
||||
data, //
|
||||
expected //
|
||||
);
|
||||
if (diff.empty()) {
|
||||
std::cerr << "Unexpected data: '" << data.dump() << "' instead of expected '" << expected.dump() << "' differences are:" << diff.dump() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -78,19 +78,19 @@ int main(void)
|
||||
}
|
||||
|
||||
if (default_patch.size() != 1) {
|
||||
std::cerr << "Patch with defaults is expected to contain one opperation" << std::endl;
|
||||
std::cerr << "Patch with defaults is expected to contain one operation" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto &single_op = default_patch[0];
|
||||
|
||||
if (!single_op.contains("op")) {
|
||||
std::cerr << "Patch with defaults is expected to contain opperation entry" << std::endl;
|
||||
std::cerr << "Patch with defaults is expected to contain operation entry" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (single_op["op"].get<std::string>() != "add") {
|
||||
std::cerr << "Patch with defaults is expected to contain add opperation" << std::endl;
|
||||
std::cerr << "Patch with defaults is expected to contain add operation" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -132,19 +132,19 @@ int main(void)
|
||||
}
|
||||
|
||||
if (default_patch.size() != 1) {
|
||||
std::cerr << "Patch with defaults is expected to contain one opperation" << std::endl;
|
||||
std::cerr << "Patch with defaults is expected to contain one operation" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto &single_op = default_patch[0];
|
||||
|
||||
if (!single_op.contains("op")) {
|
||||
std::cerr << "Patch with defaults is expected to contain opperation entry" << std::endl;
|
||||
std::cerr << "Patch with defaults is expected to contain operation entry" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (single_op["op"].get<std::string>() != "add") {
|
||||
std::cerr << "Patch with defaults is expected to contain add opperation" << std::endl;
|
||||
std::cerr << "Patch with defaults is expected to contain add operation" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user