rj_schema 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) 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/idandref.json +69 -0
  6. data/ext/rj_schema/rapidjson/doc/stream.md +7 -7
  7. data/ext/rj_schema/rapidjson/doc/stream.zh-cn.md +1 -1
  8. data/ext/rj_schema/rapidjson/doc/tutorial.md +15 -15
  9. data/ext/rj_schema/rapidjson/example/schemavalidator/schemavalidator.cpp +2 -0
  10. data/ext/rj_schema/rapidjson/example/traverseaspointer.cpp +39 -0
  11. data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +460 -52
  12. data/ext/rj_schema/rapidjson/include/rapidjson/document.h +350 -60
  13. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strfunc.h +14 -0
  14. data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +68 -1
  15. data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +60 -11
  16. data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +249 -102
  17. data/ext/rj_schema/rapidjson/include/rapidjson/uri.h +466 -0
  18. data/ext/rj_schema/rapidjson/test/perftest/perftest.h +5 -4
  19. data/ext/rj_schema/rapidjson/test/perftest/rapidjsontest.cpp +20 -2
  20. data/ext/rj_schema/rapidjson/test/unittest/CMakeLists.txt +2 -0
  21. data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +193 -1
  22. data/ext/rj_schema/rapidjson/test/unittest/documenttest.cpp +2 -0
  23. data/ext/rj_schema/rapidjson/test/unittest/platformtest.cpp +40 -0
  24. data/ext/rj_schema/rapidjson/test/unittest/pointertest.cpp +62 -2
  25. data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +372 -7
  26. data/ext/rj_schema/rapidjson/test/unittest/uritest.cpp +718 -0
  27. data/ext/rj_schema/rapidjson/test/unittest/valuetest.cpp +12 -2
  28. data/ext/rj_schema/rj_schema.cpp +1 -1
  29. data/lib/rj_schema.rb +1 -1
  30. metadata +9 -3
@@ -13,6 +13,7 @@
13
13
  // specific language governing permissions and limitations under the License.
14
14
 
15
15
  #define RAPIDJSON_SCHEMA_VERBOSE 0
16
+ #define RAPIDJSON_HAS_STDSTRING 1
16
17
 
17
18
  #include "unittest.h"
18
19
  #include "rapidjson/schema.h"
@@ -1811,6 +1812,189 @@ TEST(SchemaValidator, EscapedPointer) {
1811
1812
  "}}");
1812
1813
  }
1813
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
+
1814
1998
  template <typename Allocator>
1815
1999
  static char* ReadFile(const char* filename, Allocator& allocator) {
1816
2000
  const char *paths[] = {
@@ -1952,7 +2136,7 @@ public:
1952
2136
 
1953
2137
  virtual const SchemaDocumentType* GetRemoteDocument(const char* uri, SizeType length) {
1954
2138
  for (size_t i = 0; i < kCount; i++)
1955
- if (typename SchemaDocumentType::URIType(uri, length) == sd_[i]->GetURI())
2139
+ if (typename SchemaDocumentType::SValue(uri, length) == sd_[i]->GetURI())
1956
2140
  return sd_[i];
1957
2141
  return 0;
1958
2142
  }
@@ -2032,7 +2216,7 @@ TEST(SchemaValidator, TestSuite) {
2032
2216
  ADD_FAILURE();
2033
2217
  }
2034
2218
  else {
2035
- //printf("json test suite file %s parsed ok\n", filename);
2219
+ //printf("\njson test suite file %s parsed ok\n", filename);
2036
2220
  GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > d(&documentAllocator, 1024, &documentStackAllocator);
2037
2221
  d.Parse(json);
2038
2222
  if (d.HasParseError()) {
@@ -2042,12 +2226,14 @@ TEST(SchemaValidator, TestSuite) {
2042
2226
  else {
2043
2227
  for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) {
2044
2228
  {
2229
+ const char* description1 = (*schemaItr)["description"].GetString();
2230
+ //printf("\ncompiling schema for json test %s \n", description1);
2045
2231
  SchemaDocumentType schema((*schemaItr)["schema"], filenames[i], static_cast<SizeType>(strlen(filenames[i])), &provider, &schemaAllocator);
2046
2232
  GenericSchemaValidator<SchemaDocumentType, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > validator(schema, &validatorAllocator);
2047
- const char* description1 = (*schemaItr)["description"].GetString();
2048
2233
  const Value& tests = (*schemaItr)["tests"];
2049
2234
  for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) {
2050
2235
  const char* description2 = (*testItr)["description"].GetString();
2236
+ //printf("running json test %s \n", description2);
2051
2237
  if (!onlyRunDescription || strcmp(description2, onlyRunDescription) == 0) {
2052
2238
  const Value& data = (*testItr)["data"];
2053
2239
  bool expected = (*testItr)["valid"].GetBool();
@@ -2075,8 +2261,8 @@ TEST(SchemaValidator, TestSuite) {
2075
2261
  jsonAllocator.Clear();
2076
2262
  }
2077
2263
  printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount);
2078
- // if (passCount != testCount)
2079
- // ADD_FAILURE();
2264
+ if (passCount != testCount)
2265
+ ADD_FAILURE();
2080
2266
  }
2081
2267
 
2082
2268
  TEST(SchemaValidatingReader, Simple) {
@@ -2114,7 +2300,7 @@ TEST(SchemaValidatingReader, Invalid) {
2114
2300
  Document e;
2115
2301
  e.Parse(
2116
2302
  "{ \"maxLength\": {"
2117
- " \"errorCode\": 6,"
2303
+ " \"errorCode\": 6,"
2118
2304
  " \"instanceRef\": \"#\", \"schemaRef\": \"#\","
2119
2305
  " \"expected\": 3, \"actual\": \"ABCD\""
2120
2306
  "}}");
@@ -2244,6 +2430,185 @@ TEST(SchemaValidator, Ref_remote) {
2244
2430
  kValidateDefaultFlags, SchemaValidatorType, PointerType);
2245
2431
  }
2246
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);
2610
+ }
2611
+
2247
2612
  TEST(SchemaValidator, Ref_remote_issue1210) {
2248
2613
  class SchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
2249
2614
  SchemaDocument** collection;
@@ -2260,7 +2625,7 @@ TEST(SchemaValidator, Ref_remote_issue1210) {
2260
2625
  SchemaDocumentProvider(SchemaDocument** collection) : collection(collection) { }
2261
2626
  virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
2262
2627
  int i = 0;
2263
- while (collection[i] && SchemaDocument::URIType(uri, length) != collection[i]->GetURI()) ++i;
2628
+ while (collection[i] && SchemaDocument::SValue(uri, length) != collection[i]->GetURI()) ++i;
2264
2629
  return collection[i];
2265
2630
  }
2266
2631
  };
@@ -0,0 +1,718 @@
1
+ // Tencent is pleased to support the open source community by making RapidJSON available.
2
+ //
3
+ // (C) Copyright IBM Corporation 2021
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
+ #define RAPIDJSON_SCHEMA_VERBOSE 0
16
+ #define RAPIDJSON_HAS_STDSTRING 1
17
+
18
+ #include "unittest.h"
19
+ #include "rapidjson/document.h"
20
+ #include "rapidjson/uri.h"
21
+
22
+ #ifdef __clang__
23
+ RAPIDJSON_DIAG_PUSH
24
+ RAPIDJSON_DIAG_OFF(variadic-macros)
25
+ #elif defined(_MSC_VER)
26
+ RAPIDJSON_DIAG_PUSH
27
+ RAPIDJSON_DIAG_OFF(4822) // local class member function does not have a body
28
+ #endif
29
+
30
+ using namespace rapidjson;
31
+
32
+ TEST(Uri, DefaultConstructor) {
33
+ typedef GenericUri<Value> UriType;
34
+ UriType u;
35
+ EXPECT_TRUE(u.GetSchemeString() == 0);
36
+ EXPECT_TRUE(u.GetAuthString() == 0);
37
+ EXPECT_TRUE(u.GetPathString() == 0);
38
+ EXPECT_TRUE(u.GetBaseString() == 0);
39
+ EXPECT_TRUE(u.GetQueryString() == 0);
40
+ EXPECT_TRUE(u.GetFragString() == 0);
41
+ EXPECT_TRUE(u.GetString() == 0);
42
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
43
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
44
+ EXPECT_TRUE(u.GetPathStringLength() == 0);
45
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
46
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
47
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
48
+ EXPECT_TRUE(u.GetStringLength() == 0);
49
+ }
50
+
51
+
52
+ TEST(Uri, Parse) {
53
+ typedef GenericUri<Value, MemoryPoolAllocator<> > UriType;
54
+ MemoryPoolAllocator<CrtAllocator> allocator;
55
+ Value v;
56
+ Value w;
57
+
58
+ v.SetString("http://auth/path/xxx?query#frag", allocator);
59
+ UriType u = UriType(v, &allocator);
60
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0);
61
+ EXPECT_TRUE(StrCmp(u.GetAuthString(), "//auth") == 0);
62
+ EXPECT_TRUE(StrCmp(u.GetPathString(), "/path/xxx") == 0);
63
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "http://auth/path/xxx?query") == 0);
64
+ EXPECT_TRUE(StrCmp(u.GetQueryString(), "?query") == 0);
65
+ EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag") == 0);
66
+ u.Get(w, allocator);
67
+ EXPECT_TRUE(*w.GetString() == *v.GetString());
68
+
69
+ #if RAPIDJSON_HAS_STDSTRING
70
+ typedef std::basic_string<Value::Ch> String;
71
+ String str = "http://auth/path/xxx?query#frag";
72
+ const UriType uri = UriType(str);
73
+ EXPECT_TRUE(UriType::GetScheme(uri) == "http:");
74
+ EXPECT_TRUE(UriType::GetAuth(uri) == "//auth");
75
+ EXPECT_TRUE(UriType::GetPath(uri) == "/path/xxx");
76
+ EXPECT_TRUE(UriType::GetBase(uri) == "http://auth/path/xxx?query");
77
+ EXPECT_TRUE(UriType::GetQuery(uri) == "?query");
78
+ EXPECT_TRUE(UriType::GetFrag(uri) == "#frag");
79
+ EXPECT_TRUE(UriType::Get(uri) == str);
80
+ #endif
81
+
82
+ v.SetString("urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f", allocator);
83
+ u = UriType(v);
84
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), "urn:") == 0);
85
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
86
+ EXPECT_TRUE(StrCmp(u.GetPathString(), "uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0);
87
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0);
88
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
89
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
90
+ u.Get(w, allocator);
91
+ EXPECT_TRUE(*w.GetString() == *v.GetString());
92
+
93
+ v.SetString("", allocator);
94
+ u = UriType(v);
95
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
96
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
97
+ EXPECT_TRUE(u.GetPathStringLength() == 0);
98
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
99
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
100
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
101
+
102
+ v.SetString("http://auth/", allocator);
103
+ u = UriType(v);
104
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0);
105
+ EXPECT_TRUE(StrCmp(u.GetAuthString(), "//auth") == 0);
106
+ EXPECT_TRUE(StrCmp(u.GetPathString(), "/") == 0);
107
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "http://auth/") == 0);
108
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
109
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
110
+
111
+ u = UriType("/path/sub");
112
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
113
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
114
+ EXPECT_TRUE(StrCmp(u.GetPathString(), "/path/sub") == 0);
115
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "/path/sub") == 0);
116
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
117
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
118
+
119
+ // absolute path gets normalized
120
+ u = UriType("/path/../sub/");
121
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
122
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
123
+ EXPECT_TRUE(StrCmp(u.GetPathString(), "/sub/") == 0);
124
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "/sub/") == 0);
125
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
126
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
127
+
128
+ // relative path does not
129
+ u = UriType("path/../sub");
130
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
131
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
132
+ EXPECT_TRUE(StrCmp(u.GetPathString(), "path/../sub") == 0);
133
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "path/../sub") == 0);
134
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
135
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
136
+
137
+ u = UriType("http://auth#frag/stuff");
138
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0);
139
+ EXPECT_TRUE(StrCmp(u.GetAuthString(), "//auth") == 0);
140
+ EXPECT_TRUE(u.GetPathStringLength() == 0);
141
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "http://auth") == 0);
142
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
143
+ EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag/stuff") == 0);
144
+ EXPECT_TRUE(StrCmp(u.GetString(), "http://auth#frag/stuff") == 0);
145
+
146
+ const Value::Ch c[] = { '#', 'f', 'r', 'a', 'g', '/', 's', 't', 'u', 'f', 'f', '\0'};
147
+ SizeType len = internal::StrLen<Value::Ch>(c);
148
+ u = UriType(c, len);
149
+ EXPECT_TRUE(StrCmp(u.GetString(), "#frag/stuff") == 0);
150
+ EXPECT_TRUE(u.GetStringLength() == len);
151
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "") == 0);
152
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
153
+ EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag/stuff") == 0);
154
+ EXPECT_TRUE(u.GetFragStringLength() == len);
155
+
156
+ u = UriType(c);
157
+ EXPECT_TRUE(StrCmp(u.GetString(), "#frag/stuff") == 0);
158
+ EXPECT_TRUE(u.GetStringLength() == len);
159
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), "") == 0);
160
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
161
+ EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag/stuff") == 0);
162
+ EXPECT_TRUE(u.GetFragStringLength() == len);
163
+
164
+ // Incomplete auth treated as path
165
+ str = "http:/";
166
+ const UriType u2 = UriType(str);
167
+ EXPECT_TRUE(StrCmp(u2.GetSchemeString(), "http:") == 0);
168
+ EXPECT_TRUE(u2.GetAuthStringLength() == 0);
169
+ EXPECT_TRUE(StrCmp(u2.GetPathString(), "/") == 0);
170
+ EXPECT_TRUE(StrCmp(u2.GetBaseString(), "http:/") == 0);
171
+ }
172
+
173
+ TEST(Uri, Parse_UTF16) {
174
+ typedef GenericValue<UTF16<> > Value16;
175
+ typedef GenericUri<Value16, MemoryPoolAllocator<> > UriType;
176
+ MemoryPoolAllocator<CrtAllocator> allocator;
177
+ Value16 v;
178
+ Value16 w;
179
+
180
+ v.SetString(L"http://auth/path/xxx?query#frag", allocator);
181
+ UriType u = UriType(v, &allocator);
182
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0);
183
+ EXPECT_TRUE(StrCmp(u.GetAuthString(), L"//auth") == 0);
184
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"/path/xxx") == 0);
185
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http://auth/path/xxx?query") == 0);
186
+ EXPECT_TRUE(StrCmp(u.GetQueryString(), L"?query") == 0);
187
+ EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag") == 0);
188
+ u.Get(w, allocator);
189
+ EXPECT_TRUE(*w.GetString() == *v.GetString());
190
+
191
+ #if RAPIDJSON_HAS_STDSTRING
192
+ typedef std::basic_string<Value16::Ch> String;
193
+ String str = L"http://auth/path/xxx?query#frag";
194
+ const UriType uri = UriType(str);
195
+ EXPECT_TRUE(UriType::GetScheme(uri) == L"http:");
196
+ EXPECT_TRUE(UriType::GetAuth(uri) == L"//auth");
197
+ EXPECT_TRUE(UriType::GetPath(uri) == L"/path/xxx");
198
+ EXPECT_TRUE(UriType::GetBase(uri) == L"http://auth/path/xxx?query");
199
+ EXPECT_TRUE(UriType::GetQuery(uri) == L"?query");
200
+ EXPECT_TRUE(UriType::GetFrag(uri) == L"#frag");
201
+ EXPECT_TRUE(UriType::Get(uri) == str);
202
+ #endif
203
+
204
+ v.SetString(L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f", allocator);
205
+ u = UriType(v);
206
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"urn:") == 0);
207
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
208
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0);
209
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0);
210
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
211
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
212
+ u.Get(w, allocator);
213
+ EXPECT_TRUE(*w.GetString() == *v.GetString());
214
+
215
+ v.SetString(L"", allocator);
216
+ u = UriType(v);
217
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
218
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
219
+ EXPECT_TRUE(u.GetPathStringLength() == 0);
220
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
221
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
222
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
223
+
224
+ v.SetString(L"http://auth/", allocator);
225
+ u = UriType(v);
226
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0);
227
+ EXPECT_TRUE(StrCmp(u.GetAuthString(), L"//auth") == 0);
228
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"/") == 0);
229
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http://auth/") == 0);
230
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
231
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
232
+
233
+ u = UriType(L"/path/sub");
234
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
235
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
236
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"/path/sub") == 0);
237
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"/path/sub") == 0);
238
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
239
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
240
+
241
+ // absolute path gets normalized
242
+ u = UriType(L"/path/../sub/");
243
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
244
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
245
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"/sub/") == 0);
246
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"/sub/") == 0);
247
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
248
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
249
+
250
+ // relative path does not
251
+ u = UriType(L"path/../sub");
252
+ EXPECT_TRUE(u.GetSchemeStringLength() == 0);
253
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
254
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"path/../sub") == 0);
255
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"path/../sub") == 0);
256
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
257
+ EXPECT_TRUE(u.GetFragStringLength() == 0);
258
+
259
+ u = UriType(L"http://auth#frag/stuff");
260
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0);
261
+ EXPECT_TRUE(StrCmp(u.GetAuthString(), L"//auth") == 0);
262
+ EXPECT_TRUE(u.GetPathStringLength() == 0);
263
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http://auth") == 0);
264
+ EXPECT_TRUE(u.GetQueryStringLength() == 0);
265
+ EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag/stuff") == 0);
266
+ EXPECT_TRUE(StrCmp(u.GetString(), L"http://auth#frag/stuff") == 0);
267
+
268
+ const Value16::Ch c[] = { '#', 'f', 'r', 'a', 'g', '/', 's', 't', 'u', 'f', 'f', '\0'};
269
+ SizeType len = internal::StrLen<Value16::Ch>(c);
270
+ u = UriType(c, len);
271
+ EXPECT_TRUE(StrCmp(u.GetString(), L"#frag/stuff") == 0);
272
+ EXPECT_TRUE(u.GetStringLength() == len);
273
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"") == 0);
274
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
275
+ EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag/stuff") == 0);
276
+ EXPECT_TRUE(u.GetFragStringLength() == len);
277
+
278
+ u = UriType(c);
279
+ EXPECT_TRUE(StrCmp(u.GetString(), L"#frag/stuff") == 0);
280
+ EXPECT_TRUE(u.GetStringLength() == len);
281
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"") == 0);
282
+ EXPECT_TRUE(u.GetBaseStringLength() == 0);
283
+ EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag/stuff") == 0);
284
+ EXPECT_TRUE(u.GetFragStringLength() == len);
285
+
286
+ // Incomplete auth treated as path
287
+ u = UriType(L"http:/");
288
+ EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0);
289
+ EXPECT_TRUE(u.GetAuthStringLength() == 0);
290
+ EXPECT_TRUE(StrCmp(u.GetPathString(), L"/") == 0);
291
+ EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http:/") == 0);
292
+ }
293
+
294
+ TEST(Uri, CopyConstructor) {
295
+ typedef GenericUri<Value> UriType;
296
+ CrtAllocator allocator;
297
+
298
+ UriType u("http://auth/path/xxx?query#frag", &allocator);
299
+ UriType u2(u);
300
+ EXPECT_TRUE(u == u2);
301
+ EXPECT_NE(&u.GetAllocator(), &u2.GetAllocator());
302
+ }
303
+
304
+ TEST(Uri, Assignment) {
305
+ typedef GenericUri<Value> UriType;
306
+ CrtAllocator allocator;
307
+
308
+ UriType u("http://auth/path/xxx?query#frag", &allocator);
309
+ UriType u2;
310
+ u2 = u;
311
+ EXPECT_TRUE(u == u2);
312
+ EXPECT_NE(&u.GetAllocator(), &u2.GetAllocator());
313
+ }
314
+
315
+ TEST(Uri, Resolve) {
316
+ typedef GenericUri<Value> UriType;
317
+ CrtAllocator allocator;
318
+
319
+ // ref is full uri
320
+ UriType base = UriType("http://auth/path/#frag");
321
+ UriType ref = UriType("http://newauth/newpath#newfrag");
322
+ UriType res = ref.Resolve(base);
323
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://newauth/newpath#newfrag") == 0);
324
+
325
+ base = UriType("/path/#frag", &allocator);
326
+ ref = UriType("http://newauth/newpath#newfrag", &allocator);
327
+ res = ref.Resolve(base, &allocator);
328
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://newauth/newpath#newfrag") == 0);
329
+
330
+ // ref is alternate uri
331
+ base = UriType("http://auth/path/#frag");
332
+ ref = UriType("urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f");
333
+ res = ref.Resolve(base);
334
+ EXPECT_TRUE(StrCmp(res.GetString(), "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0);
335
+
336
+ // ref is absolute path
337
+ base = UriType("http://auth/path/#");
338
+ ref = UriType("/newpath#newfrag");
339
+ res = ref.Resolve(base);
340
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/newpath#newfrag") == 0);
341
+
342
+ // ref is relative path
343
+ base = UriType("http://auth/path/file.json#frag");
344
+ ref = UriType("newfile.json#");
345
+ res = ref.Resolve(base);
346
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/path/newfile.json#") == 0);
347
+
348
+ base = UriType("http://auth/path/file.json#frag/stuff");
349
+ ref = UriType("newfile.json#newfrag/newstuff");
350
+ res = ref.Resolve(base);
351
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/path/newfile.json#newfrag/newstuff") == 0);
352
+
353
+ base = UriType("file.json", &allocator);
354
+ ref = UriType("newfile.json", &base.GetAllocator());
355
+ res = ref.Resolve(base, &ref.GetAllocator());
356
+ EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0);
357
+
358
+ base = UriType("file.json", &allocator);
359
+ ref = UriType("./newfile.json", &allocator);
360
+ res = ref.Resolve(base, &allocator);
361
+ EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0);
362
+
363
+ base = UriType("file.json");
364
+ ref = UriType("parent/../newfile.json");
365
+ res = ref.Resolve(base);
366
+ EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0);
367
+
368
+ base = UriType("file.json");
369
+ ref = UriType("parent/./newfile.json");
370
+ res = ref.Resolve(base);
371
+ EXPECT_TRUE(StrCmp(res.GetString(), "parent/newfile.json") == 0);
372
+
373
+ base = UriType("file.json");
374
+ ref = UriType("../../parent/.././newfile.json");
375
+ res = ref.Resolve(base);
376
+ EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0);
377
+
378
+ // This adds a joining slash so resolved length is base length + ref length + 1
379
+ base = UriType("http://auth");
380
+ ref = UriType("newfile.json");
381
+ res = ref.Resolve(base);
382
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/newfile.json") == 0);
383
+
384
+ // ref is fragment
385
+ base = UriType("#frag/stuff");
386
+ ref = UriType("#newfrag/newstuff");
387
+ res = ref.Resolve(base);
388
+ EXPECT_TRUE(StrCmp(res.GetString(), "#newfrag/newstuff") == 0);
389
+
390
+ // test ref fragment always wins
391
+ base = UriType("/path#frag");
392
+ ref = UriType("");
393
+ res = ref.Resolve(base);
394
+ EXPECT_TRUE(StrCmp(res.GetString(), "/path") == 0);
395
+
396
+ // Examples from RFC3896
397
+ base = UriType("http://a/b/c/d;p?q");
398
+ ref = UriType("g:h");
399
+ res = ref.Resolve(base);
400
+ EXPECT_TRUE(StrCmp(res.GetString(), "g:h") == 0);
401
+ ref = UriType("g");
402
+ res = ref.Resolve(base);
403
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g") == 0);
404
+ ref = UriType("./g");
405
+ res = ref.Resolve(base);
406
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g") == 0);
407
+ ref = UriType("g/");
408
+ res = ref.Resolve(base);
409
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g/") == 0);
410
+ ref = UriType("/g");
411
+ res = ref.Resolve(base);
412
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0);
413
+ ref = UriType("//g");
414
+ res = ref.Resolve(base);
415
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://g") == 0);
416
+ ref = UriType("?y");
417
+ res = ref.Resolve(base);
418
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/d;p?y") == 0);
419
+ ref = UriType("g?y");
420
+ res = ref.Resolve(base);
421
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g?y") == 0);
422
+ ref = UriType("#s");
423
+ res = ref.Resolve(base);
424
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/d;p?q#s") == 0);
425
+ ref = UriType("g#s");
426
+ res = ref.Resolve(base);
427
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g#s") == 0);
428
+ ref = UriType("g?y#s");
429
+ res = ref.Resolve(base);
430
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g?y#s") == 0);
431
+ ref = UriType(";x");
432
+ res = ref.Resolve(base);
433
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/;x") == 0);
434
+ ref = UriType("g;x");
435
+ res = ref.Resolve(base);
436
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g;x") == 0);
437
+ ref = UriType("g;x?y#s");
438
+ res = ref.Resolve(base);
439
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g;x?y#s") == 0);
440
+ ref = UriType("");
441
+ res = ref.Resolve(base);
442
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/d;p?q") == 0);
443
+ ref = UriType(".");
444
+ res = ref.Resolve(base);
445
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/") == 0);
446
+ ref = UriType("./");
447
+ res = ref.Resolve(base);
448
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/") == 0);
449
+ ref = UriType("..");
450
+ res = ref.Resolve(base);
451
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/") == 0);
452
+ ref = UriType("../");
453
+ res = ref.Resolve(base);
454
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/") == 0);
455
+ ref = UriType("../g");
456
+ res = ref.Resolve(base);
457
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/g") == 0);
458
+ ref = UriType("../..");
459
+ res = ref.Resolve(base);
460
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/") == 0);
461
+ ref = UriType("../../");
462
+ res = ref.Resolve(base);
463
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/") == 0);
464
+ ref = UriType("../../g");
465
+ res = ref.Resolve(base);
466
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0);
467
+ ref = UriType("../../../g");
468
+ res = ref.Resolve(base);
469
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0);
470
+ ref = UriType("../../../../g");
471
+ res = ref.Resolve(base);
472
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0);
473
+ ref = UriType("/./g");
474
+ res = ref.Resolve(base);
475
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0);
476
+ ref = UriType("/../g");
477
+ res = ref.Resolve(base);
478
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0);
479
+ ref = UriType("g.");
480
+ res = ref.Resolve(base);
481
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g.") == 0);
482
+ ref = UriType(".g");
483
+ res = ref.Resolve(base);
484
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/.g") == 0);
485
+ ref = UriType("g..");
486
+ res = ref.Resolve(base);
487
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g..") == 0);
488
+ ref = UriType("..g");
489
+ res = ref.Resolve(base);
490
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/..g") == 0);
491
+ ref = UriType("g#s/../x");
492
+ res = ref.Resolve(base);
493
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g#s/../x") == 0);
494
+ }
495
+
496
+ TEST(Uri, Resolve_UTF16) {
497
+ typedef GenericValue<UTF16<> > Value16;
498
+ typedef GenericUri<Value16> UriType;
499
+ CrtAllocator allocator;
500
+
501
+ // ref is full uri
502
+ UriType base = UriType(L"http://auth/path/#frag");
503
+ UriType ref = UriType(L"http://newauth/newpath#newfrag");
504
+ UriType res = ref.Resolve(base);
505
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://newauth/newpath#newfrag") == 0);
506
+
507
+ base = UriType(L"/path/#frag");
508
+ ref = UriType(L"http://newauth/newpath#newfrag");
509
+ res = ref.Resolve(base);
510
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://newauth/newpath#newfrag") == 0);
511
+
512
+ // ref is alternate uri
513
+ base = UriType(L"http://auth/path/#frag");
514
+ ref = UriType(L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f");
515
+ res = ref.Resolve(base);
516
+ EXPECT_TRUE(StrCmp(res.GetString(), L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0);
517
+
518
+ // ref is absolute path
519
+ base = UriType(L"http://auth/path/#");
520
+ ref = UriType(L"/newpath#newfrag");
521
+ res = ref.Resolve(base);
522
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/newpath#newfrag") == 0);
523
+
524
+ // ref is relative path
525
+ base = UriType(L"http://auth/path/file.json#frag");
526
+ ref = UriType(L"newfile.json#");
527
+ res = ref.Resolve(base);
528
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/path/newfile.json#") == 0);
529
+
530
+ base = UriType(L"http://auth/path/file.json#frag/stuff");
531
+ ref = UriType(L"newfile.json#newfrag/newstuff");
532
+ res = ref.Resolve(base);
533
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/path/newfile.json#newfrag/newstuff") == 0);
534
+
535
+ base = UriType(L"file.json", &allocator);
536
+ ref = UriType(L"newfile.json", &base.GetAllocator());
537
+ res = ref.Resolve(base, &ref.GetAllocator());
538
+ EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0);
539
+
540
+ base = UriType(L"file.json", &allocator);
541
+ ref = UriType(L"./newfile.json", &allocator);
542
+ res = ref.Resolve(base, &allocator);
543
+ EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0);
544
+
545
+ base = UriType(L"file.json");
546
+ ref = UriType(L"parent/../newfile.json");
547
+ res = ref.Resolve(base);
548
+ EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0);
549
+
550
+ base = UriType(L"file.json");
551
+ ref = UriType(L"parent/./newfile.json");
552
+ res = ref.Resolve(base);
553
+ EXPECT_TRUE(StrCmp(res.GetString(), L"parent/newfile.json") == 0);
554
+
555
+ base = UriType(L"file.json");
556
+ ref = UriType(L"../../parent/.././newfile.json");
557
+ res = ref.Resolve(base);
558
+ EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0);
559
+
560
+ // This adds a joining slash so resolved length is base length + ref length + 1
561
+ base = UriType(L"http://auth");
562
+ ref = UriType(L"newfile.json");
563
+ res = ref.Resolve(base);
564
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/newfile.json") == 0);
565
+
566
+ // ref is fragment
567
+ base = UriType(L"#frag/stuff");
568
+ ref = UriType(L"#newfrag/newstuff");
569
+ res = ref.Resolve(base);
570
+ EXPECT_TRUE(StrCmp(res.GetString(), L"#newfrag/newstuff") == 0);
571
+
572
+ // test ref fragment always wins
573
+ base = UriType(L"/path#frag");
574
+ ref = UriType(L"");
575
+ res = ref.Resolve(base);
576
+ EXPECT_TRUE(StrCmp(res.GetString(), L"/path") == 0);
577
+
578
+ // Examples from RFC3896
579
+ base = UriType(L"http://a/b/c/d;p?q");
580
+ ref = UriType(L"g:h");
581
+ res = ref.Resolve(base);
582
+ EXPECT_TRUE(StrCmp(res.GetString(), L"g:h") == 0);
583
+ ref = UriType(L"g");
584
+ res = ref.Resolve(base);
585
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g") == 0);
586
+ ref = UriType(L"./g");
587
+ res = ref.Resolve(base);
588
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g") == 0);
589
+ ref = UriType(L"g/");
590
+ res = ref.Resolve(base);
591
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g/") == 0);
592
+ ref = UriType(L"/g");
593
+ res = ref.Resolve(base);
594
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0);
595
+ ref = UriType(L"//g");
596
+ res = ref.Resolve(base);
597
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://g") == 0);
598
+ ref = UriType(L"?y");
599
+ res = ref.Resolve(base);
600
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/d;p?y") == 0);
601
+ ref = UriType(L"g?y");
602
+ res = ref.Resolve(base);
603
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g?y") == 0);
604
+ ref = UriType(L"#s");
605
+ res = ref.Resolve(base);
606
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/d;p?q#s") == 0);
607
+ ref = UriType(L"g#s");
608
+ res = ref.Resolve(base);
609
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g#s") == 0);
610
+ ref = UriType(L"g?y#s");
611
+ res = ref.Resolve(base);
612
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g?y#s") == 0);
613
+ ref = UriType(L";x");
614
+ res = ref.Resolve(base);
615
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/;x") == 0);
616
+ ref = UriType(L"g;x");
617
+ res = ref.Resolve(base);
618
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g;x") == 0);
619
+ ref = UriType(L"g;x?y#s");
620
+ res = ref.Resolve(base);
621
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g;x?y#s") == 0);
622
+ ref = UriType(L"");
623
+ res = ref.Resolve(base);
624
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/d;p?q") == 0);
625
+ ref = UriType(L".");
626
+ res = ref.Resolve(base);
627
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/") == 0);
628
+ ref = UriType(L"./");
629
+ res = ref.Resolve(base);
630
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/") == 0);
631
+ ref = UriType(L"..");
632
+ res = ref.Resolve(base);
633
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/") == 0);
634
+ ref = UriType(L"../");
635
+ res = ref.Resolve(base);
636
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/") == 0);
637
+ ref = UriType(L"../g");
638
+ res = ref.Resolve(base);
639
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/g") == 0);
640
+ ref = UriType(L"../..");
641
+ res = ref.Resolve(base);
642
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/") == 0);
643
+ ref = UriType(L"../../");
644
+ res = ref.Resolve(base);
645
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/") == 0);
646
+ ref = UriType(L"../../g");
647
+ res = ref.Resolve(base);
648
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0);
649
+ ref = UriType(L"../../../g");
650
+ res = ref.Resolve(base);
651
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0);
652
+ ref = UriType(L"../../../../g");
653
+ res = ref.Resolve(base);
654
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0);
655
+ ref = UriType(L"/./g");
656
+ res = ref.Resolve(base);
657
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0);
658
+ ref = UriType(L"/../g");
659
+ res = ref.Resolve(base);
660
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0);
661
+ ref = UriType(L"g.");
662
+ res = ref.Resolve(base);
663
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g.") == 0);
664
+ ref = UriType(L".g");
665
+ res = ref.Resolve(base);
666
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/.g") == 0);
667
+ ref = UriType(L"g..");
668
+ res = ref.Resolve(base);
669
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g..") == 0);
670
+ ref = UriType(L"..g");
671
+ res = ref.Resolve(base);
672
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/..g") == 0);
673
+ ref = UriType(L"g#s/../x");
674
+ res = ref.Resolve(base);
675
+ EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g#s/../x") == 0);
676
+ }
677
+
678
+ TEST(Uri, Equals) {
679
+ typedef GenericUri<Value> UriType;
680
+
681
+ UriType a = UriType("http://a/a#a");
682
+ UriType b = UriType("http://a/a#b");
683
+ UriType c = a;
684
+
685
+ EXPECT_TRUE(a == a);
686
+ EXPECT_TRUE(a == c);
687
+ EXPECT_TRUE(a != b);
688
+ }
689
+
690
+ TEST(Uri, Match) {
691
+ typedef GenericUri<Value> UriType;
692
+
693
+ UriType a = UriType("http://a/a#a");
694
+ UriType b = UriType("http://a/a#b");
695
+ UriType c = a;
696
+ UriType d;
697
+
698
+ EXPECT_TRUE(a.Match(a));
699
+ EXPECT_TRUE(a.Match(c));
700
+ EXPECT_FALSE(a.Match(b));
701
+ EXPECT_FALSE(a.Match(b, true));
702
+ EXPECT_TRUE(a.Match(b, false)); // Base Uri same
703
+ EXPECT_FALSE(a.Match(d));
704
+ EXPECT_FALSE(d.Match(a));
705
+ }
706
+
707
+ TEST(Uri, Issue1899) {
708
+ typedef GenericUri<Value, MemoryPoolAllocator<> > UriType;
709
+
710
+ UriType base = UriType("http://auth/path/#frag");
711
+ UriType ref = UriType("http://newauth/newpath#newfrag");
712
+ UriType res = ref.Resolve(base);
713
+ EXPECT_TRUE(StrCmp(res.GetString(), "http://newauth/newpath#newfrag") == 0);
714
+ }
715
+
716
+ #if defined(_MSC_VER) || defined(__clang__)
717
+ RAPIDJSON_DIAG_POP
718
+ #endif