2
0

unit-inspection.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. // __ _____ _____ _____
  2. // __| | __| | | | JSON for Modern C++ (supporting code)
  3. // | | |__ | | | | | | version 3.11.2
  4. // |_____|_____|_____|_|___| https://github.com/nlohmann/json
  5. //
  6. // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  7. // SPDX-License-Identifier: MIT
  8. #include "doctest_compatibility.h"
  9. #include <nlohmann/json.hpp>
  10. using nlohmann::json;
  11. #include <fstream>
  12. #include <sstream>
  13. #include "make_test_data_available.hpp"
  14. TEST_CASE("object inspection")
  15. {
  16. SECTION("convenience type checker")
  17. {
  18. SECTION("object")
  19. {
  20. json const j {{"foo", 1}, {"bar", false}};
  21. CHECK(!j.is_null());
  22. CHECK(!j.is_boolean());
  23. CHECK(!j.is_number());
  24. CHECK(!j.is_number_integer());
  25. CHECK(!j.is_number_unsigned());
  26. CHECK(!j.is_number_float());
  27. CHECK(!j.is_binary());
  28. CHECK(j.is_object());
  29. CHECK(!j.is_array());
  30. CHECK(!j.is_string());
  31. CHECK(!j.is_discarded());
  32. CHECK(!j.is_primitive());
  33. CHECK(j.is_structured());
  34. }
  35. SECTION("array")
  36. {
  37. json const j {"foo", 1, 1u, 42.23, false};
  38. CHECK(!j.is_null());
  39. CHECK(!j.is_boolean());
  40. CHECK(!j.is_number());
  41. CHECK(!j.is_number_integer());
  42. CHECK(!j.is_number_unsigned());
  43. CHECK(!j.is_number_float());
  44. CHECK(!j.is_binary());
  45. CHECK(!j.is_object());
  46. CHECK(j.is_array());
  47. CHECK(!j.is_string());
  48. CHECK(!j.is_discarded());
  49. CHECK(!j.is_primitive());
  50. CHECK(j.is_structured());
  51. }
  52. SECTION("null")
  53. {
  54. json const j(nullptr);
  55. CHECK(j.is_null());
  56. CHECK(!j.is_boolean());
  57. CHECK(!j.is_number());
  58. CHECK(!j.is_number_integer());
  59. CHECK(!j.is_number_unsigned());
  60. CHECK(!j.is_number_float());
  61. CHECK(!j.is_binary());
  62. CHECK(!j.is_object());
  63. CHECK(!j.is_array());
  64. CHECK(!j.is_string());
  65. CHECK(!j.is_discarded());
  66. CHECK(j.is_primitive());
  67. CHECK(!j.is_structured());
  68. }
  69. SECTION("boolean")
  70. {
  71. json const j(true);
  72. CHECK(!j.is_null());
  73. CHECK(j.is_boolean());
  74. CHECK(!j.is_number());
  75. CHECK(!j.is_number_integer());
  76. CHECK(!j.is_number_unsigned());
  77. CHECK(!j.is_number_float());
  78. CHECK(!j.is_binary());
  79. CHECK(!j.is_object());
  80. CHECK(!j.is_array());
  81. CHECK(!j.is_string());
  82. CHECK(!j.is_discarded());
  83. CHECK(j.is_primitive());
  84. CHECK(!j.is_structured());
  85. }
  86. SECTION("string")
  87. {
  88. json const j("Hello world");
  89. CHECK(!j.is_null());
  90. CHECK(!j.is_boolean());
  91. CHECK(!j.is_number());
  92. CHECK(!j.is_number_integer());
  93. CHECK(!j.is_number_unsigned());
  94. CHECK(!j.is_number_float());
  95. CHECK(!j.is_binary());
  96. CHECK(!j.is_object());
  97. CHECK(!j.is_array());
  98. CHECK(j.is_string());
  99. CHECK(!j.is_discarded());
  100. CHECK(j.is_primitive());
  101. CHECK(!j.is_structured());
  102. }
  103. SECTION("number (integer)")
  104. {
  105. json const j(42);
  106. CHECK(!j.is_null());
  107. CHECK(!j.is_boolean());
  108. CHECK(j.is_number());
  109. CHECK(j.is_number_integer());
  110. CHECK(!j.is_number_unsigned());
  111. CHECK(!j.is_number_float());
  112. CHECK(!j.is_binary());
  113. CHECK(!j.is_object());
  114. CHECK(!j.is_array());
  115. CHECK(!j.is_string());
  116. CHECK(!j.is_discarded());
  117. CHECK(j.is_primitive());
  118. CHECK(!j.is_structured());
  119. }
  120. SECTION("number (unsigned)")
  121. {
  122. json const j(42u);
  123. CHECK(!j.is_null());
  124. CHECK(!j.is_boolean());
  125. CHECK(j.is_number());
  126. CHECK(j.is_number_integer());
  127. CHECK(j.is_number_unsigned());
  128. CHECK(!j.is_number_float());
  129. CHECK(!j.is_binary());
  130. CHECK(!j.is_object());
  131. CHECK(!j.is_array());
  132. CHECK(!j.is_string());
  133. CHECK(!j.is_discarded());
  134. CHECK(j.is_primitive());
  135. CHECK(!j.is_structured());
  136. }
  137. SECTION("number (floating-point)")
  138. {
  139. json const j(42.23);
  140. CHECK(!j.is_null());
  141. CHECK(!j.is_boolean());
  142. CHECK(j.is_number());
  143. CHECK(!j.is_number_integer());
  144. CHECK(!j.is_number_unsigned());
  145. CHECK(j.is_number_float());
  146. CHECK(!j.is_binary());
  147. CHECK(!j.is_object());
  148. CHECK(!j.is_array());
  149. CHECK(!j.is_string());
  150. CHECK(!j.is_discarded());
  151. CHECK(j.is_primitive());
  152. CHECK(!j.is_structured());
  153. }
  154. SECTION("binary")
  155. {
  156. json const j(json::value_t::binary);
  157. CHECK(!j.is_null());
  158. CHECK(!j.is_boolean());
  159. CHECK(!j.is_number());
  160. CHECK(!j.is_number_integer());
  161. CHECK(!j.is_number_unsigned());
  162. CHECK(!j.is_number_float());
  163. CHECK(j.is_binary());
  164. CHECK(!j.is_object());
  165. CHECK(!j.is_array());
  166. CHECK(!j.is_string());
  167. CHECK(!j.is_discarded());
  168. CHECK(j.is_primitive());
  169. CHECK(!j.is_structured());
  170. }
  171. SECTION("discarded")
  172. {
  173. json const j(json::value_t::discarded);
  174. CHECK(!j.is_null());
  175. CHECK(!j.is_boolean());
  176. CHECK(!j.is_number());
  177. CHECK(!j.is_number_integer());
  178. CHECK(!j.is_number_unsigned());
  179. CHECK(!j.is_number_float());
  180. CHECK(!j.is_binary());
  181. CHECK(!j.is_object());
  182. CHECK(!j.is_array());
  183. CHECK(!j.is_string());
  184. CHECK(j.is_discarded());
  185. CHECK(!j.is_primitive());
  186. CHECK(!j.is_structured());
  187. }
  188. }
  189. SECTION("serialization")
  190. {
  191. json const j {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
  192. SECTION("no indent / indent=-1")
  193. {
  194. CHECK(j.dump() ==
  195. "{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
  196. CHECK(j.dump() == j.dump(-1));
  197. }
  198. SECTION("indent=0")
  199. {
  200. CHECK(j.dump(0) ==
  201. "{\n\"array\": [\n1,\n2,\n3,\n4\n],\n\"boolean\": false,\n\"null\": null,\n\"number\": 42,\n\"object\": {},\n\"string\": \"Hello world\"\n}");
  202. }
  203. SECTION("indent=1, space='\t'")
  204. {
  205. CHECK(j.dump(1, '\t') ==
  206. "{\n\t\"array\": [\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t4\n\t],\n\t\"boolean\": false,\n\t\"null\": null,\n\t\"number\": 42,\n\t\"object\": {},\n\t\"string\": \"Hello world\"\n}");
  207. }
  208. SECTION("indent=4")
  209. {
  210. CHECK(j.dump(4) ==
  211. "{\n \"array\": [\n 1,\n 2,\n 3,\n 4\n ],\n \"boolean\": false,\n \"null\": null,\n \"number\": 42,\n \"object\": {},\n \"string\": \"Hello world\"\n}");
  212. }
  213. SECTION("indent=x")
  214. {
  215. CHECK(j.dump().size() == 94);
  216. CHECK(j.dump(1).size() == 127);
  217. CHECK(j.dump(2).size() == 142);
  218. CHECK(j.dump(512).size() == 7792);
  219. // important test, because it yields a resize of the indent_string
  220. // inside the dump() function
  221. CHECK(j.dump(1024).size() == 15472);
  222. const auto binary = json::binary({1, 2, 3}, 128);
  223. CHECK(binary.dump(1024).size() == 2086);
  224. }
  225. SECTION("dump and floating-point numbers")
  226. {
  227. auto s = json(42.23).dump();
  228. CHECK(s.find("42.23") != std::string::npos);
  229. }
  230. SECTION("dump and small floating-point numbers")
  231. {
  232. auto s = json(1.23456e-78).dump();
  233. CHECK(s.find("1.23456e-78") != std::string::npos);
  234. }
  235. SECTION("dump and non-ASCII characters")
  236. {
  237. CHECK(json("ä").dump() == "\"ä\"");
  238. CHECK(json("Ö").dump() == "\"Ö\"");
  239. CHECK(json("❤️").dump() == "\"❤️\"");
  240. }
  241. SECTION("dump with ensure_ascii and non-ASCII characters")
  242. {
  243. CHECK(json("ä").dump(-1, ' ', true) == "\"\\u00e4\"");
  244. CHECK(json("Ö").dump(-1, ' ', true) == "\"\\u00d6\"");
  245. CHECK(json("❤️").dump(-1, ' ', true) == "\"\\u2764\\ufe0f\"");
  246. }
  247. SECTION("full Unicode escaping to ASCII")
  248. {
  249. SECTION("parsing yields the same JSON value")
  250. {
  251. std::ifstream f_escaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode_ascii.json");
  252. std::ifstream f_unescaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json");
  253. json j1 = json::parse(f_escaped);
  254. json j2 = json::parse(f_unescaped);
  255. CHECK(j1 == j2);
  256. }
  257. SECTION("dumping yields the same JSON text")
  258. {
  259. std::ifstream f_escaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode_ascii.json");
  260. std::ifstream f_unescaped(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json");
  261. json const value = json::parse(f_unescaped);
  262. std::string text = value.dump(4, ' ', true);
  263. std::string expected((std::istreambuf_iterator<char>(f_escaped)),
  264. std::istreambuf_iterator<char>());
  265. CHECK(text == expected);
  266. }
  267. }
  268. SECTION("serialization of discarded element")
  269. {
  270. json const j_discarded(json::value_t::discarded);
  271. CHECK(j_discarded.dump() == "<discarded>");
  272. }
  273. SECTION("check that precision is reset after serialization")
  274. {
  275. // create stringstream and set precision
  276. std::stringstream ss;
  277. ss.precision(3);
  278. ss << 3.141592653589793 << std::fixed;
  279. CHECK(ss.str() == "3.14");
  280. // reset stringstream
  281. ss.str(std::string());
  282. // use stringstream for JSON serialization
  283. json const j_number = 3.14159265358979;
  284. ss << j_number;
  285. // check that precision has been overridden during serialization
  286. CHECK(ss.str() == "3.14159265358979");
  287. // check that precision has been restored
  288. CHECK(ss.precision() == 3);
  289. }
  290. }
  291. SECTION("round trips")
  292. {
  293. for (const auto& s :
  294. {"3.141592653589793", "1000000000000000010E5"
  295. })
  296. {
  297. json const j1 = json::parse(s);
  298. std::string s1 = j1.dump();
  299. json const j2 = json::parse(s1);
  300. std::string s2 = j2.dump();
  301. CHECK(s1 == s2);
  302. }
  303. }
  304. SECTION("return the type of the object (explicit)")
  305. {
  306. SECTION("null")
  307. {
  308. json const j = nullptr;
  309. CHECK(j.type() == json::value_t::null);
  310. }
  311. SECTION("object")
  312. {
  313. json const j = {{"foo", "bar"}};
  314. CHECK(j.type() == json::value_t::object);
  315. }
  316. SECTION("array")
  317. {
  318. json const j = {1, 2, 3, 4};
  319. CHECK(j.type() == json::value_t::array);
  320. }
  321. SECTION("boolean")
  322. {
  323. json const j = true;
  324. CHECK(j.type() == json::value_t::boolean);
  325. }
  326. SECTION("string")
  327. {
  328. json const j = "Hello world";
  329. CHECK(j.type() == json::value_t::string);
  330. }
  331. SECTION("number (integer)")
  332. {
  333. json const j = 23;
  334. CHECK(j.type() == json::value_t::number_integer);
  335. }
  336. SECTION("number (unsigned)")
  337. {
  338. json const j = 23u;
  339. CHECK(j.type() == json::value_t::number_unsigned);
  340. }
  341. SECTION("number (floating-point)")
  342. {
  343. json const j = 42.23;
  344. CHECK(j.type() == json::value_t::number_float);
  345. }
  346. }
  347. SECTION("return the type of the object (implicit)")
  348. {
  349. SECTION("null")
  350. {
  351. json const j = nullptr;
  352. json::value_t t = j;
  353. CHECK(t == j.type());
  354. }
  355. SECTION("object")
  356. {
  357. json const j = {{"foo", "bar"}};
  358. json::value_t t = j;
  359. CHECK(t == j.type());
  360. }
  361. SECTION("array")
  362. {
  363. json const j = {1, 2, 3, 4};
  364. json::value_t t = j;
  365. CHECK(t == j.type());
  366. }
  367. SECTION("boolean")
  368. {
  369. json const j = true;
  370. json::value_t t = j;
  371. CHECK(t == j.type());
  372. }
  373. SECTION("string")
  374. {
  375. json const j = "Hello world";
  376. json::value_t t = j;
  377. CHECK(t == j.type());
  378. }
  379. SECTION("number (integer)")
  380. {
  381. json const j = 23;
  382. json::value_t t = j;
  383. CHECK(t == j.type());
  384. }
  385. SECTION("number (unsigned)")
  386. {
  387. json const j = 23u;
  388. json::value_t t = j;
  389. CHECK(t == j.type());
  390. }
  391. SECTION("number (floating-point)")
  392. {
  393. json const j = 42.23;
  394. json::value_t t = j;
  395. CHECK(t == j.type());
  396. }
  397. SECTION("binary")
  398. {
  399. json const j = json::binary({});
  400. json::value_t t = j;
  401. CHECK(t == j.type());
  402. }
  403. }
  404. }