rj_schema 0.2.5 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rj_schema/rapidjson/CMakeLists.txt +23 -1
  3. data/ext/rj_schema/rapidjson/appveyor.yml +49 -1
  4. data/ext/rj_schema/rapidjson/bin/types/alotofkeys.json +502 -0
  5. data/ext/rj_schema/rapidjson/bin/unittestschema/address.json +139 -0
  6. data/ext/rj_schema/rapidjson/bin/unittestschema/allOf_address.json +7 -0
  7. data/ext/rj_schema/rapidjson/bin/unittestschema/anyOf_address.json +7 -0
  8. data/ext/rj_schema/rapidjson/bin/unittestschema/idandref.json +69 -0
  9. data/ext/rj_schema/rapidjson/bin/unittestschema/oneOf_address.json +7 -0
  10. data/ext/rj_schema/rapidjson/doc/stream.md +7 -7
  11. data/ext/rj_schema/rapidjson/doc/stream.zh-cn.md +1 -1
  12. data/ext/rj_schema/rapidjson/doc/tutorial.md +15 -15
  13. data/ext/rj_schema/rapidjson/example/schemavalidator/schemavalidator.cpp +120 -0
  14. data/ext/rj_schema/rapidjson/example/traverseaspointer.cpp +39 -0
  15. data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +464 -56
  16. data/ext/rj_schema/rapidjson/include/rapidjson/cursorstreamwrapper.h +1 -1
  17. data/ext/rj_schema/rapidjson/include/rapidjson/document.h +367 -72
  18. data/ext/rj_schema/rapidjson/include/rapidjson/encodedstream.h +1 -1
  19. data/ext/rj_schema/rapidjson/include/rapidjson/encodings.h +1 -1
  20. data/ext/rj_schema/rapidjson/include/rapidjson/error/en.h +49 -1
  21. data/ext/rj_schema/rapidjson/include/rapidjson/error/error.h +56 -1
  22. data/ext/rj_schema/rapidjson/include/rapidjson/filereadstream.h +1 -1
  23. data/ext/rj_schema/rapidjson/include/rapidjson/filewritestream.h +1 -1
  24. data/ext/rj_schema/rapidjson/include/rapidjson/fwd.h +1 -1
  25. data/ext/rj_schema/rapidjson/include/rapidjson/internal/biginteger.h +1 -1
  26. data/ext/rj_schema/rapidjson/include/rapidjson/internal/clzll.h +4 -4
  27. data/ext/rj_schema/rapidjson/include/rapidjson/internal/diyfp.h +1 -1
  28. data/ext/rj_schema/rapidjson/include/rapidjson/internal/dtoa.h +1 -1
  29. data/ext/rj_schema/rapidjson/include/rapidjson/internal/ieee754.h +1 -1
  30. data/ext/rj_schema/rapidjson/include/rapidjson/internal/itoa.h +1 -1
  31. data/ext/rj_schema/rapidjson/include/rapidjson/internal/meta.h +1 -1
  32. data/ext/rj_schema/rapidjson/include/rapidjson/internal/pow10.h +1 -1
  33. data/ext/rj_schema/rapidjson/include/rapidjson/internal/regex.h +1 -1
  34. data/ext/rj_schema/rapidjson/include/rapidjson/internal/stack.h +1 -1
  35. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strfunc.h +15 -1
  36. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strtod.h +1 -1
  37. data/ext/rj_schema/rapidjson/include/rapidjson/internal/swap.h +1 -1
  38. data/ext/rj_schema/rapidjson/include/rapidjson/istreamwrapper.h +1 -1
  39. data/ext/rj_schema/rapidjson/include/rapidjson/memorybuffer.h +1 -1
  40. data/ext/rj_schema/rapidjson/include/rapidjson/memorystream.h +1 -1
  41. data/ext/rj_schema/rapidjson/include/rapidjson/ostreamwrapper.h +1 -1
  42. data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +69 -2
  43. data/ext/rj_schema/rapidjson/include/rapidjson/prettywriter.h +1 -1
  44. data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +77 -12
  45. data/ext/rj_schema/rapidjson/include/rapidjson/reader.h +17 -9
  46. data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +558 -259
  47. data/ext/rj_schema/rapidjson/include/rapidjson/stream.h +1 -1
  48. data/ext/rj_schema/rapidjson/include/rapidjson/stringbuffer.h +1 -1
  49. data/ext/rj_schema/rapidjson/include/rapidjson/uri.h +466 -0
  50. data/ext/rj_schema/rapidjson/include/rapidjson/writer.h +3 -3
  51. data/ext/rj_schema/rapidjson/readme.md +3 -3
  52. data/ext/rj_schema/rapidjson/readme.zh-cn.md +2 -2
  53. data/ext/rj_schema/rapidjson/test/perftest/misctest.cpp +1 -1
  54. data/ext/rj_schema/rapidjson/test/perftest/perftest.cpp +1 -1
  55. data/ext/rj_schema/rapidjson/test/perftest/perftest.h +6 -5
  56. data/ext/rj_schema/rapidjson/test/perftest/platformtest.cpp +1 -1
  57. data/ext/rj_schema/rapidjson/test/perftest/rapidjsontest.cpp +21 -3
  58. data/ext/rj_schema/rapidjson/test/unittest/CMakeLists.txt +3 -0
  59. data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +194 -2
  60. data/ext/rj_schema/rapidjson/test/unittest/bigintegertest.cpp +1 -1
  61. data/ext/rj_schema/rapidjson/test/unittest/clzlltest.cpp +34 -0
  62. data/ext/rj_schema/rapidjson/test/unittest/cursorstreamwrappertest.cpp +1 -1
  63. data/ext/rj_schema/rapidjson/test/unittest/documenttest.cpp +3 -1
  64. data/ext/rj_schema/rapidjson/test/unittest/dtoatest.cpp +1 -1
  65. data/ext/rj_schema/rapidjson/test/unittest/encodedstreamtest.cpp +1 -1
  66. data/ext/rj_schema/rapidjson/test/unittest/encodingstest.cpp +1 -1
  67. data/ext/rj_schema/rapidjson/test/unittest/filestreamtest.cpp +1 -1
  68. data/ext/rj_schema/rapidjson/test/unittest/fwdtest.cpp +1 -1
  69. data/ext/rj_schema/rapidjson/test/unittest/istreamwrappertest.cpp +1 -1
  70. data/ext/rj_schema/rapidjson/test/unittest/itoatest.cpp +1 -1
  71. data/ext/rj_schema/rapidjson/test/unittest/jsoncheckertest.cpp +1 -1
  72. data/ext/rj_schema/rapidjson/test/unittest/namespacetest.cpp +1 -1
  73. data/ext/rj_schema/rapidjson/test/unittest/ostreamwrappertest.cpp +1 -1
  74. data/ext/rj_schema/rapidjson/test/unittest/platformtest.cpp +40 -0
  75. data/ext/rj_schema/rapidjson/test/unittest/pointertest.cpp +95 -3
  76. data/ext/rj_schema/rapidjson/test/unittest/prettywritertest.cpp +1 -1
  77. data/ext/rj_schema/rapidjson/test/unittest/readertest.cpp +4 -1
  78. data/ext/rj_schema/rapidjson/test/unittest/regextest.cpp +1 -1
  79. data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +961 -81
  80. data/ext/rj_schema/rapidjson/test/unittest/simdtest.cpp +1 -1
  81. data/ext/rj_schema/rapidjson/test/unittest/strfunctest.cpp +1 -1
  82. data/ext/rj_schema/rapidjson/test/unittest/stringbuffertest.cpp +1 -1
  83. data/ext/rj_schema/rapidjson/test/unittest/strtodtest.cpp +1 -1
  84. data/ext/rj_schema/rapidjson/test/unittest/unittest.cpp +1 -1
  85. data/ext/rj_schema/rapidjson/test/unittest/unittest.h +1 -1
  86. data/ext/rj_schema/rapidjson/test/unittest/uritest.cpp +718 -0
  87. data/ext/rj_schema/rapidjson/test/unittest/valuetest.cpp +13 -3
  88. data/ext/rj_schema/rapidjson/test/unittest/writertest.cpp +1 -1
  89. data/ext/rj_schema/rj_schema.cpp +162 -18
  90. data/lib/rj_schema.rb +1 -1
  91. metadata +14 -3
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -325,6 +325,8 @@ TEST(Document, Swap) {
325
325
  EXPECT_TRUE(d1.IsNull());
326
326
 
327
327
  // reset document, including allocator
328
+ // so clear o before so that it doesnt contain dangling elements
329
+ o.Clear();
328
330
  Document().Swap(d2);
329
331
  EXPECT_TRUE(d2.IsNull());
330
332
  EXPECT_NE(&d2.GetAllocator(), &a);
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -0,0 +1,40 @@
1
+ // Tencent is pleased to support the open source community by making RapidJSON available.
2
+ //
3
+ // Copyright (C) 2021 THL A29 Limited, a Tencent company, and Milo Yip.
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
+
17
+ // see https://github.com/Tencent/rapidjson/issues/1448
18
+ // including windows.h on purpose to provoke a compile time problem as GetObject is a
19
+ // macro that gets defined when windows.h is included
20
+ #ifdef _WIN32
21
+ #include <windows.h>
22
+ #endif
23
+
24
+ #include "rapidjson/document.h"
25
+ #undef GetObject
26
+
27
+ using namespace rapidjson;
28
+
29
+ TEST(Platform, GetObject) {
30
+ Document doc;
31
+ doc.Parse(" { \"object\" : { \"pi\": 3.1416} } ");
32
+ EXPECT_TRUE(doc.IsObject());
33
+ EXPECT_TRUE(doc.HasMember("object"));
34
+ const Document::ValueType& o = doc["object"];
35
+ EXPECT_TRUE(o.IsObject());
36
+ Value::ConstObject sub = o.GetObject();
37
+ EXPECT_TRUE(sub.HasMember("pi"));
38
+ Value::ConstObject sub2 = o.GetObj();
39
+ EXPECT_TRUE(sub2.HasMember("pi"));
40
+ }
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -475,7 +475,9 @@ TEST(Pointer, CopyConstructor) {
475
475
  EXPECT_EQ(1u, q.GetTokens()[1].length);
476
476
  EXPECT_STREQ("0", q.GetTokens()[1].name);
477
477
  EXPECT_EQ(0u, q.GetTokens()[1].index);
478
- EXPECT_EQ(&p.GetAllocator(), &q.GetAllocator());
478
+
479
+ // Copied pointer needs to have its own allocator
480
+ EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
479
481
  }
480
482
 
481
483
  // Static tokens
@@ -648,6 +650,52 @@ TEST(Pointer, Create) {
648
650
  }
649
651
  }
650
652
 
653
+ static const char kJsonIds[] = "{\n"
654
+ " \"id\": \"/root/\","
655
+ " \"foo\":[\"bar\", \"baz\", {\"id\": \"inarray\", \"child\": 1}],\n"
656
+ " \"int\" : 2,\n"
657
+ " \"str\" : \"val\",\n"
658
+ " \"obj\": {\"id\": \"inobj\", \"child\": 3},\n"
659
+ " \"jbo\": {\"id\": true, \"child\": 4}\n"
660
+ "}";
661
+
662
+
663
+ TEST(Pointer, GetUri) {
664
+ CrtAllocator allocator;
665
+ Document d;
666
+ d.Parse(kJsonIds);
667
+ Pointer::UriType doc("http://doc");
668
+ Pointer::UriType root("http://doc/root/");
669
+ Pointer::UriType empty = Pointer::UriType();
670
+
671
+ EXPECT_TRUE(Pointer("").GetUri(d, doc) == doc);
672
+ EXPECT_TRUE(Pointer("/foo").GetUri(d, doc) == root);
673
+ EXPECT_TRUE(Pointer("/foo/0").GetUri(d, doc) == root);
674
+ EXPECT_TRUE(Pointer("/foo/2").GetUri(d, doc) == root);
675
+ EXPECT_TRUE(Pointer("/foo/2/child").GetUri(d, doc) == Pointer::UriType("http://doc/root/inarray"));
676
+ EXPECT_TRUE(Pointer("/int").GetUri(d, doc) == root);
677
+ EXPECT_TRUE(Pointer("/str").GetUri(d, doc) == root);
678
+ EXPECT_TRUE(Pointer("/obj").GetUri(d, doc) == root);
679
+ EXPECT_TRUE(Pointer("/obj/child").GetUri(d, doc) == Pointer::UriType("http://doc/root/inobj"));
680
+ EXPECT_TRUE(Pointer("/jbo").GetUri(d, doc) == root);
681
+ EXPECT_TRUE(Pointer("/jbo/child").GetUri(d, doc) == root); // id not string
682
+
683
+ size_t unresolvedTokenIndex;
684
+ EXPECT_TRUE(Pointer("/abc").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary
685
+ EXPECT_EQ(0u, unresolvedTokenIndex);
686
+ EXPECT_TRUE(Pointer("/foo/3").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary
687
+ EXPECT_EQ(1u, unresolvedTokenIndex);
688
+ EXPECT_TRUE(Pointer("/foo/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo" is an array, cannot query by "a"
689
+ EXPECT_EQ(1u, unresolvedTokenIndex);
690
+ EXPECT_TRUE(Pointer("/foo/0/0").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query
691
+ EXPECT_EQ(2u, unresolvedTokenIndex);
692
+ EXPECT_TRUE(Pointer("/foo/0/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query
693
+ EXPECT_EQ(2u, unresolvedTokenIndex);
694
+
695
+ Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };
696
+ EXPECT_TRUE(Pointer(tokens, 1).GetUri(d, doc) == root);
697
+ }
698
+
651
699
  TEST(Pointer, Get) {
652
700
  Document d;
653
701
  d.Parse(kJson);
@@ -664,7 +712,8 @@ TEST(Pointer, Get) {
664
712
  EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
665
713
  EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
666
714
  EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
667
- EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
715
+
716
+ EXPECT_TRUE(Pointer("/abc").Get(d) == 0); // Out of boundary
668
717
  size_t unresolvedTokenIndex;
669
718
  EXPECT_TRUE(Pointer("/foo/2").Get(d, &unresolvedTokenIndex) == 0); // Out of boundary
670
719
  EXPECT_EQ(1u, unresolvedTokenIndex);
@@ -1529,6 +1578,38 @@ TEST(Pointer, Ambiguity) {
1529
1578
  }
1530
1579
  }
1531
1580
 
1581
+ TEST(Pointer, ResolveOnObject) {
1582
+ Document d;
1583
+ EXPECT_FALSE(d.Parse("{\"a\": 123}").HasParseError());
1584
+
1585
+ {
1586
+ Value::ConstObject o = static_cast<const Document&>(d).GetObject();
1587
+ EXPECT_EQ(123, Pointer("/a").Get(o)->GetInt());
1588
+ }
1589
+
1590
+ {
1591
+ Value::Object o = d.GetObject();
1592
+ Pointer("/a").Set(o, 456, d.GetAllocator());
1593
+ EXPECT_EQ(456, Pointer("/a").Get(o)->GetInt());
1594
+ }
1595
+ }
1596
+
1597
+ TEST(Pointer, ResolveOnArray) {
1598
+ Document d;
1599
+ EXPECT_FALSE(d.Parse("[1, 2, 3]").HasParseError());
1600
+
1601
+ {
1602
+ Value::ConstArray a = static_cast<const Document&>(d).GetArray();
1603
+ EXPECT_EQ(2, Pointer("/1").Get(a)->GetInt());
1604
+ }
1605
+
1606
+ {
1607
+ Value::Array a = d.GetArray();
1608
+ Pointer("/1").Set(a, 123, d.GetAllocator());
1609
+ EXPECT_EQ(123, Pointer("/1").Get(a)->GetInt());
1610
+ }
1611
+ }
1612
+
1532
1613
  TEST(Pointer, LessThan) {
1533
1614
  static const struct {
1534
1615
  const char *str;
@@ -1636,3 +1717,14 @@ TEST(Pointer, Issue483) {
1636
1717
  value.SetString(mystr.c_str(), static_cast<SizeType>(mystr.length()), document.GetAllocator());
1637
1718
  myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator());
1638
1719
  }
1720
+
1721
+ TEST(Pointer, Issue1899) {
1722
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
1723
+ PointerType p;
1724
+ PointerType q = p.Append("foo");
1725
+ EXPECT_TRUE(PointerType("/foo") == q);
1726
+ q = q.Append(1234);
1727
+ EXPECT_TRUE(PointerType("/foo/1234") == q);
1728
+ q = q.Append("");
1729
+ EXPECT_TRUE(PointerType("/foo/1234/") == q);
1730
+ }
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -944,6 +944,9 @@ TEST(Reader, ParseString_Error) {
944
944
  TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]", 2u, 8u);
945
945
  TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]", 2u, 14u);
946
946
 
947
+ // Single low surrogate pair in string is invalid.
948
+ TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\udc4d\"]", 2u, 8u);
949
+
947
950
  // Missing a closing quotation mark in string.
948
951
  TEST_STRING_ERROR(kParseErrorStringMissQuotationMark, "[\"Test]", 7u, 7u);
949
952
 
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -1,6 +1,6 @@
1
1
  // Tencent is pleased to support the open source community by making RapidJSON available.
2
2
  //
3
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
3
+ // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4
4
  //
5
5
  // Licensed under the MIT License (the "License"); you may not use this file except
6
6
  // in compliance with the License. You may obtain a copy of the License at
@@ -12,10 +12,15 @@
12
12
  // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13
13
  // specific language governing permissions and limitations under the License.
14
14
 
15
+ #define RAPIDJSON_SCHEMA_VERBOSE 0
16
+ #define RAPIDJSON_HAS_STDSTRING 1
17
+
15
18
  #include "unittest.h"
16
19
  #include "rapidjson/schema.h"
17
20
  #include "rapidjson/stringbuffer.h"
18
21
  #include "rapidjson/writer.h"
22
+ #include "rapidjson/error/error.h"
23
+ #include "rapidjson/error/en.h"
19
24
 
20
25
  #ifdef __clang__
21
26
  RAPIDJSON_DIAG_PUSH
@@ -114,11 +119,18 @@ TEST(SchemaValidator, Hasher) {
114
119
  EXPECT_FALSE(d.HasParseError());\
115
120
  EXPECT_TRUE(expected == d.Accept(validator));\
116
121
  EXPECT_TRUE(expected == validator.IsValid());\
122
+ ValidateErrorCode code = validator.GetInvalidSchemaCode();\
123
+ if (expected) {\
124
+ EXPECT_TRUE(code == kValidateErrorNone);\
125
+ EXPECT_TRUE(validator.GetInvalidSchemaKeyword() == 0);\
126
+ }\
117
127
  if ((expected) && !validator.IsValid()) {\
118
128
  StringBuffer sb;\
119
129
  validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\
120
130
  printf("Invalid schema: %s\n", sb.GetString());\
121
131
  printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());\
132
+ printf("Invalid code: %d\n", code);\
133
+ printf("Invalid message: %s\n", GetValidateError_En(code));\
122
134
  sb.Clear();\
123
135
  validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);\
124
136
  printf("Invalid document: %s\n", sb.GetString());\
@@ -131,19 +143,23 @@ TEST(SchemaValidator, Hasher) {
131
143
 
132
144
  #define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error) \
133
145
  {\
134
- INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, SchemaValidator, Pointer) \
146
+ INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, kValidateDefaultFlags, SchemaValidator, Pointer) \
135
147
  }
136
148
 
137
149
  #define INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, \
138
- SchemaValidatorType, PointerType) \
150
+ flags, SchemaValidatorType, PointerType) \
139
151
  {\
140
152
  SchemaValidatorType validator(schema);\
153
+ validator.SetValidateFlags(flags);\
141
154
  Document d;\
142
155
  /*printf("\n%s\n", json);*/\
143
156
  d.Parse(json);\
144
157
  EXPECT_FALSE(d.HasParseError());\
145
- EXPECT_FALSE(d.Accept(validator));\
158
+ d.Accept(validator);\
146
159
  EXPECT_FALSE(validator.IsValid());\
160
+ ValidateErrorCode code = validator.GetInvalidSchemaCode();\
161
+ ASSERT_TRUE(code != kValidateErrorNone);\
162
+ ASSERT_TRUE(strcmp(GetValidateError_En(code), "Unknown error.") != 0);\
147
163
  if (validator.GetInvalidSchemaPointer() != PointerType(invalidSchemaPointer)) {\
148
164
  StringBuffer sb;\
149
165
  validator.GetInvalidSchemaPointer().Stringify(sb);\
@@ -191,6 +207,7 @@ TEST(SchemaValidator, MultiType) {
191
207
  VALIDATE(s, "\"Life, the universe, and everything\"", true);
192
208
  INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "",
193
209
  "{ \"type\": {"
210
+ " \"errorCode\": 20,"
194
211
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
195
212
  " \"expected\": [\"string\", \"number\"], \"actual\": \"array\""
196
213
  "}}");
@@ -203,7 +220,7 @@ TEST(SchemaValidator, Enum_Typed) {
203
220
 
204
221
  VALIDATE(s, "\"red\"", true);
205
222
  INVALIDATE(s, "\"blue\"", "", "enum", "",
206
- "{ \"enum\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
223
+ "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
207
224
  }
208
225
 
209
226
  TEST(SchemaValidator, Enum_Typless) {
@@ -215,7 +232,7 @@ TEST(SchemaValidator, Enum_Typless) {
215
232
  VALIDATE(s, "null", true);
216
233
  VALIDATE(s, "42", true);
217
234
  INVALIDATE(s, "0", "", "enum", "",
218
- "{ \"enum\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
235
+ "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
219
236
  }
220
237
 
221
238
  TEST(SchemaValidator, Enum_InvalidType) {
@@ -226,6 +243,7 @@ TEST(SchemaValidator, Enum_InvalidType) {
226
243
  VALIDATE(s, "\"red\"", true);
227
244
  INVALIDATE(s, "null", "", "type", "",
228
245
  "{ \"type\": {"
246
+ " \"errorCode\": 20,"
229
247
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
230
248
  " \"expected\": [\"string\"], \"actual\": \"null\""
231
249
  "}}");
@@ -239,9 +257,12 @@ TEST(SchemaValidator, AllOf) {
239
257
 
240
258
  VALIDATE(s, "\"ok\"", true);
241
259
  INVALIDATE(s, "\"too long\"", "", "allOf", "",
242
- "{ \"maxLength\": { "
243
- " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\", "
244
- " \"expected\": 5, \"actual\": \"too long\""
260
+ "{ \"allOf\": {"
261
+ " \"errors\": ["
262
+ " {},"
263
+ " {\"maxLength\": {\"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\", \"expected\": 5, \"actual\": \"too long\"}}"
264
+ " ],"
265
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
245
266
  "}}");
246
267
  }
247
268
  {
@@ -251,8 +272,12 @@ TEST(SchemaValidator, AllOf) {
251
272
 
252
273
  VALIDATE(s, "\"No way\"", false);
253
274
  INVALIDATE(s, "-1", "", "allOf", "",
254
- "{ \"type\": { \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\","
255
- " \"expected\": [\"string\"], \"actual\": \"integer\""
275
+ "{ \"allOf\": {"
276
+ " \"errors\": ["
277
+ " {\"type\": { \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\", \"errorCode\": 20, \"expected\": [\"string\"], \"actual\": \"integer\"}},"
278
+ " {}"
279
+ " ],"
280
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
256
281
  "}}");
257
282
  }
258
283
  }
@@ -266,13 +291,16 @@ TEST(SchemaValidator, AnyOf) {
266
291
  VALIDATE(s, "42", true);
267
292
  INVALIDATE(s, "{ \"Not a\": \"string or number\" }", "", "anyOf", "",
268
293
  "{ \"anyOf\": {"
294
+ " \"errorCode\": 24,"
269
295
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\", "
270
296
  " \"errors\": ["
271
297
  " { \"type\": {"
298
+ " \"errorCode\": 20,"
272
299
  " \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\","
273
300
  " \"expected\": [\"string\"], \"actual\": \"object\""
274
301
  " }},"
275
302
  " { \"type\": {"
303
+ " \"errorCode\": 20,"
276
304
  " \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/1\","
277
305
  " \"expected\": [\"number\"], \"actual\": \"object\""
278
306
  " }}"
@@ -289,20 +317,23 @@ TEST(SchemaValidator, OneOf) {
289
317
  VALIDATE(s, "9", true);
290
318
  INVALIDATE(s, "2", "", "oneOf", "",
291
319
  "{ \"oneOf\": {"
320
+ " \"errorCode\": 21,"
292
321
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
293
322
  " \"errors\": ["
294
323
  " { \"multipleOf\": {"
324
+ " \"errorCode\": 1,"
295
325
  " \"instanceRef\": \"#\", \"schemaRef\": \"#/oneOf/0\","
296
326
  " \"expected\": 5, \"actual\": 2"
297
327
  " }},"
298
328
  " { \"multipleOf\": {"
329
+ " \"errorCode\": 1,"
299
330
  " \"instanceRef\": \"#\", \"schemaRef\": \"#/oneOf/1\","
300
331
  " \"expected\": 3, \"actual\": 2"
301
332
  " }}"
302
333
  " ]"
303
334
  "}}");
304
335
  INVALIDATE(s, "15", "", "oneOf", "",
305
- "{ \"oneOf\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"errors\": [{}, {}]}}");
336
+ "{ \"oneOf\": { \"errorCode\": 22, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"errors\": [{}, {}]}}");
306
337
  }
307
338
 
308
339
  TEST(SchemaValidator, Not) {
@@ -313,7 +344,7 @@ TEST(SchemaValidator, Not) {
313
344
  VALIDATE(s, "42", true);
314
345
  VALIDATE(s, "{ \"key\": \"value\" }", true);
315
346
  INVALIDATE(s, "\"I am a string\"", "", "not", "",
316
- "{ \"not\": { \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
347
+ "{ \"not\": { \"errorCode\": 25, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}");
317
348
  }
318
349
 
319
350
  TEST(SchemaValidator, Ref) {
@@ -378,10 +409,12 @@ TEST(SchemaValidator, Ref_AllOf) {
378
409
  SchemaDocument s(sd);
379
410
 
380
411
  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\"]"
412
+ "{ \"allOf\": {"
413
+ " \"errors\": ["
414
+ " {},"
415
+ " {\"required\": {\"errorCode\": 15, \"instanceRef\": \"#/shipping_address\", \"schemaRef\": \"#/properties/shipping_address/allOf/1\", \"missing\": [\"type\"]}}"
416
+ " ],"
417
+ " \"errorCode\":23,\"instanceRef\":\"#/shipping_address\",\"schemaRef\":\"#/properties/shipping_address\""
385
418
  "}}");
386
419
  VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\", \"type\": \"business\"} }", true);
387
420
  }
@@ -394,26 +427,31 @@ TEST(SchemaValidator, String) {
394
427
  VALIDATE(s, "\"I'm a string\"", true);
395
428
  INVALIDATE(s, "42", "", "type", "",
396
429
  "{ \"type\": {"
430
+ " \"errorCode\": 20,"
397
431
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
398
432
  " \"expected\": [\"string\"], \"actual\": \"integer\""
399
433
  "}}");
400
434
  INVALIDATE(s, "2147483648", "", "type", "",
401
435
  "{ \"type\": {"
436
+ " \"errorCode\": 20,"
402
437
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
403
438
  " \"expected\": [\"string\"], \"actual\": \"integer\""
404
439
  "}}"); // 2^31 can only be fit in unsigned
405
440
  INVALIDATE(s, "-2147483649", "", "type", "",
406
441
  "{ \"type\": {"
442
+ " \"errorCode\": 20,"
407
443
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
408
444
  " \"expected\": [\"string\"], \"actual\": \"integer\""
409
445
  "}}"); // -2^31 - 1 can only be fit in int64_t
410
446
  INVALIDATE(s, "4294967296", "", "type", "",
411
447
  "{ \"type\": {"
448
+ " \"errorCode\": 20,"
412
449
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
413
450
  " \"expected\": [\"string\"], \"actual\": \"integer\""
414
451
  "}}"); // 2^32 can only be fit in int64_t
415
452
  INVALIDATE(s, "3.1415926", "", "type", "",
416
453
  "{ \"type\": {"
454
+ " \"errorCode\": 20,"
417
455
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
418
456
  " \"expected\": [\"string\"], \"actual\": \"number\""
419
457
  "}}");
@@ -426,6 +464,7 @@ TEST(SchemaValidator, String_LengthRange) {
426
464
 
427
465
  INVALIDATE(s, "\"A\"", "", "minLength", "",
428
466
  "{ \"minLength\": {"
467
+ " \"errorCode\": 7,"
429
468
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
430
469
  " \"expected\": 2, \"actual\": \"A\""
431
470
  "}}");
@@ -433,6 +472,7 @@ TEST(SchemaValidator, String_LengthRange) {
433
472
  VALIDATE(s, "\"ABC\"", true);
434
473
  INVALIDATE(s, "\"ABCD\"", "", "maxLength", "",
435
474
  "{ \"maxLength\": {"
475
+ " \"errorCode\": 6,"
436
476
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
437
477
  " \"expected\": 3, \"actual\": \"ABCD\""
438
478
  "}}");
@@ -448,11 +488,13 @@ TEST(SchemaValidator, String_Pattern) {
448
488
  VALIDATE(s, "\"(888)555-1212\"", true);
449
489
  INVALIDATE(s, "\"(888)555-1212 ext. 532\"", "", "pattern", "",
450
490
  "{ \"pattern\": {"
491
+ " \"errorCode\": 8,"
451
492
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
452
493
  " \"actual\": \"(888)555-1212 ext. 532\""
453
494
  "}}");
454
495
  INVALIDATE(s, "\"(800)FLOWERS\"", "", "pattern", "",
455
496
  "{ \"pattern\": {"
497
+ " \"errorCode\": 8,"
456
498
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
457
499
  " \"actual\": \"(800)FLOWERS\""
458
500
  "}}");
@@ -482,11 +524,13 @@ TEST(SchemaValidator, Integer) {
482
524
  VALIDATE(s, "4294967296", true); // 2^32 can only be fit in int64_t
483
525
  INVALIDATE(s, "3.1415926", "", "type", "",
484
526
  "{ \"type\": {"
527
+ " \"errorCode\": 20,"
485
528
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
486
529
  " \"expected\": [\"integer\"], \"actual\": \"number\""
487
530
  "}}");
488
531
  INVALIDATE(s, "\"42\"", "", "type", "",
489
532
  "{ \"type\": {"
533
+ " \"errorCode\": 20,"
490
534
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
491
535
  " \"expected\": [\"integer\"], \"actual\": \"string\""
492
536
  "}}");
@@ -499,6 +543,7 @@ TEST(SchemaValidator, Integer_Range) {
499
543
 
500
544
  INVALIDATE(s, "-1", "", "minimum", "",
501
545
  "{ \"minimum\": {"
546
+ " \"errorCode\": 4,"
502
547
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
503
548
  " \"expected\": 0, \"actual\": -1"
504
549
  "}}");
@@ -507,11 +552,13 @@ TEST(SchemaValidator, Integer_Range) {
507
552
  VALIDATE(s, "99", true);
508
553
  INVALIDATE(s, "100", "", "maximum", "",
509
554
  "{ \"maximum\": {"
555
+ " \"errorCode\": 3,"
510
556
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
511
557
  " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100"
512
558
  "}}");
513
559
  INVALIDATE(s, "101", "", "maximum", "",
514
560
  "{ \"maximum\": {"
561
+ " \"errorCode\": 3,"
515
562
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
516
563
  " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 101"
517
564
  "}}");
@@ -524,6 +571,7 @@ TEST(SchemaValidator, Integer_Range64Boundary) {
524
571
 
525
572
  INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
526
573
  "{ \"minimum\": {"
574
+ " \"errorCode\": 4,"
527
575
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
528
576
  " \"expected\": -9223372036854775807, \"actual\": -9223372036854775808"
529
577
  "}}");
@@ -536,11 +584,13 @@ TEST(SchemaValidator, Integer_Range64Boundary) {
536
584
  VALIDATE(s, "9223372036854775806", true);
537
585
  INVALIDATE(s, "9223372036854775807", "", "maximum", "",
538
586
  "{ \"maximum\": {"
587
+ " \"errorCode\": 2,"
539
588
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
540
589
  " \"expected\": 9223372036854775806, \"actual\": 9223372036854775807"
541
590
  "}}");
542
591
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
543
592
  "{ \"maximum\": {"
593
+ " \"errorCode\": 2,"
544
594
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
545
595
  " \"expected\": 9223372036854775806, \"actual\": 18446744073709551615"
546
596
  "}}"); // uint64_t max
@@ -553,36 +603,43 @@ TEST(SchemaValidator, Integer_RangeU64Boundary) {
553
603
 
554
604
  INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
555
605
  "{ \"minimum\": {"
606
+ " \"errorCode\": 4,"
556
607
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
557
608
  " \"expected\": 9223372036854775808, \"actual\": -9223372036854775808"
558
609
  "}}");
559
610
  INVALIDATE(s, "9223372036854775807", "", "minimum", "",
560
611
  "{ \"minimum\": {"
612
+ " \"errorCode\": 4,"
561
613
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
562
614
  " \"expected\": 9223372036854775808, \"actual\": 9223372036854775807"
563
615
  "}}");
564
616
  INVALIDATE(s, "-2147483648", "", "minimum", "",
565
617
  "{ \"minimum\": {"
618
+ " \"errorCode\": 4,"
566
619
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
567
620
  " \"expected\": 9223372036854775808, \"actual\": -2147483648"
568
621
  "}}"); // int min
569
622
  INVALIDATE(s, "0", "", "minimum", "",
570
623
  "{ \"minimum\": {"
624
+ " \"errorCode\": 4,"
571
625
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
572
626
  " \"expected\": 9223372036854775808, \"actual\": 0"
573
627
  "}}");
574
628
  INVALIDATE(s, "2147483647", "", "minimum", "",
575
629
  "{ \"minimum\": {"
630
+ " \"errorCode\": 4,"
576
631
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
577
632
  " \"expected\": 9223372036854775808, \"actual\": 2147483647"
578
633
  "}}"); // int max
579
634
  INVALIDATE(s, "2147483648", "", "minimum", "",
580
635
  "{ \"minimum\": {"
636
+ " \"errorCode\": 4,"
581
637
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
582
638
  " \"expected\": 9223372036854775808, \"actual\": 2147483648"
583
639
  "}}"); // unsigned first
584
640
  INVALIDATE(s, "4294967295", "", "minimum", "",
585
641
  "{ \"minimum\": {"
642
+ " \"errorCode\": 4,"
586
643
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
587
644
  " \"expected\": 9223372036854775808, \"actual\": 4294967295"
588
645
  "}}"); // unsigned max
@@ -590,6 +647,7 @@ TEST(SchemaValidator, Integer_RangeU64Boundary) {
590
647
  VALIDATE(s, "18446744073709551614", true);
591
648
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
592
649
  "{ \"maximum\": {"
650
+ " \"errorCode\": 2,"
593
651
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
594
652
  " \"expected\": 18446744073709551614, \"actual\": 18446744073709551615"
595
653
  "}}");
@@ -602,6 +660,7 @@ TEST(SchemaValidator, Integer_Range64BoundaryExclusive) {
602
660
 
603
661
  INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
604
662
  "{ \"minimum\": {"
663
+ " \"errorCode\": 5,"
605
664
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
606
665
  " \"expected\": -9223372036854775808, \"exclusiveMinimum\": true, "
607
666
  " \"actual\": -9223372036854775808"
@@ -610,6 +669,7 @@ TEST(SchemaValidator, Integer_Range64BoundaryExclusive) {
610
669
  VALIDATE(s, "18446744073709551614", true);
611
670
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
612
671
  "{ \"maximum\": {"
672
+ " \"errorCode\": 3,"
613
673
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
614
674
  " \"expected\": 18446744073709551615, \"exclusiveMaximum\": true, "
615
675
  " \"actual\": 18446744073709551615"
@@ -627,11 +687,13 @@ TEST(SchemaValidator, Integer_MultipleOf) {
627
687
  VALIDATE(s, "20", true);
628
688
  INVALIDATE(s, "23", "", "multipleOf", "",
629
689
  "{ \"multipleOf\": {"
690
+ " \"errorCode\": 1,"
630
691
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
631
692
  " \"expected\": 10, \"actual\": 23"
632
693
  "}}");
633
694
  INVALIDATE(s, "-23", "", "multipleOf", "",
634
695
  "{ \"multipleOf\": {"
696
+ " \"errorCode\": 1,"
635
697
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
636
698
  " \"expected\": 10, \"actual\": -23"
637
699
  "}}");
@@ -646,6 +708,7 @@ TEST(SchemaValidator, Integer_MultipleOf64Boundary) {
646
708
  VALIDATE(s, "18446744073709551615", true);
647
709
  INVALIDATE(s, "18446744073709551614", "", "multipleOf", "",
648
710
  "{ \"multipleOf\": {"
711
+ " \"errorCode\": 1,"
649
712
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
650
713
  " \"expected\": 18446744073709551615, \"actual\": 18446744073709551614"
651
714
  "}}");
@@ -658,6 +721,7 @@ TEST(SchemaValidator, Number_Range) {
658
721
 
659
722
  INVALIDATE(s, "-1", "", "minimum", "",
660
723
  "{ \"minimum\": {"
724
+ " \"errorCode\": 4,"
661
725
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
662
726
  " \"expected\": 0, \"actual\": -1"
663
727
  "}}");
@@ -668,16 +732,19 @@ TEST(SchemaValidator, Number_Range) {
668
732
  VALIDATE(s, "99.9", true);
669
733
  INVALIDATE(s, "100", "", "maximum", "",
670
734
  "{ \"maximum\": {"
735
+ " \"errorCode\": 3,"
671
736
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
672
737
  " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100"
673
738
  "}}");
674
739
  INVALIDATE(s, "100.0", "", "maximum", "",
675
740
  "{ \"maximum\": {"
741
+ " \"errorCode\": 3,"
676
742
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
677
743
  " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100.0"
678
744
  "}}");
679
745
  INVALIDATE(s, "101.5", "", "maximum", "",
680
746
  "{ \"maximum\": {"
747
+ " \"errorCode\": 3,"
681
748
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
682
749
  " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 101.5"
683
750
  "}}");
@@ -690,11 +757,13 @@ TEST(SchemaValidator, Number_RangeInt) {
690
757
 
691
758
  INVALIDATE(s, "-101", "", "minimum", "",
692
759
  "{ \"minimum\": {"
760
+ " \"errorCode\": 4,"
693
761
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
694
762
  " \"expected\": -100, \"actual\": -101"
695
763
  "}}");
696
764
  INVALIDATE(s, "-100.1", "", "minimum", "",
697
765
  "{ \"minimum\": {"
766
+ " \"errorCode\": 4,"
698
767
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
699
768
  " \"expected\": -100, \"actual\": -100.1"
700
769
  "}}");
@@ -702,46 +771,55 @@ TEST(SchemaValidator, Number_RangeInt) {
702
771
  VALIDATE(s, "-2", true);
703
772
  INVALIDATE(s, "-1", "", "maximum", "",
704
773
  "{ \"maximum\": {"
774
+ " \"errorCode\": 3,"
705
775
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
706
776
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": -1"
707
777
  "}}");
708
778
  INVALIDATE(s, "-0.9", "", "maximum", "",
709
779
  "{ \"maximum\": {"
780
+ " \"errorCode\": 3,"
710
781
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
711
782
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": -0.9"
712
783
  "}}");
713
784
  INVALIDATE(s, "0", "", "maximum", "",
714
785
  "{ \"maximum\": {"
786
+ " \"errorCode\": 3,"
715
787
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
716
788
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 0"
717
789
  "}}");
718
790
  INVALIDATE(s, "2147483647", "", "maximum", "",
719
791
  "{ \"maximum\": {"
792
+ " \"errorCode\": 3,"
720
793
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
721
794
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 2147483647"
722
795
  "}}"); // int max
723
796
  INVALIDATE(s, "2147483648", "", "maximum", "",
724
797
  "{ \"maximum\": {"
798
+ " \"errorCode\": 3,"
725
799
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
726
800
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 2147483648"
727
801
  "}}"); // unsigned first
728
802
  INVALIDATE(s, "4294967295", "", "maximum", "",
729
803
  "{ \"maximum\": {"
804
+ " \"errorCode\": 3,"
730
805
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
731
806
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 4294967295"
732
807
  "}}"); // unsigned max
733
808
  INVALIDATE(s, "9223372036854775808", "", "maximum", "",
734
809
  "{ \"maximum\": {"
810
+ " \"errorCode\": 3,"
735
811
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
736
812
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 9223372036854775808"
737
813
  "}}");
738
814
  INVALIDATE(s, "18446744073709551614", "", "maximum", "",
739
815
  "{ \"maximum\": {"
816
+ " \"errorCode\": 3,"
740
817
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
741
818
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614"
742
819
  "}}");
743
820
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
744
821
  "{ \"maximum\": {"
822
+ " \"errorCode\": 3,"
745
823
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
746
824
  " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615"
747
825
  "}}");
@@ -754,16 +832,19 @@ TEST(SchemaValidator, Number_RangeDouble) {
754
832
 
755
833
  INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
756
834
  "{ \"minimum\": {"
835
+ " \"errorCode\": 4,"
757
836
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
758
837
  " \"expected\": 0.1, \"actual\": -9223372036854775808"
759
838
  "}}");
760
839
  INVALIDATE(s, "-2147483648", "", "minimum", "",
761
840
  "{ \"minimum\": {"
841
+ " \"errorCode\": 4,"
762
842
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
763
843
  " \"expected\": 0.1, \"actual\": -2147483648"
764
844
  "}}"); // int min
765
845
  INVALIDATE(s, "-1", "", "minimum", "",
766
846
  "{ \"minimum\": {"
847
+ " \"errorCode\": 4,"
767
848
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
768
849
  " \"expected\": 0.1, \"actual\": -1"
769
850
  "}}");
@@ -773,51 +854,61 @@ TEST(SchemaValidator, Number_RangeDouble) {
773
854
  VALIDATE(s, "100", true);
774
855
  INVALIDATE(s, "101", "", "maximum", "",
775
856
  "{ \"maximum\": {"
857
+ " \"errorCode\": 3,"
776
858
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
777
859
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 101"
778
860
  "}}");
779
861
  INVALIDATE(s, "101.5", "", "maximum", "",
780
862
  "{ \"maximum\": {"
863
+ " \"errorCode\": 3,"
781
864
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
782
865
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 101.5"
783
866
  "}}");
784
867
  INVALIDATE(s, "18446744073709551614", "", "maximum", "",
785
868
  "{ \"maximum\": {"
869
+ " \"errorCode\": 3,"
786
870
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
787
871
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614"
788
872
  "}}");
789
873
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
790
874
  "{ \"maximum\": {"
875
+ " \"errorCode\": 3,"
791
876
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
792
877
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615"
793
878
  "}}");
794
879
  INVALIDATE(s, "2147483647", "", "maximum", "",
795
880
  "{ \"maximum\": {"
881
+ " \"errorCode\": 3,"
796
882
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
797
883
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 2147483647"
798
884
  "}}"); // int max
799
885
  INVALIDATE(s, "2147483648", "", "maximum", "",
800
886
  "{ \"maximum\": {"
887
+ " \"errorCode\": 3,"
801
888
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
802
889
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 2147483648"
803
890
  "}}"); // unsigned first
804
891
  INVALIDATE(s, "4294967295", "", "maximum", "",
805
892
  "{ \"maximum\": {"
893
+ " \"errorCode\": 3,"
806
894
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
807
895
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 4294967295"
808
896
  "}}"); // unsigned max
809
897
  INVALIDATE(s, "9223372036854775808", "", "maximum", "",
810
898
  "{ \"maximum\": {"
899
+ " \"errorCode\": 3,"
811
900
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
812
901
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 9223372036854775808"
813
902
  "}}");
814
903
  INVALIDATE(s, "18446744073709551614", "", "maximum", "",
815
904
  "{ \"maximum\": {"
905
+ " \"errorCode\": 3,"
816
906
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
817
907
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614"
818
908
  "}}");
819
909
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
820
910
  "{ \"maximum\": {"
911
+ " \"errorCode\": 3,"
821
912
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
822
913
  " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615"
823
914
  "}}");
@@ -830,31 +921,37 @@ TEST(SchemaValidator, Number_RangeDoubleU64Boundary) {
830
921
 
831
922
  INVALIDATE(s, "-9223372036854775808", "", "minimum", "",
832
923
  "{ \"minimum\": {"
924
+ " \"errorCode\": 4,"
833
925
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
834
926
  " \"expected\": 9223372036854775808.0, \"actual\": -9223372036854775808"
835
927
  "}}");
836
928
  INVALIDATE(s, "-2147483648", "", "minimum", "",
837
929
  "{ \"minimum\": {"
930
+ " \"errorCode\": 4,"
838
931
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
839
932
  " \"expected\": 9223372036854775808.0, \"actual\": -2147483648"
840
933
  "}}"); // int min
841
934
  INVALIDATE(s, "0", "", "minimum", "",
842
935
  "{ \"minimum\": {"
936
+ " \"errorCode\": 4,"
843
937
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
844
938
  " \"expected\": 9223372036854775808.0, \"actual\": 0"
845
939
  "}}");
846
940
  INVALIDATE(s, "2147483647", "", "minimum", "",
847
941
  "{ \"minimum\": {"
942
+ " \"errorCode\": 4,"
848
943
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
849
944
  " \"expected\": 9223372036854775808.0, \"actual\": 2147483647"
850
945
  "}}"); // int max
851
946
  INVALIDATE(s, "2147483648", "", "minimum", "",
852
947
  "{ \"minimum\": {"
948
+ " \"errorCode\": 4,"
853
949
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
854
950
  " \"expected\": 9223372036854775808.0, \"actual\": 2147483648"
855
951
  "}}"); // unsigned first
856
952
  INVALIDATE(s, "4294967295", "", "minimum", "",
857
953
  "{ \"minimum\": {"
954
+ " \"errorCode\": 4,"
858
955
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
859
956
  " \"expected\": 9223372036854775808.0, \"actual\": 4294967295"
860
957
  "}}"); // unsigned max
@@ -862,6 +959,7 @@ TEST(SchemaValidator, Number_RangeDoubleU64Boundary) {
862
959
  VALIDATE(s, "18446744073709540000", true);
863
960
  INVALIDATE(s, "18446744073709551615", "", "maximum", "",
864
961
  "{ \"maximum\": {"
962
+ " \"errorCode\": 2,"
865
963
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
866
964
  " \"expected\": 18446744073709550000.0, \"actual\": 18446744073709551615"
867
965
  "}}");
@@ -878,28 +976,33 @@ TEST(SchemaValidator, Number_MultipleOf) {
878
976
  VALIDATE(s, "20", true);
879
977
  INVALIDATE(s, "23", "", "multipleOf", "",
880
978
  "{ \"multipleOf\": {"
979
+ " \"errorCode\": 1,"
881
980
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
882
981
  " \"expected\": 10.0, \"actual\": 23"
883
982
  "}}");
884
983
  INVALIDATE(s, "-2147483648", "", "multipleOf", "",
885
984
  "{ \"multipleOf\": {"
985
+ " \"errorCode\": 1,"
886
986
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
887
987
  " \"expected\": 10.0, \"actual\": -2147483648"
888
988
  "}}"); // int min
889
989
  VALIDATE(s, "-2147483640", true);
890
990
  INVALIDATE(s, "2147483647", "", "multipleOf", "",
891
991
  "{ \"multipleOf\": {"
992
+ " \"errorCode\": 1,"
892
993
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
893
994
  " \"expected\": 10.0, \"actual\": 2147483647"
894
995
  "}}"); // int max
895
996
  INVALIDATE(s, "2147483648", "", "multipleOf", "",
896
997
  "{ \"multipleOf\": {"
998
+ " \"errorCode\": 1,"
897
999
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
898
1000
  " \"expected\": 10.0, \"actual\": 2147483648"
899
1001
  "}}"); // unsigned first
900
1002
  VALIDATE(s, "2147483650", true);
901
1003
  INVALIDATE(s, "4294967295", "", "multipleOf", "",
902
1004
  "{ \"multipleOf\": {"
1005
+ " \"errorCode\": 1,"
903
1006
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
904
1007
  " \"expected\": 10.0, \"actual\": 4294967295"
905
1008
  "}}"); // unsigned max
@@ -915,6 +1018,7 @@ TEST(SchemaValidator, Number_MultipleOfOne) {
915
1018
  VALIDATE(s, "42.0", true);
916
1019
  INVALIDATE(s, "3.1415926", "", "multipleOf", "",
917
1020
  "{ \"multipleOf\": {"
1021
+ " \"errorCode\": 1,"
918
1022
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
919
1023
  " \"expected\": 1, \"actual\": 3.1415926"
920
1024
  "}}");
@@ -929,11 +1033,13 @@ TEST(SchemaValidator, Object) {
929
1033
  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
1034
  INVALIDATE(s, "[\"An\", \"array\", \"not\", \"an\", \"object\"]", "", "type", "",
931
1035
  "{ \"type\": {"
1036
+ " \"errorCode\": 20,"
932
1037
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
933
1038
  " \"expected\": [\"object\"], \"actual\": \"array\""
934
1039
  "}}");
935
1040
  INVALIDATE(s, "\"Not an object\"", "", "type", "",
936
1041
  "{ \"type\": {"
1042
+ " \"errorCode\": 20,"
937
1043
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
938
1044
  " \"expected\": [\"object\"], \"actual\": \"string\""
939
1045
  "}}");
@@ -956,12 +1062,14 @@ TEST(SchemaValidator, Object_Properties) {
956
1062
  VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
957
1063
  INVALIDATE(s, "{ \"number\": \"1600\", \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", "/properties/number", "type", "/number",
958
1064
  "{ \"type\": {"
1065
+ " \"errorCode\": 20,"
959
1066
  " \"instanceRef\": \"#/number\", \"schemaRef\": \"#/properties/number\","
960
1067
  " \"expected\": [\"number\"], \"actual\": \"string\""
961
1068
  "}}");
962
1069
  INVALIDATE(s, "{ \"number\": \"One\", \"street_name\": \"Microsoft\", \"street_type\": \"Way\" }",
963
1070
  "/properties/number", "type", "/number",
964
1071
  "{ \"type\": {"
1072
+ " \"errorCode\": 20,"
965
1073
  " \"instanceRef\": \"#/number\", \"schemaRef\": \"#/properties/number\","
966
1074
  " \"expected\": [\"number\"], \"actual\": \"string\""
967
1075
  "}}"); // fail fast
@@ -990,6 +1098,7 @@ TEST(SchemaValidator, Object_AdditionalPropertiesBoolean) {
990
1098
  VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true);
991
1099
  INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", "", "additionalProperties", "/direction",
992
1100
  "{ \"additionalProperties\": {"
1101
+ " \"errorCode\": 16,"
993
1102
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
994
1103
  " \"disallowed\": \"direction\""
995
1104
  "}}");
@@ -1015,6 +1124,7 @@ TEST(SchemaValidator, Object_AdditionalPropertiesObject) {
1015
1124
  VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true);
1016
1125
  INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"office_number\": 201 }", "/additionalProperties", "type", "/office_number",
1017
1126
  "{ \"type\": {"
1127
+ " \"errorCode\": 20,"
1018
1128
  " \"instanceRef\": \"#/office_number\", \"schemaRef\": \"#/additionalProperties\","
1019
1129
  " \"expected\": [\"string\"], \"actual\": \"integer\""
1020
1130
  "}}");
@@ -1039,11 +1149,13 @@ TEST(SchemaValidator, Object_Required) {
1039
1149
  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
1150
  INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "",
1041
1151
  "{ \"required\": {"
1152
+ " \"errorCode\": 15,"
1042
1153
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1043
1154
  " \"missing\": [\"email\"]"
1044
1155
  "}}");
1045
1156
  INVALIDATE(s, "{}", "", "required", "",
1046
1157
  "{ \"required\": {"
1158
+ " \"errorCode\": 15,"
1047
1159
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1048
1160
  " \"missing\": [\"name\", \"email\"]"
1049
1161
  "}}");
@@ -1067,11 +1179,13 @@ TEST(SchemaValidator, Object_Required_PassWithDefault) {
1067
1179
  VALIDATE(s, "{ \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true);
1068
1180
  INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "",
1069
1181
  "{ \"required\": {"
1182
+ " \"errorCode\": 15,"
1070
1183
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1071
1184
  " \"missing\": [\"email\"]"
1072
1185
  "}}");
1073
1186
  INVALIDATE(s, "{}", "", "required", "",
1074
1187
  "{ \"required\": {"
1188
+ " \"errorCode\": 15,"
1075
1189
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1076
1190
  " \"missing\": [\"email\"]"
1077
1191
  "}}");
@@ -1084,11 +1198,13 @@ TEST(SchemaValidator, Object_PropertiesRange) {
1084
1198
 
1085
1199
  INVALIDATE(s, "{}", "", "minProperties", "",
1086
1200
  "{ \"minProperties\": {"
1201
+ " \"errorCode\": 14,"
1087
1202
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1088
1203
  " \"expected\": 2, \"actual\": 0"
1089
1204
  "}}");
1090
1205
  INVALIDATE(s, "{\"a\":0}", "", "minProperties", "",
1091
1206
  "{ \"minProperties\": {"
1207
+ " \"errorCode\": 14,"
1092
1208
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1093
1209
  " \"expected\": 2, \"actual\": 1"
1094
1210
  "}}");
@@ -1096,6 +1212,7 @@ TEST(SchemaValidator, Object_PropertiesRange) {
1096
1212
  VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2}", true);
1097
1213
  INVALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", "", "maxProperties", "",
1098
1214
  "{ \"maxProperties\": {"
1215
+ " \"errorCode\": 13,"
1099
1216
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\", "
1100
1217
  " \"expected\": 3, \"actual\": 4"
1101
1218
  "}}");
@@ -1123,8 +1240,15 @@ TEST(SchemaValidator, Object_PropertyDependencies) {
1123
1240
  "\"billing_address\": \"555 Debtor's Lane\" }", true);
1124
1241
  INVALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555 }", "", "dependencies", "",
1125
1242
  "{ \"dependencies\": {"
1243
+ " \"errorCode\": 18,"
1126
1244
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1127
- " \"errors\": {\"credit_card\": [\"cvv_code\", \"billing_address\"]}"
1245
+ " \"errors\": {"
1246
+ " \"credit_card\": {"
1247
+ " \"required\": {"
1248
+ " \"errorCode\": 15,"
1249
+ " \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/credit_card\","
1250
+ " \"missing\": [\"cvv_code\", \"billing_address\"]"
1251
+ " } } }"
1128
1252
  "}}");
1129
1253
  VALIDATE(s, "{ \"name\": \"John Doe\"}", true);
1130
1254
  VALIDATE(s, "{ \"name\": \"John Doe\", \"cvv_code\": 777, \"billing_address\": \"555 Debtor's Lane\" }", true);
@@ -1154,10 +1278,12 @@ TEST(SchemaValidator, Object_SchemaDependencies) {
1154
1278
  VALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555,\"billing_address\" : \"555 Debtor's Lane\"}", true);
1155
1279
  INVALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555 }", "", "dependencies", "",
1156
1280
  "{ \"dependencies\": {"
1281
+ " \"errorCode\": 18,"
1157
1282
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1158
1283
  " \"errors\": {"
1159
1284
  " \"credit_card\": {"
1160
1285
  " \"required\": {"
1286
+ " \"errorCode\": 15,"
1161
1287
  " \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/credit_card\","
1162
1288
  " \"missing\": [\"billing_address\"]"
1163
1289
  " } } }"
@@ -1182,18 +1308,20 @@ TEST(SchemaValidator, Object_PatternProperties) {
1182
1308
  VALIDATE(s, "{ \"I_0\": 42 }", true);
1183
1309
  INVALIDATE(s, "{ \"S_0\": 42 }", "", "patternProperties", "/S_0",
1184
1310
  "{ \"type\": {"
1311
+ " \"errorCode\": 20,"
1185
1312
  " \"instanceRef\": \"#/S_0\", \"schemaRef\": \"#/patternProperties/%5ES_\","
1186
1313
  " \"expected\": [\"string\"], \"actual\": \"integer\""
1187
1314
  "}}");
1188
1315
  INVALIDATE(s, "{ \"I_42\": \"This is a string\" }", "", "patternProperties", "/I_42",
1189
1316
  "{ \"type\": {"
1317
+ " \"errorCode\": 20,"
1190
1318
  " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/patternProperties/%5EI_\","
1191
1319
  " \"expected\": [\"integer\"], \"actual\": \"string\""
1192
1320
  "}}");
1193
1321
  VALIDATE(s, "{ \"keyword\": \"value\" }", true);
1194
1322
  }
1195
1323
 
1196
- TEST(SchemaValidator, Object_PattternProperties_ErrorConflict) {
1324
+ TEST(SchemaValidator, Object_PatternProperties_ErrorConflict) {
1197
1325
  Document sd;
1198
1326
  sd.Parse(
1199
1327
  "{"
@@ -1209,9 +1337,11 @@ TEST(SchemaValidator, Object_PattternProperties_ErrorConflict) {
1209
1337
  INVALIDATE(s, "{ \"I_30\": 7 }", "", "patternProperties", "/I_30",
1210
1338
  "{ \"multipleOf\": ["
1211
1339
  " {"
1340
+ " \"errorCode\": 1,"
1212
1341
  " \"instanceRef\": \"#/I_30\", \"schemaRef\": \"#/patternProperties/%5EI_\","
1213
1342
  " \"expected\": 5, \"actual\": 7"
1214
1343
  " }, {"
1344
+ " \"errorCode\": 1,"
1215
1345
  " \"instanceRef\": \"#/I_30\", \"schemaRef\": \"#/patternProperties/30%24\","
1216
1346
  " \"expected\": 6, \"actual\": 7"
1217
1347
  " }"
@@ -1236,22 +1366,25 @@ TEST(SchemaValidator, Object_Properties_PatternProperties) {
1236
1366
  VALIDATE(s, "{ \"I_42\": 78 }", true);
1237
1367
  INVALIDATE(s, "{ \"I_42\": 42 }", "", "patternProperties", "/I_42",
1238
1368
  "{ \"minimum\": {"
1369
+ " \"errorCode\": 4,"
1239
1370
  " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/properties/I_42\","
1240
1371
  " \"expected\": 73, \"actual\": 42"
1241
1372
  "}}");
1242
1373
  INVALIDATE(s, "{ \"I_42\": 7 }", "", "patternProperties", "/I_42",
1243
1374
  "{ \"minimum\": {"
1375
+ " \"errorCode\": 4,"
1244
1376
  " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/properties/I_42\","
1245
1377
  " \"expected\": 73, \"actual\": 7"
1246
1378
  " },"
1247
1379
  " \"multipleOf\": {"
1380
+ " \"errorCode\": 1,"
1248
1381
  " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/patternProperties/%5EI_\","
1249
1382
  " \"expected\": 6, \"actual\": 7"
1250
1383
  " }"
1251
1384
  "}");
1252
1385
  }
1253
1386
 
1254
- TEST(SchemaValidator, Object_PatternProperties_AdditionalProperties) {
1387
+ TEST(SchemaValidator, Object_PatternProperties_AdditionalPropertiesObject) {
1255
1388
  Document sd;
1256
1389
  sd.Parse(
1257
1390
  "{"
@@ -1271,10 +1404,35 @@ TEST(SchemaValidator, Object_PatternProperties_AdditionalProperties) {
1271
1404
  VALIDATE(s, "{ \"keyword\": \"value\" }", true);
1272
1405
  INVALIDATE(s, "{ \"keyword\": 42 }", "/additionalProperties", "type", "/keyword",
1273
1406
  "{ \"type\": {"
1407
+ " \"errorCode\": 20,"
1274
1408
  " \"instanceRef\": \"#/keyword\", \"schemaRef\": \"#/additionalProperties\","
1275
1409
  " \"expected\": [\"string\"], \"actual\": \"integer\""
1276
1410
  "}}");
1277
1411
  }
1412
+
1413
+ // Replaces test Issue285 and tests failure as well as success
1414
+ TEST(SchemaValidator, Object_PatternProperties_AdditionalPropertiesBoolean) {
1415
+ Document sd;
1416
+ sd.Parse(
1417
+ "{"
1418
+ " \"type\": \"object\","
1419
+ " \"patternProperties\": {"
1420
+ " \"^S_\": { \"type\": \"string\" },"
1421
+ " \"^I_\": { \"type\": \"integer\" }"
1422
+ " },"
1423
+ " \"additionalProperties\": false"
1424
+ "}");
1425
+ SchemaDocument s(sd);
1426
+
1427
+ VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true);
1428
+ VALIDATE(s, "{ \"I_0\": 42 }", true);
1429
+ INVALIDATE(s, "{ \"keyword\": \"value\" }", "", "additionalProperties", "/keyword",
1430
+ "{ \"additionalProperties\": {"
1431
+ " \"errorCode\": 16,"
1432
+ " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1433
+ " \"disallowed\": \"keyword\""
1434
+ "}}");
1435
+ }
1278
1436
  #endif
1279
1437
 
1280
1438
  TEST(SchemaValidator, Array) {
@@ -1286,6 +1444,7 @@ TEST(SchemaValidator, Array) {
1286
1444
  VALIDATE(s, "[3, \"different\", { \"types\" : \"of values\" }]", true);
1287
1445
  INVALIDATE(s, "{\"Not\": \"an array\"}", "", "type", "",
1288
1446
  "{ \"type\": {"
1447
+ " \"errorCode\": 20,"
1289
1448
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1290
1449
  " \"expected\": [\"array\"], \"actual\": \"object\""
1291
1450
  "}}");
@@ -1305,6 +1464,7 @@ TEST(SchemaValidator, Array_ItemsList) {
1305
1464
  VALIDATE(s, "[1, 2, 3, 4, 5]", true);
1306
1465
  INVALIDATE(s, "[1, 2, \"3\", 4, 5]", "/items", "type", "/2",
1307
1466
  "{ \"type\": {"
1467
+ " \"errorCode\": 20,"
1308
1468
  " \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items\","
1309
1469
  " \"expected\": [\"number\"], \"actual\": \"string\""
1310
1470
  "}}");
@@ -1337,14 +1497,16 @@ TEST(SchemaValidator, Array_ItemsTuple) {
1337
1497
 
1338
1498
  VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
1339
1499
  INVALIDATE(s, "[24, \"Sussex\", \"Drive\"]", "/items/2", "enum", "/2",
1340
- "{ \"enum\": { \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items/2\" }}");
1500
+ "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items/2\" }}");
1341
1501
  INVALIDATE(s, "[\"Palais de l'Elysee\"]", "/items/0", "type", "/0",
1342
1502
  "{ \"type\": {"
1503
+ " \"errorCode\": 20,"
1343
1504
  " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items/0\","
1344
1505
  " \"expected\": [\"number\"], \"actual\": \"string\""
1345
1506
  "}}");
1346
1507
  INVALIDATE(s, "[\"Twenty-four\", \"Sussex\", \"Drive\"]", "/items/0", "type", "/0",
1347
1508
  "{ \"type\": {"
1509
+ " \"errorCode\": 20,"
1348
1510
  " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items/0\","
1349
1511
  " \"expected\": [\"number\"], \"actual\": \"string\""
1350
1512
  "}}"); // fail fast
@@ -1352,7 +1514,7 @@ TEST(SchemaValidator, Array_ItemsTuple) {
1352
1514
  VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true);
1353
1515
  }
1354
1516
 
1355
- TEST(SchemaValidator, Array_AdditionalItmes) {
1517
+ TEST(SchemaValidator, Array_AdditionalItems) {
1356
1518
  Document sd;
1357
1519
  sd.Parse(
1358
1520
  "{"
@@ -1379,8 +1541,9 @@ TEST(SchemaValidator, Array_AdditionalItmes) {
1379
1541
 
1380
1542
  VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
1381
1543
  VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\"]", true);
1382
- INVALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", "", "items", "/4",
1544
+ INVALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", "", "additionalItems", "/4",
1383
1545
  "{ \"additionalItems\": {"
1546
+ " \"errorCode\": 12,"
1384
1547
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1385
1548
  " \"disallowed\": 4"
1386
1549
  "}}");
@@ -1393,11 +1556,13 @@ TEST(SchemaValidator, Array_ItemsRange) {
1393
1556
 
1394
1557
  INVALIDATE(s, "[]", "", "minItems", "",
1395
1558
  "{ \"minItems\": {"
1559
+ " \"errorCode\": 10,"
1396
1560
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1397
1561
  " \"expected\": 2, \"actual\": 0"
1398
1562
  "}}");
1399
1563
  INVALIDATE(s, "[1]", "", "minItems", "",
1400
1564
  "{ \"minItems\": {"
1565
+ " \"errorCode\": 10,"
1401
1566
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1402
1567
  " \"expected\": 2, \"actual\": 1"
1403
1568
  "}}");
@@ -1405,6 +1570,7 @@ TEST(SchemaValidator, Array_ItemsRange) {
1405
1570
  VALIDATE(s, "[1, 2, 3]", true);
1406
1571
  INVALIDATE(s, "[1, 2, 3, 4]", "", "maxItems", "",
1407
1572
  "{ \"maxItems\": {"
1573
+ " \"errorCode\": 9,"
1408
1574
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1409
1575
  " \"expected\": 3, \"actual\": 4"
1410
1576
  "}}");
@@ -1418,11 +1584,13 @@ TEST(SchemaValidator, Array_UniqueItems) {
1418
1584
  VALIDATE(s, "[1, 2, 3, 4, 5]", true);
1419
1585
  INVALIDATE(s, "[1, 2, 3, 3, 4]", "", "uniqueItems", "/3",
1420
1586
  "{ \"uniqueItems\": {"
1587
+ " \"errorCode\": 11,"
1421
1588
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1422
1589
  " \"duplicates\": [2, 3]"
1423
1590
  "}}");
1424
1591
  INVALIDATE(s, "[1, 2, 3, 3, 3]", "", "uniqueItems", "/3",
1425
1592
  "{ \"uniqueItems\": {"
1593
+ " \"errorCode\": 11,"
1426
1594
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1427
1595
  " \"duplicates\": [2, 3]"
1428
1596
  "}}"); // fail fast
@@ -1438,11 +1606,13 @@ TEST(SchemaValidator, Boolean) {
1438
1606
  VALIDATE(s, "false", true);
1439
1607
  INVALIDATE(s, "\"true\"", "", "type", "",
1440
1608
  "{ \"type\": {"
1609
+ " \"errorCode\": 20,"
1441
1610
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1442
1611
  " \"expected\": [\"boolean\"], \"actual\": \"string\""
1443
1612
  "}}");
1444
1613
  INVALIDATE(s, "0", "", "type", "",
1445
1614
  "{ \"type\": {"
1615
+ " \"errorCode\": 20,"
1446
1616
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1447
1617
  " \"expected\": [\"boolean\"], \"actual\": \"integer\""
1448
1618
  "}}");
@@ -1456,16 +1626,19 @@ TEST(SchemaValidator, Null) {
1456
1626
  VALIDATE(s, "null", true);
1457
1627
  INVALIDATE(s, "false", "", "type", "",
1458
1628
  "{ \"type\": {"
1629
+ " \"errorCode\": 20,"
1459
1630
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1460
1631
  " \"expected\": [\"null\"], \"actual\": \"boolean\""
1461
1632
  "}}");
1462
1633
  INVALIDATE(s, "0", "", "type", "",
1463
1634
  "{ \"type\": {"
1635
+ " \"errorCode\": 20,"
1464
1636
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1465
1637
  " \"expected\": [\"null\"], \"actual\": \"integer\""
1466
1638
  "}}");
1467
1639
  INVALIDATE(s, "\"\"", "", "type", "",
1468
1640
  "{ \"type\": {"
1641
+ " \"errorCode\": 20,"
1469
1642
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1470
1643
  " \"expected\": [\"null\"], \"actual\": \"string\""
1471
1644
  "}}");
@@ -1481,11 +1654,13 @@ TEST(SchemaValidator, ObjectInArray) {
1481
1654
  VALIDATE(s, "[\"a\"]", true);
1482
1655
  INVALIDATE(s, "[1]", "/items", "type", "/0",
1483
1656
  "{ \"type\": {"
1657
+ " \"errorCode\": 20,"
1484
1658
  " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items\","
1485
1659
  " \"expected\": [\"string\"], \"actual\": \"integer\""
1486
1660
  "}}");
1487
1661
  INVALIDATE(s, "[{}]", "/items", "type", "/0",
1488
1662
  "{ \"type\": {"
1663
+ " \"errorCode\": 20,"
1489
1664
  " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items\","
1490
1665
  " \"expected\": [\"string\"], \"actual\": \"object\""
1491
1666
  "}}");
@@ -1508,6 +1683,7 @@ TEST(SchemaValidator, MultiTypeInObject) {
1508
1683
  VALIDATE(s, "{ \"tel\": \"123-456\" }", true);
1509
1684
  INVALIDATE(s, "{ \"tel\": true }", "/properties/tel", "type", "/tel",
1510
1685
  "{ \"type\": {"
1686
+ " \"errorCode\": 20,"
1511
1687
  " \"instanceRef\": \"#/tel\", \"schemaRef\": \"#/properties/tel\","
1512
1688
  " \"expected\": [\"string\", \"integer\"], \"actual\": \"boolean\""
1513
1689
  "}}");
@@ -1530,6 +1706,7 @@ TEST(SchemaValidator, MultiTypeWithObject) {
1530
1706
  VALIDATE(s, "{ \"tel\": 999 }", true);
1531
1707
  INVALIDATE(s, "{ \"tel\": \"fail\" }", "/properties/tel", "type", "/tel",
1532
1708
  "{ \"type\": {"
1709
+ " \"errorCode\": 20,"
1533
1710
  " \"instanceRef\": \"#/tel\", \"schemaRef\": \"#/properties/tel\","
1534
1711
  " \"expected\": [\"integer\"], \"actual\": \"string\""
1535
1712
  "}}");
@@ -1550,48 +1727,71 @@ TEST(SchemaValidator, AllOf_Nested) {
1550
1727
  VALIDATE(s, "\"ok\"", true);
1551
1728
  VALIDATE(s, "\"OK\"", true);
1552
1729
  INVALIDATE(s, "\"okay\"", "", "allOf", "",
1553
- "{ \"enum\": {"
1554
- " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\""
1730
+ "{ \"allOf\": {"
1731
+ " \"errors\": ["
1732
+ " {},{},"
1733
+ " { \"allOf\": {"
1734
+ " \"errors\": ["
1735
+ " {},"
1736
+ " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\" }}"
1737
+ " ],"
1738
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\""
1739
+ " }}],"
1740
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
1555
1741
  "}}");
1556
1742
  INVALIDATE(s, "\"o\"", "", "allOf", "",
1557
- "{ \"minLength\": {"
1558
- " \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\","
1559
- " \"expected\": 2, \"actual\": \"o\""
1743
+ "{ \"allOf\": {"
1744
+ " \"errors\": ["
1745
+ " { \"minLength\": {\"actual\": \"o\", \"expected\": 2, \"errorCode\": 7, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\" }},"
1746
+ " {},{}"
1747
+ " ],"
1748
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
1560
1749
  "}}");
1561
1750
  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
- "}")
1751
+ "{ \"allOf\": {"
1752
+ " \"errors\": ["
1753
+ " { \"minLength\": {\"actual\": \"n\", \"expected\": 2, \"errorCode\": 7, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\" }},"
1754
+ " {},"
1755
+ " { \"allOf\": {"
1756
+ " \"errors\": ["
1757
+ " { \"enum\": {\"errorCode\": 19 ,\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"}},"
1758
+ " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}}"
1759
+ " ],"
1760
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\""
1761
+ " }}"
1762
+ " ],"
1763
+ " \"errorCode\":23,\"instanceRef\":\"#\",\"schemaRef\":\"#\""
1764
+ "}}");
1571
1765
  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
- "}");
1766
+ "{ \"allOf\": {"
1767
+ " \"errors\": ["
1768
+ " {},"
1769
+ " { \"maxLength\": {\"actual\": \"too long\", \"expected\": 5, \"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\" }},"
1770
+ " { \"allOf\": {"
1771
+ " \"errors\": ["
1772
+ " { \"enum\": {\"errorCode\": 19 ,\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"}},"
1773
+ " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}}"
1774
+ " ],"
1775
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\""
1776
+ " }}"
1777
+ " ],"
1778
+ " \"errorCode\":23,\"instanceRef\":\"#\",\"schemaRef\":\"#\""
1779
+ "}}");
1581
1780
  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
- "}");
1781
+ "{ \"allOf\": {"
1782
+ " \"errors\": ["
1783
+ " {\"type\": {\"expected\": [\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\"}},"
1784
+ " {\"type\": {\"expected\": [\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\"}},"
1785
+ " { \"allOf\": {"
1786
+ " \"errors\": ["
1787
+ " { \"enum\": {\"errorCode\": 19 ,\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"}},"
1788
+ " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}}"
1789
+ " ],"
1790
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\""
1791
+ " }}"
1792
+ " ],"
1793
+ " \"errorCode\":23,\"instanceRef\":\"#\",\"schemaRef\":\"#\""
1794
+ "}}");
1595
1795
  }
1596
1796
 
1597
1797
  TEST(SchemaValidator, EscapedPointer) {
@@ -1606,11 +1806,195 @@ TEST(SchemaValidator, EscapedPointer) {
1606
1806
  SchemaDocument s(sd);
1607
1807
  INVALIDATE(s, "{\"~/\":true}", "/properties/~0~1", "type", "/~0~1",
1608
1808
  "{ \"type\": {"
1809
+ " \"errorCode\": 20,"
1609
1810
  " \"instanceRef\": \"#/~0~1\", \"schemaRef\": \"#/properties/~0~1\","
1610
1811
  " \"expected\": [\"number\"], \"actual\": \"boolean\""
1611
1812
  "}}");
1612
1813
  }
1613
1814
 
1815
+ TEST(SchemaValidator, SchemaPointer) {
1816
+ Document sd;
1817
+ sd.Parse(
1818
+ "{"
1819
+ " \"swagger\": \"2.0\","
1820
+ " \"paths\": {"
1821
+ " \"/some/path\": {"
1822
+ " \"post\": {"
1823
+ " \"parameters\": ["
1824
+ " {"
1825
+ " \"in\": \"body\","
1826
+ " \"name\": \"body\","
1827
+ " \"schema\": {"
1828
+ " \"properties\": {"
1829
+ " \"a\": {"
1830
+ " \"$ref\": \"#/definitions/Prop_a\""
1831
+ " },"
1832
+ " \"b\": {"
1833
+ " \"type\": \"integer\""
1834
+ " }"
1835
+ " },"
1836
+ " \"type\": \"object\""
1837
+ " }"
1838
+ " }"
1839
+ " ],"
1840
+ " \"responses\": {"
1841
+ " \"200\": {"
1842
+ " \"schema\": {"
1843
+ " \"$ref\": \"#/definitions/Resp_200\""
1844
+ " }"
1845
+ " }"
1846
+ " }"
1847
+ " }"
1848
+ " }"
1849
+ " },"
1850
+ " \"definitions\": {"
1851
+ " \"Prop_a\": {"
1852
+ " \"properties\": {"
1853
+ " \"c\": {"
1854
+ " \"enum\": ["
1855
+ " \"C1\","
1856
+ " \"C2\","
1857
+ " \"C3\""
1858
+ " ],"
1859
+ " \"type\": \"string\""
1860
+ " },"
1861
+ " \"d\": {"
1862
+ " \"$ref\": \"#/definitions/Prop_d\""
1863
+ " },"
1864
+ " \"s\": {"
1865
+ " \"type\": \"string\""
1866
+ " }"
1867
+ " },"
1868
+ " \"required\": [\"c\"],"
1869
+ " \"type\": \"object\""
1870
+ " },"
1871
+ " \"Prop_d\": {"
1872
+ " \"properties\": {"
1873
+ " \"a\": {"
1874
+ " \"$ref\": \"#/definitions/Prop_a\""
1875
+ " },"
1876
+ " \"c\": {"
1877
+ " \"$ref\": \"#/definitions/Prop_a/properties/c\""
1878
+ " }"
1879
+ " },"
1880
+ " \"type\": \"object\""
1881
+ " },"
1882
+ " \"Resp_200\": {"
1883
+ " \"properties\": {"
1884
+ " \"e\": {"
1885
+ " \"type\": \"string\""
1886
+ " },"
1887
+ " \"f\": {"
1888
+ " \"type\": \"boolean\""
1889
+ " },"
1890
+ " \"cyclic_source\": {"
1891
+ " \"$ref\": \"#/definitions/Resp_200/properties/cyclic_target\""
1892
+ " },"
1893
+ " \"cyclic_target\": {"
1894
+ " \"$ref\": \"#/definitions/Resp_200/properties/cyclic_source\""
1895
+ " }"
1896
+ " },"
1897
+ " \"type\": \"object\""
1898
+ " }"
1899
+ " }"
1900
+ "}");
1901
+ SchemaDocument s1(sd, NULL, 0, NULL, NULL, Pointer("#/paths/~1some~1path/post/parameters/0/schema"));
1902
+ VALIDATE(s1,
1903
+ "{"
1904
+ " \"a\": {"
1905
+ " \"c\": \"C1\","
1906
+ " \"d\": {"
1907
+ " \"a\": {"
1908
+ " \"c\": \"C2\""
1909
+ " },"
1910
+ " \"c\": \"C3\""
1911
+ " }"
1912
+ " },"
1913
+ " \"b\": 123"
1914
+ "}",
1915
+ true);
1916
+ INVALIDATE(s1,
1917
+ "{"
1918
+ " \"a\": {"
1919
+ " \"c\": \"C1\","
1920
+ " \"d\": {"
1921
+ " \"a\": {"
1922
+ " \"c\": \"C2\""
1923
+ " },"
1924
+ " \"c\": \"C3\""
1925
+ " }"
1926
+ " },"
1927
+ " \"b\": \"should be an int\""
1928
+ "}",
1929
+ "#/paths/~1some~1path/post/parameters/0/schema/properties/b", "type", "#/b",
1930
+ "{ \"type\": {"
1931
+ " \"errorCode\": 20,"
1932
+ " \"instanceRef\":\"#/b\","
1933
+ " \"schemaRef\":\"#/paths/~1some~1path/post/parameters/0/schema/properties/b\","
1934
+ " \"expected\": [\"integer\"], \"actual\":\"string\""
1935
+ "}}");
1936
+ INVALIDATE(s1,
1937
+ "{"
1938
+ " \"a\": {"
1939
+ " \"c\": \"C1\","
1940
+ " \"d\": {"
1941
+ " \"a\": {"
1942
+ " \"c\": \"should be within enum\""
1943
+ " },"
1944
+ " \"c\": \"C3\""
1945
+ " }"
1946
+ " },"
1947
+ " \"b\": 123"
1948
+ "}",
1949
+ "#/definitions/Prop_a/properties/c", "enum", "#/a/d/a/c",
1950
+ "{ \"enum\": {"
1951
+ " \"errorCode\": 19,"
1952
+ " \"instanceRef\":\"#/a/d/a/c\","
1953
+ " \"schemaRef\":\"#/definitions/Prop_a/properties/c\""
1954
+ "}}");
1955
+ INVALIDATE(s1,
1956
+ "{"
1957
+ " \"a\": {"
1958
+ " \"c\": \"C1\","
1959
+ " \"d\": {"
1960
+ " \"a\": {"
1961
+ " \"s\": \"required 'c' is missing\""
1962
+ " }"
1963
+ " }"
1964
+ " },"
1965
+ " \"b\": 123"
1966
+ "}",
1967
+ "#/definitions/Prop_a", "required", "#/a/d/a",
1968
+ "{ \"required\": {"
1969
+ " \"errorCode\": 15,"
1970
+ " \"missing\":[\"c\"],"
1971
+ " \"instanceRef\":\"#/a/d/a\","
1972
+ " \"schemaRef\":\"#/definitions/Prop_a\""
1973
+ "}}");
1974
+ SchemaDocument s2(sd, NULL, 0, NULL, NULL, Pointer("#/paths/~1some~1path/post/responses/200/schema"));
1975
+ VALIDATE(s2,
1976
+ "{ \"e\": \"some string\", \"f\": false }",
1977
+ true);
1978
+ INVALIDATE(s2,
1979
+ "{ \"e\": true, \"f\": false }",
1980
+ "#/definitions/Resp_200/properties/e", "type", "#/e",
1981
+ "{ \"type\": {"
1982
+ " \"errorCode\": 20,"
1983
+ " \"instanceRef\":\"#/e\","
1984
+ " \"schemaRef\":\"#/definitions/Resp_200/properties/e\","
1985
+ " \"expected\": [\"string\"], \"actual\":\"boolean\""
1986
+ "}}");
1987
+ INVALIDATE(s2,
1988
+ "{ \"e\": \"some string\", \"f\": 123 }",
1989
+ "#/definitions/Resp_200/properties/f", "type", "#/f",
1990
+ "{ \"type\": {"
1991
+ " \"errorCode\": 20,"
1992
+ " \"instanceRef\":\"#/f\","
1993
+ " \"schemaRef\":\"#/definitions/Resp_200/properties/f\","
1994
+ " \"expected\": [\"boolean\"], \"actual\":\"integer\""
1995
+ "}}");
1996
+ }
1997
+
1614
1998
  template <typename Allocator>
1615
1999
  static char* ReadFile(const char* filename, Allocator& allocator) {
1616
2000
  const char *paths[] = {
@@ -1650,11 +2034,14 @@ TEST(SchemaValidator, ValidateMetaSchema) {
1650
2034
  ASSERT_FALSE(d.HasParseError());
1651
2035
  SchemaDocument sd(d);
1652
2036
  SchemaValidator validator(sd);
1653
- if (!d.Accept(validator)) {
2037
+ d.Accept(validator);
2038
+ if (!validator.IsValid()) {
1654
2039
  StringBuffer sb;
1655
2040
  validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
1656
2041
  printf("Invalid schema: %s\n", sb.GetString());
1657
2042
  printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
2043
+ printf("Invalid code: %d\n", validator.GetInvalidSchemaCode());
2044
+ printf("Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode()));
1658
2045
  sb.Clear();
1659
2046
  validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
1660
2047
  printf("Invalid document: %s\n", sb.GetString());
@@ -1681,7 +2068,8 @@ TEST(SchemaValidator, ValidateMetaSchema_UTF16) {
1681
2068
  ASSERT_FALSE(d.HasParseError());
1682
2069
  SD sd(d);
1683
2070
  SV validator(sd);
1684
- if (!d.Accept(validator)) {
2071
+ d.Accept(validator);
2072
+ if (!validator.IsValid()) {
1685
2073
  GenericStringBuffer<UTF16<> > sb;
1686
2074
  validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
1687
2075
  wprintf(L"Invalid schema: %ls\n", sb.GetString());
@@ -1709,13 +2097,15 @@ public:
1709
2097
  "jsonschema/remotes/integer.json",
1710
2098
  "jsonschema/remotes/subSchemas.json",
1711
2099
  "jsonschema/remotes/folder/folderInteger.json",
1712
- "draft-04/schema"
2100
+ "draft-04/schema",
2101
+ "unittestschema/address.json"
1713
2102
  };
1714
2103
  const char* uris[kCount] = {
1715
2104
  "http://localhost:1234/integer.json",
1716
2105
  "http://localhost:1234/subSchemas.json",
1717
2106
  "http://localhost:1234/folder/folderInteger.json",
1718
- "http://json-schema.org/draft-04/schema"
2107
+ "http://json-schema.org/draft-04/schema",
2108
+ "http://localhost:1234/address.json"
1719
2109
  };
1720
2110
 
1721
2111
  for (size_t i = 0; i < kCount; i++) {
@@ -1746,7 +2136,7 @@ public:
1746
2136
 
1747
2137
  virtual const SchemaDocumentType* GetRemoteDocument(const char* uri, SizeType length) {
1748
2138
  for (size_t i = 0; i < kCount; i++)
1749
- if (typename SchemaDocumentType::URIType(uri, length) == sd_[i]->GetURI())
2139
+ if (typename SchemaDocumentType::SValue(uri, length) == sd_[i]->GetURI())
1750
2140
  return sd_[i];
1751
2141
  return 0;
1752
2142
  }
@@ -1757,7 +2147,7 @@ private:
1757
2147
  RemoteSchemaDocumentProvider(const RemoteSchemaDocumentProvider&);
1758
2148
  RemoteSchemaDocumentProvider& operator=(const RemoteSchemaDocumentProvider&);
1759
2149
 
1760
- static const size_t kCount = 4;
2150
+ static const size_t kCount = 5;
1761
2151
  SchemaDocumentType* sd_[kCount];
1762
2152
  typename DocumentType::AllocatorType documentAllocator_;
1763
2153
  typename SchemaDocumentType::AllocatorType schemaAllocator_;
@@ -1826,6 +2216,7 @@ TEST(SchemaValidator, TestSuite) {
1826
2216
  ADD_FAILURE();
1827
2217
  }
1828
2218
  else {
2219
+ //printf("\njson test suite file %s parsed ok\n", filename);
1829
2220
  GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > d(&documentAllocator, 1024, &documentStackAllocator);
1830
2221
  d.Parse(json);
1831
2222
  if (d.HasParseError()) {
@@ -1835,22 +2226,27 @@ TEST(SchemaValidator, TestSuite) {
1835
2226
  else {
1836
2227
  for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) {
1837
2228
  {
2229
+ const char* description1 = (*schemaItr)["description"].GetString();
2230
+ //printf("\ncompiling schema for json test %s \n", description1);
1838
2231
  SchemaDocumentType schema((*schemaItr)["schema"], filenames[i], static_cast<SizeType>(strlen(filenames[i])), &provider, &schemaAllocator);
1839
2232
  GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > validator(schema, &validatorAllocator);
1840
- const char* description1 = (*schemaItr)["description"].GetString();
1841
2233
  const Value& tests = (*schemaItr)["tests"];
1842
2234
  for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) {
1843
2235
  const char* description2 = (*testItr)["description"].GetString();
2236
+ //printf("running json test %s \n", description2);
1844
2237
  if (!onlyRunDescription || strcmp(description2, onlyRunDescription) == 0) {
1845
2238
  const Value& data = (*testItr)["data"];
1846
2239
  bool expected = (*testItr)["valid"].GetBool();
1847
2240
  testCount++;
1848
2241
  validator.Reset();
1849
- bool actual = data.Accept(validator);
2242
+ data.Accept(validator);
2243
+ bool actual = validator.IsValid();
1850
2244
  if (expected != actual)
1851
2245
  printf("Fail: %30s \"%s\" \"%s\"\n", filename, description1, description2);
1852
- else
2246
+ else {
2247
+ //printf("Passed: %30s \"%s\" \"%s\"\n", filename, description1, description2);
1853
2248
  passCount++;
2249
+ }
1854
2250
  }
1855
2251
  }
1856
2252
  //printf("%zu %zu %zu\n", documentAllocator.Size(), schemaAllocator.Size(), validatorAllocator.Size());
@@ -1865,8 +2261,8 @@ TEST(SchemaValidator, TestSuite) {
1865
2261
  jsonAllocator.Clear();
1866
2262
  }
1867
2263
  printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount);
1868
- // if (passCount != testCount)
1869
- // ADD_FAILURE();
2264
+ if (passCount != testCount)
2265
+ ADD_FAILURE();
1870
2266
  }
1871
2267
 
1872
2268
  TEST(SchemaValidatingReader, Simple) {
@@ -1897,12 +2293,14 @@ TEST(SchemaValidatingReader, Invalid) {
1897
2293
  EXPECT_FALSE(reader.IsValid());
1898
2294
  EXPECT_EQ(kParseErrorTermination, reader.GetParseResult().Code());
1899
2295
  EXPECT_STREQ("maxLength", reader.GetInvalidSchemaKeyword());
2296
+ EXPECT_TRUE(reader.GetInvalidSchemaCode() == kValidateErrorMaxLength);
1900
2297
  EXPECT_TRUE(reader.GetInvalidSchemaPointer() == SchemaDocument::PointerType(""));
1901
2298
  EXPECT_TRUE(reader.GetInvalidDocumentPointer() == SchemaDocument::PointerType(""));
1902
2299
  EXPECT_TRUE(d.IsNull());
1903
2300
  Document e;
1904
2301
  e.Parse(
1905
2302
  "{ \"maxLength\": {"
2303
+ " \"errorCode\": 6,"
1906
2304
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1907
2305
  " \"expected\": 3, \"actual\": \"ABCD\""
1908
2306
  "}}");
@@ -1933,9 +2331,11 @@ TEST(SchemaValidatingWriter, Simple) {
1933
2331
  EXPECT_FALSE(validator.IsValid());
1934
2332
  EXPECT_TRUE(validator.GetInvalidSchemaPointer() == SchemaDocument::PointerType(""));
1935
2333
  EXPECT_TRUE(validator.GetInvalidDocumentPointer() == SchemaDocument::PointerType(""));
2334
+ EXPECT_TRUE(validator.GetInvalidSchemaCode() == kValidateErrorMaxLength);
1936
2335
  Document e;
1937
2336
  e.Parse(
1938
2337
  "{ \"maxLength\": {"
2338
+ " \"errorCode\": 6,"
1939
2339
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1940
2340
  " \"expected\": 3, \"actual\": \"ABCD\""
1941
2341
  "}}");
@@ -1963,6 +2363,7 @@ TEST(Schema, Issue552) {
1963
2363
  VALIDATE(s, "\"Life, the universe, and everything\"", true);
1964
2364
  INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "",
1965
2365
  "{ \"type\": {"
2366
+ " \"errorCode\": 20,"
1966
2367
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1967
2368
  " \"expected\": [\"string\", \"number\"], \"actual\": \"array\""
1968
2369
  "}}");
@@ -1978,6 +2379,7 @@ TEST(SchemaValidator, Issue608) {
1978
2379
  VALIDATE(s, "{\"a\" : null, \"b\": null}", true);
1979
2380
  INVALIDATE(s, "{\"a\" : null, \"a\" : null}", "", "required", "",
1980
2381
  "{ \"required\": {"
2382
+ " \"errorCode\": 15,"
1981
2383
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
1982
2384
  " \"missing\": [\"b\"]"
1983
2385
  "}}");
@@ -1991,13 +2393,6 @@ TEST(SchemaValidator, Issue728_AllOfRef) {
1991
2393
  VALIDATE(s, "{\"key1\": \"abc\", \"key2\": \"def\"}", true);
1992
2394
  }
1993
2395
 
1994
- TEST(SchemaValidator, Issue825) {
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
-
2001
2396
  TEST(SchemaValidator, Issue1017_allOfHandler) {
2002
2397
  Document sd;
2003
2398
  sd.Parse("{\"allOf\": [{\"type\": \"object\",\"properties\": {\"cyanArray2\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}}},{\"type\": \"object\",\"properties\": {\"blackArray\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}},\"required\": [ \"blackArray\" ]}]}");
@@ -2027,25 +2422,210 @@ TEST(SchemaValidator, Ref_remote) {
2027
2422
  typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2028
2423
  INVALIDATE_(s, "null", "/integer", "type", "",
2029
2424
  "{ \"type\": {"
2425
+ " \"errorCode\": 20,"
2030
2426
  " \"instanceRef\": \"#\","
2031
2427
  " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\","
2032
2428
  " \"expected\": [\"integer\"], \"actual\": \"null\""
2033
2429
  "}}",
2034
- SchemaValidatorType, PointerType);
2430
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2431
+ }
2432
+
2433
+ // Merge with id where $ref is full URI
2434
+ TEST(SchemaValidator, Ref_remote_change_resolution_scope_uri) {
2435
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2436
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2437
+ Document sd;
2438
+ sd.Parse("{\"id\": \"http://ignore/blah#/ref\", \"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"http://localhost:1234/subSchemas.json#/integer\"}}}");
2439
+ SchemaDocumentType s(sd, 0, 0, &provider);
2440
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2441
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2442
+ INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt",
2443
+ "{ \"type\": {"
2444
+ " \"errorCode\": 20,"
2445
+ " \"instanceRef\": \"#/myInt\","
2446
+ " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\","
2447
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2448
+ "}}",
2449
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2450
+ }
2451
+
2452
+ // Merge with id where $ref is a relative path
2453
+ TEST(SchemaValidator, Ref_remote_change_resolution_scope_relative_path) {
2454
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2455
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2456
+ Document sd;
2457
+ sd.Parse("{\"id\": \"http://localhost:1234/\", \"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"subSchemas.json#/integer\"}}}");
2458
+ SchemaDocumentType s(sd, 0, 0, &provider);
2459
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2460
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2461
+ INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt",
2462
+ "{ \"type\": {"
2463
+ " \"errorCode\": 20,"
2464
+ " \"instanceRef\": \"#/myInt\","
2465
+ " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\","
2466
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2467
+ "}}",
2468
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2469
+ }
2470
+
2471
+ // Merge with id where $ref is an absolute path
2472
+ TEST(SchemaValidator, Ref_remote_change_resolution_scope_absolute_path) {
2473
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2474
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2475
+ Document sd;
2476
+ sd.Parse("{\"id\": \"http://localhost:1234/xxxx\", \"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/integer\"}}}");
2477
+ SchemaDocumentType s(sd, 0, 0, &provider);
2478
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2479
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2480
+ INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt",
2481
+ "{ \"type\": {"
2482
+ " \"errorCode\": 20,"
2483
+ " \"instanceRef\": \"#/myInt\","
2484
+ " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\","
2485
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2486
+ "}}",
2487
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2488
+ }
2489
+
2490
+ // Merge with id where $ref is an absolute path, and the document has a base URI
2491
+ TEST(SchemaValidator, Ref_remote_change_resolution_scope_absolute_path_document) {
2492
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2493
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2494
+ Document sd;
2495
+ sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/integer\"}}}");
2496
+ SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider);
2497
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2498
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2499
+ INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt",
2500
+ "{ \"type\": {"
2501
+ " \"errorCode\": 20,"
2502
+ " \"instanceRef\": \"#/myInt\","
2503
+ " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\","
2504
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2505
+ "}}",
2506
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2507
+ }
2508
+
2509
+ // $ref is a non-JSON pointer fragment and there a matching id
2510
+ TEST(SchemaValidator, Ref_internal_id_1) {
2511
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2512
+ Document sd;
2513
+ sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myStr\": {\"type\": \"string\", \"id\": \"#myStrId\"}, \"myInt2\": {\"type\": \"integer\", \"id\": \"#myId\"}}}");
2514
+ SchemaDocumentType s(sd);
2515
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2516
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2517
+ INVALIDATE_(s, "{\"myInt1\": null}", "/properties/myInt2", "type", "/myInt1",
2518
+ "{ \"type\": {"
2519
+ " \"errorCode\": 20,"
2520
+ " \"instanceRef\": \"#/myInt1\","
2521
+ " \"schemaRef\": \"#/properties/myInt2\","
2522
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2523
+ "}}",
2524
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2525
+ }
2526
+
2527
+ // $ref is a non-JSON pointer fragment and there are two matching ids so we take the first
2528
+ TEST(SchemaValidator, Ref_internal_id_2) {
2529
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2530
+ Document sd;
2531
+ sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myInt2\": {\"type\": \"integer\", \"id\": \"#myId\"}, \"myStr\": {\"type\": \"string\", \"id\": \"#myId\"}}}");
2532
+ SchemaDocumentType s(sd);
2533
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2534
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2535
+ INVALIDATE_(s, "{\"myInt1\": null}", "/properties/myInt2", "type", "/myInt1",
2536
+ "{ \"type\": {"
2537
+ " \"errorCode\": 20,"
2538
+ " \"instanceRef\": \"#/myInt1\","
2539
+ " \"schemaRef\": \"#/properties/myInt2\","
2540
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2541
+ "}}",
2542
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2543
+ }
2544
+
2545
+ // $ref is a non-JSON pointer fragment and there is a matching id within array
2546
+ TEST(SchemaValidator, Ref_internal_id_in_array) {
2547
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2548
+ Document sd;
2549
+ sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myInt2\": {\"anyOf\": [{\"type\": \"string\", \"id\": \"#myStrId\"}, {\"type\": \"integer\", \"id\": \"#myId\"}]}}}");
2550
+ SchemaDocumentType s(sd);
2551
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2552
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2553
+ INVALIDATE_(s, "{\"myInt1\": null}", "/properties/myInt2/anyOf/1", "type", "/myInt1",
2554
+ "{ \"type\": {"
2555
+ " \"errorCode\": 20,"
2556
+ " \"instanceRef\": \"#/myInt1\","
2557
+ " \"schemaRef\": \"#/properties/myInt2/anyOf/1\","
2558
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2559
+ "}}",
2560
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2561
+ }
2562
+
2563
+ // $ref is a non-JSON pointer fragment and there is a matching id, and the schema is embedded in the document
2564
+ TEST(SchemaValidator, Ref_internal_id_and_schema_pointer) {
2565
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2566
+ Document sd;
2567
+ sd.Parse("{ \"schema\": {\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myInt2\": {\"anyOf\": [{\"type\": \"integer\", \"id\": \"#myId\"}]}}}}");
2568
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2569
+ SchemaDocumentType s(sd, 0, 0, 0, 0, PointerType("/schema"));
2570
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2571
+ INVALIDATE_(s, "{\"myInt1\": null}", "/schema/properties/myInt2/anyOf/0", "type", "/myInt1",
2572
+ "{ \"type\": {"
2573
+ " \"errorCode\": 20,"
2574
+ " \"instanceRef\": \"#/myInt1\","
2575
+ " \"schemaRef\": \"#/schema/properties/myInt2/anyOf/0\","
2576
+ " \"expected\": [\"integer\"], \"actual\": \"null\""
2577
+ "}}",
2578
+ kValidateDefaultFlags, SchemaValidatorType, PointerType);
2579
+ }
2580
+
2581
+ // Test that $refs are correctly resolved when intermediate multiple ids are present
2582
+ // Includes $ref to a part of the document with a different in-scope id, which also contains $ref..
2583
+ TEST(SchemaValidator, Ref_internal_multiple_ids) {
2584
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2585
+ //RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2586
+ CrtAllocator allocator;
2587
+ char* schema = ReadFile("unittestschema/idandref.json", allocator);
2588
+ Document sd;
2589
+ sd.Parse(schema);
2590
+ ASSERT_FALSE(sd.HasParseError());
2591
+ SchemaDocumentType s(sd, "http://xyz", 10/*, &provider*/);
2592
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2593
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2594
+ INVALIDATE_(s, "{\"PA1\": \"s\", \"PA2\": \"t\", \"PA3\": \"r\", \"PX1\": 1, \"PX2Y\": 2, \"PX3Z\": 3, \"PX4\": 4, \"PX5\": 5, \"PX6\": 6, \"PX7W\": 7, \"PX8N\": { \"NX\": 8}}", "#", "errors", "#",
2595
+ "{ \"type\": ["
2596
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PA1\", \"schemaRef\": \"http://xyz#/definitions/A\", \"expected\": [\"integer\"], \"actual\": \"string\"},"
2597
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PA2\", \"schemaRef\": \"http://xyz#/definitions/A\", \"expected\": [\"integer\"], \"actual\": \"string\"},"
2598
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PA3\", \"schemaRef\": \"http://xyz#/definitions/A\", \"expected\": [\"integer\"], \"actual\": \"string\"},"
2599
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX1\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2600
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX2Y\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2601
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX3Z\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2602
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX4\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2603
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX5\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2604
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX6\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2605
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX7W\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"},"
2606
+ " {\"errorCode\": 20, \"instanceRef\": \"#/PX8N/NX\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}"
2607
+ "]}",
2608
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType);
2609
+ CrtAllocator::Free(schema);
2035
2610
  }
2036
2611
 
2037
2612
  TEST(SchemaValidator, Ref_remote_issue1210) {
2038
2613
  class SchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
2039
2614
  SchemaDocument** collection;
2040
2615
 
2041
- SchemaDocumentProvider(const SchemaDocumentProvider&);
2042
- SchemaDocumentProvider& operator=(const SchemaDocumentProvider&);
2616
+ // Dummy private copy constructor & assignment operator.
2617
+ // Function bodies added so that they compile in MSVC 2019.
2618
+ SchemaDocumentProvider(const SchemaDocumentProvider&) : collection(NULL) {
2619
+ }
2620
+ SchemaDocumentProvider& operator=(const SchemaDocumentProvider&) {
2621
+ return *this;
2622
+ }
2043
2623
 
2044
2624
  public:
2045
2625
  SchemaDocumentProvider(SchemaDocument** collection) : collection(collection) { }
2046
2626
  virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
2047
2627
  int i = 0;
2048
- while (collection[i] && SchemaDocument::URIType(uri, length) != collection[i]->GetURI()) ++i;
2628
+ while (collection[i] && SchemaDocument::SValue(uri, length) != collection[i]->GetURI()) ++i;
2049
2629
  return collection[i];
2050
2630
  }
2051
2631
  };
@@ -2067,6 +2647,306 @@ TEST(SchemaValidator, Ref_remote_issue1210) {
2067
2647
  VALIDATE(sx, "{\"country\":\"US\"}", true);
2068
2648
  }
2069
2649
 
2650
+ // Test that when kValidateContinueOnErrorFlag is set, all errors are reported.
2651
+ TEST(SchemaValidator, ContinueOnErrors) {
2652
+ CrtAllocator allocator;
2653
+ char* schema = ReadFile("unittestschema/address.json", allocator);
2654
+ Document sd;
2655
+ sd.Parse(schema);
2656
+ ASSERT_FALSE(sd.HasParseError());
2657
+ SchemaDocument s(sd);
2658
+ VALIDATE(s, "{\"version\": 1.0, \"address\": {\"number\": 24, \"street1\": \"The Woodlands\", \"street3\": \"Ham\", \"city\": \"Romsey\", \"area\": \"Kent\", \"country\": \"UK\", \"postcode\": \"SO51 0GP\"}, \"phones\": [\"0111-222333\", \"0777-666888\"], \"names\": [\"Fred\", \"Bloggs\"]}", true);
2659
+ INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#",
2660
+ "{ \"multipleOf\": {"
2661
+ " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01"
2662
+ " },"
2663
+ " \"minimum\": {"
2664
+ " \"errorCode\": 5, \"instanceRef\": \"#/address/number\", \"schemaRef\": \"#/definitions/positiveInt_type\", \"expected\": 0, \"actual\": 0, \"exclusiveMinimum\": true"
2665
+ " },"
2666
+ " \"type\": ["
2667
+ " {\"expected\": [\"null\", \"string\"], \"actual\": \"boolean\", \"errorCode\": 20, \"instanceRef\": \"#/address/street2\", \"schemaRef\": \"#/definitions/address_type/properties/street2\"},"
2668
+ " {\"expected\": [\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#/extra/S_xxx\", \"schemaRef\": \"#/properties/extra/patternProperties/%5ES_\"}"
2669
+ " ],"
2670
+ " \"maxLength\": {"
2671
+ " \"actual\": \"RomseyTownFC\", \"expected\": 10, \"errorCode\": 6, \"instanceRef\": \"#/address/city\", \"schemaRef\": \"#/definitions/address_type/properties/city\""
2672
+ " },"
2673
+ " \"anyOf\": {"
2674
+ " \"errors\":["
2675
+ " {\"pattern\": {\"actual\": \"999ABC\", \"errorCode\": 8, \"instanceRef\": \"#/address/postcode\", \"schemaRef\": \"#/definitions/address_type/properties/postcode/anyOf/0\"}},"
2676
+ " {\"pattern\": {\"actual\": \"999ABC\", \"errorCode\": 8, \"instanceRef\": \"#/address/postcode\", \"schemaRef\": \"#/definitions/address_type/properties/postcode/anyOf/1\"}}"
2677
+ " ],"
2678
+ " \"errorCode\": 24, \"instanceRef\": \"#/address/postcode\", \"schemaRef\": \"#/definitions/address_type/properties/postcode\""
2679
+ " },"
2680
+ " \"allOf\": {"
2681
+ " \"errors\":["
2682
+ " {\"enum\":{\"errorCode\":19,\"instanceRef\":\"#/address/country\",\"schemaRef\":\"#/definitions/country_type\"}}"
2683
+ " ],"
2684
+ " \"errorCode\":23,\"instanceRef\":\"#/address/country\",\"schemaRef\":\"#/definitions/address_type/properties/country\""
2685
+ " },"
2686
+ " \"minItems\": {"
2687
+ " \"actual\": 0, \"expected\": 1, \"errorCode\": 10, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\""
2688
+ " },"
2689
+ " \"additionalProperties\": {"
2690
+ " \"disallowed\": \"planet\", \"errorCode\": 16, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2691
+ " },"
2692
+ " \"required\": {"
2693
+ " \"missing\": [\"street1\"], \"errorCode\": 15, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\""
2694
+ " }"
2695
+ "}",
2696
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2697
+ INVALIDATE_(s, "{\"address\": {\"number\": 200, \"street1\": {}, \"street3\": null, \"city\": \"Rom\", \"area\": \"Dorset\", \"postcode\": \"SO51 0GP\"}, \"phones\": [\"0111-222333\", \"0777-666888\", \"0777-666888\"], \"names\": [\"Fred\", \"S\", \"M\", \"Bloggs\"]}", "#", "errors", "#",
2698
+ "{ \"maximum\": {"
2699
+ " \"errorCode\": 3, \"instanceRef\": \"#/address/number\", \"schemaRef\": \"#/definitions/positiveInt_type\", \"expected\": 100, \"actual\": 200, \"exclusiveMaximum\": true"
2700
+ " },"
2701
+ " \"type\": {"
2702
+ " \"expected\": [\"string\"], \"actual\": \"object\", \"errorCode\": 20, \"instanceRef\": \"#/address/street1\", \"schemaRef\": \"#/definitions/address_type/properties/street1\""
2703
+ " },"
2704
+ " \"not\": {"
2705
+ " \"errorCode\": 25, \"instanceRef\": \"#/address/street3\", \"schemaRef\": \"#/definitions/address_type/properties/street3\""
2706
+ " },"
2707
+ " \"minLength\": {"
2708
+ " \"actual\": \"Rom\", \"expected\": 4, \"errorCode\": 7, \"instanceRef\": \"#/address/city\", \"schemaRef\": \"#/definitions/address_type/properties/city\""
2709
+ " },"
2710
+ " \"maxItems\": {"
2711
+ " \"actual\": 3, \"expected\": 2, \"errorCode\": 9, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\""
2712
+ " },"
2713
+ " \"uniqueItems\": {"
2714
+ " \"duplicates\": [1, 2], \"errorCode\": 11, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\""
2715
+ " },"
2716
+ " \"minProperties\": {\"actual\": 6, \"expected\": 7, \"errorCode\": 14, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\""
2717
+ " },"
2718
+ " \"additionalItems\": ["
2719
+ " {\"disallowed\": 2, \"errorCode\": 12, \"instanceRef\": \"#/names\", \"schemaRef\": \"#/properties/names\"},"
2720
+ " {\"disallowed\": 3, \"errorCode\": 12, \"instanceRef\": \"#/names\", \"schemaRef\": \"#/properties/names\"}"
2721
+ " ],"
2722
+ " \"dependencies\": {"
2723
+ " \"errors\": {"
2724
+ " \"address\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/address\"}},"
2725
+ " \"names\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/names\"}}"
2726
+ " },"
2727
+ " \"errorCode\": 18, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2728
+ " },"
2729
+ " \"oneOf\": {"
2730
+ " \"errors\": ["
2731
+ " {\"enum\": {\"errorCode\": 19, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/county_type\"}},"
2732
+ " {\"enum\": {\"errorCode\": 19, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/province_type\"}}"
2733
+ " ],"
2734
+ " \"errorCode\": 21, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/address_type/properties/area\""
2735
+ " }"
2736
+ "}",
2737
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2738
+
2739
+ CrtAllocator::Free(schema);
2740
+ }
2741
+
2742
+ // Test that when kValidateContinueOnErrorFlag is set, it is not propagated to oneOf sub-validator so we only get the first error.
2743
+ TEST(SchemaValidator, ContinueOnErrors_OneOf) {
2744
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2745
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2746
+ CrtAllocator allocator;
2747
+ char* schema = ReadFile("unittestschema/oneOf_address.json", allocator);
2748
+ Document sd;
2749
+ sd.Parse(schema);
2750
+ ASSERT_FALSE(sd.HasParseError());
2751
+ SchemaDocumentType s(sd, 0, 0, &provider);
2752
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2753
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2754
+ INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#",
2755
+ "{ \"oneOf\": {"
2756
+ " \"errors\": [{"
2757
+ " \"multipleOf\": {"
2758
+ " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"http://localhost:1234/address.json#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01"
2759
+ " }"
2760
+ " }],"
2761
+ " \"errorCode\": 21, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2762
+ " }"
2763
+ "}",
2764
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType);
2765
+ CrtAllocator::Free(schema);
2766
+ }
2767
+
2768
+ // Test that when kValidateContinueOnErrorFlag is set, it is not propagated to allOf sub-validator so we only get the first error.
2769
+ TEST(SchemaValidator, ContinueOnErrors_AllOf) {
2770
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2771
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2772
+ CrtAllocator allocator;
2773
+ char* schema = ReadFile("unittestschema/allOf_address.json", allocator);
2774
+ Document sd;
2775
+ sd.Parse(schema);
2776
+ ASSERT_FALSE(sd.HasParseError());
2777
+ SchemaDocumentType s(sd, 0, 0, &provider);
2778
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2779
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2780
+ INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#",
2781
+ "{ \"allOf\": {"
2782
+ " \"errors\": [{"
2783
+ " \"multipleOf\": {"
2784
+ " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"http://localhost:1234/address.json#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01"
2785
+ " }"
2786
+ " }],"
2787
+ " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2788
+ " }"
2789
+ "}",
2790
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType);
2791
+ CrtAllocator::Free(schema);
2792
+ }
2793
+
2794
+ // Test that when kValidateContinueOnErrorFlag is set, it is not propagated to anyOf sub-validator so we only get the first error.
2795
+ TEST(SchemaValidator, ContinueOnErrors_AnyOf) {
2796
+ typedef GenericSchemaDocument<Value, MemoryPoolAllocator<> > SchemaDocumentType;
2797
+ RemoteSchemaDocumentProvider<SchemaDocumentType> provider;
2798
+ CrtAllocator allocator;
2799
+ char* schema = ReadFile("unittestschema/anyOf_address.json", allocator);
2800
+ Document sd;
2801
+ sd.Parse(schema);
2802
+ ASSERT_FALSE(sd.HasParseError());
2803
+ SchemaDocumentType s(sd, 0, 0, &provider);
2804
+ typedef GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > SchemaValidatorType;
2805
+ typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
2806
+ INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#",
2807
+ "{ \"anyOf\": {"
2808
+ " \"errors\": [{"
2809
+ " \"multipleOf\": {"
2810
+ " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"http://localhost:1234/address.json#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01"
2811
+ " }"
2812
+ " }],"
2813
+ " \"errorCode\": 24, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2814
+ " }"
2815
+ "}",
2816
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType);
2817
+
2818
+ CrtAllocator::Free(schema);
2819
+ }
2820
+
2821
+ // Test that when kValidateContinueOnErrorFlag is set, arrays with uniqueItems:true are correctly processed when an item is invalid.
2822
+ // This tests that we don't blow up if a hasher does not get created.
2823
+ TEST(SchemaValidator, ContinueOnErrors_UniqueItems) {
2824
+ CrtAllocator allocator;
2825
+ char* schema = ReadFile("unittestschema/address.json", allocator);
2826
+ Document sd;
2827
+ sd.Parse(schema);
2828
+ ASSERT_FALSE(sd.HasParseError());
2829
+ SchemaDocument s(sd);
2830
+ VALIDATE(s, "{\"phones\":[\"12-34\",\"56-78\"]}", true);
2831
+ INVALIDATE_(s, "{\"phones\":[\"12-34\",\"12-34\"]}", "#", "errors", "#",
2832
+ "{\"uniqueItems\": {\"duplicates\": [0,1], \"errorCode\": 11, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"}}",
2833
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2834
+ INVALIDATE_(s, "{\"phones\":[\"ab-34\",\"cd-78\"]}", "#", "errors", "#",
2835
+ "{\"pattern\": ["
2836
+ " {\"actual\": \"ab-34\", \"errorCode\": 8, \"instanceRef\": \"#/phones/0\", \"schemaRef\": \"#/definitions/phone_type\"},"
2837
+ " {\"actual\": \"cd-78\", \"errorCode\": 8, \"instanceRef\": \"#/phones/1\", \"schemaRef\": \"#/definitions/phone_type\"}"
2838
+ "]}",
2839
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2840
+ CrtAllocator::Free(schema);
2841
+ }
2842
+
2843
+ // Test that when kValidateContinueOnErrorFlag is set, an enum field is correctly processed when it has an invalid value.
2844
+ // This tests that we don't blow up if a hasher does not get created.
2845
+ TEST(SchemaValidator, ContinueOnErrors_Enum) {
2846
+ CrtAllocator allocator;
2847
+ char* schema = ReadFile("unittestschema/address.json", allocator);
2848
+ Document sd;
2849
+ sd.Parse(schema);
2850
+ ASSERT_FALSE(sd.HasParseError());
2851
+ SchemaDocument s(sd);
2852
+ VALIDATE(s, "{\"gender\":\"M\"}", true);
2853
+ INVALIDATE_(s, "{\"gender\":\"X\"}", "#", "errors", "#",
2854
+ "{\"enum\": {\"errorCode\": 19, \"instanceRef\": \"#/gender\", \"schemaRef\": \"#/properties/gender\"}}",
2855
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2856
+ INVALIDATE_(s, "{\"gender\":1}", "#", "errors", "#",
2857
+ "{\"type\": {\"expected\":[\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#/gender\", \"schemaRef\": \"#/properties/gender\"}}",
2858
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2859
+ CrtAllocator::Free(schema);
2860
+ }
2861
+
2862
+ // Test that when kValidateContinueOnErrorFlag is set, an array appearing for an object property is handled
2863
+ // This tests that we don't blow up when there is a type mismatch.
2864
+ TEST(SchemaValidator, ContinueOnErrors_RogueArray) {
2865
+ CrtAllocator allocator;
2866
+ char* schema = ReadFile("unittestschema/address.json", allocator);
2867
+ Document sd;
2868
+ sd.Parse(schema);
2869
+ ASSERT_FALSE(sd.HasParseError());
2870
+ SchemaDocument s(sd);
2871
+ INVALIDATE_(s, "{\"address\":[{\"number\": 0}]}", "#", "errors", "#",
2872
+ "{\"type\": {\"expected\":[\"object\"], \"actual\": \"array\", \"errorCode\": 20, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"},"
2873
+ " \"dependencies\": {"
2874
+ " \"errors\": {"
2875
+ " \"address\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/address\"}}"
2876
+ " },\"errorCode\": 18, \"instanceRef\": \"#\", \"schemaRef\": \"#\"}}",
2877
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2878
+ CrtAllocator::Free(schema);
2879
+ }
2880
+
2881
+ // Test that when kValidateContinueOnErrorFlag is set, an object appearing for an array property is handled
2882
+ // This tests that we don't blow up when there is a type mismatch.
2883
+ TEST(SchemaValidator, ContinueOnErrors_RogueObject) {
2884
+ CrtAllocator allocator;
2885
+ char* schema = ReadFile("unittestschema/address.json", allocator);
2886
+ Document sd;
2887
+ sd.Parse(schema);
2888
+ ASSERT_FALSE(sd.HasParseError());
2889
+ SchemaDocument s(sd);
2890
+ INVALIDATE_(s, "{\"phones\":{\"number\": 0}}", "#", "errors", "#",
2891
+ "{\"type\": {\"expected\":[\"array\"], \"actual\": \"object\", \"errorCode\": 20, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"}}",
2892
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2893
+ CrtAllocator::Free(schema);
2894
+ }
2895
+
2896
+ // Test that when kValidateContinueOnErrorFlag is set, a string appearing for an array or object property is handled
2897
+ // This tests that we don't blow up when there is a type mismatch.
2898
+ TEST(SchemaValidator, ContinueOnErrors_RogueString) {
2899
+ CrtAllocator allocator;
2900
+ char* schema = ReadFile("unittestschema/address.json", allocator);
2901
+ Document sd;
2902
+ sd.Parse(schema);
2903
+ ASSERT_FALSE(sd.HasParseError());
2904
+ SchemaDocument s(sd);
2905
+ INVALIDATE_(s, "{\"address\":\"number\"}", "#", "errors", "#",
2906
+ "{\"type\": {\"expected\":[\"object\"], \"actual\": \"string\", \"errorCode\": 20, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"},"
2907
+ " \"dependencies\": {"
2908
+ " \"errors\": {"
2909
+ " \"address\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/address\"}}"
2910
+ " },\"errorCode\": 18, \"instanceRef\": \"#\", \"schemaRef\": \"#\"}}",
2911
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2912
+ INVALIDATE_(s, "{\"phones\":\"number\"}", "#", "errors", "#",
2913
+ "{\"type\": {\"expected\":[\"array\"], \"actual\": \"string\", \"errorCode\": 20, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"}}",
2914
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2915
+ CrtAllocator::Free(schema);
2916
+ }
2917
+
2918
+ // Test that when kValidateContinueOnErrorFlag is set, an incorrect simple type with a sub-schema is handled correctly.
2919
+ // This tests that we don't blow up when there is a type mismatch but there is a sub-schema present
2920
+ TEST(SchemaValidator, ContinueOnErrors_Issue2) {
2921
+ Document sd;
2922
+ sd.Parse("{\"type\":\"string\", \"anyOf\":[{\"maxLength\":2}]}");
2923
+ ASSERT_FALSE(sd.HasParseError());
2924
+ SchemaDocument s(sd);
2925
+ VALIDATE(s, "\"AB\"", true);
2926
+ INVALIDATE_(s, "\"ABC\"", "#", "errors", "#",
2927
+ "{ \"anyOf\": {"
2928
+ " \"errors\": [{"
2929
+ " \"maxLength\": {"
2930
+ " \"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\", \"expected\": 2, \"actual\": \"ABC\""
2931
+ " }"
2932
+ " }],"
2933
+ " \"errorCode\": 24, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2934
+ " }"
2935
+ "}",
2936
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2937
+ // Invalid type
2938
+ INVALIDATE_(s, "333", "#", "errors", "#",
2939
+ "{ \"type\": {"
2940
+ " \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"expected\": [\"string\"], \"actual\": \"integer\""
2941
+ " }"
2942
+ "}",
2943
+ kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2944
+ }
2945
+
2946
+ TEST(SchemaValidator, Schema_UnknownError) {
2947
+ ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null"));
2948
+ }
2949
+
2070
2950
  #if defined(_MSC_VER) || defined(__clang__)
2071
2951
  RAPIDJSON_DIAG_POP
2072
2952
  #endif