Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
schematest.cpp
Go to the documentation of this file.
1// Tencent is pleased to support the open source community by making RapidJSON available.
2//
3// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4//
5// Licensed under the MIT License (the "License"); you may not use this file except
6// in compliance with the License. You may obtain a copy of the License at
7//
8// http://opensource.org/licenses/MIT
9//
10// Unless required by applicable law or agreed to in writing, software distributed
11// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12// CONDITIONS OF ANY KIND, either express or implied. See the License for the
13// specific language governing permissions and limitations under the License.
14
15#include "unittest.h"
16#include "rapidjson/schema.h"
18#include "rapidjson/writer.h"
19
20#ifdef __clang__
21RAPIDJSON_DIAG_PUSH
22RAPIDJSON_DIAG_OFF(variadic-macros)
23#elif defined(_MSC_VER)
24RAPIDJSON_DIAG_PUSH
25RAPIDJSON_DIAG_OFF(4822) // local class member function does not have a body
26#endif
27
28using namespace rapidjson;
29
30#define TEST_HASHER(json1, json2, expected) \
31{\
32 Document d1, d2;\
33 d1.Parse(json1);\
34 ASSERT_FALSE(d1.HasParseError());\
35 d2.Parse(json2);\
36 ASSERT_FALSE(d2.HasParseError());\
37 internal::Hasher<Value, CrtAllocator> h1, h2;\
38 d1.Accept(h1);\
39 d2.Accept(h2);\
40 ASSERT_TRUE(h1.IsValid());\
41 ASSERT_TRUE(h2.IsValid());\
42 /*printf("%s: 0x%016llx\n%s: 0x%016llx\n\n", json1, h1.GetHashCode(), json2, h2.GetHashCode());*/\
43 EXPECT_TRUE(expected == (h1.GetHashCode() == h2.GetHashCode()));\
44}
45
47 TEST_HASHER("null", "null", true);
48
49 TEST_HASHER("true", "true", true);
50 TEST_HASHER("false", "false", true);
51 TEST_HASHER("true", "false", false);
52 TEST_HASHER("false", "true", false);
53 TEST_HASHER("true", "null", false);
54 TEST_HASHER("false", "null", false);
55
56 TEST_HASHER("1", "1", true);
57 TEST_HASHER("2147483648", "2147483648", true); // 2^31 can only be fit in unsigned
58 TEST_HASHER("-2147483649", "-2147483649", true); // -2^31 - 1 can only be fit in int64_t
59 TEST_HASHER("2147483648", "2147483648", true); // 2^31 can only be fit in unsigned
60 TEST_HASHER("4294967296", "4294967296", true); // 2^32 can only be fit in int64_t
61 TEST_HASHER("9223372036854775808", "9223372036854775808", true); // 2^63 can only be fit in uint64_t
62 TEST_HASHER("1.5", "1.5", true);
63 TEST_HASHER("1", "1.0", true);
64 TEST_HASHER("1", "-1", false);
65 TEST_HASHER("0.0", "-0.0", false);
66 TEST_HASHER("1", "true", false);
67 TEST_HASHER("0", "false", false);
68 TEST_HASHER("0", "null", false);
69
70 TEST_HASHER("\"\"", "\"\"", true);
71 TEST_HASHER("\"\"", "\"\\u0000\"", false);
72 TEST_HASHER("\"Hello\"", "\"Hello\"", true);
73 TEST_HASHER("\"Hello\"", "\"World\"", false);
74 TEST_HASHER("\"Hello\"", "null", false);
75 TEST_HASHER("\"Hello\\u0000\"", "\"Hello\"", false);
76 TEST_HASHER("\"\"", "null", false);
77 TEST_HASHER("\"\"", "true", false);
78 TEST_HASHER("\"\"", "false", false);
79
80 TEST_HASHER("[]", "[ ]", true);
81 TEST_HASHER("[1, true, false]", "[1, true, false]", true);
82 TEST_HASHER("[1, true, false]", "[1, true]", false);
83 TEST_HASHER("[1, 2]", "[2, 1]", false);
84 TEST_HASHER("[[1], 2]", "[[1, 2]]", false);
85 TEST_HASHER("[1, 2]", "[1, [2]]", false);
86 TEST_HASHER("[]", "null", false);
87 TEST_HASHER("[]", "true", false);
88 TEST_HASHER("[]", "false", false);
89 TEST_HASHER("[]", "0", false);
90 TEST_HASHER("[]", "0.0", false);
91 TEST_HASHER("[]", "\"\"", false);
92
93 TEST_HASHER("{}", "{ }", true);
94 TEST_HASHER("{\"a\":1}", "{\"a\":1}", true);
95 TEST_HASHER("{\"a\":1}", "{\"b\":1}", false);
96 TEST_HASHER("{\"a\":1}", "{\"a\":2}", false);
97 TEST_HASHER("{\"a\":1, \"b\":2}", "{\"b\":2, \"a\":1}", true); // Member order insensitive
98 TEST_HASHER("{}", "null", false);
99 TEST_HASHER("{}", "false", false);
100 TEST_HASHER("{}", "true", false);
101 TEST_HASHER("{}", "0", false);
102 TEST_HASHER("{}", "0.0", false);
103 TEST_HASHER("{}", "\"\"", false);
104}
105
106// Test cases following http://spacetelescope.github.io/understanding-json-schema
107
108#define VALIDATE(schema, json, expected) \
109{\
110 SchemaValidator validator(schema);\
111 Document d;\
112 /*printf("\n%s\n", json);*/\
113 d.Parse(json);\
114 EXPECT_FALSE(d.HasParseError());\
115 EXPECT_TRUE(expected == d.Accept(validator));\
116 EXPECT_TRUE(expected == validator.IsValid());\
117 if ((expected) && !validator.IsValid()) {\
118 StringBuffer sb;\
119 validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\
120 printf("Invalid schema: %s\n", sb.GetString());\
121 printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());\
122 sb.Clear();\
123 validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);\
124 printf("Invalid document: %s\n", sb.GetString());\
125 sb.Clear();\
126 Writer<StringBuffer> w(sb);\
127 validator.GetError().Accept(w);\
128 printf("Validation error: %s\n", sb.GetString());\
129 }\
130}
131
132#define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error) \
133{\
134 INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, SchemaValidator, Pointer) \
135}
136
137#define INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, \
138 SchemaValidatorType, PointerType) \
139{\
140 SchemaValidatorType validator(schema);\
141 Document d;\
142 /*printf("\n%s\n", json);*/\
143 d.Parse(json);\
144 EXPECT_FALSE(d.HasParseError());\
145 EXPECT_FALSE(d.Accept(validator));\
146 EXPECT_FALSE(validator.IsValid());\
147 if (validator.GetInvalidSchemaPointer() != PointerType(invalidSchemaPointer)) {\
148 StringBuffer sb;\
149 validator.GetInvalidSchemaPointer().Stringify(sb);\
150 printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\
151 ADD_FAILURE();\
152 }\
153 ASSERT_TRUE(validator.GetInvalidSchemaKeyword() != 0);\
154 if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\
155 printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\
156 ADD_FAILURE();\
157 }\
158 if (validator.GetInvalidDocumentPointer() != PointerType(invalidDocumentPointer)) {\
159 StringBuffer sb;\
160 validator.GetInvalidDocumentPointer().Stringify(sb);\
161 printf("GetInvalidDocumentPointer() Expected: %s Actual: %s\n", invalidDocumentPointer, sb.GetString());\
162 ADD_FAILURE();\
163 }\
164 Document e;\
165 e.Parse(error);\
166 if (validator.GetError() != e) {\
167 StringBuffer sb;\
168 Writer<StringBuffer> w(sb);\
169 validator.GetError().Accept(w);\
170 printf("GetError() Expected: %s Actual: %s\n", error, sb.GetString());\
171 ADD_FAILURE();\
172 }\
173}
174
176 Document sd;
177 sd.Parse("{}");
178 SchemaDocument s(sd);
179
180 VALIDATE(s, "42", true);
181 VALIDATE(s, "\"I'm a string\"", true);
182 VALIDATE(s, "{ \"an\": [ \"arbitrarily\", \"nested\" ], \"data\": \"structure\" }", true);
183}
184
186 Document sd;
187 sd.Parse("{ \"type\": [\"number\", \"string\"] }");
188 SchemaDocument s(sd);
189
190 VALIDATE(s, "42", true);
191 VALIDATE(s, "\"Life, the universe, and everything\"", true);
192 INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "",
193 "{ \"type\": {"
194 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
195 " \"expected\": [\"string\", \"number\"], \"actual\": \"array\""
196 "}}");
197}
198
199TEST(SchemaValidator, Enum_Typed) {
200 Document sd;
201 sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
202 SchemaDocument s(sd);
203
204 VALIDATE(s, "\"red\"", true);
205 INVALIDATE(s, "\"blue\"", "", "enum", "",
206 "{ \"enum\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
207}
208
209TEST(SchemaValidator, Enum_Typless) {
210 Document sd;
211 sd.Parse("{ \"enum\": [\"red\", \"amber\", \"green\", null, 42] }");
212 SchemaDocument s(sd);
213
214 VALIDATE(s, "\"red\"", true);
215 VALIDATE(s, "null", true);
216 VALIDATE(s, "42", true);
217 INVALIDATE(s, "0", "", "enum", "",
218 "{ \"enum\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
219}
220
221TEST(SchemaValidator, Enum_InvalidType) {
222 Document sd;
223 sd.Parse("{ \"type\": \"string\", \"enum\": [\"red\", \"amber\", \"green\", null] }");
224 SchemaDocument s(sd);
225
226 VALIDATE(s, "\"red\"", true);
227 INVALIDATE(s, "null", "", "type", "",
228 "{ \"type\": {"
229 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
230 " \"expected\": [\"string\"], \"actual\": \"null\""
231 "}}");
232}
233
235 {
236 Document sd;
237 sd.Parse("{\"allOf\": [{ \"type\": \"string\" }, { \"type\": \"string\", \"maxLength\": 5 }]}");
238 SchemaDocument s(sd);
239
240 VALIDATE(s, "\"ok\"", true);
241 INVALIDATE(s, "\"too long\"", "", "allOf", "",
242 "{ \"maxLength\": { "
243 " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\", "
244 " \"expected\": 5, \"actual\": \"too long\""
245 "}}");
246 }
247 {
248 Document sd;
249 sd.Parse("{\"allOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }");
250 SchemaDocument s(sd);
251
252 VALIDATE(s, "\"No way\"", false);
253 INVALIDATE(s, "-1", "", "allOf", "",
254 "{ \"type\": { \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\","
255 " \"expected\": [\"string\"], \"actual\": \"integer\""
256 "}}");
257 }
258}
259
261 Document sd;
262 sd.Parse("{\"anyOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }");
263 SchemaDocument s(sd);
264
265 VALIDATE(s, "\"Yes\"", true);
266 VALIDATE(s, "42", true);
267 INVALIDATE(s, "{ \"Not a\": \"string or number\" }", "", "anyOf", "",
268 "{ \"anyOf\": {"
269 " \"instanceRef\": \"#\", \"schemaRef\": \"#\", "
270 " \"errors\": ["
271 " { \"type\": {"
272 " \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\","
273 " \"expected\": [\"string\"], \"actual\": \"object\""
274 " }},"
275 " { \"type\": {"
276 " \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/1\","
277 " \"expected\": [\"number\"], \"actual\": \"object\""
278 " }}"
279 " ]"
280 "}}");
281}
282
284 Document sd;
285 sd.Parse("{\"oneOf\": [{ \"type\": \"number\", \"multipleOf\": 5 }, { \"type\": \"number\", \"multipleOf\": 3 } ] }");
286 SchemaDocument s(sd);
287
288 VALIDATE(s, "10", true);
289 VALIDATE(s, "9", true);
290 INVALIDATE(s, "2", "", "oneOf", "",
291 "{ \"oneOf\": {"
292 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
293 " \"errors\": ["
294 " { \"multipleOf\": {"
295 " \"instanceRef\": \"#\", \"schemaRef\": \"#/oneOf/0\","
296 " \"expected\": 5, \"actual\": 2"
297 " }},"
298 " { \"multipleOf\": {"
299 " \"instanceRef\": \"#\", \"schemaRef\": \"#/oneOf/1\","
300 " \"expected\": 3, \"actual\": 2"
301 " }}"
302 " ]"
303 "}}");
304 INVALIDATE(s, "15", "", "oneOf", "",
305 "{ \"oneOf\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"errors\": [{}, {}]}}");
306}
307
309 Document sd;
310 sd.Parse("{\"not\":{ \"type\": \"string\"}}");
311 SchemaDocument s(sd);
312
313 VALIDATE(s, "42", true);
314 VALIDATE(s, "{ \"key\": \"value\" }", true);
315 INVALIDATE(s, "\"I am a string\"", "", "not", "",
316 "{ \"not\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
317}
318
320 Document sd;
321 sd.Parse(
322 "{"
323 " \"$schema\": \"http://json-schema.org/draft-04/schema#\","
324 ""
325 " \"definitions\": {"
326 " \"address\": {"
327 " \"type\": \"object\","
328 " \"properties\": {"
329 " \"street_address\": { \"type\": \"string\" },"
330 " \"city\": { \"type\": \"string\" },"
331 " \"state\": { \"type\": \"string\" }"
332 " },"
333 " \"required\": [\"street_address\", \"city\", \"state\"]"
334 " }"
335 " },"
336 " \"type\": \"object\","
337 " \"properties\": {"
338 " \"billing_address\": { \"$ref\": \"#/definitions/address\" },"
339 " \"shipping_address\": { \"$ref\": \"#/definitions/address\" }"
340 " }"
341 "}");
342 SchemaDocument s(sd);
343
344 VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"}, \"billing_address\": {\"street_address\": \"1st Street SE\", \"city\": \"Washington\", \"state\": \"DC\"} }", true);
345}
346
348 Document sd;
349 sd.Parse(
350 "{"
351 " \"$schema\": \"http://json-schema.org/draft-04/schema#\","
352 ""
353 " \"definitions\": {"
354 " \"address\": {"
355 " \"type\": \"object\","
356 " \"properties\": {"
357 " \"street_address\": { \"type\": \"string\" },"
358 " \"city\": { \"type\": \"string\" },"
359 " \"state\": { \"type\": \"string\" }"
360 " },"
361 " \"required\": [\"street_address\", \"city\", \"state\"]"
362 " }"
363 " },"
364 " \"type\": \"object\","
365 " \"properties\": {"
366 " \"billing_address\": { \"$ref\": \"#/definitions/address\" },"
367 " \"shipping_address\": {"
368 " \"allOf\": ["
369 " { \"$ref\": \"#/definitions/address\" },"
370 " { \"properties\":"
371 " { \"type\": { \"enum\": [ \"residential\", \"business\" ] } },"
372 " \"required\": [\"type\"]"
373 " }"
374 " ]"
375 " }"
376 " }"
377 "}");
378 SchemaDocument s(sd);
379
380 INVALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"} }", "/properties/shipping_address", "allOf", "/shipping_address",
381 "{ \"required\": {"
382 " \"instanceRef\": \"#/shipping_address\","
383 " \"schemaRef\": \"#/properties/shipping_address/allOf/1\","
384 " \"missing\": [\"type\"]"
385 "}}");
386 VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\", \"type\": \"business\"} }", true);
387}
388
390 Document sd;
391 sd.Parse("{\"type\":\"string\"}");
392 SchemaDocument s(sd);
393
394 VALIDATE(s, "\"I'm a string\"", true);
395 INVALIDATE(s, "42", "", "type", "",
396 "{ \"type\": {"
397 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
398 " \"expected\": [\"string\"], \"actual\": \"integer\""
399 "}}");
400 INVALIDATE(s, "2147483648", "", "type", "",
401 "{ \"type\": {"
402 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
403 " \"expected\": [\"string\"], \"actual\": \"integer\""
404 "}}"); // 2^31 can only be fit in unsigned
405 INVALIDATE(s, "-2147483649", "", "type", "",
406 "{ \"type\": {"
407 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
408 " \"expected\": [\"string\"], \"actual\": \"integer\""
409 "}}"); // -2^31 - 1 can only be fit in int64_t
410 INVALIDATE(s, "4294967296", "", "type", "",
411 "{ \"type\": {"
412 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
413 " \"expected\": [\"string\"], \"actual\": \"integer\""
414 "}}"); // 2^32 can only be fit in int64_t
415 INVALIDATE(s, "3.1415926", "", "type", "",
416 "{ \"type\": {"
417 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
418 " \"expected\": [\"string\"], \"actual\": \"number\""
419 "}}");
420}
421
422TEST(SchemaValidator, String_LengthRange) {
423 Document sd;
424 sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
425 SchemaDocument s(sd);
426
427 INVALIDATE(s, "\"A\"", "", "minLength", "",
428 "{ \"minLength\": {"
429 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
430 " \"expected\": 2, \"actual\": \"A\""
431 "}}");
432 VALIDATE(s, "\"AB\"", true);
433 VALIDATE(s, "\"ABC\"", true);
434 INVALIDATE(s, "\"ABCD\"", "", "maxLength", "",
435 "{ \"maxLength\": {"
436 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
437 " \"expected\": 3, \"actual\": \"ABCD\""
438 "}}");
439}
440
441#if RAPIDJSON_SCHEMA_HAS_REGEX
442TEST(SchemaValidator, String_Pattern) {
443 Document sd;
444 sd.Parse("{\"type\":\"string\",\"pattern\":\"^(\\\\([0-9]{3}\\\\))?[0-9]{3}-[0-9]{4}$\"}");
445 SchemaDocument s(sd);
446
447 VALIDATE(s, "\"555-1212\"", true);
448 VALIDATE(s, "\"(888)555-1212\"", true);
449 INVALIDATE(s, "\"(888)555-1212 ext. 532\"", "", "pattern", "",
450 "{ \"pattern\": {"
451 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
452 " \"actual\": \"(888)555-1212 ext. 532\""
453 "}}");
454 INVALIDATE(s, "\"(800)FLOWERS\"", "", "pattern", "",
455 "{ \"pattern\": {"
456 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
457 " \"actual\": \"(800)FLOWERS\""
458 "}}");
459}
460
461TEST(SchemaValidator, String_Pattern_Invalid) {
462 Document sd;
463 sd.Parse("{\"type\":\"string\",\"pattern\":\"a{0}\"}"); // TODO: report regex is invalid somehow
464 SchemaDocument s(sd);
465
466 VALIDATE(s, "\"\"", true);
467 VALIDATE(s, "\"a\"", true);
468 VALIDATE(s, "\"aa\"", true);
469}
470#endif
471
473 Document sd;
474 sd.Parse("{\"type\":\"integer\"}");
475 SchemaDocument s(sd);
476
477 VALIDATE(s, "42", true);
478 VALIDATE(s, "-1", true);
479 VALIDATE(s, "2147483648", true); // 2^31 can only be fit in unsigned
480 VALIDATE(s, "-2147483649", true); // -2^31 - 1 can only be fit in int64_t
481 VALIDATE(s, "2147483648", true); // 2^31 can only be fit in unsigned
482 VALIDATE(s, "4294967296", true); // 2^32 can only be fit in int64_t
483 INVALIDATE(s, "3.1415926", "", "type", "",
484 "{ \"type\": {"
485 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
486 " \"expected\": [\"integer\"], \"actual\": \"number\""
487 "}}");
488 INVALIDATE(s, "\"42\"", "", "type", "",
489 "{ \"type\": {"
490 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
491 " \"expected\": [\"integer\"], \"actual\": \"string\""
492 "}}");
493}
494
495TEST(SchemaValidator, Integer_Range) {
496 Document sd;
497 sd.Parse("{\"type\":\"integer\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}");
498 SchemaDocument s(sd);
499
500 INVALIDATE(s, "-1", "", "minimum", "",
501 "{ \"minimum\": {"
502 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
503 " \"expected\": 0, \"actual\": -1"
504 "}}");
505 VALIDATE(s, "0", true);
506 VALIDATE(s, "10", true);
507 VALIDATE(s, "99", true);
508 INVALIDATE(s, "100", "", "maximum", "",
509 "{ \"maximum\": {"
510 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
511 " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100"
512 "}}");
513 INVALIDATE(s, "101", "", "maximum", "",
514 "{ \"maximum\": {"
515 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
516 " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 101"
517 "}}");
518}
519
520TEST(SchemaValidator, Integer_Range64Boundary) {
521 Document sd;
522 sd.Parse("{\"type\":\"integer\",\"minimum\":-9223372036854775807,\"maximum\":9223372036854775806}");
523 SchemaDocument s(sd);
524
525 INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
526 "{ \"minimum\": {"
527 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
528 " \"expected\": -9223372036854775807, \"actual\": -9223372036854775808"
529 "}}");
530 VALIDATE(s, "-9223372036854775807", true);
531 VALIDATE(s, "-2147483648", true); // int min
532 VALIDATE(s, "0", true);
533 VALIDATE(s, "2147483647", true); // int max
534 VALIDATE(s, "2147483648", true); // unsigned first
535 VALIDATE(s, "4294967295", true); // unsigned max
536 VALIDATE(s, "9223372036854775806", true);
537 INVALIDATE(s, "9223372036854775807", "", "maximum", "",
538 "{ \"maximum\": {"
539 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
540 " \"expected\": 9223372036854775806, \"actual\": 9223372036854775807"
541 "}}");
542 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
543 "{ \"maximum\": {"
544 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
545 " \"expected\": 9223372036854775806, \"actual\": 18446744073709551615"
546 "}}"); // uint64_t max
547}
548
549TEST(SchemaValidator, Integer_RangeU64Boundary) {
550 Document sd;
551 sd.Parse("{\"type\":\"integer\",\"minimum\":9223372036854775808,\"maximum\":18446744073709551614}");
552 SchemaDocument s(sd);
553
554 INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
555 "{ \"minimum\": {"
556 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
557 " \"expected\": 9223372036854775808, \"actual\": -9223372036854775808"
558 "}}");
559 INVALIDATE(s, "9223372036854775807", "", "minimum", "",
560 "{ \"minimum\": {"
561 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
562 " \"expected\": 9223372036854775808, \"actual\": 9223372036854775807"
563 "}}");
564 INVALIDATE(s, "-2147483648", "", "minimum", "",
565 "{ \"minimum\": {"
566 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
567 " \"expected\": 9223372036854775808, \"actual\": -2147483648"
568 "}}"); // int min
569 INVALIDATE(s, "0", "", "minimum", "",
570 "{ \"minimum\": {"
571 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
572 " \"expected\": 9223372036854775808, \"actual\": 0"
573 "}}");
574 INVALIDATE(s, "2147483647", "", "minimum", "",
575 "{ \"minimum\": {"
576 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
577 " \"expected\": 9223372036854775808, \"actual\": 2147483647"
578 "}}"); // int max
579 INVALIDATE(s, "2147483648", "", "minimum", "",
580 "{ \"minimum\": {"
581 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
582 " \"expected\": 9223372036854775808, \"actual\": 2147483648"
583 "}}"); // unsigned first
584 INVALIDATE(s, "4294967295", "", "minimum", "",
585 "{ \"minimum\": {"
586 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
587 " \"expected\": 9223372036854775808, \"actual\": 4294967295"
588 "}}"); // unsigned max
589 VALIDATE(s, "9223372036854775808", true);
590 VALIDATE(s, "18446744073709551614", true);
591 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
592 "{ \"maximum\": {"
593 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
594 " \"expected\": 18446744073709551614, \"actual\": 18446744073709551615"
595 "}}");
596}
597
598TEST(SchemaValidator, Integer_Range64BoundaryExclusive) {
599 Document sd;
600 sd.Parse("{\"type\":\"integer\",\"minimum\":-9223372036854775808,\"maximum\":18446744073709551615,\"exclusiveMinimum\":true,\"exclusiveMaximum\":true}");
601 SchemaDocument s(sd);
602
603 INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
604 "{ \"minimum\": {"
605 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
606 " \"expected\": -9223372036854775808, \"exclusiveMinimum\": true, "
607 " \"actual\": -9223372036854775808"
608 "}}");
609 VALIDATE(s, "-9223372036854775807", true);
610 VALIDATE(s, "18446744073709551614", true);
611 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
612 "{ \"maximum\": {"
613 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
614 " \"expected\": 18446744073709551615, \"exclusiveMaximum\": true, "
615 " \"actual\": 18446744073709551615"
616 "}}");
617}
618
619TEST(SchemaValidator, Integer_MultipleOf) {
620 Document sd;
621 sd.Parse("{\"type\":\"integer\",\"multipleOf\":10}");
622 SchemaDocument s(sd);
623
624 VALIDATE(s, "0", true);
625 VALIDATE(s, "10", true);
626 VALIDATE(s, "-10", true);
627 VALIDATE(s, "20", true);
628 INVALIDATE(s, "23", "", "multipleOf", "",
629 "{ \"multipleOf\": {"
630 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
631 " \"expected\": 10, \"actual\": 23"
632 "}}");
633 INVALIDATE(s, "-23", "", "multipleOf", "",
634 "{ \"multipleOf\": {"
635 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
636 " \"expected\": 10, \"actual\": -23"
637 "}}");
638}
639
640TEST(SchemaValidator, Integer_MultipleOf64Boundary) {
641 Document sd;
642 sd.Parse("{\"type\":\"integer\",\"multipleOf\":18446744073709551615}");
643 SchemaDocument s(sd);
644
645 VALIDATE(s, "0", true);
646 VALIDATE(s, "18446744073709551615", true);
647 INVALIDATE(s, "18446744073709551614", "", "multipleOf", "",
648 "{ \"multipleOf\": {"
649 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
650 " \"expected\": 18446744073709551615, \"actual\": 18446744073709551614"
651 "}}");
652}
653
654TEST(SchemaValidator, Number_Range) {
655 Document sd;
656 sd.Parse("{\"type\":\"number\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}");
657 SchemaDocument s(sd);
658
659 INVALIDATE(s, "-1", "", "minimum", "",
660 "{ \"minimum\": {"
661 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
662 " \"expected\": 0, \"actual\": -1"
663 "}}");
664 VALIDATE(s, "0", true);
665 VALIDATE(s, "0.1", true);
666 VALIDATE(s, "10", true);
667 VALIDATE(s, "99", true);
668 VALIDATE(s, "99.9", true);
669 INVALIDATE(s, "100", "", "maximum", "",
670 "{ \"maximum\": {"
671 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
672 " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100"
673 "}}");
674 INVALIDATE(s, "100.0", "", "maximum", "",
675 "{ \"maximum\": {"
676 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
677 " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100.0"
678 "}}");
679 INVALIDATE(s, "101.5", "", "maximum", "",
680 "{ \"maximum\": {"
681 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
682 " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 101.5"
683 "}}");
684}
685
686TEST(SchemaValidator, Number_RangeInt) {
687 Document sd;
688 sd.Parse("{\"type\":\"number\",\"minimum\":-100,\"maximum\":-1,\"exclusiveMaximum\":true}");
689 SchemaDocument s(sd);
690
691 INVALIDATE(s, "-101", "", "minimum", "",
692 "{ \"minimum\": {"
693 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
694 " \"expected\": -100, \"actual\": -101"
695 "}}");
696 INVALIDATE(s, "-100.1", "", "minimum", "",
697 "{ \"minimum\": {"
698 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
699 " \"expected\": -100, \"actual\": -100.1"
700 "}}");
701 VALIDATE(s, "-100", true);
702 VALIDATE(s, "-2", true);
703 INVALIDATE(s, "-1", "", "maximum", "",
704 "{ \"maximum\": {"
705 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
706 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": -1"
707 "}}");
708 INVALIDATE(s, "-0.9", "", "maximum", "",
709 "{ \"maximum\": {"
710 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
711 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": -0.9"
712 "}}");
713 INVALIDATE(s, "0", "", "maximum", "",
714 "{ \"maximum\": {"
715 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
716 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 0"
717 "}}");
718 INVALIDATE(s, "2147483647", "", "maximum", "",
719 "{ \"maximum\": {"
720 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
721 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 2147483647"
722 "}}"); // int max
723 INVALIDATE(s, "2147483648", "", "maximum", "",
724 "{ \"maximum\": {"
725 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
726 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 2147483648"
727 "}}"); // unsigned first
728 INVALIDATE(s, "4294967295", "", "maximum", "",
729 "{ \"maximum\": {"
730 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
731 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 4294967295"
732 "}}"); // unsigned max
733 INVALIDATE(s, "9223372036854775808", "", "maximum", "",
734 "{ \"maximum\": {"
735 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
736 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 9223372036854775808"
737 "}}");
738 INVALIDATE(s, "18446744073709551614", "", "maximum", "",
739 "{ \"maximum\": {"
740 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
741 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614"
742 "}}");
743 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
744 "{ \"maximum\": {"
745 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
746 " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615"
747 "}}");
748}
749
750TEST(SchemaValidator, Number_RangeDouble) {
751 Document sd;
752 sd.Parse("{\"type\":\"number\",\"minimum\":0.1,\"maximum\":100.1,\"exclusiveMaximum\":true}");
753 SchemaDocument s(sd);
754
755 INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
756 "{ \"minimum\": {"
757 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
758 " \"expected\": 0.1, \"actual\": -9223372036854775808"
759 "}}");
760 INVALIDATE(s, "-2147483648", "", "minimum", "",
761 "{ \"minimum\": {"
762 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
763 " \"expected\": 0.1, \"actual\": -2147483648"
764 "}}"); // int min
765 INVALIDATE(s, "-1", "", "minimum", "",
766 "{ \"minimum\": {"
767 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
768 " \"expected\": 0.1, \"actual\": -1"
769 "}}");
770 VALIDATE(s, "0.1", true);
771 VALIDATE(s, "10", true);
772 VALIDATE(s, "99", true);
773 VALIDATE(s, "100", true);
774 INVALIDATE(s, "101", "", "maximum", "",
775 "{ \"maximum\": {"
776 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
777 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 101"
778 "}}");
779 INVALIDATE(s, "101.5", "", "maximum", "",
780 "{ \"maximum\": {"
781 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
782 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 101.5"
783 "}}");
784 INVALIDATE(s, "18446744073709551614", "", "maximum", "",
785 "{ \"maximum\": {"
786 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
787 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614"
788 "}}");
789 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
790 "{ \"maximum\": {"
791 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
792 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615"
793 "}}");
794 INVALIDATE(s, "2147483647", "", "maximum", "",
795 "{ \"maximum\": {"
796 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
797 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 2147483647"
798 "}}"); // int max
799 INVALIDATE(s, "2147483648", "", "maximum", "",
800 "{ \"maximum\": {"
801 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
802 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 2147483648"
803 "}}"); // unsigned first
804 INVALIDATE(s, "4294967295", "", "maximum", "",
805 "{ \"maximum\": {"
806 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
807 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 4294967295"
808 "}}"); // unsigned max
809 INVALIDATE(s, "9223372036854775808", "", "maximum", "",
810 "{ \"maximum\": {"
811 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
812 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 9223372036854775808"
813 "}}");
814 INVALIDATE(s, "18446744073709551614", "", "maximum", "",
815 "{ \"maximum\": {"
816 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
817 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614"
818 "}}");
819 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
820 "{ \"maximum\": {"
821 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
822 " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615"
823 "}}");
824}
825
826TEST(SchemaValidator, Number_RangeDoubleU64Boundary) {
827 Document sd;
828 sd.Parse("{\"type\":\"number\",\"minimum\":9223372036854775808.0,\"maximum\":18446744073709550000.0}");
829 SchemaDocument s(sd);
830
831 INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
832 "{ \"minimum\": {"
833 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
834 " \"expected\": 9223372036854775808.0, \"actual\": -9223372036854775808"
835 "}}");
836 INVALIDATE(s, "-2147483648", "", "minimum", "",
837 "{ \"minimum\": {"
838 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
839 " \"expected\": 9223372036854775808.0, \"actual\": -2147483648"
840 "}}"); // int min
841 INVALIDATE(s, "0", "", "minimum", "",
842 "{ \"minimum\": {"
843 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
844 " \"expected\": 9223372036854775808.0, \"actual\": 0"
845 "}}");
846 INVALIDATE(s, "2147483647", "", "minimum", "",
847 "{ \"minimum\": {"
848 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
849 " \"expected\": 9223372036854775808.0, \"actual\": 2147483647"
850 "}}"); // int max
851 INVALIDATE(s, "2147483648", "", "minimum", "",
852 "{ \"minimum\": {"
853 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
854 " \"expected\": 9223372036854775808.0, \"actual\": 2147483648"
855 "}}"); // unsigned first
856 INVALIDATE(s, "4294967295", "", "minimum", "",
857 "{ \"minimum\": {"
858 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
859 " \"expected\": 9223372036854775808.0, \"actual\": 4294967295"
860 "}}"); // unsigned max
861 VALIDATE(s, "9223372036854775808", true);
862 VALIDATE(s, "18446744073709540000", true);
863 INVALIDATE(s, "18446744073709551615", "", "maximum", "",
864 "{ \"maximum\": {"
865 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
866 " \"expected\": 18446744073709550000.0, \"actual\": 18446744073709551615"
867 "}}");
868}
869
870TEST(SchemaValidator, Number_MultipleOf) {
871 Document sd;
872 sd.Parse("{\"type\":\"number\",\"multipleOf\":10.0}");
873 SchemaDocument s(sd);
874
875 VALIDATE(s, "0", true);
876 VALIDATE(s, "10", true);
877 VALIDATE(s, "-10", true);
878 VALIDATE(s, "20", true);
879 INVALIDATE(s, "23", "", "multipleOf", "",
880 "{ \"multipleOf\": {"
881 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
882 " \"expected\": 10.0, \"actual\": 23"
883 "}}");
884 INVALIDATE(s, "-2147483648", "", "multipleOf", "",
885 "{ \"multipleOf\": {"
886 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
887 " \"expected\": 10.0, \"actual\": -2147483648"
888 "}}"); // int min
889 VALIDATE(s, "-2147483640", true);
890 INVALIDATE(s, "2147483647", "", "multipleOf", "",
891 "{ \"multipleOf\": {"
892 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
893 " \"expected\": 10.0, \"actual\": 2147483647"
894 "}}"); // int max
895 INVALIDATE(s, "2147483648", "", "multipleOf", "",
896 "{ \"multipleOf\": {"
897 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
898 " \"expected\": 10.0, \"actual\": 2147483648"
899 "}}"); // unsigned first
900 VALIDATE(s, "2147483650", true);
901 INVALIDATE(s, "4294967295", "", "multipleOf", "",
902 "{ \"multipleOf\": {"
903 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
904 " \"expected\": 10.0, \"actual\": 4294967295"
905 "}}"); // unsigned max
906 VALIDATE(s, "4294967300", true);
907}
908
909TEST(SchemaValidator, Number_MultipleOfOne) {
910 Document sd;
911 sd.Parse("{\"type\":\"number\",\"multipleOf\":1}");
912 SchemaDocument s(sd);
913
914 VALIDATE(s, "42", true);
915 VALIDATE(s, "42.0", true);
916 INVALIDATE(s, "3.1415926", "", "multipleOf", "",
917 "{ \"multipleOf\": {"
918 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
919 " \"expected\": 1, \"actual\": 3.1415926"
920 "}}");
921}
922
924 Document sd;
925 sd.Parse("{\"type\":\"object\"}");
926 SchemaDocument s(sd);
927
928 VALIDATE(s, "{\"key\":\"value\",\"another_key\":\"another_value\"}", true);
929 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);
930 INVALIDATE(s, "[\"An\", \"array\", \"not\", \"an\", \"object\"]", "", "type", "",
931 "{ \"type\": {"
932 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
933 " \"expected\": [\"object\"], \"actual\": \"array\""
934 "}}");
935 INVALIDATE(s, "\"Not an object\"", "", "type", "",
936 "{ \"type\": {"
937 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
938 " \"expected\": [\"object\"], \"actual\": \"string\""
939 "}}");
940}
941
942TEST(SchemaValidator, Object_Properties) {
943 Document sd;
944 sd.Parse(
945 "{"
946 " \"type\": \"object\","
947 " \"properties\" : {"
948 " \"number\": { \"type\": \"number\" },"
949 " \"street_name\" : { \"type\": \"string\" },"
950 " \"street_type\" : { \"type\": \"string\", \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"] }"
951 " }"
952 "}");
953
954 SchemaDocument s(sd);
955
956 VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
957 INVALIDATE(s, "{ \"number\": \"1600\", \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", "/properties/number", "type", "/number",
958 "{ \"type\": {"
959 " \"instanceRef\": \"#/number\", \"schemaRef\": \"#/properties/number\","
960 " \"expected\": [\"number\"], \"actual\": \"string\""
961 "}}");
962 INVALIDATE(s, "{ \"number\": \"One\", \"street_name\": \"Microsoft\", \"street_type\": \"Way\" }",
963 "/properties/number", "type", "/number",
964 "{ \"type\": {"
965 " \"instanceRef\": \"#/number\", \"schemaRef\": \"#/properties/number\","
966 " \"expected\": [\"number\"], \"actual\": \"string\""
967 "}}"); // fail fast
968 VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\" }", true);
969 VALIDATE(s, "{}", true);
970 VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true);
971}
972
973TEST(SchemaValidator, Object_AdditionalPropertiesBoolean) {
974 Document sd;
975 sd.Parse(
976 "{"
977 " \"type\": \"object\","
978 " \"properties\" : {"
979 " \"number\": { \"type\": \"number\" },"
980 " \"street_name\" : { \"type\": \"string\" },"
981 " \"street_type\" : { \"type\": \"string\","
982 " \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"]"
983 " }"
984 " },"
985 " \"additionalProperties\": false"
986 "}");
987
988 SchemaDocument s(sd);
989
990 VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
991 INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", "", "additionalProperties", "/direction",
992 "{ \"additionalProperties\": {"
993 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
994 " \"disallowed\": \"direction\""
995 "}}");
996}
997
998TEST(SchemaValidator, Object_AdditionalPropertiesObject) {
999 Document sd;
1000 sd.Parse(
1001 "{"
1002 " \"type\": \"object\","
1003 " \"properties\" : {"
1004 " \"number\": { \"type\": \"number\" },"
1005 " \"street_name\" : { \"type\": \"string\" },"
1006 " \"street_type\" : { \"type\": \"string\","
1007 " \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"]"
1008 " }"
1009 " },"
1010 " \"additionalProperties\": { \"type\": \"string\" }"
1011 "}");
1012 SchemaDocument s(sd);
1013
1014 VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
1015 VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true);
1016 INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"office_number\": 201 }", "/additionalProperties", "type", "/office_number",
1017 "{ \"type\": {"
1018 " \"instanceRef\": \"#/office_number\", \"schemaRef\": \"#/additionalProperties\","
1019 " \"expected\": [\"string\"], \"actual\": \"integer\""
1020 "}}");
1021}
1022
1023TEST(SchemaValidator, Object_Required) {
1024 Document sd;
1025 sd.Parse(
1026 "{"
1027 " \"type\": \"object\","
1028 " \"properties\" : {"
1029 " \"name\": { \"type\": \"string\" },"
1030 " \"email\" : { \"type\": \"string\" },"
1031 " \"address\" : { \"type\": \"string\" },"
1032 " \"telephone\" : { \"type\": \"string\" }"
1033 " },"
1034 " \"required\":[\"name\", \"email\"]"
1035 "}");
1036 SchemaDocument s(sd);
1037
1038 VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\" }", true);
1039 VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true);
1040 INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "",
1041 "{ \"required\": {"
1042 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1043 " \"missing\": [\"email\"]"
1044 "}}");
1045 INVALIDATE(s, "{}", "", "required", "",
1046 "{ \"required\": {"
1047 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1048 " \"missing\": [\"name\", \"email\"]"
1049 "}}");
1050}
1051
1052TEST(SchemaValidator, Object_Required_PassWithDefault) {
1053 Document sd;
1054 sd.Parse(
1055 "{"
1056 " \"type\": \"object\","
1057 " \"properties\" : {"
1058 " \"name\": { \"type\": \"string\", \"default\": \"William Shakespeare\" },"
1059 " \"email\" : { \"type\": \"string\", \"default\": \"\" },"
1060 " \"address\" : { \"type\": \"string\" },"
1061 " \"telephone\" : { \"type\": \"string\" }"
1062 " },"
1063 " \"required\":[\"name\", \"email\"]"
1064 "}");
1065 SchemaDocument s(sd);
1066
1067 VALIDATE(s, "{ \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true);
1068 INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "",
1069 "{ \"required\": {"
1070 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1071 " \"missing\": [\"email\"]"
1072 "}}");
1073 INVALIDATE(s, "{}", "", "required", "",
1074 "{ \"required\": {"
1075 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1076 " \"missing\": [\"email\"]"
1077 "}}");
1078}
1079
1080TEST(SchemaValidator, Object_PropertiesRange) {
1081 Document sd;
1082 sd.Parse("{\"type\":\"object\", \"minProperties\":2, \"maxProperties\":3}");
1083 SchemaDocument s(sd);
1084
1085 INVALIDATE(s, "{}", "", "minProperties", "",
1086 "{ \"minProperties\": {"
1087 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1088 " \"expected\": 2, \"actual\": 0"
1089 "}}");
1090 INVALIDATE(s, "{\"a\":0}", "", "minProperties", "",
1091 "{ \"minProperties\": {"
1092 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1093 " \"expected\": 2, \"actual\": 1"
1094 "}}");
1095 VALIDATE(s, "{\"a\":0,\"b\":1}", true);
1096 VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2}", true);
1097 INVALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", "", "maxProperties", "",
1098 "{ \"maxProperties\": {"
1099 " \"instanceRef\": \"#\", \"schemaRef\": \"#\", "
1100 " \"expected\": 3, \"actual\": 4"
1101 "}}");
1102}
1103
1104TEST(SchemaValidator, Object_PropertyDependencies) {
1105 Document sd;
1106 sd.Parse(
1107 "{"
1108 " \"type\": \"object\","
1109 " \"properties\": {"
1110 " \"name\": { \"type\": \"string\" },"
1111 " \"credit_card\": { \"type\": \"number\" },"
1112 " \"cvv_code\": { \"type\": \"number\" },"
1113 " \"billing_address\": { \"type\": \"string\" }"
1114 " },"
1115 " \"required\": [\"name\"],"
1116 " \"dependencies\": {"
1117 " \"credit_card\": [\"cvv_code\", \"billing_address\"]"
1118 " }"
1119 "}");
1120 SchemaDocument s(sd);
1121
1122 VALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555, \"cvv_code\": 777, "
1123 "\"billing_address\": \"555 Debtor's Lane\" }", true);
1124 INVALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555 }", "", "dependencies", "",
1125 "{ \"dependencies\": {"
1126 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1127 " \"errors\": {\"credit_card\": [\"cvv_code\", \"billing_address\"]}"
1128 "}}");
1129 VALIDATE(s, "{ \"name\": \"John Doe\"}", true);
1130 VALIDATE(s, "{ \"name\": \"John Doe\", \"cvv_code\": 777, \"billing_address\": \"555 Debtor's Lane\" }", true);
1131}
1132
1133TEST(SchemaValidator, Object_SchemaDependencies) {
1134 Document sd;
1135 sd.Parse(
1136 "{"
1137 " \"type\": \"object\","
1138 " \"properties\" : {"
1139 " \"name\": { \"type\": \"string\" },"
1140 " \"credit_card\" : { \"type\": \"number\" }"
1141 " },"
1142 " \"required\" : [\"name\"],"
1143 " \"dependencies\" : {"
1144 " \"credit_card\": {"
1145 " \"properties\": {"
1146 " \"billing_address\": { \"type\": \"string\" }"
1147 " },"
1148 " \"required\" : [\"billing_address\"]"
1149 " }"
1150 " }"
1151 "}");
1152 SchemaDocument s(sd);
1153
1154 VALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555,\"billing_address\" : \"555 Debtor's Lane\"}", true);
1155 INVALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555 }", "", "dependencies", "",
1156 "{ \"dependencies\": {"
1157 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1158 " \"errors\": {"
1159 " \"credit_card\": {"
1160 " \"required\": {"
1161 " \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/credit_card\","
1162 " \"missing\": [\"billing_address\"]"
1163 " } } }"
1164 "}}");
1165 VALIDATE(s, "{\"name\": \"John Doe\", \"billing_address\" : \"555 Debtor's Lane\"}", true);
1166}
1167
1168#if RAPIDJSON_SCHEMA_HAS_REGEX
1169TEST(SchemaValidator, Object_PatternProperties) {
1170 Document sd;
1171 sd.Parse(
1172 "{"
1173 " \"type\": \"object\","
1174 " \"patternProperties\": {"
1175 " \"^S_\": { \"type\": \"string\" },"
1176 " \"^I_\": { \"type\": \"integer\" }"
1177 " }"
1178 "}");
1179 SchemaDocument s(sd);
1180
1181 VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true);
1182 VALIDATE(s, "{ \"I_0\": 42 }", true);
1183 INVALIDATE(s, "{ \"S_0\": 42 }", "", "patternProperties", "/S_0",
1184 "{ \"type\": {"
1185 " \"instanceRef\": \"#/S_0\", \"schemaRef\": \"#/patternProperties/%5ES_\","
1186 " \"expected\": [\"string\"], \"actual\": \"integer\""
1187 "}}");
1188 INVALIDATE(s, "{ \"I_42\": \"This is a string\" }", "", "patternProperties", "/I_42",
1189 "{ \"type\": {"
1190 " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/patternProperties/%5EI_\","
1191 " \"expected\": [\"integer\"], \"actual\": \"string\""
1192 "}}");
1193 VALIDATE(s, "{ \"keyword\": \"value\" }", true);
1194}
1195
1196TEST(SchemaValidator, Object_PattternProperties_ErrorConflict) {
1197 Document sd;
1198 sd.Parse(
1199 "{"
1200 " \"type\": \"object\","
1201 " \"patternProperties\": {"
1202 " \"^I_\": { \"multipleOf\": 5 },"
1203 " \"30$\": { \"multipleOf\": 6 }"
1204 " }"
1205 "}");
1206 SchemaDocument s(sd);
1207
1208 VALIDATE(s, "{ \"I_30\": 30 }", true);
1209 INVALIDATE(s, "{ \"I_30\": 7 }", "", "patternProperties", "/I_30",
1210 "{ \"multipleOf\": ["
1211 " {"
1212 " \"instanceRef\": \"#/I_30\", \"schemaRef\": \"#/patternProperties/%5EI_\","
1213 " \"expected\": 5, \"actual\": 7"
1214 " }, {"
1215 " \"instanceRef\": \"#/I_30\", \"schemaRef\": \"#/patternProperties/30%24\","
1216 " \"expected\": 6, \"actual\": 7"
1217 " }"
1218 "]}");
1219}
1220
1221TEST(SchemaValidator, Object_Properties_PatternProperties) {
1222 Document sd;
1223 sd.Parse(
1224 "{"
1225 " \"type\": \"object\","
1226 " \"properties\": {"
1227 " \"I_42\": { \"type\": \"integer\", \"minimum\": 73 }"
1228 " },"
1229 " \"patternProperties\": {"
1230 " \"^I_\": { \"type\": \"integer\", \"multipleOf\": 6 }"
1231 " }"
1232 "}");
1233 SchemaDocument s(sd);
1234
1235 VALIDATE(s, "{ \"I_6\": 6 }", true);
1236 VALIDATE(s, "{ \"I_42\": 78 }", true);
1237 INVALIDATE(s, "{ \"I_42\": 42 }", "", "patternProperties", "/I_42",
1238 "{ \"minimum\": {"
1239 " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/properties/I_42\","
1240 " \"expected\": 73, \"actual\": 42"
1241 "}}");
1242 INVALIDATE(s, "{ \"I_42\": 7 }", "", "patternProperties", "/I_42",
1243 "{ \"minimum\": {"
1244 " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/properties/I_42\","
1245 " \"expected\": 73, \"actual\": 7"
1246 " },"
1247 " \"multipleOf\": {"
1248 " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/patternProperties/%5EI_\","
1249 " \"expected\": 6, \"actual\": 7"
1250 " }"
1251 "}");
1252}
1253
1254TEST(SchemaValidator, Object_PatternProperties_AdditionalProperties) {
1255 Document sd;
1256 sd.Parse(
1257 "{"
1258 " \"type\": \"object\","
1259 " \"properties\": {"
1260 " \"builtin\": { \"type\": \"number\" }"
1261 " },"
1262 " \"patternProperties\": {"
1263 " \"^S_\": { \"type\": \"string\" },"
1264 " \"^I_\": { \"type\": \"integer\" }"
1265 " },"
1266 " \"additionalProperties\": { \"type\": \"string\" }"
1267 "}");
1268 SchemaDocument s(sd);
1269
1270 VALIDATE(s, "{ \"builtin\": 42 }", true);
1271 VALIDATE(s, "{ \"keyword\": \"value\" }", true);
1272 INVALIDATE(s, "{ \"keyword\": 42 }", "/additionalProperties", "type", "/keyword",
1273 "{ \"type\": {"
1274 " \"instanceRef\": \"#/keyword\", \"schemaRef\": \"#/additionalProperties\","
1275 " \"expected\": [\"string\"], \"actual\": \"integer\""
1276 "}}");
1277}
1278#endif
1279
1281 Document sd;
1282 sd.Parse("{\"type\":\"array\"}");
1283 SchemaDocument s(sd);
1284
1285 VALIDATE(s, "[1, 2, 3, 4, 5]", true);
1286 VALIDATE(s, "[3, \"different\", { \"types\" : \"of values\" }]", true);
1287 INVALIDATE(s, "{\"Not\": \"an array\"}", "", "type", "",
1288 "{ \"type\": {"
1289 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1290 " \"expected\": [\"array\"], \"actual\": \"object\""
1291 "}}");
1292}
1293
1294TEST(SchemaValidator, Array_ItemsList) {
1295 Document sd;
1296 sd.Parse(
1297 "{"
1298 " \"type\": \"array\","
1299 " \"items\" : {"
1300 " \"type\": \"number\""
1301 " }"
1302 "}");
1303 SchemaDocument s(sd);
1304
1305 VALIDATE(s, "[1, 2, 3, 4, 5]", true);
1306 INVALIDATE(s, "[1, 2, \"3\", 4, 5]", "/items", "type", "/2",
1307 "{ \"type\": {"
1308 " \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items\","
1309 " \"expected\": [\"number\"], \"actual\": \"string\""
1310 "}}");
1311 VALIDATE(s, "[]", true);
1312}
1313
1314TEST(SchemaValidator, Array_ItemsTuple) {
1315 Document sd;
1316 sd.Parse(
1317 "{"
1318 " \"type\": \"array\","
1319 " \"items\": ["
1320 " {"
1321 " \"type\": \"number\""
1322 " },"
1323 " {"
1324 " \"type\": \"string\""
1325 " },"
1326 " {"
1327 " \"type\": \"string\","
1328 " \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]"
1329 " },"
1330 " {"
1331 " \"type\": \"string\","
1332 " \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]"
1333 " }"
1334 " ]"
1335 "}");
1336 SchemaDocument s(sd);
1337
1338 VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
1339 INVALIDATE(s, "[24, \"Sussex\", \"Drive\"]", "/items/2", "enum", "/2",
1340 "{ \"enum\": { \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items/2\" }}");
1341 INVALIDATE(s, "[\"Palais de l'Elysee\"]", "/items/0", "type", "/0",
1342 "{ \"type\": {"
1343 " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items/0\","
1344 " \"expected\": [\"number\"], \"actual\": \"string\""
1345 "}}");
1346 INVALIDATE(s, "[\"Twenty-four\", \"Sussex\", \"Drive\"]", "/items/0", "type", "/0",
1347 "{ \"type\": {"
1348 " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items/0\","
1349 " \"expected\": [\"number\"], \"actual\": \"string\""
1350 "}}"); // fail fast
1351 VALIDATE(s, "[10, \"Downing\", \"Street\"]", true);
1352 VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true);
1353}
1354
1355TEST(SchemaValidator, Array_AdditionalItmes) {
1356 Document sd;
1357 sd.Parse(
1358 "{"
1359 " \"type\": \"array\","
1360 " \"items\": ["
1361 " {"
1362 " \"type\": \"number\""
1363 " },"
1364 " {"
1365 " \"type\": \"string\""
1366 " },"
1367 " {"
1368 " \"type\": \"string\","
1369 " \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]"
1370 " },"
1371 " {"
1372 " \"type\": \"string\","
1373 " \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]"
1374 " }"
1375 " ],"
1376 " \"additionalItems\": false"
1377 "}");
1378 SchemaDocument s(sd);
1379
1380 VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
1381 VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\"]", true);
1382 INVALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", "", "items", "/4",
1383 "{ \"additionalItems\": {"
1384 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1385 " \"disallowed\": 4"
1386 "}}");
1387}
1388
1389TEST(SchemaValidator, Array_ItemsRange) {
1390 Document sd;
1391 sd.Parse("{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}");
1392 SchemaDocument s(sd);
1393
1394 INVALIDATE(s, "[]", "", "minItems", "",
1395 "{ \"minItems\": {"
1396 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1397 " \"expected\": 2, \"actual\": 0"
1398 "}}");
1399 INVALIDATE(s, "[1]", "", "minItems", "",
1400 "{ \"minItems\": {"
1401 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1402 " \"expected\": 2, \"actual\": 1"
1403 "}}");
1404 VALIDATE(s, "[1, 2]", true);
1405 VALIDATE(s, "[1, 2, 3]", true);
1406 INVALIDATE(s, "[1, 2, 3, 4]", "", "maxItems", "",
1407 "{ \"maxItems\": {"
1408 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1409 " \"expected\": 3, \"actual\": 4"
1410 "}}");
1411}
1412
1413TEST(SchemaValidator, Array_UniqueItems) {
1414 Document sd;
1415 sd.Parse("{\"type\": \"array\", \"uniqueItems\": true}");
1416 SchemaDocument s(sd);
1417
1418 VALIDATE(s, "[1, 2, 3, 4, 5]", true);
1419 INVALIDATE(s, "[1, 2, 3, 3, 4]", "", "uniqueItems", "/3",
1420 "{ \"uniqueItems\": {"
1421 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1422 " \"duplicates\": [2, 3]"
1423 "}}");
1424 INVALIDATE(s, "[1, 2, 3, 3, 3]", "", "uniqueItems", "/3",
1425 "{ \"uniqueItems\": {"
1426 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1427 " \"duplicates\": [2, 3]"
1428 "}}"); // fail fast
1429 VALIDATE(s, "[]", true);
1430}
1431
1433 Document sd;
1434 sd.Parse("{\"type\":\"boolean\"}");
1435 SchemaDocument s(sd);
1436
1437 VALIDATE(s, "true", true);
1438 VALIDATE(s, "false", true);
1439 INVALIDATE(s, "\"true\"", "", "type", "",
1440 "{ \"type\": {"
1441 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1442 " \"expected\": [\"boolean\"], \"actual\": \"string\""
1443 "}}");
1444 INVALIDATE(s, "0", "", "type", "",
1445 "{ \"type\": {"
1446 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1447 " \"expected\": [\"boolean\"], \"actual\": \"integer\""
1448 "}}");
1449}
1450
1452 Document sd;
1453 sd.Parse("{\"type\":\"null\"}");
1454 SchemaDocument s(sd);
1455
1456 VALIDATE(s, "null", true);
1457 INVALIDATE(s, "false", "", "type", "",
1458 "{ \"type\": {"
1459 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1460 " \"expected\": [\"null\"], \"actual\": \"boolean\""
1461 "}}");
1462 INVALIDATE(s, "0", "", "type", "",
1463 "{ \"type\": {"
1464 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1465 " \"expected\": [\"null\"], \"actual\": \"integer\""
1466 "}}");
1467 INVALIDATE(s, "\"\"", "", "type", "",
1468 "{ \"type\": {"
1469 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1470 " \"expected\": [\"null\"], \"actual\": \"string\""
1471 "}}");
1472}
1473
1474// Additional tests
1475
1476TEST(SchemaValidator, ObjectInArray) {
1477 Document sd;
1478 sd.Parse("{\"type\":\"array\", \"items\": { \"type\":\"string\" }}");
1479 SchemaDocument s(sd);
1480
1481 VALIDATE(s, "[\"a\"]", true);
1482 INVALIDATE(s, "[1]", "/items", "type", "/0",
1483 "{ \"type\": {"
1484 " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items\","
1485 " \"expected\": [\"string\"], \"actual\": \"integer\""
1486 "}}");
1487 INVALIDATE(s, "[{}]", "/items", "type", "/0",
1488 "{ \"type\": {"
1489 " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items\","
1490 " \"expected\": [\"string\"], \"actual\": \"object\""
1491 "}}");
1492}
1493
1494TEST(SchemaValidator, MultiTypeInObject) {
1495 Document sd;
1496 sd.Parse(
1497 "{"
1498 " \"type\":\"object\","
1499 " \"properties\": {"
1500 " \"tel\" : {"
1501 " \"type\":[\"integer\", \"string\"]"
1502 " }"
1503 " }"
1504 "}");
1505 SchemaDocument s(sd);
1506
1507 VALIDATE(s, "{ \"tel\": 999 }", true);
1508 VALIDATE(s, "{ \"tel\": \"123-456\" }", true);
1509 INVALIDATE(s, "{ \"tel\": true }", "/properties/tel", "type", "/tel",
1510 "{ \"type\": {"
1511 " \"instanceRef\": \"#/tel\", \"schemaRef\": \"#/properties/tel\","
1512 " \"expected\": [\"string\", \"integer\"], \"actual\": \"boolean\""
1513 "}}");
1514}
1515
1516TEST(SchemaValidator, MultiTypeWithObject) {
1517 Document sd;
1518 sd.Parse(
1519 "{"
1520 " \"type\": [\"object\",\"string\"],"
1521 " \"properties\": {"
1522 " \"tel\" : {"
1523 " \"type\": \"integer\""
1524 " }"
1525 " }"
1526 "}");
1527 SchemaDocument s(sd);
1528
1529 VALIDATE(s, "\"Hello\"", true);
1530 VALIDATE(s, "{ \"tel\": 999 }", true);
1531 INVALIDATE(s, "{ \"tel\": \"fail\" }", "/properties/tel", "type", "/tel",
1532 "{ \"type\": {"
1533 " \"instanceRef\": \"#/tel\", \"schemaRef\": \"#/properties/tel\","
1534 " \"expected\": [\"integer\"], \"actual\": \"string\""
1535 "}}");
1536}
1537
1538TEST(SchemaValidator, AllOf_Nested) {
1539 Document sd;
1540 sd.Parse(
1541 "{"
1542 " \"allOf\": ["
1543 " { \"type\": \"string\", \"minLength\": 2 },"
1544 " { \"type\": \"string\", \"maxLength\": 5 },"
1545 " { \"allOf\": [ { \"enum\" : [\"ok\", \"okay\", \"OK\", \"o\"] }, { \"enum\" : [\"ok\", \"OK\", \"o\"]} ] }"
1546 " ]"
1547 "}");
1548 SchemaDocument s(sd);
1549
1550 VALIDATE(s, "\"ok\"", true);
1551 VALIDATE(s, "\"OK\"", true);
1552 INVALIDATE(s, "\"okay\"", "", "allOf", "",
1553 "{ \"enum\": {"
1554 " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\""
1555 "}}");
1556 INVALIDATE(s, "\"o\"", "", "allOf", "",
1557 "{ \"minLength\": {"
1558 " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\","
1559 " \"expected\": 2, \"actual\": \"o\""
1560 "}}");
1561 INVALIDATE(s, "\"n\"", "", "allOf", "",
1562 "{ \"minLength\": {"
1563 " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\","
1564 " \"expected\": 2, \"actual\": \"n\""
1565 " },"
1566 " \"enum\": ["
1567 " {\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"},"
1568 " {\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}"
1569 " ]"
1570 "}")
1571 INVALIDATE(s, "\"too long\"", "", "allOf", "",
1572 "{ \"maxLength\": {"
1573 " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\","
1574 " \"expected\": 5, \"actual\": \"too long\""
1575 " },"
1576 " \"enum\": ["
1577 " {\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"},"
1578 " {\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}"
1579 " ]"
1580 "}");
1581 INVALIDATE(s, "123", "", "allOf", "",
1582 "{ \"type\": ["
1583 " { \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\","
1584 " \"expected\": [\"string\"], \"actual\": \"integer\""
1585 " },"
1586 " { \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\","
1587 " \"expected\": [\"string\"], \"actual\": \"integer\""
1588 " }"
1589 " ],"
1590 " \"enum\": ["
1591 " {\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"},"
1592 " {\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}"
1593 " ]"
1594 "}");
1595}
1596
1597TEST(SchemaValidator, EscapedPointer) {
1598 Document sd;
1599 sd.Parse(
1600 "{"
1601 " \"type\": \"object\","
1602 " \"properties\": {"
1603 " \"~/\": { \"type\": \"number\" }"
1604 " }"
1605 "}");
1606 SchemaDocument s(sd);
1607 INVALIDATE(s, "{\"~/\":true}", "/properties/~0~1", "type", "/~0~1",
1608 "{ \"type\": {"
1609 " \"instanceRef\": \"#/~0~1\", \"schemaRef\": \"#/properties/~0~1\","
1610 " \"expected\": [\"number\"], \"actual\": \"boolean\""
1611 "}}");
1612}
1613
1614template <typename Allocator>
1615static char* ReadFile(const char* filename, Allocator& allocator) {
1616 const char *paths[] = {
1617 "",
1618 "bin/",
1619 "../bin/",
1620 "../../bin/",
1621 "../../../bin/"
1622 };
1623 char buffer[1024];
1624 FILE *fp = 0;
1625 for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
1626 sprintf(buffer, "%s%s", paths[i], filename);
1627 fp = fopen(buffer, "rb");
1628 if (fp)
1629 break;
1630 }
1631
1632 if (!fp)
1633 return 0;
1634
1635 fseek(fp, 0, SEEK_END);
1636 size_t length = static_cast<size_t>(ftell(fp));
1637 fseek(fp, 0, SEEK_SET);
1638 char* json = reinterpret_cast<char*>(allocator.Malloc(length + 1));
1639 size_t readLength = fread(json, 1, length, fp);
1640 json[readLength] = '\0';
1641 fclose(fp);
1642 return json;
1643}
1644
1645TEST(SchemaValidator, ValidateMetaSchema) {
1646 CrtAllocator allocator;
1647 char* json = ReadFile("draft-04/schema", allocator);
1648 Document d;
1649 d.Parse(json);
1650 ASSERT_FALSE(d.HasParseError());
1651 SchemaDocument sd(d);
1652 SchemaValidator validator(sd);
1653 if (!d.Accept(validator)) {
1654 StringBuffer sb;
1655 validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
1656 printf("Invalid schema: %s\n", sb.GetString());
1657 printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
1658 sb.Clear();
1659 validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
1660 printf("Invalid document: %s\n", sb.GetString());
1661 sb.Clear();
1663 validator.GetError().Accept(w);
1664 printf("Validation error: %s\n", sb.GetString());
1665 ADD_FAILURE();
1666 }
1667 CrtAllocator::Free(json);
1668}
1669
1670TEST(SchemaValidator, ValidateMetaSchema_UTF16) {
1671 typedef GenericDocument<UTF16<> > D;
1673 typedef GenericSchemaValidator<SD> SV;
1674
1675 CrtAllocator allocator;
1676 char* json = ReadFile("draft-04/schema", allocator);
1677
1678 D d;
1679 StringStream ss(json);
1680 d.ParseStream<0, UTF8<> >(ss);
1681 ASSERT_FALSE(d.HasParseError());
1682 SD sd(d);
1683 SV validator(sd);
1684 if (!d.Accept(validator)) {
1686 validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
1687 wprintf(L"Invalid schema: %ls\n", sb.GetString());
1688 wprintf(L"Invalid keyword: %ls\n", validator.GetInvalidSchemaKeyword());
1689 sb.Clear();
1690 validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
1691 wprintf(L"Invalid document: %ls\n", sb.GetString());
1692 sb.Clear();
1694 validator.GetError().Accept(w);
1695 printf("Validation error: %ls\n", sb.GetString());
1696 ADD_FAILURE();
1697 }
1698 CrtAllocator::Free(json);
1699}
1700
1701template <typename SchemaDocumentType = SchemaDocument>
1703public:
1705 documentAllocator_(documentBuffer_, sizeof(documentBuffer_)),
1706 schemaAllocator_(schemaBuffer_, sizeof(schemaBuffer_))
1707 {
1708 const char* filenames[kCount] = {
1709 "jsonschema/remotes/integer.json",
1710 "jsonschema/remotes/subSchemas.json",
1711 "jsonschema/remotes/folder/folderInteger.json",
1712 "draft-04/schema"
1713 };
1714 const char* uris[kCount] = {
1715 "http://localhost:1234/integer.json",
1716 "http://localhost:1234/subSchemas.json",
1717 "http://localhost:1234/folder/folderInteger.json",
1718 "http://json-schema.org/draft-04/schema"
1719 };
1720
1721 for (size_t i = 0; i < kCount; i++) {
1722 sd_[i] = 0;
1723
1724 char jsonBuffer[8192];
1725 MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer));
1726 char* json = ReadFile(filenames[i], jsonAllocator);
1727 if (!json) {
1728 printf("json remote file %s not found", filenames[i]);
1729 ADD_FAILURE();
1730 }
1731 else {
1732 char stackBuffer[4096];
1733 MemoryPoolAllocator<> stackAllocator(stackBuffer, sizeof(stackBuffer));
1734 DocumentType d(&documentAllocator_, 1024, &stackAllocator);
1735 d.Parse(json);
1736 sd_[i] = new SchemaDocumentType(d, uris[i], static_cast<SizeType>(strlen(uris[i])), 0, &schemaAllocator_);
1738 }
1739 };
1740 }
1741
1743 for (size_t i = 0; i < kCount; i++)
1744 delete sd_[i];
1745 }
1746
1747 virtual const SchemaDocumentType* GetRemoteDocument(const char* uri, SizeType length) {
1748 for (size_t i = 0; i < kCount; i++)
1749 if (typename SchemaDocumentType::URIType(uri, length) == sd_[i]->GetURI())
1750 return sd_[i];
1751 return 0;
1752 }
1753
1754private:
1756
1759
1760 static const size_t kCount = 4;
1761 SchemaDocumentType* sd_[kCount];
1762 typename DocumentType::AllocatorType documentAllocator_;
1763 typename SchemaDocumentType::AllocatorType schemaAllocator_;
1764 char documentBuffer_[16384];
1765 char schemaBuffer_[128u * 1024];
1766};
1767
1769 const char* filenames[] = {
1770 "additionalItems.json",
1771 "additionalProperties.json",
1772 "allOf.json",
1773 "anyOf.json",
1774 "default.json",
1775 "definitions.json",
1776 "dependencies.json",
1777 "enum.json",
1778 "items.json",
1779 "maximum.json",
1780 "maxItems.json",
1781 "maxLength.json",
1782 "maxProperties.json",
1783 "minimum.json",
1784 "minItems.json",
1785 "minLength.json",
1786 "minProperties.json",
1787 "multipleOf.json",
1788 "not.json",
1789 "oneOf.json",
1790 "pattern.json",
1791 "patternProperties.json",
1792 "properties.json",
1793 "ref.json",
1794 "refRemote.json",
1795 "required.json",
1796 "type.json",
1797 "uniqueItems.json"
1798 };
1799
1800 const char* onlyRunDescription = 0;
1801 //const char* onlyRunDescription = "a string is a string";
1802
1803 unsigned testCount = 0;
1804 unsigned passCount = 0;
1805
1806 typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
1808
1809 char jsonBuffer[65536];
1810 char documentBuffer[65536];
1811 char documentStackBuffer[65536];
1812 char schemaBuffer[65536];
1813 char validatorBuffer[65536];
1814 MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer));
1815 MemoryPoolAllocator<> documentAllocator(documentBuffer, sizeof(documentBuffer));
1816 MemoryPoolAllocator<> documentStackAllocator(documentStackBuffer, sizeof(documentStackBuffer));
1817 MemoryPoolAllocator<> schemaAllocator(schemaBuffer, sizeof(schemaBuffer));
1818 MemoryPoolAllocator<> validatorAllocator(validatorBuffer, sizeof(validatorBuffer));
1819
1820 for (size_t i = 0; i < sizeof(filenames) / sizeof(filenames[0]); i++) {
1821 char filename[FILENAME_MAX];
1822 sprintf(filename, "jsonschema/tests/draft4/%s", filenames[i]);
1823 char* json = ReadFile(filename, jsonAllocator);
1824 if (!json) {
1825 printf("json test suite file %s not found", filename);
1826 ADD_FAILURE();
1827 }
1828 else {
1829 GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > d(&documentAllocator, 1024, &documentStackAllocator);
1830 d.Parse(json);
1831 if (d.HasParseError()) {
1832 printf("json test suite file %s has parse error", filename);
1833 ADD_FAILURE();
1834 }
1835 else {
1836 for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) {
1837 {
1838 SchemaDocumentType schema((*schemaItr)["schema"], filenames[i], static_cast<SizeType>(strlen(filenames[i])), &provider, &schemaAllocator);
1840 const char* description1 = (*schemaItr)["description"].GetString();
1841 const Value& tests = (*schemaItr)["tests"];
1842 for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) {
1843 const char* description2 = (*testItr)["description"].GetString();
1844 if (!onlyRunDescription || strcmp(description2, onlyRunDescription) == 0) {
1845 const Value& data = (*testItr)["data"];
1846 bool expected = (*testItr)["valid"].GetBool();
1847 testCount++;
1848 validator.Reset();
1849 bool actual = data.Accept(validator);
1850 if (expected != actual)
1851 printf("Fail: %30s \"%s\" \"%s\"\n", filename, description1, description2);
1852 else
1853 passCount++;
1854 }
1855 }
1856 //printf("%zu %zu %zu\n", documentAllocator.Size(), schemaAllocator.Size(), validatorAllocator.Size());
1857 }
1858 schemaAllocator.Clear();
1859 validatorAllocator.Clear();
1860 }
1861 }
1862 }
1863 documentAllocator.Clear();
1865 jsonAllocator.Clear();
1866 }
1867 printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount);
1868 // if (passCount != testCount)
1869 // ADD_FAILURE();
1870}
1871
1873 Document sd;
1874 sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
1875 SchemaDocument s(sd);
1876
1877 Document d;
1878 StringStream ss("\"red\"");
1880 d.Populate(reader);
1881 EXPECT_TRUE(reader.GetParseResult());
1882 EXPECT_TRUE(reader.IsValid());
1883 EXPECT_TRUE(d.IsString());
1884 EXPECT_STREQ("red", d.GetString());
1885}
1886
1888 Document sd;
1889 sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
1890 SchemaDocument s(sd);
1891
1892 Document d;
1893 StringStream ss("\"ABCD\"");
1895 d.Populate(reader);
1896 EXPECT_FALSE(reader.GetParseResult());
1897 EXPECT_FALSE(reader.IsValid());
1899 EXPECT_STREQ("maxLength", reader.GetInvalidSchemaKeyword());
1902 EXPECT_TRUE(d.IsNull());
1903 Document e;
1904 e.Parse(
1905 "{ \"maxLength\": {"
1906 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1907 " \"expected\": 3, \"actual\": \"ABCD\""
1908 "}}");
1909 if (e != reader.GetError()) {
1910 ADD_FAILURE();
1911 }
1912}
1913
1914TEST(SchemaValidatingWriter, Simple) {
1915 Document sd;
1916 sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
1917 SchemaDocument s(sd);
1918
1919 Document d;
1920 StringBuffer sb;
1921 Writer<StringBuffer> writer(sb);
1923
1924 d.Parse("\"red\"");
1925 EXPECT_TRUE(d.Accept(validator));
1926 EXPECT_TRUE(validator.IsValid());
1927 EXPECT_STREQ("\"red\"", sb.GetString());
1928
1929 sb.Clear();
1930 validator.Reset();
1931 d.Parse("\"ABCD\"");
1932 EXPECT_FALSE(d.Accept(validator));
1933 EXPECT_FALSE(validator.IsValid());
1936 Document e;
1937 e.Parse(
1938 "{ \"maxLength\": {"
1939 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1940 " \"expected\": 3, \"actual\": \"ABCD\""
1941 "}}");
1942 EXPECT_EQ(e, validator.GetError());
1943}
1944
1945TEST(Schema, Issue848) {
1946 rapidjson::Document d;
1947 rapidjson::SchemaDocument s(d);
1948 rapidjson::GenericSchemaValidator<rapidjson::SchemaDocument, rapidjson::Document> v(s);
1949}
1950
1951#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1952
1953static SchemaDocument ReturnSchemaDocument() {
1954 Document sd;
1955 sd.Parse("{ \"type\": [\"number\", \"string\"] }");
1956 SchemaDocument s(sd);
1957 return s;
1958}
1959
1960TEST(Schema, Issue552) {
1961 SchemaDocument s = ReturnSchemaDocument();
1962 VALIDATE(s, "42", true);
1963 VALIDATE(s, "\"Life, the universe, and everything\"", true);
1964 INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "",
1965 "{ \"type\": {"
1966 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1967 " \"expected\": [\"string\", \"number\"], \"actual\": \"array\""
1968 "}}");
1969}
1970
1971#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
1972
1974 Document sd;
1975 sd.Parse("{\"required\": [\"a\", \"b\"] }");
1976 SchemaDocument s(sd);
1977
1978 VALIDATE(s, "{\"a\" : null, \"b\": null}", true);
1979 INVALIDATE(s, "{\"a\" : null, \"a\" : null}", "", "required", "",
1980 "{ \"required\": {"
1981 " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1982 " \"missing\": [\"b\"]"
1983 "}}");
1984}
1985
1986// Fail to resolve $ref in allOf causes crash in SchemaValidator::StartObject()
1987TEST(SchemaValidator, Issue728_AllOfRef) {
1988 Document sd;
1989 sd.Parse("{\"allOf\": [{\"$ref\": \"#/abc\"}]}");
1990 SchemaDocument s(sd);
1991 VALIDATE(s, "{\"key1\": \"abc\", \"key2\": \"def\"}", true);
1992}
1993
1995 Document sd;
1996 sd.Parse("{\"type\": \"object\", \"additionalProperties\": false, \"patternProperties\": {\"^i\": { \"type\": \"string\" } } }");
1997 SchemaDocument s(sd);
1998 VALIDATE(s, "{ \"item\": \"hello\" }", true);
1999}
2000
2001TEST(SchemaValidator, Issue1017_allOfHandler) {
2002 Document sd;
2003 sd.Parse("{\"allOf\": [{\"type\": \"object\",\"properties\": {\"cyanArray2\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}}},{\"type\": \"object\",\"properties\": {\"blackArray\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}},\"required\": [ \"blackArray\" ]}]}");
2004 SchemaDocument s(sd);
2005 StringBuffer sb;
2006 Writer<StringBuffer> writer(sb);
2008 EXPECT_TRUE(validator.StartObject());
2009 EXPECT_TRUE(validator.Key("cyanArray2", 10, false));
2010 EXPECT_TRUE(validator.StartArray());
2011 EXPECT_TRUE(validator.EndArray(0));
2012 EXPECT_TRUE(validator.Key("blackArray", 10, false));
2013 EXPECT_TRUE(validator.StartArray());
2014 EXPECT_TRUE(validator.EndArray(0));
2015 EXPECT_TRUE(validator.EndObject(0));
2016 EXPECT_TRUE(validator.IsValid());
2017 EXPECT_STREQ("{\"cyanArray2\":[],\"blackArray\":[]}", sb.GetString());
2018}
2019
2020TEST(SchemaValidator, Ref_remote) {
2021 typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2023 Document sd;
2024 sd.Parse("{\"$ref\": \"http://localhost:1234/subSchemas.json#/integer\"}");
2025 SchemaDocumentType s(sd, 0, 0, &provider);
2027 typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2028 INVALIDATE_(s, "null", "/integer", "type", "",
2029 "{ \"type\": {"
2030 " \"instanceRef\": \"#\","
2031 " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\","
2032 " \"expected\": [\"integer\"], \"actual\": \"null\""
2033 "}}",
2034 SchemaValidatorType, PointerType);
2035}
2036
2037TEST(SchemaValidator, Ref_remote_issue1210) {
2038 class SchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
2039 SchemaDocument** collection;
2040
2041 SchemaDocumentProvider(const SchemaDocumentProvider&);
2042 SchemaDocumentProvider& operator=(const SchemaDocumentProvider&);
2043
2044 public:
2045 SchemaDocumentProvider(SchemaDocument** collection) : collection(collection) { }
2046 virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
2047 int i = 0;
2048 while (collection[i] && SchemaDocument::URIType(uri, length) != collection[i]->GetURI()) ++i;
2049 return collection[i];
2050 }
2051 };
2052 SchemaDocument* collection[] = { 0, 0, 0 };
2053 SchemaDocumentProvider provider(collection);
2054
2055 Document x, y, z;
2056 x.Parse("{\"properties\":{\"country\":{\"$ref\":\"y.json#/definitions/country_remote\"}},\"type\":\"object\"}");
2057 y.Parse("{\"definitions\":{\"country_remote\":{\"$ref\":\"z.json#/definitions/country_list\"}}}");
2058 z.Parse("{\"definitions\":{\"country_list\":{\"enum\":[\"US\"]}}}");
2059
2060 SchemaDocument sz(z, "z.json", 6, &provider);
2061 collection[0] = &sz;
2062 SchemaDocument sy(y, "y.json", 6, &provider);
2063 collection[1] = &sy;
2064 SchemaDocument sx(x, "x.json", 6, &provider);
2065
2066 VALIDATE(sx, "{\"country\":\"UK\"}", false);
2067 VALIDATE(sx, "{\"country\":\"US\"}", true);
2068}
2069
2070#if defined(_MSC_VER) || defined(__clang__)
2071RAPIDJSON_DIAG_POP
2072#endif
C-runtime library allocator.
Definition allocators.h:75
static void Free(void *ptr)
Definition allocators.h:92
GenericDocument & Parse(const typename SourceEncoding::Ch *str)
Parse JSON text from a read-only string (with Encoding conversion)
Definition document.h:2325
Allocator AllocatorType
Allocator type from template parameter.
Definition document.h:2128
JSON schema document.
Definition schema.h:1501
JSON Schema Validator.
Definition schema.h:1767
ValueType & GetError()
Gets the error object.
Definition schema.h:1860
void Reset()
Reset the internal states.
Definition schema.h:1845
PointerType GetInvalidSchemaPointer() const
Gets the JSON pointer pointed to the invalid schema.
Definition schema.h:1864
bool EndArray(SizeType elementCount)
Definition schema.h:2142
bool Key(const Ch *str, SizeType len, bool copy)
Definition schema.h:2121
virtual bool IsValid() const
Checks whether the current state is valid.
Definition schema.h:1857
bool EndObject(SizeType memberCount)
Definition schema.h:2129
const Ch * GetInvalidSchemaKeyword() const
Gets the keyword of invalid schema.
Definition schema.h:1869
PointerType GetInvalidDocumentPointer() const
Gets the JSON pointer pointed to the invalid value.
Definition schema.h:1874
const Ch * GetString() const
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
Definition document.h:578
Default memory allocator used by the parser and DOM.
Definition allocators.h:115
void Clear()
Deallocates all memory chunks, excluding the user-supplied buffer.
Definition allocators.h:158
static void Free(void *ptr)
Frees a memory block (concept Allocator)
Definition allocators.h:238
virtual const SchemaDocumentType * GetRemoteDocument(const char *uri, SizeType length)
A helper class for parsing with validation.
Definition schema.h:2437
const PointerType & GetInvalidDocumentPointer() const
Definition schema.h:2477
bool IsValid() const
Definition schema.h:2474
const PointerType & GetInvalidSchemaPointer() const
Definition schema.h:2475
const Ch * GetInvalidSchemaKeyword() const
Definition schema.h:2476
const ParseResult & GetParseResult() const
Definition schema.h:2473
const ValueType & GetError() const
Definition schema.h:2478
JSON writer.
Definition writer.h:89
Concept for allocating, resizing and freeing memory block.
#define D(var, file, col, who, lev,...)
Definition debug.h:44
@ kParseErrorTermination
Parsing was terminated.
Definition error.h:88
#define EXPECT_EQ(val1, val2)
Definition gtest.h:1954
#define ASSERT_FALSE(condition)
Definition gtest.h:1904
#define EXPECT_TRUE(condition)
Definition gtest.h:1895
#define EXPECT_STREQ(s1, s2)
Definition gtest.h:2027
#define TEST(test_case_name, test_name)
Definition gtest.h:2275
#define ADD_FAILURE()
Definition gtest.h:1844
#define EXPECT_FALSE(condition)
Definition gtest.h:1898
bip::allocator< T, pinnable_mapped_file::segment_manager > allocator
Definition chainbase.hpp:56
main RapidJSON namespace
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition rapidjson.h:384
Read-only string stream.
Definition stream.h:154
ParseErrorCode Code() const
Get the error code.
Definition error.h:116
UTF-16 encoding.
Definition encodings.h:269
UTF-8 encoding.
Definition encodings.h:96
#define VALIDATE(schema, json, expected)
#define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error)
#define INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, SchemaValidatorType, PointerType)
#define TEST_HASHER(json1, json2, expected)
CK_ULONG d
char * s
c_gkp_out sizeof(template))