22 RAPIDJSON_DIAG_OFF(variadic-macros)
27 #define TEST_HASHER(json1, json2, expected) \ 31 ASSERT_FALSE(d1.HasParseError());\ 33 ASSERT_FALSE(d2.HasParseError());\ 34 internal::Hasher<Value, CrtAllocator> h1, h2;\ 37 ASSERT_TRUE(h1.IsValid());\ 38 ASSERT_TRUE(h2.IsValid());\ 40 EXPECT_TRUE(expected == (h1.GetHashCode() == h2.GetHashCode()));\ 58 TEST_HASHER(
"9223372036854775808",
"9223372036854775808",
true);
72 TEST_HASHER(
"\"Hello\\u0000\"",
"\"Hello\"",
false);
78 TEST_HASHER(
"[1, true, false]",
"[1, true, false]",
true);
79 TEST_HASHER(
"[1, true, false]",
"[1, true]",
false);
94 TEST_HASHER(
"{\"a\":1, \"b\":2}",
"{\"b\":2, \"a\":1}",
true);
105 #define VALIDATE(schema, json, expected) \ 107 SchemaValidator validator(schema);\ 111 EXPECT_FALSE(d.HasParseError());\ 112 EXPECT_TRUE(expected == d.Accept(validator));\ 113 EXPECT_TRUE(expected == validator.IsValid());\ 114 if ((expected) && !validator.IsValid()) {\ 116 validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\ 117 printf("Invalid schema: %s\n", sb.GetString());\ 118 printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());\ 120 validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);\ 121 printf("Invalid document: %s\n", sb.GetString());\ 125 #define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer) \ 127 SchemaValidator validator(schema);\ 131 EXPECT_FALSE(d.HasParseError());\ 132 EXPECT_FALSE(d.Accept(validator));\ 133 EXPECT_FALSE(validator.IsValid());\ 134 if (validator.GetInvalidSchemaPointer() != Pointer(invalidSchemaPointer)) {\ 136 validator.GetInvalidSchemaPointer().Stringify(sb);\ 137 printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\ 140 ASSERT_TRUE(validator.GetInvalidSchemaKeyword() != 0);\ 141 if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\ 142 printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\ 145 if (validator.GetInvalidDocumentPointer() != Pointer(invalidDocumentPointer)) {\ 147 validator.GetInvalidDocumentPointer().Stringify(sb);\ 148 printf("GetInvalidDocumentPointer() Expected: %s Actual: %s\n", invalidDocumentPointer, sb.GetString());\ 159 VALIDATE(s,
"\"I'm a string\"",
true);
160 VALIDATE(s,
"{ \"an\": [ \"arbitrarily\", \"nested\" ], \"data\": \"structure\" }",
true);
165 sd.
Parse(
"{ \"type\": [\"number\", \"string\"] }");
169 VALIDATE(s,
"\"Life, the universe, and everything\"",
true);
170 INVALIDATE(s,
"[\"Life\", \"the universe\", \"and everything\"]",
"",
"type",
"");
175 sd.
Parse(
"{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
184 sd.
Parse(
"{ \"enum\": [\"red\", \"amber\", \"green\", null, 42] }");
195 sd.
Parse(
"{ \"type\": \"string\", \"enum\": [\"red\", \"amber\", \"green\", null] }");
205 sd.
Parse(
"{\"allOf\": [{ \"type\": \"string\" }, { \"type\": \"string\", \"maxLength\": 5 }]}");
209 INVALIDATE(s,
"\"too long\"",
"",
"allOf",
"");
213 sd.
Parse(
"{\"allOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }");
223 sd.
Parse(
"{\"anyOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }");
228 INVALIDATE(s,
"{ \"Not a\": \"string or number\" }",
"",
"anyOf",
"");
233 sd.
Parse(
"{\"oneOf\": [{ \"type\": \"number\", \"multipleOf\": 5 }, { \"type\": \"number\", \"multipleOf\": 3 } ] }");
244 sd.
Parse(
"{\"not\":{ \"type\": \"string\"}}");
248 VALIDATE(s,
"{ \"key\": \"value\" }",
true);
249 INVALIDATE(s,
"\"I am a string\"",
"",
"not",
"");
256 " \"$schema\": \"http://json-schema.org/draft-04/schema#\"," 258 " \"definitions\": {" 260 " \"type\": \"object\"," 262 " \"street_address\": { \"type\": \"string\" }," 263 " \"city\": { \"type\": \"string\" }," 264 " \"state\": { \"type\": \"string\" }" 266 " \"required\": [\"street_address\", \"city\", \"state\"]" 269 " \"type\": \"object\"," 271 " \"billing_address\": { \"$ref\": \"#/definitions/address\" }," 272 " \"shipping_address\": { \"$ref\": \"#/definitions/address\" }" 277 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);
284 " \"$schema\": \"http://json-schema.org/draft-04/schema#\"," 286 " \"definitions\": {" 288 " \"type\": \"object\"," 290 " \"street_address\": { \"type\": \"string\" }," 291 " \"city\": { \"type\": \"string\" }," 292 " \"state\": { \"type\": \"string\" }" 294 " \"required\": [\"street_address\", \"city\", \"state\"]" 297 " \"type\": \"object\"," 299 " \"billing_address\": { \"$ref\": \"#/definitions/address\" }," 300 " \"shipping_address\": {" 302 " { \"$ref\": \"#/definitions/address\" }," 304 " { \"type\": { \"enum\": [ \"residential\", \"business\" ] } }," 305 " \"required\": [\"type\"]" 313 INVALIDATE(s,
"{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"} }",
"/properties/shipping_address",
"allOf",
"/shipping_address");
314 VALIDATE(s,
"{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\", \"type\": \"business\"} }",
true);
319 sd.
Parse(
"{\"type\":\"string\"}");
322 VALIDATE(s,
"\"I'm a string\"",
true);
332 sd.
Parse(
"{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
338 INVALIDATE(s,
"\"ABCD\"",
"",
"maxLength",
"");
341 #if RAPIDJSON_SCHEMA_HAS_REGEX 344 sd.
Parse(
"{\"type\":\"string\",\"pattern\":\"^(\\\\([0-9]{3}\\\\))?[0-9]{3}-[0-9]{4}$\"}");
348 VALIDATE(s,
"\"(888)555-1212\"",
true);
349 INVALIDATE(s,
"\"(888)555-1212 ext. 532\"",
"",
"pattern",
"");
350 INVALIDATE(s,
"\"(800)FLOWERS\"",
"",
"pattern",
"");
355 sd.
Parse(
"{\"type\":\"string\",\"pattern\":\"a{0}\"}");
366 sd.
Parse(
"{\"type\":\"integer\"}");
381 sd.
Parse(
"{\"type\":\"integer\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}");
394 sd.
Parse(
"{\"type\":\"integer\",\"minimum\":-9223372036854775807,\"maximum\":9223372036854775806}");
397 INVALIDATE(s,
"-9223372036854775808",
"",
"minimum",
"");
398 VALIDATE(s,
"-9223372036854775807",
true);
404 VALIDATE(s,
"9223372036854775806",
true);
405 INVALIDATE(s,
"9223372036854775807",
"",
"maximum",
"");
406 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
411 sd.
Parse(
"{\"type\":\"integer\",\"minimum\":9223372036854775808,\"maximum\":18446744073709551614}");
414 INVALIDATE(s,
"-9223372036854775808",
"",
"minimum",
"");
415 INVALIDATE(s,
"9223372036854775807",
"",
"minimum",
"");
416 INVALIDATE(s,
"-2147483648",
"",
"minimum",
"");
418 INVALIDATE(s,
"2147483647",
"",
"minimum",
"");
419 INVALIDATE(s,
"2147483648",
"",
"minimum",
"");
420 INVALIDATE(s,
"4294967295",
"",
"minimum",
"");
421 VALIDATE(s,
"9223372036854775808",
true);
422 VALIDATE(s,
"18446744073709551614",
true);
423 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
428 sd.
Parse(
"{\"type\":\"integer\",\"minimum\":-9223372036854775808,\"maximum\":18446744073709551615,\"exclusiveMinimum\":true,\"exclusiveMaximum\":true}");
431 INVALIDATE(s,
"-9223372036854775808",
"",
"minimum",
"");
432 VALIDATE(s,
"-9223372036854775807",
true);
433 VALIDATE(s,
"18446744073709551614",
true);
434 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
439 sd.
Parse(
"{\"type\":\"integer\",\"multipleOf\":10}");
452 sd.
Parse(
"{\"type\":\"integer\",\"multipleOf\":18446744073709551615}");
456 VALIDATE(s,
"18446744073709551615",
true);
457 INVALIDATE(s,
"18446744073709551614",
"",
"multipleOf",
"");
462 sd.
Parse(
"{\"type\":\"number\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}");
478 sd.
Parse(
"{\"type\":\"number\",\"minimum\":-100,\"maximum\":-1,\"exclusiveMaximum\":true}");
488 INVALIDATE(s,
"2147483647",
"",
"maximum",
"");
489 INVALIDATE(s,
"2147483648",
"",
"maximum",
"");
490 INVALIDATE(s,
"4294967295",
"",
"maximum",
"");
491 INVALIDATE(s,
"9223372036854775808",
"",
"maximum",
"");
492 INVALIDATE(s,
"18446744073709551614",
"",
"maximum",
"");
493 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
498 sd.
Parse(
"{\"type\":\"number\",\"minimum\":0.1,\"maximum\":100.1,\"exclusiveMaximum\":true}");
501 INVALIDATE(s,
"-9223372036854775808",
"",
"minimum",
"");
502 INVALIDATE(s,
"-2147483648",
"",
"minimum",
"");
510 INVALIDATE(s,
"18446744073709551614",
"",
"maximum",
"");
511 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
512 INVALIDATE(s,
"2147483647",
"",
"maximum",
"");
513 INVALIDATE(s,
"2147483648",
"",
"maximum",
"");
514 INVALIDATE(s,
"4294967295",
"",
"maximum",
"");
515 INVALIDATE(s,
"9223372036854775808",
"",
"maximum",
"");
516 INVALIDATE(s,
"18446744073709551614",
"",
"maximum",
"");
517 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
522 sd.
Parse(
"{\"type\":\"number\",\"minimum\":9223372036854775808.0,\"maximum\":18446744073709550000.0}");
525 INVALIDATE(s,
"-9223372036854775808",
"",
"minimum",
"");
526 INVALIDATE(s,
"-2147483648",
"",
"minimum",
"");
528 INVALIDATE(s,
"2147483647",
"",
"minimum",
"");
529 INVALIDATE(s,
"2147483648",
"",
"minimum",
"");
530 INVALIDATE(s,
"4294967295",
"",
"minimum",
"");
531 VALIDATE(s,
"9223372036854775808",
true);
532 VALIDATE(s,
"18446744073709540000",
true);
533 INVALIDATE(s,
"18446744073709551615",
"",
"maximum",
"");
538 sd.
Parse(
"{\"type\":\"number\",\"multipleOf\":10.0}");
546 INVALIDATE(s,
"-2147483648",
"",
"multipleOf",
"");
548 INVALIDATE(s,
"2147483647",
"",
"multipleOf",
"");
549 INVALIDATE(s,
"2147483648",
"",
"multipleOf",
"");
551 INVALIDATE(s,
"4294967295",
"",
"multipleOf",
"");
557 sd.
Parse(
"{\"type\":\"number\",\"multipleOf\":1}");
562 INVALIDATE(s,
"3.1415926",
"",
"multipleOf",
"");
567 sd.
Parse(
"{\"type\":\"object\"}");
570 VALIDATE(s,
"{\"key\":\"value\",\"another_key\":\"another_value\"}",
true);
571 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);
572 INVALIDATE(s,
"[\"An\", \"array\", \"not\", \"an\", \"object\"]",
"",
"type",
"");
573 INVALIDATE(s,
"\"Not an object\"",
"",
"type",
"");
580 " \"type\": \"object\"," 581 " \"properties\" : {" 582 " \"number\": { \"type\": \"number\" }," 583 " \"street_name\" : { \"type\": \"string\" }," 584 " \"street_type\" : { \"type\": \"string\", \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"] }" 590 VALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }",
true);
591 INVALIDATE(s,
"{ \"number\": \"1600\", \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }",
"/properties/number",
"type",
"/number");
592 VALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\" }",
true);
594 VALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }",
true);
601 " \"type\": \"object\"," 602 " \"properties\" : {" 603 " \"number\": { \"type\": \"number\" }," 604 " \"street_name\" : { \"type\": \"string\" }," 605 " \"street_type\" : { \"type\": \"string\"," 606 " \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"]" 609 " \"additionalProperties\": false" 614 VALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }",
true);
615 INVALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }",
"",
"additionalProperties",
"/direction");
622 " \"type\": \"object\"," 623 " \"properties\" : {" 624 " \"number\": { \"type\": \"number\" }," 625 " \"street_name\" : { \"type\": \"string\" }," 626 " \"street_type\" : { \"type\": \"string\"," 627 " \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"]" 630 " \"additionalProperties\": { \"type\": \"string\" }" 634 VALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }",
true);
635 VALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }",
true);
636 INVALIDATE(s,
"{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"office_number\": 201 }",
"/additionalProperties",
"type",
"/office_number");
643 " \"type\": \"object\"," 644 " \"properties\" : {" 645 " \"name\": { \"type\": \"string\" }," 646 " \"email\" : { \"type\": \"string\" }," 647 " \"address\" : { \"type\": \"string\" }," 648 " \"telephone\" : { \"type\": \"string\" }" 650 " \"required\":[\"name\", \"email\"]" 654 VALIDATE(s,
"{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\" }",
true);
655 VALIDATE(s,
"{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}",
true);
656 INVALIDATE(s,
"{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }",
"",
"required",
"");
662 sd.
Parse(
"{\"type\":\"object\", \"minProperties\":2, \"maxProperties\":3}");
666 INVALIDATE(s,
"{\"a\":0}",
"",
"minProperties",
"");
667 VALIDATE(s,
"{\"a\":0,\"b\":1}",
true);
668 VALIDATE(s,
"{\"a\":0,\"b\":1,\"c\":2}",
true);
669 INVALIDATE(s,
"{\"a\":0,\"b\":1,\"c\":2,\"d\":3}",
"",
"maxProperties",
"");
676 " \"type\": \"object\"," 678 " \"name\": { \"type\": \"string\" }," 679 " \"credit_card\": { \"type\": \"number\" }," 680 " \"billing_address\": { \"type\": \"string\" }" 682 " \"required\": [\"name\"]," 683 " \"dependencies\": {" 684 " \"credit_card\": [\"billing_address\"]" 689 VALIDATE(s,
"{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555, \"billing_address\": \"555 Debtor's Lane\" }",
true);
690 INVALIDATE(s,
"{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555 }",
"",
"dependencies",
"");
691 VALIDATE(s,
"{ \"name\": \"John Doe\"}",
true);
692 VALIDATE(s,
"{ \"name\": \"John Doe\", \"billing_address\": \"555 Debtor's Lane\" }",
true);
699 " \"type\": \"object\"," 700 " \"properties\" : {" 701 " \"name\": { \"type\": \"string\" }," 702 " \"credit_card\" : { \"type\": \"number\" }" 704 " \"required\" : [\"name\"]," 705 " \"dependencies\" : {" 706 " \"credit_card\": {" 708 " \"billing_address\": { \"type\": \"string\" }" 710 " \"required\" : [\"billing_address\"]" 716 VALIDATE(s,
"{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555,\"billing_address\" : \"555 Debtor's Lane\"}",
true);
717 INVALIDATE(s,
"{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555 }",
"",
"dependencies",
"");
718 VALIDATE(s,
"{\"name\": \"John Doe\", \"billing_address\" : \"555 Debtor's Lane\"}",
true);
721 #if RAPIDJSON_SCHEMA_HAS_REGEX 726 " \"type\": \"object\"," 727 " \"patternProperties\": {" 728 " \"^S_\": { \"type\": \"string\" }," 729 " \"^I_\": { \"type\": \"integer\" }" 734 VALIDATE(s,
"{ \"S_25\": \"This is a string\" }",
true);
735 VALIDATE(s,
"{ \"I_0\": 42 }",
true);
736 INVALIDATE(s,
"{ \"S_0\": 42 }",
"",
"patternProperties",
"/S_0");
737 INVALIDATE(s,
"{ \"I_42\": \"This is a string\" }",
"",
"patternProperties",
"/I_42");
738 VALIDATE(s,
"{ \"keyword\": \"value\" }",
true);
745 " \"type\": \"object\"," 747 " \"builtin\": { \"type\": \"number\" }" 749 " \"patternProperties\": {" 750 " \"^S_\": { \"type\": \"string\" }," 751 " \"^I_\": { \"type\": \"integer\" }" 753 " \"additionalProperties\": { \"type\": \"string\" }" 757 VALIDATE(s,
"{ \"builtin\": 42 }",
true);
758 VALIDATE(s,
"{ \"keyword\": \"value\" }",
true);
759 INVALIDATE(s,
"{ \"keyword\": 42 }",
"/additionalProperties",
"type",
"/keyword");
765 sd.
Parse(
"{\"type\":\"array\"}");
768 VALIDATE(s,
"[1, 2, 3, 4, 5]",
true);
769 VALIDATE(s,
"[3, \"different\", { \"types\" : \"of values\" }]",
true);
770 INVALIDATE(s,
"{\"Not\": \"an array\"}",
"",
"type",
"");
777 " \"type\": \"array\"," 779 " \"type\": \"number\"" 784 VALIDATE(s,
"[1, 2, 3, 4, 5]",
true);
785 INVALIDATE(s,
"[1, 2, \"3\", 4, 5]",
"/items",
"type",
"/2");
793 " \"type\": \"array\"," 796 " \"type\": \"number\"" 799 " \"type\": \"string\"" 802 " \"type\": \"string\"," 803 " \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]" 806 " \"type\": \"string\"," 807 " \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]" 813 VALIDATE(s,
"[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]",
true);
814 INVALIDATE(s,
"[24, \"Sussex\", \"Drive\"]",
"/items/2",
"enum",
"/2");
815 INVALIDATE(s,
"[\"Palais de l'Elysee\"]",
"/items/0",
"type",
"/0");
816 VALIDATE(s,
"[10, \"Downing\", \"Street\"]",
true);
817 VALIDATE(s,
"[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]",
true);
824 " \"type\": \"array\"," 827 " \"type\": \"number\"" 830 " \"type\": \"string\"" 833 " \"type\": \"string\"," 834 " \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]" 837 " \"type\": \"string\"," 838 " \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]" 841 " \"additionalItems\": false" 845 VALIDATE(s,
"[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]",
true);
846 VALIDATE(s,
"[1600, \"Pennsylvania\", \"Avenue\"]",
true);
847 INVALIDATE(s,
"[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]",
"",
"items",
"/4");
852 sd.
Parse(
"{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}");
859 INVALIDATE(s,
"[1, 2, 3, 4]",
"",
"maxItems",
"");
864 sd.
Parse(
"{\"type\": \"array\", \"uniqueItems\": true}");
867 VALIDATE(s,
"[1, 2, 3, 4, 5]",
true);
868 INVALIDATE(s,
"[1, 2, 3, 3, 4]",
"",
"uniqueItems",
"/3");
874 sd.
Parse(
"{\"type\":\"boolean\"}");
885 sd.
Parse(
"{\"type\":\"null\"}");
898 sd.
Parse(
"{\"type\":\"array\", \"items\": { \"type\":\"string\" }}");
903 INVALIDATE(s,
"[{}]",
"/items",
"type",
"/0");
910 " \"type\":\"object\"," 913 " \"type\":[\"integer\", \"string\"]" 919 VALIDATE(s,
"{ \"tel\": 999 }",
true);
920 VALIDATE(s,
"{ \"tel\": \"123-456\" }",
true);
921 INVALIDATE(s,
"{ \"tel\": true }",
"/properties/tel",
"type",
"/tel");
928 " \"type\": [\"object\",\"string\"]," 931 " \"type\": \"integer\"" 938 VALIDATE(s,
"{ \"tel\": 999 }",
true);
939 INVALIDATE(s,
"{ \"tel\": \"fail\" }",
"/properties/tel",
"type",
"/tel");
947 " { \"type\": \"string\", \"minLength\": 2 }," 948 " { \"type\": \"string\", \"maxLength\": 5 }," 949 " { \"allOf\": [ { \"enum\" : [\"ok\", \"okay\", \"OK\", \"o\"] }, { \"enum\" : [\"ok\", \"OK\", \"o\"]} ] }" 959 INVALIDATE(s,
"\"too long\"",
"",
"allOf",
"");
967 " \"type\": \"object\"," 969 " \"~/\": { \"type\": \"number\" }" 973 INVALIDATE(s,
"{\"~/\":true}",
"/properties/~0~1",
"type",
"/~0~1");
976 template <
typename Allocator>
978 const char *paths[] = {
987 for (
size_t i = 0; i <
sizeof(paths) /
sizeof(paths[0]); i++) {
988 sprintf(buffer,
"%s%s", paths[i], filename);
989 fp = fopen(buffer,
"rb");
997 fseek(fp, 0, SEEK_END);
998 size_t length =
static_cast<size_t>(ftell(fp));
999 fseek(fp, 0, SEEK_SET);
1000 char*
json =
reinterpret_cast<char*
>(allocator.Malloc(length + 1));
1001 size_t readLength = fread(json, 1, length, fp);
1002 json[readLength] =
'\0';
1015 if (!d.Accept(validator)) {
1018 printf(
"Invalid schema: %s\n", sb.
GetString());
1022 printf(
"Invalid document: %s\n", sb.
GetString());
1038 d.ParseStream<0,
UTF8<> >(ss);
1039 ASSERT_FALSE(d.HasParseError());
1042 if (!d.Accept(validator)) {
1044 validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
1045 wprintf(L
"Invalid schema: %ls\n", sb.
GetString());
1046 wprintf(L
"Invalid keyword: %ls\n", validator.GetInvalidSchemaKeyword());
1048 validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
1049 wprintf(L
"Invalid document: %ls\n", sb.
GetString());
1055 template <
typename SchemaDocumentType = SchemaDocument>
1059 documentAllocator_(documentBuffer_, sizeof(documentBuffer_)),
1060 schemaAllocator_(schemaBuffer_, sizeof(schemaBuffer_))
1062 const char* filenames[kCount] = {
1063 "jsonschema/remotes/integer.json",
1064 "jsonschema/remotes/subSchemas.json",
1065 "jsonschema/remotes/folder/folderInteger.json",
1069 for (
size_t i = 0; i < kCount; i++) {
1072 char jsonBuffer[8192];
1076 printf(
"json remote file %s not found", filenames[i]);
1080 char stackBuffer[4096];
1084 sd_[i] =
new SchemaDocumentType(d, 0, &schemaAllocator_);
1091 for (
size_t i = 0; i < kCount; i++)
1096 const char* uris[kCount] = {
1097 "http://localhost:1234/integer.json",
1098 "http://localhost:1234/subSchemas.json",
1099 "http://localhost:1234/folder/folderInteger.json",
1100 "http://json-schema.org/draft-04/schema" 1103 for (
size_t i = 0; i < kCount; i++)
1104 if (strncmp(uri, uris[i], length) == 0 && strlen(uris[i]) == length)
1115 static const size_t kCount = 4;
1116 SchemaDocumentType* sd_[kCount];
1119 char documentBuffer_[16384];
1120 char schemaBuffer_[128 * 1024];
1124 const char* filenames[] = {
1125 "additionalItems.json",
1126 "additionalProperties.json",
1131 "dependencies.json",
1137 "maxProperties.json",
1141 "minProperties.json",
1146 "patternProperties.json",
1155 const char* onlyRunDescription = 0;
1158 unsigned testCount = 0;
1159 unsigned passCount = 0;
1164 char jsonBuffer[65536];
1165 char documentBuffer[65536];
1166 char documentStackBuffer[65536];
1167 char schemaBuffer[65536];
1168 char validatorBuffer[65536];
1175 for (
size_t i = 0; i <
sizeof(filenames) /
sizeof(filenames[0]); i++) {
1176 char filename[FILENAME_MAX];
1177 sprintf(filename,
"jsonschema/tests/draft4/%s", filenames[i]);
1180 printf(
"json test suite file %s not found", filename);
1187 printf(
"json test suite file %s has parse error", filename);
1193 SchemaDocumentType schema((*schemaItr)[
"schema"], &provider, &schemaAllocator);
1195 const char* description1 = (*schemaItr)[
"description"].GetString();
1196 const Value& tests = (*schemaItr)[
"tests"];
1198 const char* description2 = (*testItr)[
"description"].GetString();
1199 if (!onlyRunDescription || strcmp(description2, onlyRunDescription) == 0) {
1200 const Value& data = (*testItr)[
"data"];
1201 bool expected = (*testItr)[
"valid"].GetBool();
1204 bool actual = data.Accept(validator);
1205 if (expected != actual)
1206 printf(
"Fail: %30s \"%s\" \"%s\"\n", filename, description1, description2);
1213 schemaAllocator.
Clear();
1214 validatorAllocator.
Clear();
1218 documentAllocator.
Clear();
1220 jsonAllocator.
Clear();
1222 printf(
"%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount);
1229 sd.
Parse(
"{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
1237 EXPECT_TRUE(reader.
IsValid());
1238 EXPECT_TRUE(d.IsString());
1239 EXPECT_STREQ(
"red", d.GetString());
1244 sd.
Parse(
"{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
1252 EXPECT_FALSE(reader.
IsValid());
1257 EXPECT_TRUE(d.IsNull());
1260 TEST(SchemaValidatingWriter, Simple) {
1262 sd.
Parse(
"{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}");
1271 EXPECT_TRUE(d.Accept(validator));
1272 EXPECT_TRUE(validator.
IsValid());
1273 EXPECT_STREQ(
"\"red\"", sb.
GetString());
1277 d.
Parse(
"\"ABCD\"");
1278 EXPECT_FALSE(d.Accept(validator));
1279 EXPECT_FALSE(validator.
IsValid());
1287 rapidjson::GenericSchemaValidator<rapidjson::SchemaDocument, rapidjson::Document> v(s);
1290 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 1294 sd.
Parse(
"{ \"type\": [\"number\", \"string\"] }");
1302 VALIDATE(s,
"\"Life, the universe, and everything\"",
true);
1303 INVALIDATE(s,
"[\"Life\", \"the universe\", \"and everything\"]",
"",
"type",
"");
1306 #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS 1310 sd.
Parse(
"{\"required\": [\"a\", \"b\"] }");
1313 VALIDATE(s,
"{\"a\" : null, \"b\": null}",
true);
1314 INVALIDATE(s,
"{\"a\" : null, \"a\" : null}",
"",
"required",
"");
1320 sd.
Parse(
"{\"allOf\": [{\"$ref\": \"#/abc\"}]}");
1322 VALIDATE(s,
"{\"key1\": \"abc\", \"key2\": \"def\"}",
true);
1327 sd.
Parse(
"{\"type\": \"object\", \"additionalProperties\": false, \"patternProperties\": {\"^i\": { \"type\": \"string\" } } }");
1329 VALIDATE(s,
"{ \"item\": \"hello\" }",
true);
1334 sd.
Parse(
"{\"allOf\": [{\"type\": \"object\",\"properties\": {\"cyanArray2\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}}},{\"type\": \"object\",\"properties\": {\"blackArray\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}},\"required\": [ \"blackArray\" ]}]}");
1340 EXPECT_TRUE(validator.
Key(
"cyanArray2", 10,
false));
1342 EXPECT_TRUE(validator.
EndArray(0));
1343 EXPECT_TRUE(validator.
Key(
"blackArray", 10,
false));
1345 EXPECT_TRUE(validator.
EndArray(0));
1347 EXPECT_TRUE(validator.
IsValid());
1348 EXPECT_STREQ(
"{\"cyanArray2\":[],\"blackArray\":[]}", sb.
GetString());
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
#define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer)
const Ch * GetString() const
GenericDocument & Populate(Generator &g)
Populate this document by a generator which produces SAX events.
TEST(SchemaValidator, Hasher)
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
~RemoteSchemaDocumentProvider()
bool EndArray(SizeType elementCount)
#define VALIDATE(schema, json, expected)
void Reset()
Reset the internal states.
static char * ReadFile(const char *filename, Allocator &allocator)
SchemaDocumentType::AllocatorType schemaAllocator_
void Clear()
Deallocates all memory chunks, excluding the user-supplied buffer.
RemoteSchemaDocumentProvider()
const PointerType & GetInvalidSchemaPointer() const
bool Key(const Ch *str, SizeType len, bool copy)
ParseErrorCode Code() const
Get the error code.
const ParseResult & GetParseResult() const
Concept for allocating, resizing and freeing memory block.
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
const PointerType & GetInvalidDocumentPointer() const
PointerType GetInvalidSchemaPointer() const
Gets the JSON pointer pointed to the invalid schema.
DocumentType::AllocatorType documentAllocator_
GenericDocument & Parse(const typename SourceEncoding::Ch *str)
Parse JSON text from a read-only string (with Encoding conversion)
GenericDocument< typename SchemaDocumentType::EncodingType, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType
#define TEST_HASHER(json1, json2, expected)
PointerType GetInvalidDocumentPointer() const
Gets the JSON pointer pointed to the invalid value.
C-runtime library allocator.
virtual bool IsValid() const
Checks whether the current state is valid.
A helper class for parsing with validation.
virtual const SchemaDocumentType * GetRemoteDocument(const char *uri, SizeType length)
const Ch * GetInvalidSchemaKeyword() const
Gets the keyword of invalid schema.
static void Free(void *ptr)
static void Free(void *ptr)
Frees a memory block (concept Allocator)
GenericSchemaDocument< Value, CrtAllocator > SchemaDocument
const Ch * GetInvalidSchemaKeyword() const
bool HasParseError() const
Whether a parse error has occured in the last parsing.
bool EndObject(SizeType memberCount)
GenericPointer< ValueType, Allocator > PointerType