ValueBaseJsonParserTest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #include "ValueBaseJsonParser.h"
  2. #include <cppunit/extensions/HelperMacros.h>
  3. #include "RecoverableException.h"
  4. #include "array_fun.h"
  5. #include "ValueBase.h"
  6. namespace aria2 {
  7. class ValueBaseJsonParserTest:public CppUnit::TestFixture {
  8. CPPUNIT_TEST_SUITE(ValueBaseJsonParserTest);
  9. CPPUNIT_TEST(testParseUpdate);
  10. CPPUNIT_TEST(testParseUpdate_error);
  11. CPPUNIT_TEST_SUITE_END();
  12. private:
  13. public:
  14. void testParseUpdate();
  15. void testParseUpdate_error();
  16. };
  17. CPPUNIT_TEST_SUITE_REGISTRATION( ValueBaseJsonParserTest );
  18. void ValueBaseJsonParserTest::testParseUpdate()
  19. {
  20. json::ValueBaseJsonParser parser;
  21. ssize_t error;
  22. {
  23. // empty object
  24. std::string src = "{}";
  25. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  26. error);
  27. const Dict* dict = downcast<Dict>(r);
  28. CPPUNIT_ASSERT(dict);
  29. }
  30. {
  31. // empty object
  32. std::string src = "{ }";
  33. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  34. error);
  35. const Dict* dict = downcast<Dict>(r);
  36. CPPUNIT_ASSERT(dict);
  37. }
  38. {
  39. // empty array
  40. std::string src = "[]";
  41. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  42. error);
  43. const List* list = downcast<List>(r);
  44. CPPUNIT_ASSERT(list);
  45. }
  46. {
  47. // empty array
  48. std::string src = "[ ]";
  49. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  50. error);
  51. const List* list = downcast<List>(r);
  52. CPPUNIT_ASSERT(list);
  53. }
  54. {
  55. // empty string
  56. std::string src = "[\"\"]";
  57. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  58. error);
  59. const List* list = downcast<List>(r);
  60. CPPUNIT_ASSERT(list);
  61. const String* s = downcast<String>(list->get(0));
  62. CPPUNIT_ASSERT_EQUAL(std::string(), s->s());
  63. }
  64. {
  65. // string
  66. std::string src = "[\"foobar\"]";
  67. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  68. error);
  69. const List* list = downcast<List>(r);
  70. CPPUNIT_ASSERT(list);
  71. const String* s = downcast<String>(list->get(0));
  72. CPPUNIT_ASSERT_EQUAL(std::string("foobar"), s->s());
  73. }
  74. {
  75. // string with escape
  76. std::string src = "[\"\\\\foo\\\"\\\"bar\"]";
  77. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  78. error);
  79. const List* list = downcast<List>(r);
  80. CPPUNIT_ASSERT(list);
  81. const String* s = downcast<String>(list->get(0));
  82. CPPUNIT_ASSERT_EQUAL(std::string("\\foo\"\"bar"), s->s());
  83. }
  84. {
  85. // string with escape
  86. std::string src = "[\"foo\\\"\"]";
  87. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  88. error);
  89. const List* list = downcast<List>(r);
  90. CPPUNIT_ASSERT(list);
  91. const String* s = downcast<String>(list->get(0));
  92. CPPUNIT_ASSERT_EQUAL(std::string("foo\""), s->s());
  93. }
  94. {
  95. // string: utf-8 1 to 3 bytes.
  96. std::string src = "[\"\\u0024\\u00A2\\u20AC\"]";
  97. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  98. error);
  99. const List* list = downcast<List>(r);
  100. CPPUNIT_ASSERT(list);
  101. const String* s = downcast<String>(list->get(0));
  102. CPPUNIT_ASSERT_EQUAL(std::string("$¢€"), s->s());
  103. }
  104. {
  105. // string: utf-8 4 bytes
  106. std::string src = "[\"\\uD852\\uDF62\"]";
  107. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  108. error);
  109. const List* list = downcast<List>(r);
  110. CPPUNIT_ASSERT(list);
  111. const String* s = downcast<String>(list->get(0));
  112. const unsigned char arr[] = { 0xF0u, 0xA4u, 0xADu, 0xA2u };
  113. CPPUNIT_ASSERT_EQUAL(std::string(vbegin(arr), vend(arr)), s->s());
  114. }
  115. {
  116. // null
  117. std::string src = "[null]";
  118. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  119. error);
  120. const List* list = downcast<List>(r);
  121. CPPUNIT_ASSERT(list);
  122. const Null* s = downcast<Null>(list->get(0));
  123. CPPUNIT_ASSERT(s);
  124. }
  125. {
  126. // true, false
  127. std::string src = "[true, false]";
  128. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  129. error);
  130. const List* list = downcast<List>(r);
  131. CPPUNIT_ASSERT(list);
  132. const Bool* trueValue = downcast<Bool>(list->get(0));
  133. CPPUNIT_ASSERT(trueValue);
  134. CPPUNIT_ASSERT(trueValue->val());
  135. const Bool* falseValue = downcast<Bool>(list->get(1));
  136. CPPUNIT_ASSERT(falseValue);
  137. CPPUNIT_ASSERT(!falseValue->val());
  138. }
  139. {
  140. // object: 1 member
  141. std::string src = "{\"foo\":[\"bar\"]}";
  142. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  143. error);
  144. const Dict* dict = downcast<Dict>(r);
  145. CPPUNIT_ASSERT(dict);
  146. const List* list = downcast<List>(dict->get("foo"));
  147. CPPUNIT_ASSERT(list);
  148. const String* s = downcast<String>(list->get(0));
  149. CPPUNIT_ASSERT_EQUAL(std::string("bar"), s->s());
  150. }
  151. {
  152. // object: 2 members
  153. // TODO ValueBaseJsonParser does not allow empty dict key
  154. std::string src = "{\"foo\":[\"bar\"], \"alpha\" : \"bravo\"}";
  155. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  156. error);
  157. const Dict* dict = downcast<Dict>(r);
  158. CPPUNIT_ASSERT(dict);
  159. const List* list = downcast<List>(dict->get("foo"));
  160. CPPUNIT_ASSERT(list);
  161. const String* s = downcast<String>(list->get(0));
  162. CPPUNIT_ASSERT_EQUAL(std::string("bar"), s->s());
  163. const String* str = downcast<String>(dict->get("alpha"));
  164. CPPUNIT_ASSERT_EQUAL(std::string("bravo"), str->s());
  165. }
  166. {
  167. // array: 2 values
  168. std::string src = "[\"foo\", {}]";
  169. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  170. error);
  171. const List* list = downcast<List>(r);
  172. CPPUNIT_ASSERT(list);
  173. const String* s = downcast<String>(list->get(0));
  174. CPPUNIT_ASSERT_EQUAL(std::string("foo"), s->s());
  175. const Dict* dict = downcast<Dict>(list->get(1));
  176. CPPUNIT_ASSERT(dict);
  177. }
  178. {
  179. // Number: currently we ignore frac and exp
  180. std::string src = "[0,-1,1.2,-1.2e-10,-1e10]";
  181. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  182. error);
  183. const List* list = downcast<List>(r);
  184. CPPUNIT_ASSERT(list);
  185. const Integer* i = downcast<Integer>(list->get(0));
  186. CPPUNIT_ASSERT_EQUAL((Integer::ValueType)0, i->i());
  187. const Integer* i1 = downcast<Integer>(list->get(1));
  188. CPPUNIT_ASSERT_EQUAL((Integer::ValueType)-1, i1->i());
  189. const Integer* i2 = downcast<Integer>(list->get(2));
  190. CPPUNIT_ASSERT_EQUAL((Integer::ValueType)1, i2->i());
  191. const Integer* i3 = downcast<Integer>(list->get(3));
  192. CPPUNIT_ASSERT_EQUAL((Integer::ValueType)-1, i3->i());
  193. const Integer* i4 = downcast<Integer>(list->get(4));
  194. CPPUNIT_ASSERT_EQUAL((Integer::ValueType)-1, i4->i());
  195. }
  196. {
  197. // escape chars: ", \, /, \b, \f, \n, \r, \t
  198. std::string src = "[\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"]";
  199. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  200. error);
  201. const List* list = downcast<List>(r);
  202. const String* s = downcast<String>(list->get(0));
  203. CPPUNIT_ASSERT_EQUAL(std::string("\"\\/\b\f\n\r\t"), s->s());
  204. }
  205. {
  206. // string: literal + escaped chars.
  207. std::string src = "[\"foo\\u0024b\\u00A2\\u20ACbaz\"]";
  208. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  209. error);
  210. const List* list = downcast<List>(r);
  211. CPPUNIT_ASSERT(list);
  212. const String* s = downcast<String>(list->get(0));
  213. CPPUNIT_ASSERT_EQUAL(std::string("foo$b¢€baz"), s->s());
  214. }
  215. {
  216. // ignore garbage at the end of the input.
  217. std::string src = "[]trail";
  218. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  219. error);
  220. const List* list = downcast<List>(r);
  221. CPPUNIT_ASSERT(list);
  222. CPPUNIT_ASSERT_EQUAL((ssize_t)2, error);
  223. }
  224. }
  225. namespace {
  226. void checkDecodeError(const std::string& src)
  227. {
  228. json::ValueBaseJsonParser parser;
  229. ssize_t error;
  230. SharedHandle<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  231. error);
  232. CPPUNIT_ASSERT(!r);
  233. CPPUNIT_ASSERT(error < 0);
  234. }
  235. } // namespace
  236. void ValueBaseJsonParserTest::testParseUpdate_error()
  237. {
  238. // object
  239. checkDecodeError("{");
  240. // object
  241. checkDecodeError("}");
  242. // object
  243. checkDecodeError("{\"\":");
  244. // object
  245. checkDecodeError("{\"\":\"\",");
  246. // array
  247. checkDecodeError("[");
  248. // array
  249. checkDecodeError("]");
  250. // array
  251. checkDecodeError("[\"\"");
  252. // array
  253. checkDecodeError("[\"\",");
  254. // string
  255. checkDecodeError("[\"foo]");
  256. // string
  257. checkDecodeError("[\"\\u\"]");
  258. // string
  259. checkDecodeError("[\"\\u");
  260. // string
  261. checkDecodeError("[\"\\u000\"]");
  262. // string
  263. checkDecodeError("[\"\\u000");
  264. // string
  265. checkDecodeError("[\"\\uD852foo\"]");
  266. // string
  267. checkDecodeError("[\"\\uD852");
  268. // string
  269. checkDecodeError("[\"\\uD852\\u\"]");
  270. // string
  271. checkDecodeError("[\"\\uD852\\u");
  272. // string
  273. checkDecodeError("[\"\\uD852\\u0000\"]");
  274. // string
  275. checkDecodeError("[\"\\uD852\\uDF62");
  276. // object
  277. checkDecodeError("{:\"\"}");
  278. // object
  279. checkDecodeError("{\"foo\":}");
  280. // number
  281. // TODO ValueBaseJsonParser allows leading zeros
  282. //checkDecodeError("[00]");
  283. // number
  284. checkDecodeError("[1.]");
  285. // number
  286. checkDecodeError("[1.1e]");
  287. // bool
  288. checkDecodeError("[t");
  289. // too deep structure
  290. checkDecodeError(std::string(51, '[')+std::string(51,']'));
  291. checkDecodeError(std::string(50, '[')+"{\"foo\":100}"+std::string(50,']'));
  292. }
  293. } // namespace aria2