unit-deserialization.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. // __ _____ _____ _____
  2. // __| | __| | | | JSON for Modern C++ (supporting code)
  3. // | | |__ | | | | | | version 3.11.2
  4. // |_____|_____|_____|_|___| https://github.com/nlohmann/json
  5. //
  6. // Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
  7. // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  8. // SPDX-License-Identifier: MIT
  9. #include "doctest_compatibility.h"
  10. #include <nlohmann/json.hpp>
  11. using nlohmann::json;
  12. #ifdef JSON_TEST_NO_GLOBAL_UDLS
  13. using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
  14. #endif
  15. #include <iostream>
  16. #include <iterator>
  17. #include <sstream>
  18. #include <valarray>
  19. namespace
  20. {
  21. struct SaxEventLogger : public nlohmann::json_sax<json>
  22. {
  23. bool null() override
  24. {
  25. events.emplace_back("null()");
  26. return true;
  27. }
  28. bool boolean(bool val) override
  29. {
  30. events.emplace_back(val ? "boolean(true)" : "boolean(false)");
  31. return true;
  32. }
  33. bool number_integer(json::number_integer_t val) override
  34. {
  35. events.push_back("number_integer(" + std::to_string(val) + ")");
  36. return true;
  37. }
  38. bool number_unsigned(json::number_unsigned_t val) override
  39. {
  40. events.push_back("number_unsigned(" + std::to_string(val) + ")");
  41. return true;
  42. }
  43. bool number_float(json::number_float_t /*val*/, const std::string& s) override
  44. {
  45. events.push_back("number_float(" + s + ")");
  46. return true;
  47. }
  48. bool string(std::string& val) override
  49. {
  50. events.push_back("string(" + val + ")");
  51. return true;
  52. }
  53. bool binary(json::binary_t& val) override
  54. {
  55. std::string binary_contents = "binary(";
  56. std::string comma_space;
  57. for (auto b : val)
  58. {
  59. binary_contents.append(comma_space);
  60. binary_contents.append(std::to_string(static_cast<int>(b)));
  61. comma_space = ", ";
  62. }
  63. binary_contents.append(")");
  64. events.push_back(binary_contents);
  65. return true;
  66. }
  67. bool start_object(std::size_t elements) override
  68. {
  69. if (elements == static_cast<std::size_t>(-1))
  70. {
  71. events.emplace_back("start_object()");
  72. }
  73. else
  74. {
  75. events.push_back("start_object(" + std::to_string(elements) + ")");
  76. }
  77. return true;
  78. }
  79. bool key(std::string& val) override
  80. {
  81. events.push_back("key(" + val + ")");
  82. return true;
  83. }
  84. bool end_object() override
  85. {
  86. events.emplace_back("end_object()");
  87. return true;
  88. }
  89. bool start_array(std::size_t elements) override
  90. {
  91. if (elements == static_cast<std::size_t>(-1))
  92. {
  93. events.emplace_back("start_array()");
  94. }
  95. else
  96. {
  97. events.push_back("start_array(" + std::to_string(elements) + ")");
  98. }
  99. return true;
  100. }
  101. bool end_array() override
  102. {
  103. events.emplace_back("end_array()");
  104. return true;
  105. }
  106. bool parse_error(std::size_t position, const std::string& /*last_token*/, const json::exception& /*ex*/) override
  107. {
  108. events.push_back("parse_error(" + std::to_string(position) + ")");
  109. return false;
  110. }
  111. std::vector<std::string> events {};
  112. };
  113. struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
  114. {
  115. bool start_object(std::size_t elements) override
  116. {
  117. if (elements == static_cast<std::size_t>(-1))
  118. {
  119. events.emplace_back("start_object()");
  120. }
  121. else
  122. {
  123. events.push_back("start_object(" + std::to_string(elements) + ")");
  124. }
  125. return false;
  126. }
  127. };
  128. struct SaxEventLoggerExitAfterKey : public SaxEventLogger
  129. {
  130. bool key(std::string& val) override
  131. {
  132. events.push_back("key(" + val + ")");
  133. return false;
  134. }
  135. };
  136. struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
  137. {
  138. bool start_array(std::size_t elements) override
  139. {
  140. if (elements == static_cast<std::size_t>(-1))
  141. {
  142. events.emplace_back("start_array()");
  143. }
  144. else
  145. {
  146. events.push_back("start_array(" + std::to_string(elements) + ")");
  147. }
  148. return false;
  149. }
  150. };
  151. template <typename T>
  152. class proxy_iterator
  153. {
  154. public:
  155. using iterator = typename T::iterator;
  156. using value_type = typename std::iterator_traits<iterator>::value_type;
  157. using reference = typename std::iterator_traits<iterator>::reference;
  158. using pointer = typename std::iterator_traits<iterator>::pointer;
  159. using difference_type =
  160. typename std::iterator_traits<iterator>::difference_type;
  161. using iterator_category = std::input_iterator_tag;
  162. proxy_iterator() = default;
  163. explicit proxy_iterator(iterator& it) : m_it(std::addressof(it)) {}
  164. proxy_iterator& operator++()
  165. {
  166. ++*m_it;
  167. return *this;
  168. }
  169. proxy_iterator& operator--()
  170. {
  171. --*m_it;
  172. return *this;
  173. }
  174. bool operator==(const proxy_iterator& rhs) const
  175. {
  176. return (m_it && rhs.m_it) ? (*m_it == *rhs.m_it) : (m_it == rhs.m_it);
  177. }
  178. bool operator!=(const proxy_iterator& rhs) const
  179. {
  180. return !(*this == rhs);
  181. }
  182. reference operator*() const
  183. {
  184. return **m_it;
  185. }
  186. private:
  187. iterator* m_it = nullptr;
  188. };
  189. } // namespace
  190. TEST_CASE("deserialization")
  191. {
  192. SECTION("successful deserialization")
  193. {
  194. SECTION("stream")
  195. {
  196. std::stringstream ss1;
  197. std::stringstream ss2;
  198. std::stringstream ss3;
  199. ss1 << R"(["foo",1,2,3,false,{"one":1}])";
  200. ss2 << R"(["foo",1,2,3,false,{"one":1}])";
  201. ss3 << R"(["foo",1,2,3,false,{"one":1}])";
  202. json j = json::parse(ss1);
  203. CHECK(json::accept(ss2));
  204. CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
  205. SaxEventLogger l;
  206. CHECK(json::sax_parse(ss3, &l));
  207. CHECK(l.events.size() == 11);
  208. CHECK(l.events == std::vector<std::string>(
  209. {
  210. "start_array()", "string(foo)", "number_unsigned(1)",
  211. "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
  212. "start_object()", "key(one)", "number_unsigned(1)",
  213. "end_object()", "end_array()"
  214. }));
  215. }
  216. SECTION("string literal")
  217. {
  218. const auto* s = R"(["foo",1,2,3,false,{"one":1}])";
  219. json j = json::parse(s);
  220. CHECK(json::accept(s));
  221. CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
  222. SaxEventLogger l;
  223. CHECK(json::sax_parse(s, &l));
  224. CHECK(l.events.size() == 11);
  225. CHECK(l.events == std::vector<std::string>(
  226. {
  227. "start_array()", "string(foo)", "number_unsigned(1)",
  228. "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
  229. "start_object()", "key(one)", "number_unsigned(1)",
  230. "end_object()", "end_array()"
  231. }));
  232. }
  233. SECTION("string_t")
  234. {
  235. json::string_t const s = R"(["foo",1,2,3,false,{"one":1}])";
  236. json j = json::parse(s);
  237. CHECK(json::accept(s));
  238. CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
  239. SaxEventLogger l;
  240. CHECK(json::sax_parse(s, &l));
  241. CHECK(l.events.size() == 11);
  242. CHECK(l.events == std::vector<std::string>(
  243. {
  244. "start_array()", "string(foo)", "number_unsigned(1)",
  245. "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
  246. "start_object()", "key(one)", "number_unsigned(1)",
  247. "end_object()", "end_array()"
  248. }));
  249. }
  250. SECTION("operator<<")
  251. {
  252. std::stringstream ss;
  253. ss << R"(["foo",1,2,3,false,{"one":1}])";
  254. json j;
  255. j << ss;
  256. CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
  257. }
  258. SECTION("operator>>")
  259. {
  260. std::stringstream ss;
  261. ss << R"(["foo",1,2,3,false,{"one":1}])";
  262. json j;
  263. ss >> j;
  264. CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
  265. }
  266. SECTION("user-defined string literal")
  267. {
  268. CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
  269. }
  270. }
  271. SECTION("unsuccessful deserialization")
  272. {
  273. SECTION("stream")
  274. {
  275. std::stringstream ss1;
  276. std::stringstream ss3;
  277. std::stringstream ss4;
  278. std::stringstream ss5;
  279. ss1 << R"(["foo",1,2,3,false,{"one":1})";
  280. ss3 << R"(["foo",1,2,3,false,{"one":1})";
  281. ss4 << R"(["foo",1,2,3,false,{"one":1})";
  282. ss5 << R"(["foo",1,2,3,false,{"one":1})";
  283. json _;
  284. CHECK_THROWS_WITH_AS(_ = json::parse(ss1), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
  285. CHECK(!json::accept(ss3));
  286. json j_error;
  287. CHECK_NOTHROW(j_error = json::parse(ss4, nullptr, false));
  288. CHECK(j_error.is_discarded());
  289. SaxEventLogger l;
  290. CHECK(!json::sax_parse(ss5, &l));
  291. CHECK(l.events.size() == 11);
  292. CHECK(l.events == std::vector<std::string>(
  293. {
  294. "start_array()", "string(foo)", "number_unsigned(1)",
  295. "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
  296. "start_object()", "key(one)", "number_unsigned(1)",
  297. "end_object()", "parse_error(29)"
  298. }));
  299. }
  300. SECTION("string")
  301. {
  302. json::string_t const s = R"(["foo",1,2,3,false,{"one":1})";
  303. json _;
  304. CHECK_THROWS_WITH_AS(_ = json::parse(s), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
  305. CHECK(!json::accept(s));
  306. json j_error;
  307. CHECK_NOTHROW(j_error = json::parse(s, nullptr, false));
  308. CHECK(j_error.is_discarded());
  309. SaxEventLogger l;
  310. CHECK(!json::sax_parse(s, &l));
  311. CHECK(l.events.size() == 11);
  312. CHECK(l.events == std::vector<std::string>(
  313. {
  314. "start_array()", "string(foo)", "number_unsigned(1)",
  315. "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
  316. "start_object()", "key(one)", "number_unsigned(1)",
  317. "end_object()", "parse_error(29)"
  318. }));
  319. }
  320. SECTION("operator<<")
  321. {
  322. std::stringstream ss;
  323. ss << R"(["foo",1,2,3,false,{"one":1})";
  324. json j;
  325. CHECK_THROWS_WITH_AS(j << ss, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
  326. }
  327. SECTION("operator>>")
  328. {
  329. std::stringstream ss;
  330. ss << R"(["foo",1,2,3,false,{"one":1})";
  331. json j;
  332. CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
  333. }
  334. SECTION("user-defined string literal")
  335. {
  336. CHECK_THROWS_WITH_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
  337. }
  338. }
  339. SECTION("contiguous containers")
  340. {
  341. SECTION("directly")
  342. {
  343. SECTION("from std::vector")
  344. {
  345. std::vector<uint8_t> const v = {'t', 'r', 'u', 'e'};
  346. CHECK(json::parse(v) == json(true));
  347. CHECK(json::accept(v));
  348. SaxEventLogger l;
  349. CHECK(json::sax_parse(v, &l));
  350. CHECK(l.events.size() == 1);
  351. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  352. }
  353. SECTION("from std::array")
  354. {
  355. std::array<uint8_t, 5> const v { {'t', 'r', 'u', 'e'} };
  356. CHECK(json::parse(v) == json(true));
  357. CHECK(json::accept(v));
  358. SaxEventLogger l;
  359. CHECK(json::sax_parse(v, &l));
  360. CHECK(l.events.size() == 1);
  361. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  362. }
  363. SECTION("from array")
  364. {
  365. uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  366. CHECK(json::parse(v) == json(true));
  367. CHECK(json::accept(v));
  368. SaxEventLogger l;
  369. CHECK(json::sax_parse(v, &l));
  370. CHECK(l.events.size() == 1);
  371. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  372. }
  373. SECTION("from chars")
  374. {
  375. auto* v = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory)
  376. v[0] = 't';
  377. v[1] = 'r';
  378. v[2] = 'u';
  379. v[3] = 'e';
  380. v[4] = '\0';
  381. CHECK(json::parse(v) == json(true));
  382. CHECK(json::accept(v));
  383. SaxEventLogger l;
  384. CHECK(json::sax_parse(v, &l));
  385. CHECK(l.events.size() == 1);
  386. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  387. delete[] v; // NOLINT(cppcoreguidelines-owning-memory)
  388. }
  389. SECTION("from std::string")
  390. {
  391. std::string const v = {'t', 'r', 'u', 'e'};
  392. CHECK(json::parse(v) == json(true));
  393. CHECK(json::accept(v));
  394. SaxEventLogger l;
  395. CHECK(json::sax_parse(v, &l));
  396. CHECK(l.events.size() == 1);
  397. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  398. }
  399. SECTION("from std::initializer_list")
  400. {
  401. std::initializer_list<uint8_t> const v = {'t', 'r', 'u', 'e'};
  402. CHECK(json::parse(v) == json(true));
  403. CHECK(json::accept(v));
  404. SaxEventLogger l;
  405. CHECK(json::sax_parse(v, &l));
  406. CHECK(l.events.size() == 1);
  407. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  408. }
  409. SECTION("empty container")
  410. {
  411. std::vector<uint8_t> const v;
  412. json _;
  413. CHECK_THROWS_AS(_ = json::parse(v), json::parse_error&);
  414. CHECK(!json::accept(v));
  415. SaxEventLogger l;
  416. CHECK(!json::sax_parse(v, &l));
  417. CHECK(l.events.size() == 1);
  418. CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
  419. }
  420. }
  421. SECTION("via iterator range")
  422. {
  423. SECTION("from std::vector")
  424. {
  425. std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
  426. CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
  427. CHECK(json::accept(std::begin(v), std::end(v)));
  428. SaxEventLogger l;
  429. CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
  430. CHECK(l.events.size() == 1);
  431. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  432. }
  433. SECTION("from std::array")
  434. {
  435. std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
  436. CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
  437. CHECK(json::accept(std::begin(v), std::end(v)));
  438. SaxEventLogger l;
  439. CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
  440. CHECK(l.events.size() == 1);
  441. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  442. }
  443. SECTION("from array")
  444. {
  445. uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  446. CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
  447. CHECK(json::accept(std::begin(v), std::end(v)));
  448. SaxEventLogger l;
  449. CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
  450. CHECK(l.events.size() == 1);
  451. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  452. }
  453. SECTION("from std::string")
  454. {
  455. std::string v = {'t', 'r', 'u', 'e'};
  456. CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
  457. CHECK(json::accept(std::begin(v), std::end(v)));
  458. SaxEventLogger l;
  459. CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
  460. CHECK(l.events.size() == 1);
  461. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  462. }
  463. SECTION("from std::initializer_list")
  464. {
  465. std::initializer_list<uint8_t> const v = {'t', 'r', 'u', 'e'};
  466. CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
  467. CHECK(json::accept(std::begin(v), std::end(v)));
  468. SaxEventLogger l;
  469. CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
  470. CHECK(l.events.size() == 1);
  471. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  472. }
  473. SECTION("from std::valarray")
  474. {
  475. std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
  476. CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
  477. CHECK(json::accept(std::begin(v), std::end(v)));
  478. SaxEventLogger l;
  479. CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
  480. CHECK(l.events.size() == 1);
  481. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  482. }
  483. SECTION("with empty range")
  484. {
  485. std::vector<uint8_t> v;
  486. json _;
  487. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  488. CHECK(!json::accept(std::begin(v), std::end(v)));
  489. SaxEventLogger l;
  490. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  491. CHECK(l.events.size() == 1);
  492. CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
  493. }
  494. SECTION("iterator_input_adapter advances iterators correctly")
  495. {
  496. using nlohmann::json;
  497. using nlohmann::detail::input_format_t;
  498. using nlohmann::detail::json_sax_dom_parser;
  499. using proxy = proxy_iterator<std::string>;
  500. std::string str1 = "[1]";
  501. std::string str2 = "[2]";
  502. std::string str = str1 + str2;
  503. auto first = str.begin();
  504. auto last = str.end();
  505. json j;
  506. json_sax_dom_parser<json> sax(j, true);
  507. CHECK(json::sax_parse(proxy(first), proxy(last), &sax,
  508. input_format_t::json, false));
  509. CHECK(j.dump() == str1);
  510. CHECK(std::string(first, last) == str2);
  511. }
  512. }
  513. // these cases are required for 100% line coverage
  514. SECTION("error cases")
  515. {
  516. SECTION("case 1")
  517. {
  518. std::array<std::uint8_t, 9> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}};
  519. json _;
  520. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  521. CHECK(!json::accept(std::begin(v), std::end(v)));
  522. json j_error;
  523. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  524. CHECK(j_error.is_discarded());
  525. SaxEventLogger l;
  526. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  527. CHECK(l.events.size() == 1);
  528. CHECK(l.events == std::vector<std::string>({"parse_error(10)"}));
  529. }
  530. SECTION("case 2")
  531. {
  532. std::array<std::uint8_t, 10> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}};
  533. json _;
  534. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  535. CHECK(!json::accept(std::begin(v), std::end(v)));
  536. json j_error;
  537. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  538. CHECK(j_error.is_discarded());
  539. SaxEventLogger l;
  540. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  541. CHECK(l.events.size() == 1);
  542. CHECK(l.events == std::vector<std::string>({"parse_error(11)"}));
  543. }
  544. SECTION("case 3")
  545. {
  546. std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}};
  547. json _;
  548. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  549. CHECK(!json::accept(std::begin(v), std::end(v)));
  550. json j_error;
  551. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  552. CHECK(j_error.is_discarded());
  553. SaxEventLogger l;
  554. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  555. CHECK(l.events.size() == 1);
  556. CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
  557. }
  558. SECTION("case 4")
  559. {
  560. std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}};
  561. json _;
  562. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  563. CHECK(!json::accept(std::begin(v), std::end(v)));
  564. json j_error;
  565. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  566. CHECK(j_error.is_discarded());
  567. SaxEventLogger l;
  568. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  569. CHECK(l.events.size() == 1);
  570. CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
  571. }
  572. SECTION("case 5")
  573. {
  574. std::array<std::uint8_t, 3> v = {{'\"', 0x7F, 0xC1}};
  575. json _;
  576. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  577. CHECK(!json::accept(std::begin(v), std::end(v)));
  578. json j_error;
  579. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  580. CHECK(j_error.is_discarded());
  581. SaxEventLogger l;
  582. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  583. CHECK(l.events.size() == 1);
  584. CHECK(l.events == std::vector<std::string>({"parse_error(3)"}));
  585. }
  586. SECTION("case 6")
  587. {
  588. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0x7F}};
  589. json _;
  590. CHECK_THROWS_WITH_AS(_ = json::parse(std::begin(v), std::end(v)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'", json::parse_error&);
  591. CHECK(!json::accept(std::begin(v), std::end(v)));
  592. json j_error;
  593. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  594. CHECK(j_error.is_discarded());
  595. SaxEventLogger l;
  596. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  597. CHECK(l.events.size() == 1);
  598. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  599. }
  600. SECTION("case 7")
  601. {
  602. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0xC0}};
  603. json _;
  604. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  605. CHECK(!json::accept(std::begin(v), std::end(v)));
  606. json j_error;
  607. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  608. CHECK(j_error.is_discarded());
  609. SaxEventLogger l;
  610. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  611. CHECK(l.events.size() == 1);
  612. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  613. }
  614. SECTION("case 8")
  615. {
  616. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xE0, 0x9F}};
  617. json _;
  618. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  619. CHECK(!json::accept(std::begin(v), std::end(v)));
  620. json j_error;
  621. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  622. CHECK(j_error.is_discarded());
  623. SaxEventLogger l;
  624. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  625. CHECK(l.events.size() == 1);
  626. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  627. }
  628. SECTION("case 9")
  629. {
  630. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xEF, 0xC0}};
  631. json _;
  632. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  633. CHECK(!json::accept(std::begin(v), std::end(v)));
  634. json j_error;
  635. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  636. CHECK(j_error.is_discarded());
  637. SaxEventLogger l;
  638. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  639. CHECK(l.events.size() == 1);
  640. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  641. }
  642. SECTION("case 10")
  643. {
  644. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xED, 0x7F}};
  645. json _;
  646. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  647. CHECK(!json::accept(std::begin(v), std::end(v)));
  648. json j_error;
  649. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  650. CHECK(j_error.is_discarded());
  651. SaxEventLogger l;
  652. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  653. CHECK(l.events.size() == 1);
  654. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  655. }
  656. SECTION("case 11")
  657. {
  658. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0x8F}};
  659. json _;
  660. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  661. CHECK(!json::accept(std::begin(v), std::end(v)));
  662. json j_error;
  663. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  664. CHECK(j_error.is_discarded());
  665. SaxEventLogger l;
  666. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  667. CHECK(l.events.size() == 1);
  668. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  669. }
  670. SECTION("case 12")
  671. {
  672. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0xC0}};
  673. json _;
  674. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  675. CHECK(!json::accept(std::begin(v), std::end(v)));
  676. json j_error;
  677. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  678. CHECK(j_error.is_discarded());
  679. SaxEventLogger l;
  680. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  681. CHECK(l.events.size() == 1);
  682. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  683. }
  684. SECTION("case 13")
  685. {
  686. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0x7F}};
  687. json _;
  688. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  689. CHECK(!json::accept(std::begin(v), std::end(v)));
  690. json j_error;
  691. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  692. CHECK(j_error.is_discarded());
  693. SaxEventLogger l;
  694. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  695. CHECK(l.events.size() == 1);
  696. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  697. }
  698. SECTION("case 14")
  699. {
  700. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0xC0}};
  701. json _;
  702. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  703. CHECK(!json::accept(std::begin(v), std::end(v)));
  704. json j_error;
  705. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  706. CHECK(j_error.is_discarded());
  707. SaxEventLogger l;
  708. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  709. CHECK(l.events.size() == 1);
  710. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  711. }
  712. SECTION("case 15")
  713. {
  714. std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF4, 0x7F}};
  715. json _;
  716. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  717. CHECK(!json::accept(std::begin(v), std::end(v)));
  718. json j_error;
  719. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  720. CHECK(j_error.is_discarded());
  721. SaxEventLogger l;
  722. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  723. CHECK(l.events.size() == 1);
  724. CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
  725. }
  726. SECTION("case 16")
  727. {
  728. std::array<std::uint8_t, 6> v = {{'{', '\"', '\"', ':', '1', '1'}};
  729. json _;
  730. CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
  731. CHECK(!json::accept(std::begin(v), std::end(v)));
  732. json j_error;
  733. CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
  734. CHECK(j_error.is_discarded());
  735. SaxEventLogger l;
  736. CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
  737. CHECK(l.events.size() == 4);
  738. CHECK(l.events == std::vector<std::string>(
  739. {
  740. "start_object()", "key()", "number_unsigned(11)",
  741. "parse_error(7)"
  742. }));
  743. }
  744. }
  745. }
  746. SECTION("ignoring byte-order marks")
  747. {
  748. std::string bom = "\xEF\xBB\xBF";
  749. SECTION("BOM only")
  750. {
  751. json _;
  752. CHECK_THROWS_WITH_AS(_ = json::parse(bom), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
  753. CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
  754. SaxEventLogger l;
  755. CHECK(!json::sax_parse(bom, &l));
  756. CHECK(l.events.size() == 1);
  757. CHECK(l.events == std::vector<std::string>(
  758. {
  759. "parse_error(4)"
  760. }));
  761. }
  762. SECTION("BOM and content")
  763. {
  764. CHECK(json::parse(bom + "1") == 1);
  765. CHECK(json::parse(std::istringstream(bom + "1")) == 1);
  766. SaxEventLogger l1;
  767. SaxEventLogger l2;
  768. CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
  769. CHECK(json::sax_parse(bom + "1", &l2));
  770. CHECK(l1.events.size() == 1);
  771. CHECK(l1.events == std::vector<std::string>(
  772. {
  773. "number_unsigned(1)"
  774. }));
  775. CHECK(l2.events.size() == 1);
  776. CHECK(l2.events == std::vector<std::string>(
  777. {
  778. "number_unsigned(1)"
  779. }));
  780. }
  781. SECTION("2 byte of BOM")
  782. {
  783. json _;
  784. CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 2)), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&);
  785. CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 2))), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&);
  786. SaxEventLogger l1;
  787. SaxEventLogger l2;
  788. CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
  789. CHECK(!json::sax_parse(bom.substr(0, 2), &l2));
  790. CHECK(l1.events.size() == 1);
  791. CHECK(l1.events == std::vector<std::string>(
  792. {
  793. "parse_error(3)"
  794. }));
  795. CHECK(l2.events.size() == 1);
  796. CHECK(l2.events == std::vector<std::string>(
  797. {
  798. "parse_error(3)"
  799. }));
  800. }
  801. SECTION("1 byte of BOM")
  802. {
  803. json _;
  804. CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 1)), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&);
  805. CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 1))), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&);
  806. SaxEventLogger l1;
  807. SaxEventLogger l2;
  808. CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
  809. CHECK(!json::sax_parse(bom.substr(0, 1), &l2));
  810. CHECK(l1.events.size() == 1);
  811. CHECK(l1.events == std::vector<std::string>(
  812. {
  813. "parse_error(2)"
  814. }));
  815. CHECK(l2.events.size() == 1);
  816. CHECK(l2.events == std::vector<std::string>(
  817. {
  818. "parse_error(2)"
  819. }));
  820. }
  821. SECTION("variations")
  822. {
  823. // calculate variations of each byte of the BOM to make sure
  824. // that the BOM and only the BOM is skipped
  825. for (int i0 = -1; i0 < 2; ++i0)
  826. {
  827. for (int i1 = -1; i1 < 2; ++i1)
  828. {
  829. for (int i2 = -1; i2 < 2; ++i2)
  830. {
  831. // debug output for the variations
  832. CAPTURE(i0)
  833. CAPTURE(i1)
  834. CAPTURE(i2)
  835. std::string s;
  836. s.push_back(static_cast<char>(bom[0] + i0));
  837. s.push_back(static_cast<char>(bom[1] + i1));
  838. s.push_back(static_cast<char>(bom[2] + i2));
  839. if (i0 == 0 && i1 == 0 && i2 == 0)
  840. {
  841. // without any variation, we skip the BOM
  842. CHECK(json::parse(s + "null") == json());
  843. CHECK(json::parse(std::istringstream(s + "null")) == json());
  844. SaxEventLogger l;
  845. CHECK(json::sax_parse(s + "null", &l));
  846. CHECK(l.events.size() == 1);
  847. CHECK(l.events == std::vector<std::string>(
  848. {
  849. "null()"
  850. }));
  851. }
  852. else
  853. {
  854. // any variation is an error
  855. json _;
  856. CHECK_THROWS_AS(_ = json::parse(s + "null"), json::parse_error&);
  857. CHECK_THROWS_AS(_ = json::parse(std::istringstream(s + "null")), json::parse_error&);
  858. SaxEventLogger l;
  859. CHECK(!json::sax_parse(s + "null", &l));
  860. CHECK(l.events.size() == 1);
  861. if (i0 != 0)
  862. {
  863. CHECK(l.events == std::vector<std::string>(
  864. {
  865. "parse_error(1)"
  866. }));
  867. }
  868. else if (i1 != 0)
  869. {
  870. CHECK(l.events == std::vector<std::string>(
  871. {
  872. "parse_error(2)"
  873. }));
  874. }
  875. else
  876. {
  877. CHECK(l.events == std::vector<std::string>(
  878. {
  879. "parse_error(3)"
  880. }));
  881. }
  882. }
  883. }
  884. }
  885. }
  886. }
  887. SECTION("preserve state after parsing")
  888. {
  889. std::istringstream s(bom + "123 456");
  890. json j;
  891. j << s;
  892. CHECK(j == 123);
  893. j << s;
  894. CHECK(j == 456);
  895. }
  896. }
  897. SECTION("SAX and early abort")
  898. {
  899. std::string const s = R"([1, ["string", 43.12], null, {"key1": true, "key2": false}])";
  900. SaxEventLogger default_logger;
  901. SaxEventLoggerExitAfterStartObject exit_after_start_object;
  902. SaxEventLoggerExitAfterKey exit_after_key;
  903. SaxEventLoggerExitAfterStartArray exit_after_start_array;
  904. json::sax_parse(s, &default_logger);
  905. CHECK(default_logger.events.size() == 14);
  906. CHECK(default_logger.events == std::vector<std::string>(
  907. {
  908. "start_array()", "number_unsigned(1)", "start_array()",
  909. "string(string)", "number_float(43.12)", "end_array()", "null()",
  910. "start_object()", "key(key1)", "boolean(true)", "key(key2)",
  911. "boolean(false)", "end_object()", "end_array()"
  912. }));
  913. json::sax_parse(s, &exit_after_start_object);
  914. CHECK(exit_after_start_object.events.size() == 8);
  915. CHECK(exit_after_start_object.events == std::vector<std::string>(
  916. {
  917. "start_array()", "number_unsigned(1)", "start_array()",
  918. "string(string)", "number_float(43.12)", "end_array()", "null()",
  919. "start_object()"
  920. }));
  921. json::sax_parse(s, &exit_after_key);
  922. CHECK(exit_after_key.events.size() == 9);
  923. CHECK(exit_after_key.events == std::vector<std::string>(
  924. {
  925. "start_array()", "number_unsigned(1)", "start_array()",
  926. "string(string)", "number_float(43.12)", "end_array()", "null()",
  927. "start_object()", "key(key1)"
  928. }));
  929. json::sax_parse(s, &exit_after_start_array);
  930. CHECK(exit_after_start_array.events.size() == 1);
  931. CHECK(exit_after_start_array.events == std::vector<std::string>(
  932. {
  933. "start_array()"
  934. }));
  935. }
  936. SECTION("JSON Lines")
  937. {
  938. SECTION("Example file")
  939. {
  940. std::stringstream ss;
  941. ss << R"({"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
  942. {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]}
  943. {"name": "May", "wins": []}
  944. {"name": "Deloise", "wins": [["three of a kind", "5♣"]]}
  945. )";
  946. std::string line;
  947. int object_count = 0;
  948. while (std::getline(ss, line))
  949. {
  950. ++object_count;
  951. CHECK(json::accept(line));
  952. }
  953. CHECK(object_count == 4);
  954. }
  955. SECTION("Example file without trailing newline")
  956. {
  957. std::stringstream ss;
  958. ss << R"({"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
  959. {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]}
  960. {"name": "May", "wins": []}
  961. {"name": "Deloise", "wins": [["three of a kind", "5♣"]]})";
  962. std::string line;
  963. int object_count = 0;
  964. while (std::getline(ss, line))
  965. {
  966. ++object_count;
  967. CHECK(json::accept(line));
  968. }
  969. CHECK(object_count == 4);
  970. }
  971. }
  972. }
  973. TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T,
  974. char, unsigned char, signed char,
  975. wchar_t,
  976. char16_t, char32_t,
  977. std::uint8_t, std::int8_t,
  978. std::int16_t, std::uint16_t,
  979. std::int32_t, std::uint32_t)
  980. {
  981. std::vector<T> const v = {'t', 'r', 'u', 'e'};
  982. CHECK(json::parse(v) == json(true));
  983. CHECK(json::accept(v));
  984. SaxEventLogger l;
  985. CHECK(json::sax_parse(v, &l));
  986. CHECK(l.events.size() == 1);
  987. CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
  988. }
  989. TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T,
  990. char, unsigned char, std::uint8_t)
  991. {
  992. // a star emoji
  993. std::vector<T> const v = {'"', static_cast<T>(0xe2u), static_cast<T>(0xadu), static_cast<T>(0x90u), static_cast<T>(0xefu), static_cast<T>(0xb8u), static_cast<T>(0x8fu), '"'};
  994. CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
  995. CHECK(json::accept(v));
  996. SaxEventLogger l;
  997. CHECK(json::sax_parse(v, &l));
  998. CHECK(l.events.size() == 1);
  999. }
  1000. TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T,
  1001. char16_t, std::uint16_t)
  1002. {
  1003. // a star emoji
  1004. std::vector<T> const v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
  1005. CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
  1006. CHECK(json::accept(v));
  1007. SaxEventLogger l;
  1008. CHECK(json::sax_parse(v, &l));
  1009. CHECK(l.events.size() == 1);
  1010. }
  1011. TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T,
  1012. char32_t, std::uint32_t)
  1013. {
  1014. // a star emoji
  1015. std::vector<T> const v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
  1016. CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
  1017. CHECK(json::accept(v));
  1018. SaxEventLogger l;
  1019. CHECK(json::sax_parse(v, &l));
  1020. CHECK(l.events.size() == 1);
  1021. }