pointertest.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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(0, p.GetTokenCount());
  42. }
  43. {
  44. Pointer p("/foo");
  45. EXPECT_TRUE(p.IsValid());
  46. EXPECT_EQ(1, p.GetTokenCount());
  47. EXPECT_EQ(3, 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(2, p.GetTokenCount());
  54. EXPECT_EQ(3, p.GetTokens()[0].length);
  55. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  56. EXPECT_EQ(1, p.GetTokens()[1].length);
  57. EXPECT_STREQ("0", p.GetTokens()[1].name);
  58. EXPECT_EQ(0, p.GetTokens()[1].index);
  59. }
  60. {
  61. // Unescape ~1
  62. Pointer p("/a~1b");
  63. EXPECT_TRUE(p.IsValid());
  64. EXPECT_EQ(1, p.GetTokenCount());
  65. EXPECT_EQ(3, 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(1, p.GetTokenCount());
  73. EXPECT_EQ(3, 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(1, p.GetTokenCount());
  81. EXPECT_EQ(0, 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(2, p.GetTokenCount());
  89. EXPECT_EQ(0, p.GetTokens()[0].length);
  90. EXPECT_STREQ("", p.GetTokens()[0].name);
  91. EXPECT_EQ(1, 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(1, p.GetTokenCount());
  99. EXPECT_EQ(2, 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(1, p.GetTokenCount());
  109. EXPECT_STREQ("123", p.GetTokens()[0].name);
  110. EXPECT_EQ(123, p.GetTokens()[0].index);
  111. }
  112. {
  113. // Invalid index (with leading zero)
  114. Pointer p("/01");
  115. EXPECT_TRUE(p.IsValid());
  116. EXPECT_EQ(1, p.GetTokenCount());
  117. EXPECT_STREQ("01", p.GetTokens()[0].name);
  118. EXPECT_EQ(Pointer::kInvalidIndex, 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(1, p.GetTokenCount());
  125. EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
  126. EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index);
  127. }
  128. }
  129. TEST(Pointer, Stringify) {
  130. // Test by roundtrip
  131. const char* sources[] = {
  132. "",
  133. "/foo",
  134. "/foo/0",
  135. "/",
  136. "/a~1b",
  137. "/c%d",
  138. "/e^f",
  139. "/g|h",
  140. "/i\\j",
  141. "/k\"l",
  142. "/ ",
  143. "/m~0n"
  144. };
  145. for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
  146. Pointer p(sources[i]);
  147. StringBuffer s;
  148. p.Stringify(s);
  149. EXPECT_STREQ(sources[i], s.GetString());
  150. }
  151. }
  152. // Construct a Pointer with static tokens, no dynamic allocation involved.
  153. #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, Pointer::kInvalidIndex }
  154. #define INDEX(i) { #i, sizeof(#i) - 1, i }
  155. static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
  156. #undef NAME
  157. #undef INDEX
  158. TEST(Pointer, ConstructorWithToken) {
  159. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  160. EXPECT_TRUE(p.IsValid());
  161. EXPECT_EQ(2, p.GetTokenCount());
  162. EXPECT_EQ(3, p.GetTokens()[0].length);
  163. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  164. EXPECT_EQ(1, p.GetTokens()[1].length);
  165. EXPECT_STREQ("0", p.GetTokens()[1].name);
  166. EXPECT_EQ(0, p.GetTokens()[1].index);
  167. }
  168. TEST(Pointer, CopyConstructor) {
  169. {
  170. Pointer p("/foo/0");
  171. Pointer q(p);
  172. EXPECT_TRUE(q.IsValid());
  173. EXPECT_EQ(2, q.GetTokenCount());
  174. EXPECT_EQ(3, q.GetTokens()[0].length);
  175. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  176. EXPECT_EQ(1, q.GetTokens()[1].length);
  177. EXPECT_STREQ("0", q.GetTokens()[1].name);
  178. EXPECT_EQ(0, q.GetTokens()[1].index);
  179. }
  180. // Static tokens
  181. {
  182. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  183. Pointer q(p);
  184. EXPECT_TRUE(q.IsValid());
  185. EXPECT_EQ(2, q.GetTokenCount());
  186. EXPECT_EQ(3, q.GetTokens()[0].length);
  187. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  188. EXPECT_EQ(1, q.GetTokens()[1].length);
  189. EXPECT_STREQ("0", q.GetTokens()[1].name);
  190. EXPECT_EQ(0, q.GetTokens()[1].index);
  191. }
  192. }
  193. TEST(Pointer, Assignment) {
  194. {
  195. Pointer p("/foo/0");
  196. Pointer q;
  197. q = p;
  198. EXPECT_TRUE(q.IsValid());
  199. EXPECT_EQ(2, q.GetTokenCount());
  200. EXPECT_EQ(3, q.GetTokens()[0].length);
  201. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  202. EXPECT_EQ(1, q.GetTokens()[1].length);
  203. EXPECT_STREQ("0", q.GetTokens()[1].name);
  204. EXPECT_EQ(0, q.GetTokens()[1].index);
  205. }
  206. // Static tokens
  207. {
  208. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  209. Pointer q;
  210. q = p;
  211. EXPECT_TRUE(q.IsValid());
  212. EXPECT_EQ(2, q.GetTokenCount());
  213. EXPECT_EQ(3, q.GetTokens()[0].length);
  214. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  215. EXPECT_EQ(1, q.GetTokens()[1].length);
  216. EXPECT_STREQ("0", q.GetTokens()[1].name);
  217. EXPECT_EQ(0, q.GetTokens()[1].index);
  218. }
  219. }
  220. TEST(Pointer, Create) {
  221. Document d;
  222. EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator()));
  223. EXPECT_EQ(&d["foo"], &Pointer("/foo").Create(d, d.GetAllocator()));
  224. EXPECT_EQ(&d["foo"][0], &Pointer("/foo/0").Create(d, d.GetAllocator()));
  225. }
  226. TEST(Pointer, Get) {
  227. Document d;
  228. d.Parse(kJson);
  229. EXPECT_EQ(&d, Pointer("").Get(d));
  230. EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
  231. EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
  232. EXPECT_EQ(&d[""], Pointer("/").Get(d));
  233. EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
  234. EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
  235. EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
  236. EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
  237. EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
  238. EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
  239. EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
  240. EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
  241. }
  242. TEST(Pointer, GetWithDefault) {
  243. Document d;
  244. d.Parse(kJson);
  245. Document::AllocatorType& a = d.GetAllocator();
  246. const Value v("qux");
  247. EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
  248. EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
  249. EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
  250. }
  251. TEST(Pointer, Set) {
  252. Document d;
  253. d.Parse(kJson);
  254. Document::AllocatorType& a = d.GetAllocator();
  255. Pointer("/foo/0").Set(d, Value(123).Move(), a);
  256. EXPECT_EQ(123, d["foo"][0].GetInt());
  257. Pointer("/foo/2").Set(d, Value(456).Move(), a);
  258. EXPECT_EQ(456, d["foo"][2].GetInt());
  259. }
  260. TEST(Pointer, Swap) {
  261. Document d;
  262. d.Parse(kJson);
  263. Document::AllocatorType& a = d.GetAllocator();
  264. Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
  265. EXPECT_STREQ("baz", d["foo"][0].GetString());
  266. EXPECT_STREQ("bar", d["foo"][1].GetString());
  267. }