ValueBaseJsonParserTest.cc 8.5 KB

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