• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include "doctest_compatibility.h"
10 
11 // for some reason including this after the json header leads to linker errors with VS 2017...
12 #include <locale>
13 
14 #define JSON_TESTS_PRIVATE
15 #include <nlohmann/json.hpp>
16 using nlohmann::json;
17 #ifdef JSON_TEST_NO_GLOBAL_UDLS
18     using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
19 #endif
20 
21 #include <fstream>
22 #include <sstream>
23 #include <list>
24 #include <cstdio>
25 #include "make_test_data_available.hpp"
26 
27 #ifdef JSON_HAS_CPP_17
28     #include <variant>
29 #endif
30 
31 #include "fifo_map.hpp"
32 
33 /////////////////////////////////////////////////////////////////////
34 // for #972
35 /////////////////////////////////////////////////////////////////////
36 
37 template<class K, class V, class dummy_compare, class A>
38 using my_workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
39 using my_json = nlohmann::basic_json<my_workaround_fifo_map>;
40 
41 /////////////////////////////////////////////////////////////////////
42 // for #977
43 /////////////////////////////////////////////////////////////////////
44 
45 namespace ns
46 {
47 struct foo
48 {
49     int x;
50 };
51 
52 template <typename, typename SFINAE = void>
53 struct foo_serializer;
54 
55 template<typename T>
56 struct foo_serializer<T, typename std::enable_if<std::is_same<foo, T>::value>::type>
57 {
58     template <typename BasicJsonType>
to_jsonns::foo_serializer59     static void to_json(BasicJsonType& j, const T& value)
60     {
61         j = BasicJsonType{{"x", value.x}};
62     }
63     template <typename BasicJsonType>
from_jsonns::foo_serializer64     static void from_json(const BasicJsonType& j, T& value)     // !!!
65     {
66         nlohmann::from_json(j.at("x"), value.x);
67     }
68 };
69 
70 template<typename T>
71 struct foo_serializer < T, typename std::enable_if < !std::is_same<foo, T>::value >::type >
72 {
73     template <typename BasicJsonType>
to_jsonns::foo_serializer74     static void to_json(BasicJsonType& j, const T& value) noexcept // NOLINT(bugprone-exception-escape)
75     {
76         ::nlohmann::to_json(j, value);
77     }
78     template <typename BasicJsonType>
from_jsonns::foo_serializer79     static void from_json(const BasicJsonType& j, T& value)   //!!!
80     {
81         ::nlohmann::from_json(j, value);
82     }
83 };
84 } // namespace ns
85 
86 using foo_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t,
87       std::uint64_t, double, std::allocator, ns::foo_serializer, std::vector<std::uint8_t>>;
88 
89 /////////////////////////////////////////////////////////////////////
90 // for #805
91 /////////////////////////////////////////////////////////////////////
92 
93 namespace
94 {
95 struct nocopy // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
96 {
97     nocopy() = default;
98     nocopy(const nocopy&) = delete;
99     nocopy(nocopy&&) = delete;
100     nocopy& operator=(const nocopy&) = delete;
101     nocopy& operator=(nocopy&&) = delete;
102 
103     int val = 0;
104 
to_json(json & j,const nocopy & n)105     friend void to_json(json& j, const nocopy& n)
106     {
107         j = {{"val", n.val}};
108     }
109 };
110 } // namespace
111 
112 TEST_CASE("regression tests 1")
113 {
114     SECTION("issue #60 - Double quotation mark is not parsed correctly")
115     {
116         SECTION("escape_doublequote")
117         {
118             const auto* s = R"(["\"foo\""])";
119             json j = json::parse(s);
120             auto expected = R"(["\"foo\""])"_json;
121             CHECK(j == expected);
122         }
123     }
124 
125     SECTION("issue #70 - Handle infinity and NaN cases")
126     {
127         // previously, NAN/INFINITY created a null value; now, the values are
128         // properly stored, but are dumped as "null"
129         SECTION("NAN value")
130         {
131             CHECK(json(NAN).dump() == "null");
132             CHECK(json(json::number_float_t(NAN)).dump() == "null");
133         }
134 
135         SECTION("infinity")
136         {
137             CHECK(json(INFINITY).dump() == "null");
138             CHECK(json(json::number_float_t(INFINITY)).dump() == "null");
139         }
140 
141         // With 3.0.0, the semantics of this changed: NAN and infinity are
142         // stored properly inside the JSON value (no exception or conversion
143         // to null), but are serialized as null.
144         SECTION("NAN value")
145         {
146             json j1 = NAN;
147             CHECK(j1.is_number_float());
148             json::number_float_t f1{j1};
149             CHECK(std::isnan(f1));
150 
151             json j2 = static_cast<json::number_float_t>(NAN);
152             CHECK(j2.is_number_float());
153             json::number_float_t f2{j2};
154             CHECK(std::isnan(f2));
155         }
156 
157         SECTION("infinity")
158         {
159             json j1 = INFINITY;
160             CHECK(j1.is_number_float());
161             json::number_float_t f1{j1};
162             CHECK(!std::isfinite(f1));
163 
164             json j2 = static_cast<json::number_float_t>(INFINITY);
165             CHECK(j2.is_number_float());
166             json::number_float_t f2{j2};
167             CHECK(!std::isfinite(f2));
168         }
169     }
170 
171     SECTION("pull request #71 - handle enum type")
172     {
173         enum { t = 0, u = 102};
174         json j = json::array();
175         j.push_back(t);
176 
177         // maybe this is not the place to test this?
178         json j2 = u;
179 
180         auto anon_enum_value = j2.get<decltype(u)>();
181         CHECK(u == anon_enum_value);
182 
183         // check if the actual value was stored
184         CHECK(j2 == 102);
185 
186         static_assert(std::is_same<decltype(anon_enum_value), decltype(u)>::value, "types must be the same");
187 
188         j.push_back(json::object(
189         {
190             {"game_type", t}
191         }));
192     }
193 
194     SECTION("issue #76 - dump() / parse() not idempotent")
195     {
196         // create JSON object
197         json fields;
198         fields["one"] = std::string("one");
199         fields["two"] = std::string("two three");
200         fields["three"] = std::string("three \"four\"");
201 
202         // create another JSON object by deserializing the serialization
203         std::string payload = fields.dump();
204         json parsed_fields = json::parse(payload);
205 
206         // check individual fields to match both objects
207         CHECK(parsed_fields["one"] == fields["one"]);
208         CHECK(parsed_fields["two"] == fields["two"]);
209         CHECK(parsed_fields["three"] == fields["three"]);
210 
211         // check individual fields to match original input
212         CHECK(parsed_fields["one"] == std::string("one"));
213         CHECK(parsed_fields["two"] == std::string("two three"));
214         CHECK(parsed_fields["three"] == std::string("three \"four\""));
215 
216         // check equality of the objects
217         CHECK(parsed_fields == fields);
218 
219         // check equality of the serialized objects
220         CHECK(fields.dump() == parsed_fields.dump());
221 
222         // check everything in one line
223         CHECK(fields == json::parse(fields.dump()));
224     }
225 
226     SECTION("issue #82 - lexer::get_number return NAN")
227     {
228         const auto* const content = R"(
229         {
230             "Test":"Test1",
231             "Number":100,
232             "Foo":42.42
233         })";
234 
235         std::stringstream ss;
236         ss << content;
237         json j;
238         ss >> j;
239 
240         auto test = j["Test"].get<std::string>();
241         CHECK(test == "Test1");
242         int number{j["Number"]};
243         CHECK(number == 100);
244         float foo{j["Foo"]};
245         CHECK(static_cast<double>(foo) == Approx(42.42));
246     }
247 
248     SECTION("issue #89 - nonstandard integer type")
249     {
250         // create JSON class with nonstandard integer number type
251         using custom_json =
252             nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
253         custom_json j;
254         j["int_1"] = 1;
255         CHECK(j["int_1"] == 1);
256 
257         // tests for correct handling of non-standard integers that overflow the type selected by the user
258 
259         // unsigned integer object creation - expected to wrap and still be stored as an integer
260         j = 4294967296U; // 2^32
261         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
262         CHECK(j.get<uint32_t>() == 0);  // Wrap
263 
264         // unsigned integer parsing - expected to overflow and be stored as a float
265         j = custom_json::parse("4294967296"); // 2^32
266         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
267         CHECK(j.get<float>() == 4294967296.0f);
268 
269         // integer object creation - expected to wrap and still be stored as an integer
270         j = -2147483649LL; // -2^31-1
271         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer));
272         CHECK(j.get<int32_t>() == 2147483647);  // Wrap
273 
274         // integer parsing - expected to overflow and be stored as a float with rounding
275         j = custom_json::parse("-2147483649"); // -2^31
276         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
277         CHECK(j.get<float>() == -2147483650.0f);
278     }
279 
280     SECTION("issue #93 reverse_iterator operator inheritance problem")
281     {
282         {
283             json a = {1, 2, 3};
284             json::reverse_iterator rit = a.rbegin();
285             ++rit;
286             CHECK(*rit == json(2));
287             CHECK(rit.value() == json(2));
288         }
289         {
290             json a = {1, 2, 3};
291             json::reverse_iterator rit = ++a.rbegin();
292             CHECK(*rit == json(2));
293             CHECK(rit.value() == json(2));
294         }
295         {
296             json a = {1, 2, 3};
297             json::reverse_iterator rit = a.rbegin();
298             ++rit;
299             json b = {0, 0, 0};
300             std::transform(rit, a.rend(), b.rbegin(), [](json el)
__anon6ae0f0a10302(json el) 301             {
302                 return el;
303             });
304             CHECK(b == json({0, 1, 2}));
305         }
306         {
307             json a = {1, 2, 3};
308             json b = {0, 0, 0};
309             std::transform(++a.rbegin(), a.rend(), b.rbegin(), [](json el)
__anon6ae0f0a10402(json el) 310             {
311                 return el;
312             });
313             CHECK(b == json({0, 1, 2}));
314         }
315     }
316 
317     SECTION("issue #100 - failed to iterator json object with reverse_iterator")
318     {
319         json config =
320         {
321             { "111", 111 },
322             { "112", 112 },
323             { "113", 113 }
324         };
325 
326         std::stringstream ss;
327 
328         for (auto it = config.begin(); it != config.end(); ++it)
329         {
330             ss << it.key() << ": " << it.value() << '\n';
331         }
332 
333         for (auto it = config.rbegin(); it != config.rend(); ++it)
334         {
335             ss << it.key() << ": " << it.value() << '\n';
336         }
337 
338         CHECK(ss.str() == "111: 111\n112: 112\n113: 113\n113: 113\n112: 112\n111: 111\n");
339     }
340 
341     SECTION("issue #101 - binary string causes numbers to be dumped as hex")
342     {
343         int64_t number = 10;
344         std::string bytes{"\x00" "asdf\n", 6};
345         json j;
346         j["int64"] = number;
347         j["binary string"] = bytes;
348         // make sure the number is really printed as decimal "10" and not as
349         // hexadecimal "a"
350         CHECK(j.dump() == "{\"binary string\":\"\\u0000asdf\\n\",\"int64\":10}");
351     }
352 
353     SECTION("issue #111 - subsequent unicode chars")
354     {
355         std::string bytes{0x7, 0x7};
356         json j;
357         j["string"] = bytes;
358         CHECK(j["string"] == "\u0007\u0007");
359     }
360 
361 #if JSON_USE_IMPLICIT_CONVERSIONS
362     SECTION("issue #144 - implicit assignment to std::string fails")
363     {
364         json o = {{"name", "value"}};
365 
366         std::string s1 = o["name"];
367         CHECK(s1 == "value");
368 
369         std::string s2;
370         s2 = o["name"];
371 
372         CHECK(s2 == "value");
373 
374         // improve coverage
375         o["int"] = 1;
376 #if JSON_DIAGNOSTICS
377         CHECK_THROWS_WITH_AS(s2 = o["int"], "[json.exception.type_error.302] (/int) type must be string, but is number", json::type_error);
378 #else
379         CHECK_THROWS_WITH_AS(s2 = o["int"], "[json.exception.type_error.302] type must be string, but is number", json::type_error);
380 #endif
381     }
382 #endif
383 
384     SECTION("issue #146 - character following a surrogate pair is skipped")
385     {
386         CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == "\xf0\x93\x81\xa0\x61\x62\x63");
387     }
388 
389     SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
390     {
391         json j;
392 
393         // Non-const access with key as "char []"
394         char array_key[] = "Key1"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
395         CHECK_NOTHROW(j[array_key] = 1);
396         CHECK(j[array_key] == json(1));
397 
398         // Non-const access with key as "const char[]"
399         const char const_array_key[] = "Key2"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
400         CHECK_NOTHROW(j[const_array_key] = 2);
401         CHECK(j[const_array_key] == json(2));
402 
403         // Non-const access with key as "char *"
404         char _ptr_key[] = "Key3"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
405         char* ptr_key = &_ptr_key[0]; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
406         CHECK_NOTHROW(j[ptr_key] = 3);
407         CHECK(j[ptr_key] == json(3));
408 
409         // Non-const access with key as "const char *"
410         const char* const_ptr_key = "Key4";
411         CHECK_NOTHROW(j[const_ptr_key] = 4);
412         CHECK(j[const_ptr_key] == json(4));
413 
414         // Non-const access with key as "static constexpr const char *"
415         static constexpr const char* constexpr_ptr_key = "Key5";
416         CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
417         CHECK(j[constexpr_ptr_key] == json(5));
418 
419         const json j_const = j;
420 
421         // Const access with key as "char []"
422         CHECK(j_const[array_key] == json(1));
423 
424         // Const access with key as "const char[]"
425         CHECK(j_const[const_array_key] == json(2));
426 
427         // Const access with key as "char *"
428         CHECK(j_const[ptr_key] == json(3));
429 
430         // Const access with key as "const char *"
431         CHECK(j_const[const_ptr_key] == json(4));
432 
433         // Const access with key as "static constexpr const char *"
434         CHECK(j_const[constexpr_ptr_key] == json(5));
435     }
436 
437     SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
438     {
439         json j;
440 
441         j = json::parse("-0.0");
442         CHECK(j.get<double>() == -0.0);
443 
444         j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308");
445         CHECK(j.get<double>() == 2.2250738585072009e-308);
446 
447         j = json::parse("0.999999999999999944488848768742172978818416595458984374");
448         CHECK(j.get<double>() == 0.99999999999999989);
449 
450         j = json::parse("1.00000000000000011102230246251565404236316680908203126");
451         CHECK(j.get<double>() == 1.00000000000000022);
452 
453         j = json::parse("7205759403792793199999e-5");
454         CHECK(j.get<double>() == 72057594037927928.0);
455 
456         j = json::parse("922337203685477529599999e-5");
457         CHECK(j.get<double>() == 9223372036854774784.0);
458 
459         j = json::parse("1014120480182583464902367222169599999e-5");
460         CHECK(j.get<double>() == 10141204801825834086073718800384.0);
461 
462         j = json::parse("5708990770823839207320493820740630171355185151999e-3");
463         CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0);
464 
465         // create JSON class with nonstandard float number type
466 
467         // float
468         nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float =
469             1.23e25f;
470         CHECK(j_float.get<float>() == 1.23e25f);
471 
472         // double
473         nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double =
474             1.23e35;
475         CHECK(j_double.get<double>() == 1.23e35);
476 
477         // long double
478         nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
479         j_long_double = 1.23e45L;
480         CHECK(j_long_double.get<long double>() == 1.23e45L);
481     }
482 
483     SECTION("issue #228 - double values are serialized with commas as decimal points")
484     {
485         json j1a = 2312.42;
486         json j1b = json::parse("2312.42");
487 
488         json j2a = 2342e-2;
489         //issue #230
490         //json j2b = json::parse("2342e-2");
491 
492         json j3a = 10E3;
493         json j3b = json::parse("10E3");
494         json j3c = json::parse("10e3");
495 
496         // class to create a locale that would use a comma for decimals
497         class CommaDecimalSeparator : public std::numpunct<char>
498         {
499           protected:
do_decimal_point() const500             char do_decimal_point() const override
501             {
502                 return ',';
503             }
504 
do_thousands_sep() const505             char do_thousands_sep() const override
506             {
507                 return '.';
508             }
509 
do_grouping() const510             std::string do_grouping() const override
511             {
512                 return "\03";
513             }
514         };
515 
516         // change locale to mess with decimal points
517         auto orig_locale = std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator));
518 
519         CHECK(j1a.dump() == "2312.42");
520         CHECK(j1b.dump() == "2312.42");
521 
522         // check if locale is properly reset
523         std::stringstream ss;
524         ss.imbue(std::locale(std::locale(), new CommaDecimalSeparator));
525         ss << 4712.11;
526         CHECK(ss.str() == "4.712,11");
527         ss << j1a;
528         CHECK(ss.str() == "4.712,112312.42");
529         ss << 47.11;
530         CHECK(ss.str() == "4.712,112312.4247,11");
531 
532         CHECK(j2a.dump() == "23.42");
533         //issue #230
534         //CHECK(j2b.dump() == "23.42");
535 
536         CHECK(j3a.dump() == "10000.0");
537         CHECK(j3b.dump() == "10000.0");
538         CHECK(j3c.dump() == "10000.0");
539         //CHECK(j3b.dump() == "1E04"); // roundtrip error
540         //CHECK(j3c.dump() == "1e04"); // roundtrip error
541 
542         std::locale::global(orig_locale);
543     }
544 
545     SECTION("issue #378 - locale-independent num-to-str")
546     {
547         static_cast<void>(setlocale(LC_NUMERIC, "de_DE.UTF-8"));
548 
549         // verify that dumped correctly with '.' and no grouping
550         const json j1 = 12345.67;
551         CHECK(json(12345.67).dump() == "12345.67");
552         static_cast<void>(setlocale(LC_NUMERIC, "C"));
553     }
554 
555     SECTION("issue #379 - locale-independent str-to-num")
556     {
557         static_cast<void>(setlocale(LC_NUMERIC, "de_DE.UTF-8"));
558 
559         // verify that parsed correctly despite using strtod internally
560         CHECK(json::parse("3.14").get<double>() == 3.14);
561 
562         // check a different code path
563         CHECK(json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000").get<double>() == 1.0);
564     }
565 
566     SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator")
567     {
568         json source = {"a", "b", "c"};
569         json expected = {"a", "b"};
570         json dest;
571 
572         std::copy_n(std::make_move_iterator(source.begin()), 2, std::back_inserter(dest));
573 
574         CHECK(dest == expected);
575     }
576 
577     SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='")
578     {
579         json data = {{"key", "value"}};
580         data.push_back({"key2", "value2"});
581         data += {"key3", "value3"};
582 
583         CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}}));
584     }
585 
586     SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements")
587     {
588         json doc = R"( { "arr1": [1, 2, 3, 4] } )"_json;
589         json expected = R"( { "arr1": [1, 2] } )"_json;
590 
591         // check roundtrip
592         CHECK(doc.patch(json::diff(doc, expected)) == expected);
593     }
594 
595     SECTION("issue #283 - value() does not work with _json_pointer types")
596     {
597         json j =
598         {
599             {"object", {{"key1", 1}, {"key2", 2}}},
600         };
601 
602         int at_integer{j.at("/object/key2"_json_pointer)};
603         int val_integer = j.value("/object/key2"_json_pointer, 0);
604 
605         CHECK(at_integer == val_integer);
606     }
607 
608     SECTION("issue #304 - Unused variable warning")
609     {
610         // code triggered a "warning: unused variable" warning and is left
611         // here to avoid the warning in the future
612         json object;
613         json patch = json::array();
614         object = object.patch(patch);
615     }
616 
617     SECTION("issue #306 - Parsing fails without space at end of file")
618     {
619         for (const auto* filename :
620                 {
621                     TEST_DATA_DIRECTORY "/regression/broken_file.json",
622                     TEST_DATA_DIRECTORY "/regression/working_file.json"
623                 })
624         {
625             CAPTURE(filename)
626             json j;
627             std::ifstream f(filename);
628             CHECK_NOTHROW(f >> j);
629         }
630     }
631 
632     SECTION("issue #310 - make json_benchmarks no longer working in 2.0.4")
633     {
634         for (const auto* filename :
635                 {
636                     TEST_DATA_DIRECTORY "/regression/floats.json",
637                     TEST_DATA_DIRECTORY "/regression/signed_ints.json",
638                     TEST_DATA_DIRECTORY "/regression/unsigned_ints.json",
639                     TEST_DATA_DIRECTORY "/regression/small_signed_ints.json"
640                 })
641         {
642             CAPTURE(filename)
643             json j;
644             std::ifstream f(filename);
645             CHECK_NOTHROW(f >> j);
646         }
647     }
648 
649     SECTION("issue #323 - add nested object capabilities to pointers")
650     {
651         json j;
652         j["/this/that/2"_json_pointer] = 27;
653         CHECK(j == json({{"this", {{"that", {nullptr, nullptr, 27}}}}}));
654     }
655 
656     SECTION("issue #329 - serialized value not always can be parsed")
657     {
658         json _;
659         CHECK_THROWS_WITH_AS(_ = json::parse("22e2222"), "[json.exception.out_of_range.406] number overflow parsing '22e2222'", json::out_of_range&);
660     }
661 
662     SECTION("issue #360 - Loss of precision when serializing <double>")
663     {
664         auto check_roundtrip = [](double number)
__anon6ae0f0a10502(double number) 665         {
666             CAPTURE(number)
667 
668             json j = number;
669             CHECK(j.is_number_float());
670 
671             std::stringstream ss;
672             ss << j;
673 
674             CHECK_NOTHROW(ss >> j);
675             CHECK(j.is_number_float());
676             CHECK(j.get<json::number_float_t>() == number);
677         };
678 
679         check_roundtrip(100000000000.1236);
680         check_roundtrip((std::numeric_limits<json::number_float_t>::max)());
681 
682         // Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
683         check_roundtrip(1.541888611948064e-17);
684         check_roundtrip(5.418771028591015e-16);
685         check_roundtrip(9.398685592608595e-15);
686         check_roundtrip(8.826843952762347e-14);
687         check_roundtrip(8.143291313475335e-13);
688         check_roundtrip(4.851328172762508e-12);
689         check_roundtrip(6.677850998084358e-11);
690         check_roundtrip(3.995398518174525e-10);
691         check_roundtrip(1.960452605645124e-9);
692         check_roundtrip(3.551812586302883e-8);
693         check_roundtrip(2.947988411689261e-7);
694         check_roundtrip(8.210166748056192e-6);
695         check_roundtrip(6.104889704266753e-5);
696         check_roundtrip(0.0008629954631330876);
697         check_roundtrip(0.004936993881051611);
698         check_roundtrip(0.08309725102608073);
699         check_roundtrip(0.5210494268499783);
700         check_roundtrip(6.382927930939767);
701         check_roundtrip(59.94947245358671);
702         check_roundtrip(361.0838651266122);
703         check_roundtrip(4678.354596181877);
704         check_roundtrip(61412.17658956043);
705         check_roundtrip(725696.0799057782);
706         check_roundtrip(2811732.583399828);
707         check_roundtrip(30178351.07533605);
708         check_roundtrip(689684880.3235844);
709         check_roundtrip(5714887673.555147);
710         check_roundtrip(84652038821.18808);
711         check_roundtrip(156510583431.7721);
712         check_roundtrip(5938450569021.732);
713         check_roundtrip(83623297654460.33);
714         check_roundtrip(701466573254773.6);
715         check_roundtrip(1369013370304513);
716         check_roundtrip(96963648023094720); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
717         check_roundtrip(3.478237409280108e+17);
718     }
719 
720     SECTION("issue #366 - json::parse on failed stream gets stuck")
721     {
722         std::ifstream f("file_not_found.json");
723         json _;
724         CHECK_THROWS_WITH_AS(_ = json::parse(f), "[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&);
725     }
726 
727     SECTION("issue #367 - calling stream at EOF")
728     {
729         std::stringstream ss;
730         json j;
731         ss << "123";
732         CHECK_NOTHROW(ss >> j);
733 
734         // see https://github.com/nlohmann/json/issues/367#issuecomment-262841893:
735         // ss is not at EOF; this yielded an error before the fix
736         // (threw basic_string::append). No, it should just throw
737         // a parse error because of the EOF.
738         CHECK_THROWS_WITH_AS(ss >> j, "[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&);
739     }
740 
741     SECTION("issue #367 - behavior of operator>> should more closely resemble that of built-in overloads")
742     {
743         SECTION("(empty)")
744         {
745             std::stringstream ss;
746             json j;
747             CHECK_THROWS_WITH_AS(ss >> j, "[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&);
748         }
749 
750         SECTION("(whitespace)")
751         {
752             std::stringstream ss;
753             ss << "   ";
754             json j;
755             CHECK_THROWS_WITH_AS(ss >> j,
756                                  "[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&);
757         }
758 
759         SECTION("one value")
760         {
761             std::stringstream ss;
762             ss << "111";
763             json j;
764             CHECK_NOTHROW(ss >> j);
765             CHECK(j == 111);
766 
767             CHECK_THROWS_WITH_AS(ss >> j, "[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&);
768         }
769 
770         SECTION("one value + whitespace")
771         {
772             std::stringstream ss;
773             ss << "222 \t\n";
774             json j;
775             CHECK_NOTHROW(ss >> j);
776             CHECK(j == 222);
777 
778             CHECK_THROWS_WITH_AS(ss >> j,
779                                  "[json.exception.parse_error.101] parse error at line 2, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
780         }
781 
782         SECTION("whitespace + one value")
783         {
784             std::stringstream ss;
785             ss << "\n\t 333";
786             json j;
787             CHECK_NOTHROW(ss >> j);
788             CHECK(j == 333);
789 
790             CHECK_THROWS_WITH_AS(ss >> j, "[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&);
791         }
792 
793         SECTION("three values")
794         {
795             std::stringstream ss;
796             ss << " 111 \n222\n \n  333";
797             json j;
798             CHECK_NOTHROW(ss >> j);
799             CHECK(j == 111);
800             CHECK_NOTHROW(ss >> j);
801             CHECK(j == 222);
802             CHECK_NOTHROW(ss >> j);
803             CHECK(j == 333);
804 
805             CHECK_THROWS_WITH_AS(ss >> j, "[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&);
806         }
807 
808         SECTION("literals without whitespace")
809         {
810             std::stringstream ss;
811             ss << "truefalsenull\"\"";
812             json j;
813             CHECK_NOTHROW(ss >> j);
814             CHECK(j == true);
815             CHECK_NOTHROW(ss >> j);
816             CHECK(j == false);
817             CHECK_NOTHROW(ss >> j);
818             CHECK(j == nullptr);
819             CHECK_NOTHROW(ss >> j);
820             CHECK(j == "");
821 
822             CHECK_THROWS_WITH_AS(ss >> j, "[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&);
823         }
824 
825         SECTION("example from #529")
826         {
827             std::stringstream ss;
828             ss << "{\n    \"one\"   : 1,\n    \"two\"   : 2\n}\n{\n    \"three\" : 3\n}";
829             json j;
830             CHECK_NOTHROW(ss >> j);
831             CHECK(j == json({{"one", 1}, {"two", 2}}));
832             CHECK_NOTHROW(ss >> j);
833             CHECK(j == json({{"three", 3}}));
834 
835             CHECK_THROWS_WITH_AS(ss >> j, "[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&);
836         }
837 
838         SECTION("second example from #529")
839         {
840             std::string str = "{\n\"one\"   : 1,\n\"two\"   : 2\n}\n{\n\"three\" : 3\n}";
841 
842             {
843                 std::ofstream file("test.json");
844                 file << str;
845             }
846 
847             std::ifstream stream("test.json", std::ifstream::in);
848             json val;
849 
850             size_t i = 0;
851             while (stream.peek() != EOF)
852             {
853                 CAPTURE(i)
854                 CHECK_NOTHROW(stream >> val);
855 
856                 CHECK(i < 2);
857 
858                 if (i == 0)
859                 {
860                     CHECK(val == json({{"one", 1}, {"two", 2}}));
861                 }
862 
863                 if (i == 1)
864                 {
865                     CHECK(val == json({{"three", 3}}));
866                 }
867 
868                 ++i;
869             }
870 
871             static_cast<void>(std::remove("test.json"));
872         }
873     }
874 
875     SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
876     {
877         // original test case
878         json j1 = json::parse("-9223372036854775808");
879         CHECK(j1.is_number_integer());
880         CHECK(j1.get<json::number_integer_t>() == INT64_MIN);
881 
882         // edge case (+1; still an integer)
883         json j2 = json::parse("-9223372036854775807");
884         CHECK(j2.is_number_integer());
885         CHECK(j2.get<json::number_integer_t>() == INT64_MIN + 1);
886 
887         // edge case (-1; overflow -> floats)
888         json j3 = json::parse("-9223372036854775809");
889         CHECK(j3.is_number_float());
890     }
891 
892     SECTION("issue #380 - bug in overflow detection when parsing integers")
893     {
894         json j = json::parse("166020696663385964490");
895         CHECK(j.is_number_float());
896         CHECK(j.get<json::number_float_t>() == 166020696663385964490.0);
897     }
898 
899     SECTION("issue #405 - Heap-buffer-overflow (OSS-Fuzz issue 342)")
900     {
901         // original test case
902         std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21};
903         json _;
904         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
905     }
906 
907     SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)")
908     {
909         json _;
910 
911         // original test case: incomplete float64
912         std::vector<uint8_t> vec1 {0xcb, 0x8f, 0x0a};
913         CHECK_THROWS_WITH_AS(_ = json::from_msgpack(vec1), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input", json::parse_error&);
914 
915         // related test case: incomplete float32
916         std::vector<uint8_t> vec2 {0xca, 0x8f, 0x0a};
917         CHECK_THROWS_WITH_AS(_ = json::from_msgpack(vec2), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input", json::parse_error&);
918 
919         // related test case: incomplete Half-Precision Float (CBOR)
920         std::vector<uint8_t> vec3 {0xf9, 0x8f};
921         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
922 
923         // related test case: incomplete Single-Precision Float (CBOR)
924         std::vector<uint8_t> vec4 {0xfa, 0x8f, 0x0a};
925         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec4), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
926 
927         // related test case: incomplete Double-Precision Float (CBOR)
928         std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a};
929         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec5), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input", json::parse_error&);
930     }
931 
932     SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)")
933     {
934         json _;
935 
936         // original test case
937         std::vector<uint8_t> vec1 {0x87};
938         CHECK_THROWS_WITH_AS(_ = json::from_msgpack(vec1), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input", json::parse_error&);
939 
940         // more test cases for MessagePack
941         for (auto b :
942                 {
943                     0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap
944                     0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray
945                     0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // fixstr
946                     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
947                 })
948         {
949             std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
950             CHECK_THROWS_AS(_ = json::from_msgpack(vec), json::parse_error&);
951         }
952 
953         // more test cases for CBOR
954         for (auto b :
955                 {
956                     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
957                     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string
958                     0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
959                     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // array
960                     0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
961                     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map
962                 })
963         {
964             std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
965             CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
966         }
967 
968         // special case: empty input
969         std::vector<uint8_t> vec2;
970         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
971         CHECK_THROWS_WITH_AS(_ = json::from_msgpack(vec2), "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing MessagePack value: unexpected end of input", json::parse_error&);
972     }
973 
974     SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)")
975     {
976         json _;
977 
978         // original test case: empty UTF-8 string (indefinite length)
979         std::vector<uint8_t> vec1 {0x7f};
980         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
981 
982         // related test case: empty array (indefinite length)
983         std::vector<uint8_t> vec2 {0x9f};
984         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
985 
986         // related test case: empty map (indefinite length)
987         std::vector<uint8_t> vec3 {0xbf};
988         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
989     }
990 
991     SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)")
992     {
993         // original test case
994         std::vector<uint8_t> vec
995         {
996             0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
997             0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00,
998             0x60, 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
999             0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00,
1000             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1001             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1002             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1003             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1004             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1005             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1006             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xa0, 0x9f,
1007             0x9f, 0x97, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1008             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1009             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1010             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1011             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1012             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60
1013         };
1014 
1015         json _;
1016         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x98", json::parse_error&);
1017 
1018         // related test case: nonempty UTF-8 string (indefinite length)
1019         std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61};
1020         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1021 
1022         // related test case: nonempty array (indefinite length)
1023         std::vector<uint8_t> vec2 {0x9f, 0x01};
1024         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input", json::parse_error&);
1025 
1026         // related test case: nonempty map (indefinite length)
1027         std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01};
1028         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
1029     }
1030 
1031     SECTION("issue #414 - compare with literal 0)")
1032     {
1033 #define CHECK_TYPE(v) \
1034     CHECK((json(v) == (v)));\
1035     CHECK(((v) == json(v)));\
1036     CHECK_FALSE((json(v) != (v)));\
1037     CHECK_FALSE(((v) != json(v)));
1038 
1039         CHECK_TYPE(nullptr)
1040         CHECK_TYPE(0)
1041         CHECK_TYPE(0u)
1042         CHECK_TYPE(0L)
1043         CHECK_TYPE(0.0)
1044         CHECK_TYPE("") // NOLINT(readability-container-size-empty)
1045 
1046 #undef CHECK_TYPE
1047     }
1048 
1049     SECTION("issue #416 - Use-of-uninitialized-value (OSS-Fuzz issue 377)")
1050     {
1051         // original test case
1052         std::vector<uint8_t> vec1
1053         {
1054             0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1055             0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
1056             0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71,
1057             0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a,
1058             0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
1059             0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa
1060         };
1061 
1062         json _;
1063         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4", json::parse_error&);
1064 
1065         // related test case: double-precision
1066         std::vector<uint8_t> vec2
1067         {
1068             0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1069             0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
1070             0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71,
1071             0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a,
1072             0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
1073             0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
1074         };
1075         CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4", json::parse_error&);
1076     }
1077 
1078     SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
1079     {
1080         std::vector<uint8_t> vec = {'-', '0', '1', '2', '2', '7', '4'};
1081         json _;
1082         CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
1083     }
1084 
1085     SECTION("issue #454 - doubles are printed as integers")
1086     {
1087         json j = R"({"bool_value":true,"double_value":2.0,"int_value":10,"level1":{"list_value":[3,"hi",false],"tmp":5.0},"string_value":"hello"})"_json;
1088         CHECK(j["double_value"].is_number_float());
1089     }
1090 
1091 #if JSON_USE_IMPLICIT_CONVERSIONS
1092     SECTION("issue #464 - VS2017 implicit to std::string conversion fix")
1093     {
1094         json v = "test";
1095         std::string test;
1096         test = v;
1097         CHECK(v == "test");
1098     }
1099 #endif
1100 
1101     SECTION("issue #465 - roundtrip error while parsing 1000000000000000010E5")
1102     {
1103         json j1 = json::parse("1000000000000000010E5");
1104         std::string s1 = j1.dump();
1105         json j2 = json::parse(s1);
1106         std::string s2 = j2.dump();
1107         CHECK(s1 == s2);
1108     }
1109 
1110 #if JSON_USE_IMPLICIT_CONVERSIONS
1111     SECTION("issue #473 - inconsistent behavior in conversion to array type")
1112     {
1113         json j_array = {1, 2, 3, 4};
1114         json j_number = 42;
1115         json j_null = nullptr;
1116 
1117         SECTION("std::vector")
1118         {
1119             auto create = [](const json & j)
__anon6ae0f0a10602(const json & j) 1120             {
1121                 std::vector<int> v = j;
1122             };
1123 
1124             CHECK_NOTHROW(create(j_array));
1125             CHECK_THROWS_WITH_AS(create(j_number), "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
1126             CHECK_THROWS_WITH_AS(create(j_null), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1127         }
1128 
1129         SECTION("std::list")
1130         {
1131             auto create = [](const json & j)
__anon6ae0f0a10702(const json & j) 1132             {
1133                 std::list<int> v = j;
1134             };
1135 
1136             CHECK_NOTHROW(create(j_array));
1137             CHECK_THROWS_WITH_AS(create(j_number), "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
1138             CHECK_THROWS_WITH_AS(create(j_null), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1139         }
1140 
1141         SECTION("std::forward_list")
1142         {
1143             auto create = [](const json & j)
__anon6ae0f0a10802(const json & j) 1144             {
1145                 std::forward_list<int> v = j;
1146             };
1147 
1148             CHECK_NOTHROW(create(j_array));
1149             CHECK_THROWS_WITH_AS(create(j_number), "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
1150             CHECK_THROWS_WITH_AS(create(j_null), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1151         }
1152     }
1153 #endif
1154 
1155     SECTION("issue #486 - json::value_t can't be a map's key type in VC++ 2015")
1156     {
1157         // the code below must compile with MSVC
1158         std::map<json::value_t, std::string> jsonTypes ;
1159         jsonTypes[json::value_t::array] = "array";
1160     }
1161 
1162     SECTION("issue #494 - conversion from vector<bool> to json fails to build")
1163     {
1164         std::vector<bool> boolVector = {false, true, false, false};
1165         json j;
1166         j["bool_vector"] = boolVector;
1167 
1168         CHECK(j["bool_vector"].dump() == "[false,true,false,false]");
1169     }
1170 
1171     SECTION("issue #504 - assertion error (OSS-Fuzz 856)")
1172     {
1173         std::vector<uint8_t> vec1 = {0xf9, 0xff, 0xff, 0x4a, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x37, 0x02, 0x38};
1174         json j1 = json::from_cbor(vec1, false);
1175 
1176         // step 2: round trip
1177         std::vector<uint8_t> vec2 = json::to_cbor(j1);
1178 
1179         // parse serialization
1180         json j2 = json::from_cbor(vec2);
1181 
1182         // NaN is dumped to "null"
1183         CHECK(j2.is_number_float());
1184         CHECK(std::isnan(j2.get<json::number_float_t>()));
1185         CHECK(j2.dump() == "null");
1186 
1187         // check if serializations match
1188         CHECK(json::to_cbor(j2) == vec2);
1189     }
1190 
1191     SECTION("issue #512 - use of overloaded operator '<=' is ambiguous")
1192     {
1193         json j;
1194         j["a"] = 5;
1195 
1196         // json op scalar
1197         CHECK(j["a"] == 5);
1198         CHECK(j["a"] != 4);
1199 
1200         CHECK(j["a"] <= 7);
1201         CHECK(j["a"] <  7);
1202         CHECK(j["a"] >= 3);
1203         CHECK(j["a"] >  3);
1204 
1205 
1206         CHECK(!(j["a"] <= 4));
1207         CHECK(!(j["a"] <  4));
1208         CHECK(!(j["a"] >= 6));
1209         CHECK(!(j["a"] >  6));
1210 
1211         // scalar op json
1212         CHECK(5 == j["a"]);
1213         CHECK(4 != j["a"]);
1214 
1215         CHECK(7 >= j["a"]);
1216         CHECK(7 >  j["a"]);
1217         CHECK(3 <= j["a"]);
1218         CHECK(3 <  j["a"]);
1219 
1220         CHECK(!(4 >= j["a"]));
1221         CHECK(!(4 >  j["a"]));
1222         CHECK(!(6 <= j["a"]));
1223         CHECK(!(6 <  j["a"]));
1224     }
1225 
1226     SECTION("issue #575 - heap-buffer-overflow (OSS-Fuzz 1400)")
1227     {
1228         json _;
1229         std::vector<uint8_t> vec = {'"', '\\', '"', 'X', '"', '"'};
1230         CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
1231     }
1232 
1233 #if JSON_USE_IMPLICIT_CONVERSIONS
1234     SECTION("issue #600 - how does one convert a map in Json back to std::map?")
1235     {
1236         SECTION("example 1")
1237         {
1238             // create a map
1239             std::map<std::string, int> m1 {{"key", 1}};
1240 
1241             // create and print a JSON from the map
1242             json j = m1;
1243 
1244             // get the map out of JSON
1245             std::map<std::string, int> m2 = j;
1246 
1247             // make sure the roundtrip succeeds
1248             CHECK(m1 == m2);
1249         }
1250 
1251         SECTION("example 2")
1252         {
1253             // create a map
1254             std::map<std::string, std::string> m1 {{"key", "val"}};
1255 
1256             // create and print a JSON from the map
1257             json j = m1;
1258 
1259             // get the map out of JSON
1260             std::map<std::string, std::string> m2 = j;
1261 
1262             // make sure the roundtrip succeeds
1263             CHECK(m1 == m2);
1264         }
1265     }
1266 #endif
1267 
1268     SECTION("issue #602 - BOM not skipped when using json:parse(iterator)")
1269     {
1270         std::string i = "\xef\xbb\xbf{\n   \"foo\": true\n}";
1271         json _;
1272         CHECK_NOTHROW(_ = json::parse(i.begin(), i.end()));
1273     }
1274 
1275 #if JSON_USE_IMPLICIT_CONVERSIONS
1276     SECTION("issue #702 - conversion from valarray<double> to json fails to build")
1277     {
1278         SECTION("original example")
1279         {
1280             std::valarray<double> v;
1281             nlohmann::json j;
1282             j["test"] = v;
1283         }
1284 
1285         SECTION("full example")
1286         {
1287             std::valarray<double> v = {1.2, 2.3, 3.4, 4.5};
1288             json j = v;
1289             std::valarray<double> vj = j;
1290 
1291             CHECK(j == json(vj));
1292             CHECK(v.size() == vj.size());
1293             for (size_t i = 0; i < v.size(); ++i)
1294             {
1295                 CHECK(v[i] == vj[i]);
1296                 CHECK(v[i] == j[i]);
1297             }
1298 
1299             CHECK_THROWS_WITH_AS(json().get<std::valarray<double>>(), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1300         }
1301     }
1302 #endif
1303 
1304     SECTION("issue #367 - Behavior of operator>> should more closely resemble that of built-in overloads.")
1305     {
1306         SECTION("example 1")
1307         {
1308             std::istringstream i1_2_3( R"({"first": "one" }{"second": "two"}3)" );
1309             json j1;
1310             json j2;
1311             json j3;
1312             i1_2_3 >> j1;
1313             i1_2_3 >> j2;
1314             i1_2_3 >> j3;
1315 
1316             auto m1 = j1.get<std::map<std::string, std::string>>();
1317             auto m2 = j2.get<std::map<std::string, std::string>>();
1318             int i3{j3};
1319 
1320             CHECK( m1 == ( std::map<std::string, std::string> {{ "first",  "one" }} ));
1321             CHECK( m2 == ( std::map<std::string, std::string> {{ "second", "two" }} ));
1322             CHECK( i3 == 3 );
1323         }
1324     }
1325 
1326     SECTION("issue #714 - throw std::ios_base::failure exception when failbit set to true")
1327     {
1328         {
1329             std::ifstream is;
1330             is.exceptions(
1331                 is.exceptions()
1332                 | std::ios_base::failbit
1333                 | std::ios_base::badbit
1334             ); // handle different exceptions as 'file not found', 'permission denied'
1335 
1336             is.open(TEST_DATA_DIRECTORY "/regression/working_file.json");
1337             json _;
1338             CHECK_NOTHROW(_ = nlohmann::json::parse(is));
1339         }
1340 
1341         {
1342             std::ifstream is;
1343             is.exceptions(
1344                 is.exceptions()
1345                 | std::ios_base::failbit
1346                 | std::ios_base::badbit
1347             ); // handle different exceptions as 'file not found', 'permission denied'
1348 
1349             is.open(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json.cbor",
1350                     std::ios_base::in | std::ios_base::binary);
1351             json _;
1352             CHECK_NOTHROW(_ = nlohmann::json::from_cbor(is));
1353         }
1354     }
1355 
1356     SECTION("issue #805 - copy constructor is used with std::initializer_list constructor.")
1357     {
1358         nocopy n;
1359         json j;
1360         j = {{"nocopy", n}};
1361         CHECK(j["nocopy"]["val"] == 0);
1362     }
1363 
1364     SECTION("issue #838 - incorrect parse error with binary data in keys")
1365     {
1366         std::array<uint8_t, 28> key1 = {{ 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127, 0 }};
1367         std::string key1_str(reinterpret_cast<char*>(key1.data()));
1368         json j = key1_str;
1369         CHECK_THROWS_WITH_AS(j.dump(), "[json.exception.type_error.316] invalid UTF-8 byte at index 10: 0x7E", json::type_error&);
1370     }
1371 
1372 #if JSON_USE_IMPLICIT_CONVERSIONS
1373     SECTION("issue #843 - converting to array not working")
1374     {
1375         json j;
1376         std::array<int, 4> ar = {{1, 1, 1, 1}};
1377         j = ar;
1378         ar = j;
1379     }
1380 #endif
1381 
1382     SECTION("issue #894 - invalid RFC6902 copy operation succeeds")
1383     {
1384         auto model = R"({
1385             "one": {
1386                 "two": {
1387                     "three": "hello",
1388                     "four": 42
1389                 }
1390             }
1391         })"_json;
1392 
1393         auto p1 = R"([{"op": "move",
1394                        "from": "/one/two/three",
1395                        "path": "/a/b/c"}])"_json;
1396         CHECK_THROWS_WITH_AS(model.patch(p1),
1397                              "[json.exception.out_of_range.403] key 'a' not found", json::out_of_range&);
1398 
1399         auto p2 = R"([{"op": "copy",
1400                        "from": "/one/two/three",
1401                        "path": "/a/b/c"}])"_json;
1402         CHECK_THROWS_WITH_AS(model.patch(p2),
1403                              "[json.exception.out_of_range.403] key 'a' not found", json::out_of_range&);
1404     }
1405 
1406     SECTION("issue #961 - incorrect parsing of indefinite length CBOR strings")
1407     {
1408         std::vector<uint8_t> v_cbor =
1409         {
1410             0x7F,
1411             0x64,
1412             'a', 'b', 'c', 'd',
1413             0x63,
1414             '1', '2', '3',
1415             0xFF
1416         };
1417         json j = json::from_cbor(v_cbor);
1418         CHECK(j == "abcd123");
1419     }
1420 
1421     SECTION("issue #962 - Timeout (OSS-Fuzz 6034)")
1422     {
1423         json _;
1424         std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
1425         CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
1426         //CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
1427         //                  "[json.exception.out_of_range.408] excessive array size: 8658170730974374167");
1428 
1429         v_ubjson[0] = '{';
1430         CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
1431         //CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
1432         //                  "[json.exception.out_of_range.408] excessive object size: 8658170730974374167");
1433     }
1434 
1435     SECTION("issue #971 - Add a SAX parser - late bug")
1436     {
1437         // a JSON text
1438         const auto* text = R"(
1439     {
1440         "Image": {
1441             "Width":  800,
1442             "Height": 600,
1443             "Title":  "View from 15th Floor",
1444             "Thumbnail": {
1445                 "Url":    "http://www.example.com/image/481989943",
1446                 "Height": 125,
1447                 "Width":  100
1448             },
1449             "Animated" : false,
1450             "IDs": [116, 943, 234, 38793]
1451         }
1452     }
1453     )";
1454 
1455         // define parser callback
1456         json::parser_callback_t cb = [](int /*depth*/, json::parse_event_t event, json & parsed)
__anon6ae0f0a10902(int , json::parse_event_t event, json & parsed) 1457         {
1458             // skip object elements with key "Thumbnail"
1459             return !(event == json::parse_event_t::key && parsed == json("Thumbnail"));
1460         };
1461 
1462         // parse (with callback) and serialize JSON
1463         json j_filtered = json::parse(text, cb);
1464 
1465         CHECK(j_filtered == R"({"Image":{"Animated":false,"Height":600,"IDs":[116,943,234,38793], "Title":"View from 15th Floor","Width":800}})"_json);
1466     }
1467 
1468     SECTION("issue #972 - Segmentation fault on G++ when trying to assign json string literal to custom json type")
1469     {
1470         my_json foo = R"([1, 2, 3])"_json;
1471     }
1472 
1473     SECTION("issue #977 - Assigning between different json types")
1474     {
1475         foo_json lj = ns::foo{3};
1476         ns::foo ff(lj);
1477         CHECK(lj.is_object());
1478         CHECK(lj.size() == 1);
1479         CHECK(lj["x"] == 3);
1480         CHECK(ff.x == 3);
1481         nlohmann::json nj = lj;                // This line works as expected
1482     }
1483 }
1484 
1485 #if !defined(JSON_NOEXCEPTION)
1486 TEST_CASE("regression tests, exceptions dependent")
1487 {
1488     SECTION("issue #1340 - eof not set on exhausted input stream")
1489     {
1490         std::stringstream s("{}{}");
1491         json j;
1492         s >> j;
1493         s >> j;
1494         CHECK_THROWS_AS(s >> j, json::parse_error const&);
1495         CHECK(s.eof());
1496     }
1497 }
1498 #endif
1499 
1500 /////////////////////////////////////////////////////////////////////
1501 // for #1642
1502 /////////////////////////////////////////////////////////////////////
1503 
1504 // the code below fails with Clang on Windows, so we need to exclude it there
1505 #if DOCTEST_CLANG && (defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__))
1506 #else
1507 template <typename T> class array {};
1508 template <typename T> class object {};
1509 template <typename T> class string {};
1510 template <typename T> class number_integer {};
1511 template <typename T> class number_unsigned {};
1512 template <typename T> class number_float {};
1513 #endif
1514