MQTTSuite
Loading...
Searching...
No Matches
json-schema-test.cpp
Go to the documentation of this file.
1/*
2 * JSON schema validator for JSON for modern C++
3 *
4 * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.
5 *
6 * SPDX-License-Identifier: MIT
7 *
8 */
9#include <nlohmann/json-schema.hpp>
10
11#include <fstream>
12#include <iostream>
13#include <regex>
14
15using nlohmann::json;
16using nlohmann::json_uri;
17using nlohmann::json_schema::json_validator;
18
19static void loader(const json_uri &uri, json &schema)
20{
21 if (uri.location() == "http://json-schema.org/draft-07/schema") {
23 return;
24 }
25
26 std::string fn = JSON_SCHEMA_TEST_SUITE_PATH;
27 fn += "/remotes";
28 fn += uri.path();
29 std::cerr << fn << "\n";
30
31 std::fstream s(fn.c_str());
32 if (!s.good())
33 throw std::invalid_argument("could not open " + uri.url() + " for schema loading\n");
34
35 try {
36 s >> schema;
37 } catch (std::exception &e) {
38 throw e;
39 }
40}
41
42// from here
43// https://stackoverflow.com/a/34571089/880584
44static std::string base64_decode(const std::string &in)
45{
46 std::string out;
47
48 std::vector<int> T(256, -1);
49 for (int i = 0; i < 64; i++)
50 T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
51
52 unsigned val = 0;
53 int valb = -8;
54 for (uint8_t c : in) {
55 if (c == '=')
56 break;
57
58 if (T[c] == -1) {
59 throw std::invalid_argument("base64-decode: unexpected character in encode string: '" + std::string(1, c) + "'");
60 }
61 val = (val << 6) + T[c];
62 valb += 6;
63 if (valb >= 0) {
64 out.push_back(char((val >> valb) & 0xFF));
65 valb -= 8;
66 }
67 }
68 return out;
69}
70
71static void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance)
72{
73 std::string content = instance;
74
75 if (contentEncoding == "base64")
76 content = base64_decode(instance);
77 else if (contentEncoding != "")
78 throw std::invalid_argument("unable to check for contentEncoding '" + contentEncoding + "'");
79
80 if (contentMediaType == "application/json")
81 auto dummy = json::parse(content); // throws if conversion fails
82 else if (contentMediaType != "")
83 throw std::invalid_argument("unable to check for contentMediaType '" + contentMediaType + "'");
84}
85
86int main(void)
87{
88 json validation; // a validation case following the JSON-test-suite-schema
89
90 try {
91 std::cin >> validation;
92 } catch (std::exception &e) {
93 std::cout << e.what() << "\n";
94 return EXIT_FAILURE;
95 }
96
97 size_t total_failed = 0,
98 total = 0;
99
100 for (auto &test_group : validation) {
101 size_t group_failed = 0,
102 group_total = 0;
103
104 std::cout << "Testing Group " << test_group["description"] << "\n";
105
106 const auto &schema = test_group["schema"];
107
108 json_validator validator(loader,
110 content);
111
112 validator.set_root_schema(schema);
113
114 for (auto &test_case : test_group["tests"]) {
115 std::cout << " Testing Case " << test_case["description"] << "\n";
116
117 bool valid = true;
118
119 try {
120 validator.validate(test_case["data"]);
121 } catch (const std::out_of_range &e) {
122 valid = false;
123 std::cout << " Test Case Exception (out of range): " << e.what() << "\n";
124
125 } catch (const std::invalid_argument &e) {
126 valid = false;
127 std::cout << " Test Case Exception (invalid argument): " << e.what() << "\n";
128
129 } catch (const std::logic_error &e) {
130 valid = !test_case["valid"]; /* force test-case failure */
131 std::cout << " Not yet implemented: " << e.what() << "\n";
132 }
133
134 if (valid == test_case["valid"])
135 std::cout << " --> Test Case exited with " << valid << " as expected.\n";
136 else {
137 group_failed++;
138 std::cout << " --> Test Case exited with " << valid << " NOT expected.\n";
139 }
140 group_total++;
141 std::cout << "\n";
142 }
143 total_failed += group_failed;
144 total += group_total;
145 std::cout << "Group RESULT: " << test_group["description"] << " "
146 << (group_total - group_failed) << " of " << group_total
147 << " have succeeded - " << group_failed << " failed\n";
148 std::cout << "-------------\n";
149 }
150
151 std::cout << "Total RESULT: " << (total - total_failed) << " of " << total << " have succeeded - " << total_failed << " failed\n";
152
153 return total_failed;
154}
json_validator(schema_loader=nullptr, format_checker=nullptr, content_checker=nullptr)
std::string url() const
std::string location() const
Definition json-uri.cpp:102
const std::string & path() const
int main()
Definition format.cpp:34
static void loader(const json_uri &uri, json &schema)
static void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance)
static std::string base64_decode(const std::string &in)
void default_string_format_check(const std::string &format, const std::string &value)