| 2330 | } |
| 2331 | |
| 2332 | bool schemaMatch(json_spirit::mValue const& schemaValue, |
| 2333 | json_spirit::mValue const& resultValue, |
| 2334 | std::string& errorStr, |
| 2335 | Severity sev, |
| 2336 | bool checkCoverage, |
| 2337 | std::string path, |
| 2338 | std::string schemaPath) { |
| 2339 | // Returns true if everything in `result` is permitted by `schema` |
| 2340 | bool ok = true; |
| 2341 | |
| 2342 | try { |
| 2343 | if (normJSONType(schemaValue.type()) != normJSONType(resultValue.type())) { |
| 2344 | errorStr += format("ERROR: Incorrect value type for key `%s'\n", path.c_str()); |
| 2345 | TraceEvent(sev, "SchemaMismatch") |
| 2346 | .detail("Path", path) |
| 2347 | .detail("SchemaType", schemaValue.type()) |
| 2348 | .detail("ValueType", resultValue.type()); |
| 2349 | return false; |
| 2350 | } |
| 2351 | |
| 2352 | if (resultValue.type() == json_spirit::obj_type) { |
| 2353 | auto& result = resultValue.get_obj(); |
| 2354 | auto& schema = schemaValue.get_obj(); |
| 2355 | |
| 2356 | for (auto& rkv : result) { |
| 2357 | auto& key = rkv.first; |
| 2358 | auto& rv = rkv.second; |
| 2359 | std::string kpath = path + "." + key; |
| 2360 | std::string spath = schemaPath + "." + key; |
| 2361 | |
| 2362 | if (checkCoverage) { |
| 2363 | schemaCoverage(spath); |
| 2364 | } |
| 2365 | |
| 2366 | if (!schema.count(key)) { |
| 2367 | errorStr += format("ERROR: Unknown key `%s'\n", kpath.c_str()); |
| 2368 | TraceEvent(sev, "SchemaMismatch").detail("Path", kpath).detail("SchemaPath", spath); |
| 2369 | ok = false; |
| 2370 | continue; |
| 2371 | } |
| 2372 | auto& sv = schema.at(key); |
| 2373 | |
| 2374 | if (sv.type() == json_spirit::obj_type && sv.get_obj().count("$enum")) { |
| 2375 | auto& enum_values = sv.get_obj().at("$enum").get_array(); |
| 2376 | |
| 2377 | bool any_match = false; |
| 2378 | for (auto& enum_item : enum_values) |
| 2379 | if (enum_item == rv) { |
| 2380 | any_match = true; |
| 2381 | if (checkCoverage) { |
| 2382 | schemaCoverage(spath + ".$enum." + enum_item.get_str()); |
| 2383 | } |
| 2384 | break; |
| 2385 | } |
| 2386 | if (!any_match) { |
| 2387 | errorStr += format("ERROR: Unknown value `%s' for key `%s'\n", |
| 2388 | json_spirit::write_string(rv).c_str(), |
| 2389 | kpath.c_str()); |