unit-diagnostics.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. #ifdef JSON_DIAGNOSTICS
  11. #undef JSON_DIAGNOSTICS
  12. #endif
  13. #define JSON_DIAGNOSTICS 1
  14. #include <nlohmann/json.hpp>
  15. using nlohmann::json;
  16. TEST_CASE("Better diagnostics")
  17. {
  18. SECTION("empty JSON Pointer")
  19. {
  20. json const j = 1;
  21. std::string s;
  22. CHECK_THROWS_WITH_AS(s = j.get<std::string>(), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
  23. }
  24. SECTION("invalid type")
  25. {
  26. json j;
  27. j["a"]["b"]["c"] = 1;
  28. std::string s;
  29. CHECK_THROWS_WITH_AS(s = j["a"]["b"]["c"].get<std::string>(), "[json.exception.type_error.302] (/a/b/c) type must be string, but is number", json::type_error);
  30. }
  31. SECTION("missing key")
  32. {
  33. json j;
  34. j["object"]["object"] = true;
  35. CHECK_THROWS_WITH_AS(j["object"].at("not_found"), "[json.exception.out_of_range.403] (/object) key 'not_found' not found", json::out_of_range);
  36. }
  37. SECTION("array index out of range")
  38. {
  39. json j;
  40. j["array"][4] = true;
  41. CHECK_THROWS_WITH_AS(j["array"].at(5), "[json.exception.out_of_range.401] (/array) array index 5 is out of range", json::out_of_range);
  42. }
  43. SECTION("array index at wrong type")
  44. {
  45. json j;
  46. j["array"][4] = true;
  47. CHECK_THROWS_WITH_AS(j["array"][4][5], "[json.exception.type_error.305] (/array/4) cannot use operator[] with a numeric argument with boolean", json::type_error);
  48. }
  49. SECTION("wrong iterator")
  50. {
  51. json j;
  52. j["array"] = json::array();
  53. CHECK_THROWS_WITH_AS(j["array"].erase(j.begin()), "[json.exception.invalid_iterator.202] (/array) iterator does not fit current value", json::invalid_iterator);
  54. }
  55. SECTION("JSON Pointer escaping")
  56. {
  57. json j;
  58. j["a/b"]["m~n"] = 1;
  59. std::string s;
  60. CHECK_THROWS_WITH_AS(s = j["a/b"]["m~n"].get<std::string>(), "[json.exception.type_error.302] (/a~1b/m~0n) type must be string, but is number", json::type_error);
  61. }
  62. SECTION("Parse error")
  63. {
  64. json _;
  65. CHECK_THROWS_WITH_AS(_ = json::parse(""), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error);
  66. }
  67. SECTION("Wrong type in update()")
  68. {
  69. json j = {{"foo", "bar"}};
  70. json k = {{"bla", 1}};
  71. CHECK_THROWS_WITH_AS(j.update(k["bla"].begin(), k["bla"].end()), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
  72. CHECK_THROWS_WITH_AS(j.update(k["bla"]), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
  73. }
  74. }
  75. TEST_CASE("Regression tests for extended diagnostics")
  76. {
  77. SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
  78. {
  79. CHECK_THROWS_WITH_AS(json({"0", "0"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
  80. CHECK_THROWS_WITH_AS(json({"0", "1"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
  81. }
  82. SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
  83. {
  84. json j;
  85. j["/foo"] = {1, 2, 3};
  86. CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
  87. }
  88. SECTION("Regression test for issue #2838 - Assertion failure when inserting into arrays with JSON_DIAGNOSTICS set")
  89. {
  90. // void push_back(basic_json&& val)
  91. {
  92. json j_arr = json::array();
  93. j_arr.push_back(json::object());
  94. j_arr.push_back(json::object());
  95. j_arr.push_back(json::object());
  96. j_arr.push_back(json::object());
  97. json j_obj = json::object();
  98. j_obj["key"] = j_arr;
  99. }
  100. // void push_back(const basic_json& val)
  101. {
  102. json j_arr = json::array();
  103. auto object = json::object();
  104. j_arr.push_back(object);
  105. j_arr.push_back(object);
  106. j_arr.push_back(object);
  107. j_arr.push_back(object);
  108. json j_obj = json::object();
  109. j_obj["key"] = j_arr;
  110. }
  111. // reference emplace_back(Args&& ... args)
  112. {
  113. json j_arr = json::array();
  114. j_arr.emplace_back(json::object());
  115. j_arr.emplace_back(json::object());
  116. j_arr.emplace_back(json::object());
  117. j_arr.emplace_back(json::object());
  118. json j_obj = json::object();
  119. j_obj["key"] = j_arr;
  120. }
  121. // iterator insert(const_iterator pos, const basic_json& val)
  122. {
  123. json j_arr = json::array();
  124. j_arr.insert(j_arr.begin(), json::object());
  125. j_arr.insert(j_arr.begin(), json::object());
  126. j_arr.insert(j_arr.begin(), json::object());
  127. j_arr.insert(j_arr.begin(), json::object());
  128. json j_obj = json::object();
  129. j_obj["key"] = j_arr;
  130. }
  131. // iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
  132. {
  133. json j_arr = json::array();
  134. j_arr.insert(j_arr.begin(), 2, json::object());
  135. json j_obj = json::object();
  136. j_obj["key"] = j_arr;
  137. }
  138. // iterator insert(const_iterator pos, const_iterator first, const_iterator last)
  139. {
  140. json j_arr = json::array();
  141. json j_objects = {json::object(), json::object()};
  142. j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
  143. json j_obj = json::object();
  144. j_obj["key"] = j_arr;
  145. }
  146. }
  147. SECTION("Regression test for issue #2962 - JSON_DIAGNOSTICS assertion for ordered_json")
  148. {
  149. nlohmann::ordered_json j;
  150. nlohmann::ordered_json j2;
  151. const std::string value;
  152. j["first"] = value;
  153. j["second"] = value;
  154. j2["something"] = j;
  155. }
  156. SECTION("Regression test for issue #3007 - Parent pointers properly set when using update()")
  157. {
  158. // void update(const_reference j)
  159. {
  160. json j = json::object();
  161. {
  162. json j2 = json::object();
  163. j2["one"] = 1;
  164. j.update(j2);
  165. }
  166. // Must call operator[] on const element, otherwise m_parent gets updated.
  167. auto const& constJ = j;
  168. CHECK_THROWS_WITH_AS(constJ["one"].at(0), "[json.exception.type_error.304] (/one) cannot use at() with number", json::type_error);
  169. }
  170. // void update(const_iterator first, const_iterator last)
  171. {
  172. json j = json::object();
  173. {
  174. json j2 = json::object();
  175. j2["one"] = 1;
  176. j.update(j2.begin(), j2.end());
  177. }
  178. // Must call operator[] on const element, otherwise m_parent gets updated.
  179. auto const& constJ = j;
  180. CHECK_THROWS_WITH_AS(constJ["one"].at(0), "[json.exception.type_error.304] (/one) cannot use at() with number", json::type_error);
  181. }
  182. // Code from #3007 triggering unwanted assertion without fix to update().
  183. {
  184. json root = json::array();
  185. json lower = json::object();
  186. {
  187. json lowest = json::object();
  188. lowest["one"] = 1;
  189. lower.update(lowest);
  190. }
  191. root.push_back(lower);
  192. }
  193. }
  194. SECTION("Regression test for issue #3032 - Yet another assertion failure when inserting into arrays with JSON_DIAGNOSTICS set")
  195. {
  196. // reference operator[](size_type idx)
  197. {
  198. json j_arr = json::array();
  199. j_arr[0] = 0;
  200. j_arr[1] = 1;
  201. j_arr[2] = 2;
  202. j_arr[3] = 3;
  203. j_arr[4] = 4;
  204. j_arr[5] = 5;
  205. j_arr[6] = 6;
  206. j_arr[7] = 7;
  207. json const j_arr_copy = j_arr;
  208. }
  209. }
  210. }