pointertest.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. // Copyright (C) 2011 Milo Yip
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. #include "unittest.h"
  21. #include "rapidjson/pointer.h"
  22. #include "rapidjson/stringbuffer.h"
  23. #include <sstream>
  24. using namespace rapidjson;
  25. static const char kJson[] = "{\n"
  26. " \"foo\":[\"bar\", \"baz\"],\n"
  27. " \"\" : 0,\n"
  28. " \"a/b\" : 1,\n"
  29. " \"c%d\" : 2,\n"
  30. " \"e^f\" : 3,\n"
  31. " \"g|h\" : 4,\n"
  32. " \"i\\\\j\" : 5,\n"
  33. " \"k\\\"l\" : 6,\n"
  34. " \" \" : 7,\n"
  35. " \"m~n\" : 8\n"
  36. "}";
  37. TEST(Pointer, Parse) {
  38. {
  39. Pointer p("");
  40. EXPECT_TRUE(p.IsValid());
  41. EXPECT_EQ(0u, p.GetTokenCount());
  42. }
  43. {
  44. Pointer p("/foo");
  45. EXPECT_TRUE(p.IsValid());
  46. EXPECT_EQ(1u, p.GetTokenCount());
  47. EXPECT_EQ(3u, p.GetTokens()[0].length);
  48. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  49. }
  50. {
  51. Pointer p("/foo/0");
  52. EXPECT_TRUE(p.IsValid());
  53. EXPECT_EQ(2u, p.GetTokenCount());
  54. EXPECT_EQ(3u, p.GetTokens()[0].length);
  55. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  56. EXPECT_EQ(1u, p.GetTokens()[1].length);
  57. EXPECT_STREQ("0", p.GetTokens()[1].name);
  58. EXPECT_EQ(0u, p.GetTokens()[1].index);
  59. }
  60. {
  61. // Unescape ~1
  62. Pointer p("/a~1b");
  63. EXPECT_TRUE(p.IsValid());
  64. EXPECT_EQ(1u, p.GetTokenCount());
  65. EXPECT_EQ(3u, p.GetTokens()[0].length);
  66. EXPECT_STREQ("a/b", p.GetTokens()[0].name);
  67. }
  68. {
  69. // Unescape ~0
  70. Pointer p("/m~0n");
  71. EXPECT_TRUE(p.IsValid());
  72. EXPECT_EQ(1u, p.GetTokenCount());
  73. EXPECT_EQ(3u, p.GetTokens()[0].length);
  74. EXPECT_STREQ("m~n", p.GetTokens()[0].name);
  75. }
  76. {
  77. // empty name
  78. Pointer p("/");
  79. EXPECT_TRUE(p.IsValid());
  80. EXPECT_EQ(1u, p.GetTokenCount());
  81. EXPECT_EQ(0u, p.GetTokens()[0].length);
  82. EXPECT_STREQ("", p.GetTokens()[0].name);
  83. }
  84. {
  85. // empty and non-empty name
  86. Pointer p("//a");
  87. EXPECT_TRUE(p.IsValid());
  88. EXPECT_EQ(2u, p.GetTokenCount());
  89. EXPECT_EQ(0u, p.GetTokens()[0].length);
  90. EXPECT_STREQ("", p.GetTokens()[0].name);
  91. EXPECT_EQ(1u, p.GetTokens()[1].length);
  92. EXPECT_STREQ("a", p.GetTokens()[1].name);
  93. }
  94. {
  95. // Null characters
  96. Pointer p("/\0\0", 3);
  97. EXPECT_TRUE(p.IsValid());
  98. EXPECT_EQ(1u, p.GetTokenCount());
  99. EXPECT_EQ(2u, p.GetTokens()[0].length);
  100. EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
  101. EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
  102. EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
  103. }
  104. {
  105. // Valid index
  106. Pointer p("/123");
  107. EXPECT_TRUE(p.IsValid());
  108. EXPECT_EQ(1u, p.GetTokenCount());
  109. EXPECT_STREQ("123", p.GetTokens()[0].name);
  110. EXPECT_EQ(123u, p.GetTokens()[0].index);
  111. }
  112. {
  113. // Invalid index (with leading zero)
  114. Pointer p("/01");
  115. EXPECT_TRUE(p.IsValid());
  116. EXPECT_EQ(1u, p.GetTokenCount());
  117. EXPECT_STREQ("01", p.GetTokens()[0].name);
  118. EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
  119. }
  120. if (sizeof(SizeType) == 4) {
  121. // Invalid index (overflow)
  122. Pointer p("/4294967296");
  123. EXPECT_TRUE(p.IsValid());
  124. EXPECT_EQ(1u, p.GetTokenCount());
  125. EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
  126. EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
  127. }
  128. {
  129. // kPointerParseErrorTokenMustBeginWithSolidus
  130. Pointer p(" ");
  131. EXPECT_FALSE(p.IsValid());
  132. EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode());
  133. EXPECT_EQ(0u, p.GetParseErrorOffset());
  134. }
  135. {
  136. // kPointerParseErrorInvalidEscape
  137. Pointer p("/~");
  138. EXPECT_FALSE(p.IsValid());
  139. EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
  140. EXPECT_EQ(2u, p.GetParseErrorOffset());
  141. }
  142. {
  143. // kPointerParseErrorInvalidEscape
  144. Pointer p("/~2");
  145. EXPECT_FALSE(p.IsValid());
  146. EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
  147. EXPECT_EQ(2u, p.GetParseErrorOffset());
  148. }
  149. }
  150. TEST(Pointer, Stringify) {
  151. // Test by roundtrip
  152. const char* sources[] = {
  153. "",
  154. "/foo",
  155. "/foo/0",
  156. "/",
  157. "/a~1b",
  158. "/c%d",
  159. "/e^f",
  160. "/g|h",
  161. "/i\\j",
  162. "/k\"l",
  163. "/ ",
  164. "/m~0n"
  165. };
  166. for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
  167. Pointer p(sources[i]);
  168. StringBuffer s;
  169. p.Stringify(s);
  170. EXPECT_STREQ(sources[i], s.GetString());
  171. }
  172. }
  173. // Construct a Pointer with static tokens, no dynamic allocation involved.
  174. #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
  175. #define INDEX(i) { #i, sizeof(#i) - 1, i }
  176. static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
  177. #undef NAME
  178. #undef INDEX
  179. TEST(Pointer, ConstructorWithToken) {
  180. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  181. EXPECT_TRUE(p.IsValid());
  182. EXPECT_EQ(2u, p.GetTokenCount());
  183. EXPECT_EQ(3u, p.GetTokens()[0].length);
  184. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  185. EXPECT_EQ(1u, p.GetTokens()[1].length);
  186. EXPECT_STREQ("0", p.GetTokens()[1].name);
  187. EXPECT_EQ(0u, p.GetTokens()[1].index);
  188. }
  189. TEST(Pointer, CopyConstructor) {
  190. {
  191. Pointer p("/foo/0");
  192. Pointer q(p);
  193. EXPECT_TRUE(q.IsValid());
  194. EXPECT_EQ(2u, q.GetTokenCount());
  195. EXPECT_EQ(3u, q.GetTokens()[0].length);
  196. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  197. EXPECT_EQ(1u, q.GetTokens()[1].length);
  198. EXPECT_STREQ("0", q.GetTokens()[1].name);
  199. EXPECT_EQ(0u, q.GetTokens()[1].index);
  200. }
  201. // Static tokens
  202. {
  203. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  204. Pointer q(p);
  205. EXPECT_TRUE(q.IsValid());
  206. EXPECT_EQ(2u, q.GetTokenCount());
  207. EXPECT_EQ(3u, q.GetTokens()[0].length);
  208. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  209. EXPECT_EQ(1u, q.GetTokens()[1].length);
  210. EXPECT_STREQ("0", q.GetTokens()[1].name);
  211. EXPECT_EQ(0u, q.GetTokens()[1].index);
  212. }
  213. }
  214. TEST(Pointer, Assignment) {
  215. {
  216. Pointer p("/foo/0");
  217. Pointer q;
  218. q = p;
  219. EXPECT_TRUE(q.IsValid());
  220. EXPECT_EQ(2u, q.GetTokenCount());
  221. EXPECT_EQ(3u, q.GetTokens()[0].length);
  222. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  223. EXPECT_EQ(1u, q.GetTokens()[1].length);
  224. EXPECT_STREQ("0", q.GetTokens()[1].name);
  225. EXPECT_EQ(0u, q.GetTokens()[1].index);
  226. }
  227. // Static tokens
  228. {
  229. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  230. Pointer q;
  231. q = p;
  232. EXPECT_TRUE(q.IsValid());
  233. EXPECT_EQ(2u, q.GetTokenCount());
  234. EXPECT_EQ(3u, q.GetTokens()[0].length);
  235. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  236. EXPECT_EQ(1u, q.GetTokens()[1].length);
  237. EXPECT_STREQ("0", q.GetTokens()[1].name);
  238. EXPECT_EQ(0u, q.GetTokens()[1].index);
  239. }
  240. }
  241. TEST(Pointer, Create) {
  242. Document d;
  243. {
  244. Value* v = &Pointer("").Create(d, d.GetAllocator());
  245. EXPECT_EQ(&d, v);
  246. }
  247. {
  248. Value* v = &Pointer("/foo").Create(d, d.GetAllocator());
  249. EXPECT_EQ(&d["foo"], v);
  250. }
  251. {
  252. Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator());
  253. EXPECT_EQ(&d["foo"][0], v);
  254. }
  255. }
  256. TEST(Pointer, Get) {
  257. Document d;
  258. d.Parse(kJson);
  259. EXPECT_EQ(&d, Pointer("").Get(d));
  260. EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
  261. EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
  262. EXPECT_EQ(&d[""], Pointer("/").Get(d));
  263. EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
  264. EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
  265. EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
  266. EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
  267. EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
  268. EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
  269. EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
  270. EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
  271. EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
  272. }
  273. TEST(Pointer, GetWithDefault) {
  274. Document d;
  275. d.Parse(kJson);
  276. Document::AllocatorType& a = d.GetAllocator();
  277. const Value v("qux");
  278. EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
  279. EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
  280. EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
  281. }
  282. TEST(Pointer, Set) {
  283. Document d;
  284. d.Parse(kJson);
  285. Document::AllocatorType& a = d.GetAllocator();
  286. // Value version
  287. Pointer("/foo/0").Set(d, Value(123).Move(), a);
  288. EXPECT_EQ(123, d["foo"][0].GetInt());
  289. Pointer("/foo/null").Set(d, Value().Move(), a);
  290. EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
  291. // Generic version
  292. Pointer("/foo/int").Set(d, -1, a);
  293. EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
  294. Pointer("/foo/uint").Set(d, 0x87654321, a);
  295. EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
  296. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  297. Pointer("/foo/int64").Set(d, i64, a);
  298. EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
  299. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  300. Pointer("/foo/uint64").Set(d, u64, a);
  301. EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
  302. Pointer("/foo/true").Set(d, true, a);
  303. EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
  304. Pointer("/foo/false").Set(d, false, a);
  305. EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
  306. // StringRef version
  307. Pointer("/foo/hello").Set(d, "Hello", a);
  308. EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
  309. // Copy string version
  310. {
  311. char buffer[256];
  312. strcpy(buffer, "World");
  313. Pointer("/foo/world").Set(d, buffer, a);
  314. memset(buffer, 0, sizeof(buffer));
  315. }
  316. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  317. }
  318. TEST(Pointer, Swap) {
  319. Document d;
  320. d.Parse(kJson);
  321. Document::AllocatorType& a = d.GetAllocator();
  322. Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
  323. EXPECT_STREQ("baz", d["foo"][0].GetString());
  324. EXPECT_STREQ("bar", d["foo"][1].GetString());
  325. }
  326. TEST(Pointer, CreateValueByPointer) {
  327. Document d;
  328. Document::AllocatorType& a = d.GetAllocator();
  329. {
  330. Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a);
  331. EXPECT_EQ(&d["foo"][0], &v);
  332. }
  333. {
  334. Value& v = CreateValueByPointer(d, "/foo/1", a);
  335. EXPECT_EQ(&d["foo"][1], &v);
  336. }
  337. }
  338. TEST(Pointer, GetValueByPointer) {
  339. Document d;
  340. d.Parse(kJson);
  341. EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
  342. EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
  343. // const version
  344. const Value& v = d;
  345. EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
  346. EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
  347. }
  348. TEST(Pointer, GetValueByPointerWithDefault) {
  349. Document d;
  350. d.Parse(kJson);
  351. Document::AllocatorType& a = d.GetAllocator();
  352. const Value v("qux");
  353. EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
  354. EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a));
  355. }
  356. TEST(Pointer, SetValueByPointer_Pointer) {
  357. Document d;
  358. d.Parse(kJson);
  359. Document::AllocatorType& a = d.GetAllocator();
  360. // Value version
  361. SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a);
  362. EXPECT_EQ(123, d["foo"][0].GetInt());
  363. SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a);
  364. EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
  365. // Generic version
  366. SetValueByPointer(d, Pointer("/foo/int"), -1, a);
  367. EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
  368. SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a);
  369. EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
  370. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  371. SetValueByPointer(d, Pointer("/foo/int64"), i64, a);
  372. EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
  373. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  374. SetValueByPointer(d, Pointer("/foo/uint64"), u64, a);
  375. EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
  376. SetValueByPointer(d, Pointer("/foo/true"), true, a);
  377. EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
  378. SetValueByPointer(d, Pointer("/foo/false"), false, a);
  379. EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
  380. // StringRef version
  381. SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a);
  382. EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
  383. // Copy string version
  384. {
  385. char buffer[256];
  386. strcpy(buffer, "World");
  387. SetValueByPointer(d, Pointer("/foo/world"), buffer, a);
  388. memset(buffer, 0, sizeof(buffer));
  389. }
  390. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  391. }
  392. TEST(Pointer, SetValueByPointer_String) {
  393. Document d;
  394. d.Parse(kJson);
  395. Document::AllocatorType& a = d.GetAllocator();
  396. // Value version
  397. SetValueByPointer(d, "/foo/0", Value(123).Move(), a);
  398. EXPECT_EQ(123, d["foo"][0].GetInt());
  399. SetValueByPointer(d, "/foo/null", Value().Move(), a);
  400. EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
  401. // Generic version
  402. SetValueByPointer(d, "/foo/int", -1, a);
  403. EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
  404. SetValueByPointer(d, "/foo/uint", 0x87654321, a);
  405. EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
  406. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  407. SetValueByPointer(d, "/foo/int64", i64, a);
  408. EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
  409. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  410. SetValueByPointer(d, "/foo/uint64", u64, a);
  411. EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
  412. SetValueByPointer(d, "/foo/true", true, a);
  413. EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
  414. SetValueByPointer(d, "/foo/false", false, a);
  415. EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
  416. // StringRef version
  417. SetValueByPointer(d, "/foo/hello", "Hello", a);
  418. EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
  419. // Copy string version
  420. {
  421. char buffer[256];
  422. strcpy(buffer, "World");
  423. SetValueByPointer(d, "/foo/world", buffer, a);
  424. memset(buffer, 0, sizeof(buffer));
  425. }
  426. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  427. }
  428. TEST(Pointer, SwapValueByPointer) {
  429. Document d;
  430. d.Parse(kJson);
  431. Document::AllocatorType& a = d.GetAllocator();
  432. SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a);
  433. EXPECT_STREQ("baz", d["foo"][0].GetString());
  434. EXPECT_STREQ("bar", d["foo"][1].GetString());
  435. SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a);
  436. EXPECT_STREQ("bar", d["foo"][0].GetString());
  437. EXPECT_STREQ("baz", d["foo"][1].GetString());
  438. }