test_json_parser2.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. #include <boost/property_tree/json_parser/detail/parser.hpp>
  2. #include <boost/property_tree/json_parser/detail/narrow_encoding.hpp>
  3. #include <boost/property_tree/json_parser/detail/wide_encoding.hpp>
  4. #include <boost/property_tree/json_parser/detail/standard_callbacks.hpp>
  5. #include "prefixing_callbacks.hpp"
  6. #define BOOST_TEST_NO_MAIN
  7. #include <boost/test/unit_test.hpp>
  8. #include <boost/test/parameterized_test.hpp>
  9. #include <boost/property_tree/ptree.hpp>
  10. #include <boost/range/iterator_range.hpp>
  11. #include <cassert>
  12. #include <sstream>
  13. #include <vector>
  14. using namespace boost::property_tree;
  15. template <typename Ch> struct encoding;
  16. template <> struct encoding<char>
  17. : json_parser::detail::utf8_utf8_encoding
  18. {};
  19. template <> struct encoding<wchar_t>
  20. : json_parser::detail::wide_wide_encoding
  21. {};
  22. template <typename Callbacks, typename Ch>
  23. struct test_parser
  24. {
  25. Callbacks callbacks;
  26. ::encoding<Ch> encoding;
  27. typedef std::basic_string<Ch> string;
  28. typedef basic_ptree<string, string> tree;
  29. json_parser::detail::parser<Callbacks, ::encoding<Ch>,
  30. typename string::const_iterator,
  31. typename string::const_iterator>
  32. parser;
  33. test_parser() : parser(callbacks, encoding) {}
  34. bool parse_null(const string& input, string& output) {
  35. parser.set_input("", input);
  36. bool result = parser.parse_null();
  37. if (result) {
  38. parser.finish();
  39. output = callbacks.output().data();
  40. }
  41. return result;
  42. }
  43. bool parse_boolean(const string& input, string& output) {
  44. parser.set_input("", input);
  45. bool result = parser.parse_boolean();
  46. if (result) {
  47. parser.finish();
  48. output = callbacks.output().data();
  49. }
  50. return result;
  51. }
  52. bool parse_number(const string& input, string& output) {
  53. parser.set_input("", input);
  54. bool result = parser.parse_number();
  55. if (result) {
  56. parser.finish();
  57. output = callbacks.output().data();
  58. }
  59. return result;
  60. }
  61. bool parse_string(const string& input, string& output) {
  62. parser.set_input("", input);
  63. bool result = parser.parse_string();
  64. if (result) {
  65. parser.finish();
  66. output = callbacks.output().data();
  67. }
  68. return result;
  69. }
  70. bool parse_array(const string& input, tree& output) {
  71. parser.set_input("", input);
  72. bool result = parser.parse_array();
  73. if (result) {
  74. parser.finish();
  75. output = callbacks.output();
  76. }
  77. return result;
  78. }
  79. bool parse_object(const string& input, tree& output) {
  80. parser.set_input("", input);
  81. bool result = parser.parse_object();
  82. if (result) {
  83. parser.finish();
  84. output = callbacks.output();
  85. }
  86. return result;
  87. }
  88. void parse_value(const string& input, tree& output) {
  89. parser.set_input("", input);
  90. parser.parse_value();
  91. parser.finish();
  92. output = callbacks.output();
  93. }
  94. };
  95. template <typename Ch>
  96. struct standard_parser
  97. : test_parser<
  98. json_parser::detail::standard_callbacks<
  99. basic_ptree<std::basic_string<Ch>, std::basic_string<Ch> > >,
  100. Ch>
  101. {};
  102. template <typename Ch>
  103. struct prefixing_parser
  104. : test_parser<
  105. prefixing_callbacks<
  106. basic_ptree<std::basic_string<Ch>, std::basic_string<Ch> > >,
  107. Ch>
  108. {};
  109. #define BOM_N "\xef\xbb\xbf"
  110. #define BOM_W L"\xfeff"
  111. namespace boost { namespace test_tools { namespace tt_detail {
  112. template<>
  113. struct print_log_value<std::wstring> {
  114. void operator()(std::ostream& os, const std::wstring& s) {
  115. print_log_value<const wchar_t*>()(os, s.c_str());
  116. }
  117. };
  118. }}}
  119. BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::iterator)
  120. BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::const_iterator)
  121. BOOST_TEST_DONT_PRINT_LOG_VALUE(wptree::iterator)
  122. BOOST_TEST_DONT_PRINT_LOG_VALUE(wptree::const_iterator)
  123. BOOST_AUTO_TEST_CASE(null_parse_result_is_input) {
  124. std::string parsed;
  125. standard_parser<char> p;
  126. BOOST_REQUIRE(p.parse_null("null", parsed));
  127. BOOST_CHECK_EQUAL("null", parsed);
  128. }
  129. BOOST_AUTO_TEST_CASE(uses_traits_from_null)
  130. {
  131. std::string parsed;
  132. prefixing_parser<char> p;
  133. BOOST_REQUIRE(p.parse_null("null", parsed));
  134. BOOST_CHECK_EQUAL("_:null", parsed);
  135. }
  136. BOOST_AUTO_TEST_CASE(null_parse_skips_bom) {
  137. std::string parsed;
  138. standard_parser<char> p;
  139. BOOST_REQUIRE(p.parse_null(BOM_N "null", parsed));
  140. BOOST_CHECK_EQUAL("null", parsed);
  141. }
  142. BOOST_AUTO_TEST_CASE(null_parse_result_is_input_w) {
  143. std::wstring parsed;
  144. standard_parser<wchar_t> p;
  145. BOOST_REQUIRE(p.parse_null(L"null", parsed));
  146. BOOST_CHECK_EQUAL(L"null", parsed);
  147. }
  148. BOOST_AUTO_TEST_CASE(uses_traits_from_null_w)
  149. {
  150. std::wstring parsed;
  151. prefixing_parser<wchar_t> p;
  152. BOOST_REQUIRE(p.parse_null(L"null", parsed));
  153. BOOST_CHECK_EQUAL(L"_:null", parsed);
  154. }
  155. BOOST_AUTO_TEST_CASE(null_parse_skips_bom_w) {
  156. std::wstring parsed;
  157. standard_parser<wchar_t> p;
  158. BOOST_REQUIRE(p.parse_null(BOM_W L"null", parsed));
  159. BOOST_CHECK_EQUAL(L"null", parsed);
  160. }
  161. void boolean_parse_result_is_input_n(const char* param) {
  162. std::string parsed;
  163. standard_parser<char> p;
  164. BOOST_REQUIRE(p.parse_boolean(param, parsed));
  165. BOOST_CHECK_EQUAL(param, parsed);
  166. }
  167. const char* const booleans_n[] = { "true", "false" };
  168. BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_n)
  169. {
  170. std::string parsed;
  171. prefixing_parser<char> p;
  172. BOOST_REQUIRE(p.parse_boolean("true", parsed));
  173. BOOST_CHECK_EQUAL("b:true", parsed);
  174. }
  175. void boolean_parse_result_is_input_w(const wchar_t* param) {
  176. std::wstring parsed;
  177. standard_parser<wchar_t> p;
  178. BOOST_REQUIRE(p.parse_boolean(param, parsed));
  179. BOOST_CHECK_EQUAL(param, parsed);
  180. }
  181. const wchar_t* const booleans_w[] = { L"true", L"false" };
  182. BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_w)
  183. {
  184. std::wstring parsed;
  185. prefixing_parser<wchar_t> p;
  186. BOOST_REQUIRE(p.parse_boolean(L"true", parsed));
  187. BOOST_CHECK_EQUAL(L"b:true", parsed);
  188. }
  189. void number_parse_result_is_input_n(const char* param) {
  190. std::string parsed;
  191. standard_parser<char> p;
  192. BOOST_REQUIRE(p.parse_number(param, parsed));
  193. BOOST_CHECK_EQUAL(param, parsed);
  194. }
  195. const char* const numbers_n[] = {
  196. "0",
  197. "-0",
  198. "1824",
  199. "-0.1",
  200. "123.142",
  201. "1e+0",
  202. "1E-0",
  203. "1.1e134"
  204. };
  205. BOOST_AUTO_TEST_CASE(uses_traits_from_number_n)
  206. {
  207. std::string parsed;
  208. prefixing_parser<char> p;
  209. BOOST_REQUIRE(p.parse_number("12345", parsed));
  210. BOOST_CHECK_EQUAL("n:12345", parsed);
  211. }
  212. void number_parse_result_is_input_w(const wchar_t* param) {
  213. std::wstring parsed;
  214. standard_parser<wchar_t> p;
  215. BOOST_REQUIRE(p.parse_number(param, parsed));
  216. BOOST_CHECK_EQUAL(param, parsed);
  217. }
  218. const wchar_t* const numbers_w[] = {
  219. L"0",
  220. L"-0",
  221. L"1824",
  222. L"-0.1",
  223. L"123.142",
  224. L"1e+0",
  225. L"1E-0",
  226. L"1.1e134"
  227. };
  228. BOOST_AUTO_TEST_CASE(uses_traits_from_number_w)
  229. {
  230. std::wstring parsed;
  231. prefixing_parser<wchar_t> p;
  232. BOOST_REQUIRE(p.parse_number(L"12345", parsed));
  233. BOOST_CHECK_EQUAL(L"n:12345", parsed);
  234. }
  235. struct string_input_n {
  236. const char* encoded;
  237. const char* expected;
  238. };
  239. void string_parsed_correctly_n(string_input_n param) {
  240. std::string parsed;
  241. standard_parser<char> p;
  242. BOOST_REQUIRE(p.parse_string(param.encoded, parsed));
  243. BOOST_CHECK_EQUAL(param.expected, parsed);
  244. }
  245. const string_input_n strings_n[] = {
  246. {"\"\"", ""},
  247. {"\"abc\"", "abc"},
  248. {"\"a\\nb\"", "a\nb"},
  249. {"\"\\\"\"", "\""},
  250. {"\"\\\\\"", "\\"},
  251. {"\"\\/\"", "/"},
  252. {"\"\\b\"", "\b"},
  253. {"\"\\f\"", "\f"},
  254. {"\"\\r\"", "\r"},
  255. {"\"\\t\"", "\t"},
  256. {"\"\\u0001\\u00f2\\u28Ec\"", "\x01" "\xC3\xB2" "\xE2\xA3\xAC"},
  257. {"\"\\ud801\\udc37\"", "\xf0\x90\x90\xb7"}, // U+10437
  258. {"\xef\xbb\xbf\"\"", ""} // BOM
  259. };
  260. BOOST_AUTO_TEST_CASE(uses_string_callbacks)
  261. {
  262. std::string parsed;
  263. prefixing_parser<char> p;
  264. BOOST_REQUIRE(p.parse_string("\"a\"", parsed));
  265. BOOST_CHECK_EQUAL("s:a", parsed);
  266. }
  267. struct string_input_w {
  268. const wchar_t* encoded;
  269. const wchar_t* expected;
  270. };
  271. void string_parsed_correctly_w(string_input_w param) {
  272. std::wstring parsed;
  273. standard_parser<wchar_t> p;
  274. BOOST_REQUIRE(p.parse_string(param.encoded, parsed));
  275. BOOST_CHECK_EQUAL(param.expected, parsed);
  276. }
  277. const string_input_w strings_w[] = {
  278. {L"\"\"", L""},
  279. {L"\"abc\"", L"abc"},
  280. {L"\"a\\nb\"", L"a\nb"},
  281. {L"\"\\\"\"", L"\""},
  282. {L"\"\\\\\"", L"\\"},
  283. {L"\"\\/\"", L"/"},
  284. {L"\"\\b\"", L"\b"},
  285. {L"\"\\f\"", L"\f"},
  286. {L"\"\\r\"", L"\r"},
  287. {L"\"\\t\"", L"\t"},
  288. {L"\"\\u0001\\u00f2\\u28Ec\"", L"\x0001" L"\x00F2" L"\x28EC"},
  289. {L"\xfeff\"\"", L""} // BOM
  290. };
  291. BOOST_AUTO_TEST_CASE(empty_array) {
  292. ptree tree;
  293. standard_parser<char> p;
  294. const char* input = " [ ]";
  295. BOOST_REQUIRE(p.parse_array(input, tree));
  296. BOOST_CHECK_EQUAL("", tree.data());
  297. BOOST_CHECK_EQUAL(0u, tree.size());
  298. }
  299. BOOST_AUTO_TEST_CASE(array_gets_tagged) {
  300. wptree tree;
  301. prefixing_parser<wchar_t> p;
  302. const wchar_t* input = L" [ ]";
  303. BOOST_REQUIRE(p.parse_array(input, tree));
  304. BOOST_CHECK_EQUAL(L"a:", tree.data());
  305. BOOST_CHECK_EQUAL(0u, tree.size());
  306. }
  307. BOOST_AUTO_TEST_CASE(array_with_values) {
  308. wptree tree;
  309. standard_parser<wchar_t> p;
  310. const wchar_t* input = L"[\n"
  311. L" 123, \"abc\" ,true ,\n"
  312. L" null\n"
  313. L" ]";
  314. BOOST_REQUIRE(p.parse_array(input, tree));
  315. BOOST_REQUIRE_EQUAL(4u, tree.size());
  316. wptree::iterator it = tree.begin();
  317. BOOST_CHECK_EQUAL(L"", it->first);
  318. BOOST_CHECK_EQUAL(L"123", it->second.data());
  319. ++it;
  320. BOOST_CHECK_EQUAL(L"", it->first);
  321. BOOST_CHECK_EQUAL(L"abc", it->second.data());
  322. ++it;
  323. BOOST_CHECK_EQUAL(L"", it->first);
  324. BOOST_CHECK_EQUAL(L"true", it->second.data());
  325. ++it;
  326. BOOST_CHECK_EQUAL(L"", it->first);
  327. BOOST_CHECK_EQUAL(L"null", it->second.data());
  328. ++it;
  329. BOOST_CHECK_EQUAL(tree.end(), it);
  330. }
  331. BOOST_AUTO_TEST_CASE(array_values_get_tagged) {
  332. ptree tree;
  333. prefixing_parser<char> p;
  334. const char* input = "[\n"
  335. " 123, \"abc\" ,true ,\n"
  336. " null\n"
  337. " ]";
  338. BOOST_REQUIRE(p.parse_array(input, tree));
  339. BOOST_REQUIRE_EQUAL(4u, tree.size());
  340. BOOST_CHECK_EQUAL("a:", tree.data());
  341. ptree::iterator it = tree.begin();
  342. BOOST_CHECK_EQUAL("", it->first);
  343. BOOST_CHECK_EQUAL("n:123", it->second.data());
  344. ++it;
  345. BOOST_CHECK_EQUAL("", it->first);
  346. BOOST_CHECK_EQUAL("s:abc", it->second.data());
  347. ++it;
  348. BOOST_CHECK_EQUAL("", it->first);
  349. BOOST_CHECK_EQUAL("b:true", it->second.data());
  350. ++it;
  351. BOOST_CHECK_EQUAL("", it->first);
  352. BOOST_CHECK_EQUAL("_:null", it->second.data());
  353. ++it;
  354. BOOST_CHECK_EQUAL(tree.end(), it);
  355. }
  356. BOOST_AUTO_TEST_CASE(nested_array) {
  357. ptree tree;
  358. standard_parser<char> p;
  359. const char* input = "[[1,2],3,[4,5]]";
  360. BOOST_REQUIRE(p.parse_array(input, tree));
  361. BOOST_REQUIRE_EQUAL(3u, tree.size());
  362. ptree::iterator it = tree.begin();
  363. BOOST_CHECK_EQUAL("", it->first);
  364. {
  365. ptree& sub = it->second;
  366. BOOST_CHECK_EQUAL("", sub.data());
  367. BOOST_REQUIRE_EQUAL(2u, sub.size());
  368. ptree::iterator iit = sub.begin();
  369. BOOST_CHECK_EQUAL("", iit->first);
  370. BOOST_CHECK_EQUAL("1", iit->second.data());
  371. ++iit;
  372. BOOST_CHECK_EQUAL("", iit->first);
  373. BOOST_CHECK_EQUAL("2", iit->second.data());
  374. ++iit;
  375. BOOST_CHECK_EQUAL(sub.end(), iit);
  376. }
  377. ++it;
  378. BOOST_CHECK_EQUAL("", it->first);
  379. BOOST_CHECK_EQUAL("3", it->second.data());
  380. ++it;
  381. BOOST_CHECK_EQUAL("", it->first);
  382. {
  383. ptree& sub = it->second;
  384. BOOST_CHECK_EQUAL("", sub.data());
  385. BOOST_REQUIRE_EQUAL(2u, sub.size());
  386. ptree::iterator iit = sub.begin();
  387. BOOST_CHECK_EQUAL("", iit->first);
  388. BOOST_CHECK_EQUAL("4", iit->second.data());
  389. ++iit;
  390. BOOST_CHECK_EQUAL("", iit->first);
  391. BOOST_CHECK_EQUAL("5", iit->second.data());
  392. ++iit;
  393. BOOST_CHECK_EQUAL(sub.end(), iit);
  394. }
  395. ++it;
  396. BOOST_CHECK_EQUAL(tree.end(), it);
  397. }
  398. BOOST_AUTO_TEST_CASE(empty_object) {
  399. ptree tree;
  400. standard_parser<char> p;
  401. const char* input = " { }";
  402. BOOST_REQUIRE(p.parse_object(input, tree));
  403. BOOST_CHECK_EQUAL("", tree.data());
  404. BOOST_CHECK_EQUAL(0u, tree.size());
  405. }
  406. BOOST_AUTO_TEST_CASE(object_gets_tagged) {
  407. wptree tree;
  408. prefixing_parser<wchar_t> p;
  409. const wchar_t* input = L" { }";
  410. BOOST_REQUIRE(p.parse_object(input, tree));
  411. BOOST_CHECK_EQUAL(L"o:", tree.data());
  412. BOOST_CHECK_EQUAL(0u, tree.size());
  413. }
  414. BOOST_AUTO_TEST_CASE(object_with_values) {
  415. wptree tree;
  416. standard_parser<wchar_t> p;
  417. const wchar_t* input = L"{\n"
  418. L" \"1\":123, \"2\"\n"
  419. L" :\"abc\" ,\"3\": true ,\n"
  420. L" \"4\" : null\n"
  421. L" }";
  422. BOOST_REQUIRE(p.parse_object(input, tree));
  423. BOOST_REQUIRE_EQUAL(4u, tree.size());
  424. wptree::iterator it = tree.begin();
  425. BOOST_CHECK_EQUAL(L"1", it->first);
  426. BOOST_CHECK_EQUAL(L"123", it->second.data());
  427. ++it;
  428. BOOST_CHECK_EQUAL(L"2", it->first);
  429. BOOST_CHECK_EQUAL(L"abc", it->second.data());
  430. ++it;
  431. BOOST_CHECK_EQUAL(L"3", it->first);
  432. BOOST_CHECK_EQUAL(L"true", it->second.data());
  433. ++it;
  434. BOOST_CHECK_EQUAL(L"4", it->first);
  435. BOOST_CHECK_EQUAL(L"null", it->second.data());
  436. ++it;
  437. BOOST_CHECK_EQUAL(tree.end(), it);
  438. }
  439. BOOST_AUTO_TEST_CASE(object_values_get_tagged) {
  440. ptree tree;
  441. prefixing_parser<char> p;
  442. const char* input = "{\n"
  443. "\"1\": 123, \"2\": \"abc\" ,\"3\": true ,\n"
  444. "\"4\": null\n"
  445. "}";
  446. BOOST_REQUIRE(p.parse_object(input, tree));
  447. BOOST_REQUIRE_EQUAL(4u, tree.size());
  448. BOOST_CHECK_EQUAL("o:", tree.data());
  449. ptree::iterator it = tree.begin();
  450. BOOST_CHECK_EQUAL("1", it->first);
  451. BOOST_CHECK_EQUAL("n:123", it->second.data());
  452. ++it;
  453. BOOST_CHECK_EQUAL("2", it->first);
  454. BOOST_CHECK_EQUAL("s:abc", it->second.data());
  455. ++it;
  456. BOOST_CHECK_EQUAL("3", it->first);
  457. BOOST_CHECK_EQUAL("b:true", it->second.data());
  458. ++it;
  459. BOOST_CHECK_EQUAL("4", it->first);
  460. BOOST_CHECK_EQUAL("_:null", it->second.data());
  461. ++it;
  462. BOOST_CHECK_EQUAL(tree.end(), it);
  463. }
  464. BOOST_AUTO_TEST_CASE(nested_object) {
  465. ptree tree;
  466. standard_parser<char> p;
  467. const char* input = "{\"a\":{\"b\":1,\"c\":2},\"d\":3,\"e\":{\"f\":4,\"g\":5}}";
  468. BOOST_REQUIRE(p.parse_object(input, tree));
  469. BOOST_REQUIRE_EQUAL(3u, tree.size());
  470. ptree::iterator it = tree.begin();
  471. BOOST_CHECK_EQUAL("a", it->first);
  472. {
  473. ptree& sub = it->second;
  474. BOOST_CHECK_EQUAL("", sub.data());
  475. BOOST_REQUIRE_EQUAL(2u, sub.size());
  476. ptree::iterator iit = sub.begin();
  477. BOOST_CHECK_EQUAL("b", iit->first);
  478. BOOST_CHECK_EQUAL("1", iit->second.data());
  479. ++iit;
  480. BOOST_CHECK_EQUAL("c", iit->first);
  481. BOOST_CHECK_EQUAL("2", iit->second.data());
  482. ++iit;
  483. BOOST_CHECK_EQUAL(sub.end(), iit);
  484. }
  485. ++it;
  486. BOOST_CHECK_EQUAL("d", it->first);
  487. BOOST_CHECK_EQUAL("3", it->second.data());
  488. ++it;
  489. BOOST_CHECK_EQUAL("e", it->first);
  490. {
  491. ptree& sub = it->second;
  492. BOOST_CHECK_EQUAL("", sub.data());
  493. BOOST_REQUIRE_EQUAL(2u, sub.size());
  494. ptree::iterator iit = sub.begin();
  495. BOOST_CHECK_EQUAL("f", iit->first);
  496. BOOST_CHECK_EQUAL("4", iit->second.data());
  497. ++iit;
  498. BOOST_CHECK_EQUAL("g", iit->first);
  499. BOOST_CHECK_EQUAL("5", iit->second.data());
  500. ++iit;
  501. BOOST_CHECK_EQUAL(sub.end(), iit);
  502. }
  503. ++it;
  504. BOOST_CHECK_EQUAL(tree.end(), it);
  505. }
  506. BOOST_AUTO_TEST_CASE(array_in_object) {
  507. ptree tree;
  508. standard_parser<char> p;
  509. const char* input = "{\"a\":[1,2],\"b\":3,\"c\":[4,5]}";
  510. BOOST_REQUIRE(p.parse_object(input, tree));
  511. BOOST_REQUIRE_EQUAL(3u, tree.size());
  512. ptree::iterator it = tree.begin();
  513. BOOST_CHECK_EQUAL("a", it->first);
  514. {
  515. ptree& sub = it->second;
  516. BOOST_CHECK_EQUAL("", sub.data());
  517. BOOST_REQUIRE_EQUAL(2u, sub.size());
  518. ptree::iterator iit = sub.begin();
  519. BOOST_CHECK_EQUAL("", iit->first);
  520. BOOST_CHECK_EQUAL("1", iit->second.data());
  521. ++iit;
  522. BOOST_CHECK_EQUAL("", iit->first);
  523. BOOST_CHECK_EQUAL("2", iit->second.data());
  524. ++iit;
  525. BOOST_CHECK_EQUAL(sub.end(), iit);
  526. }
  527. ++it;
  528. BOOST_CHECK_EQUAL("b", it->first);
  529. BOOST_CHECK_EQUAL("3", it->second.data());
  530. ++it;
  531. BOOST_CHECK_EQUAL("c", it->first);
  532. {
  533. ptree& sub = it->second;
  534. BOOST_CHECK_EQUAL("", sub.data());
  535. BOOST_REQUIRE_EQUAL(2u, sub.size());
  536. ptree::iterator iit = sub.begin();
  537. BOOST_CHECK_EQUAL("", iit->first);
  538. BOOST_CHECK_EQUAL("4", iit->second.data());
  539. ++iit;
  540. BOOST_CHECK_EQUAL("", iit->first);
  541. BOOST_CHECK_EQUAL("5", iit->second.data());
  542. ++iit;
  543. BOOST_CHECK_EQUAL(sub.end(), iit);
  544. }
  545. ++it;
  546. BOOST_CHECK_EQUAL(tree.end(), it);
  547. }
  548. BOOST_AUTO_TEST_CASE(object_in_array) {
  549. ptree tree;
  550. standard_parser<char> p;
  551. const char* input = "[{\"a\":1,\"b\":2},3,{\"c\":4,\"d\":5}]";
  552. BOOST_REQUIRE(p.parse_array(input, tree));
  553. BOOST_REQUIRE_EQUAL(3u, tree.size());
  554. ptree::iterator it = tree.begin();
  555. BOOST_CHECK_EQUAL("", it->first);
  556. {
  557. ptree& sub = it->second;
  558. BOOST_CHECK_EQUAL("", sub.data());
  559. BOOST_REQUIRE_EQUAL(2u, sub.size());
  560. ptree::iterator iit = sub.begin();
  561. BOOST_CHECK_EQUAL("a", iit->first);
  562. BOOST_CHECK_EQUAL("1", iit->second.data());
  563. ++iit;
  564. BOOST_CHECK_EQUAL("b", iit->first);
  565. BOOST_CHECK_EQUAL("2", iit->second.data());
  566. ++iit;
  567. BOOST_CHECK_EQUAL(sub.end(), iit);
  568. }
  569. ++it;
  570. BOOST_CHECK_EQUAL("", it->first);
  571. BOOST_CHECK_EQUAL("3", it->second.data());
  572. ++it;
  573. BOOST_CHECK_EQUAL("", it->first);
  574. {
  575. ptree& sub = it->second;
  576. BOOST_CHECK_EQUAL("", sub.data());
  577. BOOST_REQUIRE_EQUAL(2u, sub.size());
  578. ptree::iterator iit = sub.begin();
  579. BOOST_CHECK_EQUAL("c", iit->first);
  580. BOOST_CHECK_EQUAL("4", iit->second.data());
  581. ++iit;
  582. BOOST_CHECK_EQUAL("d", iit->first);
  583. BOOST_CHECK_EQUAL("5", iit->second.data());
  584. ++iit;
  585. BOOST_CHECK_EQUAL(sub.end(), iit);
  586. }
  587. ++it;
  588. BOOST_CHECK_EQUAL(tree.end(), it);
  589. }
  590. BOOST_AUTO_TEST_CASE(parser_works_with_input_iterators) {
  591. const char* input = " {\n"
  592. " \"1\":123, \"2\"\n"
  593. " :\"abc\" ,\"3\": true ,\n"
  594. " \"4\" : null, \"5\" : [ 1, 23\n"
  595. " , 456 ]\n"
  596. " }";
  597. std::istringstream is(input);
  598. typedef std::istreambuf_iterator<char> iterator;
  599. json_parser::detail::standard_callbacks<ptree> callbacks;
  600. json_parser::detail::utf8_utf8_encoding encoding;
  601. json_parser::detail::parser<json_parser::detail::standard_callbacks<ptree>,
  602. json_parser::detail::utf8_utf8_encoding,
  603. iterator, iterator>
  604. p(callbacks, encoding);
  605. p.set_input("", boost::make_iterator_range(iterator(is), iterator()));
  606. p.parse_value();
  607. const ptree& tree = callbacks.output();
  608. BOOST_REQUIRE_EQUAL(5u, tree.size());
  609. ptree::const_iterator it = tree.begin();
  610. BOOST_CHECK_EQUAL("1", it->first);
  611. BOOST_CHECK_EQUAL("123", it->second.data());
  612. ++it;
  613. BOOST_CHECK_EQUAL("2", it->first);
  614. BOOST_CHECK_EQUAL("abc", it->second.data());
  615. ++it;
  616. BOOST_CHECK_EQUAL("3", it->first);
  617. BOOST_CHECK_EQUAL("true", it->second.data());
  618. ++it;
  619. BOOST_CHECK_EQUAL("4", it->first);
  620. BOOST_CHECK_EQUAL("null", it->second.data());
  621. ++it;
  622. BOOST_CHECK_EQUAL("5", it->first);
  623. {
  624. const ptree& sub = it->second;
  625. BOOST_CHECK_EQUAL("", sub.data());
  626. BOOST_REQUIRE_EQUAL(3u, sub.size());
  627. ptree::const_iterator iit = sub.begin();
  628. BOOST_CHECK_EQUAL("", iit->first);
  629. BOOST_CHECK_EQUAL("1", iit->second.data());
  630. ++iit;
  631. BOOST_CHECK_EQUAL("", iit->first);
  632. BOOST_CHECK_EQUAL("23", iit->second.data());
  633. ++iit;
  634. BOOST_CHECK_EQUAL("", iit->first);
  635. BOOST_CHECK_EQUAL("456", iit->second.data());
  636. ++iit;
  637. BOOST_CHECK_EQUAL(sub.end(), iit);
  638. }
  639. ++it;
  640. BOOST_CHECK_EQUAL(tree.end(), it);
  641. }
  642. struct bad_parse_n {
  643. const char* json;
  644. const char* message_substring;
  645. };
  646. void parse_error_thrown_with_message_n(bad_parse_n param) {
  647. try {
  648. standard_parser<char> p;
  649. ptree dummy;
  650. p.parse_value(param.json, dummy);
  651. BOOST_FAIL("expected exception");
  652. } catch (json_parser::json_parser_error& e) {
  653. std::string message = e.message();
  654. BOOST_CHECK_MESSAGE(message.find(param.message_substring) !=
  655. std::string::npos,
  656. "bad error message on input '" << param.json
  657. << "', need: '" << param.message_substring
  658. << "' but found '" << message << "'");
  659. }
  660. }
  661. const bad_parse_n errors_n[] = {
  662. {"", "expected value"},
  663. {"(", "expected value"},
  664. {"n", "expected 'null'"},
  665. {"nu", "expected 'null'"},
  666. {"nul", "expected 'null'"},
  667. {"n ", "expected 'null'"},
  668. {"nu ", "expected 'null'"},
  669. {"nul ", "expected 'null'"},
  670. {"nx", "expected 'null'"},
  671. {"nux", "expected 'null'"},
  672. {"nulx", "expected 'null'"},
  673. {"t", "expected 'true'"},
  674. {"tr", "expected 'true'"},
  675. {"tu", "expected 'true'"},
  676. {"t ", "expected 'true'"},
  677. {"tr ", "expected 'true'"},
  678. {"tru ", "expected 'true'"},
  679. {"tx", "expected 'true'"},
  680. {"trx", "expected 'true'"},
  681. {"trux", "expected 'true'"},
  682. {"f", "expected 'false'"},
  683. {"fa", "expected 'false'"},
  684. {"fal", "expected 'false'"},
  685. {"fals", "expected 'false'"},
  686. {"f ", "expected 'false'"},
  687. {"fa ", "expected 'false'"},
  688. {"fal ", "expected 'false'"},
  689. {"fals ", "expected 'false'"},
  690. {"fx", "expected 'false'"},
  691. {"fax", "expected 'false'"},
  692. {"falx", "expected 'false'"},
  693. {"falsx", "expected 'false'"},
  694. {"-", "expected digits"},
  695. {"01", "garbage after data"},
  696. {"0.", "need at least one digit after '.'"},
  697. {"0e", "need at least one digit in exponent"},
  698. {"0e-", "need at least one digit in exponent"},
  699. {"\"", "unterminated string"},
  700. {"\"asd", "unterminated string"},
  701. {"\"\n\"", "invalid code sequence"}, // control character
  702. {"\"\xff\"", "invalid code sequence"}, // bad lead byte
  703. {"\"\x80\"", "invalid code sequence"}, // stray trail byte
  704. {"\"\xc0", "invalid code sequence"}, // eos after lead byte
  705. {"\"\xc0\"", "invalid code sequence"}, // bad trail byte
  706. {"\"\xc0m\"", "invalid code sequence"}, // also bad trail byte
  707. {"\"\\", "invalid escape sequence"},
  708. {"\"\\p\"", "invalid escape sequence"},
  709. {"\"\\u", "invalid escape sequence"},
  710. {"\"\\u\"", "invalid escape sequence"},
  711. {"\"\\ug\"", "invalid escape sequence"},
  712. {"\"\\u1\"", "invalid escape sequence"},
  713. {"\"\\u1g\"", "invalid escape sequence"},
  714. {"\"\\u11\"", "invalid escape sequence"},
  715. {"\"\\u11g\"", "invalid escape sequence"},
  716. {"\"\\u111\"", "invalid escape sequence"},
  717. {"\"\\u111g\"", "invalid escape sequence"},
  718. {"\"\\ude00\"", "stray low surrogate"},
  719. {"\"\\ud900", "stray high surrogate"},
  720. {"\"\\ud900foo\"", "stray high surrogate"},
  721. {"\"\\ud900\\", "expected codepoint reference"},
  722. {"\"\\ud900\\n\"", "expected codepoint reference"},
  723. {"\"\\ud900\\u1000\"", "expected low surrogate"},
  724. {"[", "expected value"},
  725. {"[1", "expected ']' or ','"},
  726. {"[1,", "expected value"},
  727. {"[1,]", "expected value"},
  728. {"[1}", "expected ']' or ','"},
  729. {"{", "expected key string"},
  730. {"{1:2}", "expected key string"},
  731. {"{\"\"", "expected ':'"},
  732. {"{\"\"}", "expected ':'"},
  733. {"{\"\":", "expected value"},
  734. {"{\"\":}", "expected value"},
  735. {"{\"\":0", "expected '}' or ','"},
  736. {"{\"\":0]", "expected '}' or ','"},
  737. {"{\"\":0,", "expected key string"},
  738. {"{\"\":0,}", "expected key string"},
  739. };
  740. struct bad_parse_w {
  741. const wchar_t* json;
  742. const char* message_substring;
  743. };
  744. void parse_error_thrown_with_message_w(bad_parse_w param) {
  745. try {
  746. standard_parser<wchar_t> p;
  747. wptree dummy;
  748. p.parse_value(param.json, dummy);
  749. BOOST_FAIL("expected exception");
  750. } catch (json_parser::json_parser_error& e) {
  751. std::string message = e.message();
  752. BOOST_CHECK_MESSAGE(message.find(param.message_substring) !=
  753. std::string::npos,
  754. "bad error message on input '" << param.json
  755. << "', need: '" << param.message_substring
  756. << "' but found '" << message << "'");
  757. }
  758. }
  759. const bad_parse_w errors_w[] = {
  760. {L"", "expected value"},
  761. {L"(", "expected value"},
  762. {L"n", "expected 'null'"},
  763. {L"nu", "expected 'null'"},
  764. {L"nul", "expected 'null'"},
  765. {L"n ", "expected 'null'"},
  766. {L"nu ", "expected 'null'"},
  767. {L"nul ", "expected 'null'"},
  768. {L"nx", "expected 'null'"},
  769. {L"nux", "expected 'null'"},
  770. {L"nulx", "expected 'null'"},
  771. {L"t", "expected 'true'"},
  772. {L"tr", "expected 'true'"},
  773. {L"tu", "expected 'true'"},
  774. {L"t ", "expected 'true'"},
  775. {L"tr ", "expected 'true'"},
  776. {L"tru ", "expected 'true'"},
  777. {L"tx", "expected 'true'"},
  778. {L"trx", "expected 'true'"},
  779. {L"trux", "expected 'true'"},
  780. {L"f", "expected 'false'"},
  781. {L"fa", "expected 'false'"},
  782. {L"fal", "expected 'false'"},
  783. {L"fals", "expected 'false'"},
  784. {L"f ", "expected 'false'"},
  785. {L"fa ", "expected 'false'"},
  786. {L"fal ", "expected 'false'"},
  787. {L"fals ", "expected 'false'"},
  788. {L"fx", "expected 'false'"},
  789. {L"fax", "expected 'false'"},
  790. {L"falx", "expected 'false'"},
  791. {L"falsx", "expected 'false'"},
  792. {L"-", "expected digits"},
  793. {L"01", "garbage after data"},
  794. {L"0.", "need at least one digit after '.'"},
  795. {L"0e", "need at least one digit in exponent"},
  796. {L"0e-", "need at least one digit in exponent"},
  797. {L"\"", "unterminated string"},
  798. {L"\"asd", "unterminated string"},
  799. {L"\"\n\"", "invalid code sequence"}, // control character
  800. // Encoding not known, so no UTF-16 encoding error tests.
  801. {L"\"\\", "invalid escape sequence"},
  802. {L"\"\\p\"", "invalid escape sequence"},
  803. {L"\"\\u", "invalid escape sequence"},
  804. {L"\"\\u\"", "invalid escape sequence"},
  805. {L"\"\\ug\"", "invalid escape sequence"},
  806. {L"\"\\u1\"", "invalid escape sequence"},
  807. {L"\"\\u1g\"", "invalid escape sequence"},
  808. {L"\"\\u11\"", "invalid escape sequence"},
  809. {L"\"\\u11g\"", "invalid escape sequence"},
  810. {L"\"\\u111\"", "invalid escape sequence"},
  811. {L"\"\\u111g\"", "invalid escape sequence"},
  812. {L"\"\\ude00\"", "stray low surrogate"},
  813. {L"\"\\ud900", "stray high surrogate"},
  814. {L"\"\\ud900foo\"", "stray high surrogate"},
  815. {L"\"\\ud900\\", "expected codepoint reference"},
  816. {L"\"\\ud900\\n\"", "expected codepoint reference"},
  817. {L"\"\\ud900\\u1000\"", "expected low surrogate"},
  818. {L"[", "expected value"},
  819. {L"[1", "expected ']' or ','"},
  820. {L"[1,", "expected value"},
  821. {L"[1,]", "expected value"},
  822. {L"[1}", "expected ']' or ','"},
  823. {L"{", "expected key string"},
  824. {L"{1:2}", "expected key string"},
  825. {L"{\"\"", "expected ':'"},
  826. {L"{\"\"}", "expected ':'"},
  827. {L"{\"\":", "expected value"},
  828. {L"{\"\":}", "expected value"},
  829. {L"{\"\":0", "expected '}' or ','"},
  830. {L"{\"\":0]", "expected '}' or ','"},
  831. {L"{\"\":0,", "expected key string"},
  832. {L"{\"\":0,}", "expected key string"},
  833. };
  834. template <typename T, std::size_t N>
  835. std::size_t arraysize(T(&)[N]) { return N; }
  836. #define ARRAY_TEST_CASE(fn, a) \
  837. BOOST_PARAM_TEST_CASE(fn, (a), (a) + arraysize((a)))
  838. using namespace boost::unit_test;
  839. test_suite* init_unit_test_suite(int, char*[])
  840. {
  841. master_test_suite_t& ts = boost::unit_test::framework::master_test_suite();
  842. ts.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_n, booleans_n));
  843. ts.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_w, booleans_w));
  844. ts.add(ARRAY_TEST_CASE(number_parse_result_is_input_n, numbers_n));
  845. ts.add(ARRAY_TEST_CASE(number_parse_result_is_input_w, numbers_w));
  846. ts.add(ARRAY_TEST_CASE(string_parsed_correctly_n, strings_n));
  847. ts.add(ARRAY_TEST_CASE(string_parsed_correctly_w, strings_w));
  848. ts.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_n, errors_n));
  849. ts.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_w, errors_w));
  850. return 0;
  851. }