• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3 // |  |  |__   |  |  | | | |  version 3.11.3
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2023 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 <limits>
25 #include <cstdio>
26 #include "make_test_data_available.hpp"
27 
28 #ifdef JSON_HAS_CPP_17
29     #include <variant>
30 #endif
31 
32 #include "fifo_map.hpp"
33 
34 /////////////////////////////////////////////////////////////////////
35 // for #972
36 /////////////////////////////////////////////////////////////////////
37 
38 template<class K, class V, class dummy_compare, class A>
39 using my_workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
40 using my_json = nlohmann::basic_json<my_workaround_fifo_map>;
41 
42 /////////////////////////////////////////////////////////////////////
43 // for #977
44 /////////////////////////////////////////////////////////////////////
45 
46 namespace ns
47 {
48 struct foo
49 {
50     int x;
51 };
52 
53 template <typename, typename SFINAE = void>
54 struct foo_serializer;
55 
56 template<typename T>
57 struct foo_serializer<T, typename std::enable_if<std::is_same<foo, T>::value>::type>
58 {
59     template <typename BasicJsonType>
to_jsonns::foo_serializer60     static void to_json(BasicJsonType& j, const T& value)
61     {
62         j = BasicJsonType{{"x", value.x}};
63     }
64     template <typename BasicJsonType>
from_jsonns::foo_serializer65     static void from_json(const BasicJsonType& j, T& value)     // !!!
66     {
67         nlohmann::from_json(j.at("x"), value.x);
68     }
69 };
70 
71 template<typename T>
72 struct foo_serializer < T, typename std::enable_if < !std::is_same<foo, T>::value >::type >
73 {
74     template <typename BasicJsonType>
to_jsonns::foo_serializer75     static void to_json(BasicJsonType& j, const T& value) noexcept // NOLINT(bugprone-exception-escape)
76     {
77         ::nlohmann::to_json(j, value);
78     }
79     template <typename BasicJsonType>
from_jsonns::foo_serializer80     static void from_json(const BasicJsonType& j, T& value)   //!!!
81     {
82         ::nlohmann::from_json(j, value);
83     }
84 };
85 } // namespace ns
86 
87 using foo_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t,
88       std::uint64_t, double, std::allocator, ns::foo_serializer, std::vector<std::uint8_t>>;
89 
90 /////////////////////////////////////////////////////////////////////
91 // for #805
92 /////////////////////////////////////////////////////////////////////
93 
94 namespace
95 {
96 struct nocopy // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
97 {
98     nocopy() = default;
99     nocopy(const nocopy&) = delete;
100     nocopy(nocopy&&) = delete;
101     nocopy& operator=(const nocopy&) = delete;
102     nocopy& operator=(nocopy&&) = delete;
103 
104     int val = 0;
105 
to_json(json & j,const nocopy & n)106     friend void to_json(json& j, const nocopy& n)
107     {
108         j = {{"val", n.val}};
109     }
110 };
111 } // namespace
112 
113 TEST_CASE("regression tests 1")
114 {
115     SECTION("issue #60 - Double quotation mark is not parsed correctly")
116     {
117         SECTION("escape_doublequote")
118         {
119             const auto* s = R"(["\"foo\""])";
120             json j = json::parse(s);
121             auto expected = R"(["\"foo\""])"_json;
122             CHECK(j == expected);
123         }
124     }
125 
126     SECTION("issue #70 - Handle infinity and NaN cases")
127     {
128         // previously, NAN/INFINITY created a null value; now, the values are
129         // properly stored, but are dumped as "null"
130         SECTION("NAN value")
131         {
132             CHECK(json(NAN).dump() == "null");
133             CHECK(json(json::number_float_t(NAN)).dump() == "null");
134         }
135 
136         SECTION("infinity")
137         {
138             CHECK(json(INFINITY).dump() == "null");
139             CHECK(json(json::number_float_t(INFINITY)).dump() == "null");
140         }
141 
142         // With 3.0.0, the semantics of this changed: NAN and infinity are
143         // stored properly inside the JSON value (no exception or conversion
144         // to null), but are serialized as null.
145         SECTION("NAN value")
146         {
147             json const j1 = NAN;
148             CHECK(j1.is_number_float());
149             json::number_float_t const f1{j1};
150             CHECK(std::isnan(f1));
151 
152             json const j2 = static_cast<json::number_float_t>(NAN);
153             CHECK(j2.is_number_float());
154             json::number_float_t const f2{j2};
155             CHECK(std::isnan(f2));
156         }
157 
158         SECTION("infinity")
159         {
160             json const j1 = INFINITY;
161             CHECK(j1.is_number_float());
162             json::number_float_t const f1{j1};
163             CHECK(!std::isfinite(f1));
164 
165             json const j2 = static_cast<json::number_float_t>(INFINITY);
166             CHECK(j2.is_number_float());
167             json::number_float_t const f2{j2};
168             CHECK(!std::isfinite(f2));
169         }
170     }
171 
172     SECTION("pull request #71 - handle enum type")
173     {
174         enum { t = 0, u = 102};
175         json j = json::array();
176         j.push_back(t);
177 
178         // maybe this is not the place to test this?
179         json j2 = u;
180 
181         auto anon_enum_value = j2.get<decltype(u)>();
182         CHECK(u == anon_enum_value);
183 
184         // check if the actual value was stored
185         CHECK(j2 == 102);
186 
187         static_assert(std::is_same<decltype(anon_enum_value), decltype(u)>::value, "types must be the same");
188 
189         j.push_back(json::object(
190         {
191             {"game_type", t}
192         }));
193     }
194 
195     SECTION("issue #76 - dump() / parse() not idempotent")
196     {
197         // create JSON object
198         json fields;
199         fields["one"] = std::string("one");
200         fields["two"] = std::string("two three");
201         fields["three"] = std::string("three \"four\"");
202 
203         // create another JSON object by deserializing the serialization
204         std::string const payload = fields.dump();
205         json parsed_fields = json::parse(payload);
206 
207         // check individual fields to match both objects
208         CHECK(parsed_fields["one"] == fields["one"]);
209         CHECK(parsed_fields["two"] == fields["two"]);
210         CHECK(parsed_fields["three"] == fields["three"]);
211 
212         // check individual fields to match original input
213         CHECK(parsed_fields["one"] == std::string("one"));
214         CHECK(parsed_fields["two"] == std::string("two three"));
215         CHECK(parsed_fields["three"] == std::string("three \"four\""));
216 
217         // check equality of the objects
218         CHECK(parsed_fields == fields);
219 
220         // check equality of the serialized objects
221         CHECK(fields.dump() == parsed_fields.dump());
222 
223         // check everything in one line
224         CHECK(fields == json::parse(fields.dump()));
225     }
226 
227     SECTION("issue #82 - lexer::get_number return NAN")
228     {
229         const auto* const content = R"(
230         {
231             "Test":"Test1",
232             "Number":100,
233             "Foo":42.42
234         })";
235 
236         std::stringstream ss;
237         ss << content;
238         json j;
239         ss >> j;
240 
241         auto test = j["Test"].get<std::string>();
242         CHECK(test == "Test1");
243         int number{j["Number"]};
244         CHECK(number == 100);
245         float foo{j["Foo"]};
246         CHECK(static_cast<double>(foo) == Approx(42.42));
247     }
248 
249     SECTION("issue #89 - nonstandard integer type")
250     {
251         // create JSON class with nonstandard integer number type
252         using custom_json =
253             nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
254         custom_json j;
255         j["int_1"] = 1;
256         CHECK(j["int_1"] == 1);
257 
258         // tests for correct handling of non-standard integers that overflow the type selected by the user
259 
260         // unsigned integer object creation - expected to wrap and still be stored as an integer
261         j = 4294967296U; // 2^32
262         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
263         CHECK(j.get<uint32_t>() == 0);  // Wrap
264 
265         // unsigned integer parsing - expected to overflow and be stored as a float
266         j = custom_json::parse("4294967296"); // 2^32
267         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
268         CHECK(j.get<float>() == 4294967296.0f);
269 
270         // integer object creation - expected to wrap and still be stored as an integer
271         j = -2147483649LL; // -2^31-1
272         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer));
273         CHECK(j.get<int32_t>() == 2147483647);  // Wrap
274 
275         // integer parsing - expected to overflow and be stored as a float with rounding
276         j = custom_json::parse("-2147483649"); // -2^31
277         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
278         CHECK(j.get<float>() == -2147483650.0f);
279     }
280 
281     SECTION("issue #93 reverse_iterator operator inheritance problem")
282     {
283         {
284             json a = {1, 2, 3};
285             json::reverse_iterator rit = a.rbegin();
286             ++rit;
287             CHECK(*rit == json(2));
288             CHECK(rit.value() == json(2));
289         }
290         {
291             json a = {1, 2, 3};
292             json::reverse_iterator const rit = ++a.rbegin();
293             CHECK(*rit == json(2));
294             CHECK(rit.value() == json(2));
295         }
296         {
297             json a = {1, 2, 3};
298             json::reverse_iterator rit = a.rbegin();
299             ++rit;
300             json b = {0, 0, 0};
301             std::transform(rit, a.rend(), b.rbegin(), [](json el)
__anon525045f40302(json el) 302             {
303                 return el;
304             });
305             CHECK(b == json({0, 1, 2}));
306         }
307         {
308             json a = {1, 2, 3};
309             json b = {0, 0, 0};
310             std::transform(++a.rbegin(), a.rend(), b.rbegin(), [](json el)
__anon525045f40402(json el) 311             {
312                 return el;
313             });
314             CHECK(b == json({0, 1, 2}));
315         }
316     }
317 
318     SECTION("issue #100 - failed to iterator json object with reverse_iterator")
319     {
320         json config =
321         {
322             { "111", 111 },
323             { "112", 112 },
324             { "113", 113 }
325         };
326 
327         std::stringstream ss;
328 
329         for (auto it = config.begin(); it != config.end(); ++it)
330         {
331             ss << it.key() << ": " << it.value() << '\n';
332         }
333 
334         for (auto it = config.rbegin(); it != config.rend(); ++it)
335         {
336             ss << it.key() << ": " << it.value() << '\n';
337         }
338 
339         CHECK(ss.str() == "111: 111\n112: 112\n113: 113\n113: 113\n112: 112\n111: 111\n");
340     }
341 
342     SECTION("issue #101 - binary string causes numbers to be dumped as hex")
343     {
344         int64_t const number = 10;
345         std::string const bytes{"\x00" "asdf\n", 6};
346         json j;
347         j["int64"] = number;
348         j["binary string"] = bytes;
349         // make sure the number is really printed as decimal "10" and not as
350         // hexadecimal "a"
351         CHECK(j.dump() == "{\"binary string\":\"\\u0000asdf\\n\",\"int64\":10}");
352     }
353 
354     SECTION("issue #111 - subsequent unicode chars")
355     {
356         std::string const bytes{0x7, 0x7};
357         json j;
358         j["string"] = bytes;
359         CHECK(j["string"] == "\u0007\u0007");
360     }
361 
362 #if JSON_USE_IMPLICIT_CONVERSIONS
363     SECTION("issue #144 - implicit assignment to std::string fails")
364     {
365         json o = {{"name", "value"}};
366 
367         std::string s1 = o["name"];
368         CHECK(s1 == "value");
369 
370         std::string s2;
371         s2 = o["name"];
372 
373         CHECK(s2 == "value");
374 
375         // improve coverage
376         o["int"] = 1;
377 #if JSON_DIAGNOSTICS
378         CHECK_THROWS_WITH_AS(s2 = o["int"], "[json.exception.type_error.302] (/int) type must be string, but is number", json::type_error);
379 #else
380         CHECK_THROWS_WITH_AS(s2 = o["int"], "[json.exception.type_error.302] type must be string, but is number", json::type_error);
381 #endif
382     }
383 #endif
384 
385     SECTION("issue #146 - character following a surrogate pair is skipped")
386     {
387         CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == "\xf0\x93\x81\xa0\x61\x62\x63");
388     }
389 
390     SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
391     {
392         json j;
393 
394         // Non-const access with key as "char []"
395         char array_key[] = "Key1"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
396         CHECK_NOTHROW(j[array_key] = 1);
397         CHECK(j[array_key] == json(1));
398 
399         // Non-const access with key as "const char[]"
400         const char const_array_key[] = "Key2"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
401         CHECK_NOTHROW(j[const_array_key] = 2);
402         CHECK(j[const_array_key] == json(2));
403 
404         // Non-const access with key as "char *"
405         char _ptr_key[] = "Key3"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
406         char* ptr_key = &_ptr_key[0]; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
407         CHECK_NOTHROW(j[ptr_key] = 3);
408         CHECK(j[ptr_key] == json(3));
409 
410         // Non-const access with key as "const char *"
411         const char* const_ptr_key = "Key4";
412         CHECK_NOTHROW(j[const_ptr_key] = 4);
413         CHECK(j[const_ptr_key] == json(4));
414 
415         // Non-const access with key as "static constexpr const char *"
416         static constexpr const char* constexpr_ptr_key = "Key5";
417         CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
418         CHECK(j[constexpr_ptr_key] == json(5));
419 
420         const json j_const = j;
421 
422         // Const access with key as "char []"
423         CHECK(j_const[array_key] == json(1));
424 
425         // Const access with key as "const char[]"
426         CHECK(j_const[const_array_key] == json(2));
427 
428         // Const access with key as "char *"
429         CHECK(j_const[ptr_key] == json(3));
430 
431         // Const access with key as "const char *"
432         CHECK(j_const[const_ptr_key] == json(4));
433 
434         // Const access with key as "static constexpr const char *"
435         CHECK(j_const[constexpr_ptr_key] == json(5));
436     }
437 
438     SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
439     {
440         json j;
441 
442         j = json::parse("-0.0");
443         CHECK(j.get<double>() == -0.0);
444 
445         j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308");
446         CHECK(j.get<double>() == 2.2250738585072009e-308);
447 
448         j = json::parse("0.999999999999999944488848768742172978818416595458984374");
449         CHECK(j.get<double>() == 0.99999999999999989);
450 
451         j = json::parse("1.00000000000000011102230246251565404236316680908203126");
452         CHECK(j.get<double>() == 1.00000000000000022);
453 
454         j = json::parse("7205759403792793199999e-5");
455         CHECK(j.get<double>() == 72057594037927928.0);
456 
457         j = json::parse("922337203685477529599999e-5");
458         CHECK(j.get<double>() == 9223372036854774784.0);
459 
460         j = json::parse("1014120480182583464902367222169599999e-5");
461         CHECK(j.get<double>() == 10141204801825834086073718800384.0);
462 
463         j = json::parse("5708990770823839207320493820740630171355185151999e-3");
464         CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0);
465 
466         // create JSON class with nonstandard float number type
467 
468         // float
469         nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> const j_float =
470             1.23e25f;
471         CHECK(j_float.get<float>() == 1.23e25f);
472 
473         // double
474         nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> const j_double =
475             1.23e35;
476         CHECK(j_double.get<double>() == 1.23e35);
477 
478         // long double
479         nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
480         const j_long_double = 1.23e45L;
481         CHECK(j_long_double.get<long double>() == 1.23e45L);
482     }
483 
484     SECTION("issue #228 - double values are serialized with commas as decimal points")
485     {
486         json const j1a = 2312.42;
487         json const j1b = json::parse("2312.42");
488 
489         json const j2a = 2342e-2;
490         //issue #230
491         //json j2b = json::parse("2342e-2");
492 
493         json const j3a = 10E3;
494         json const j3b = json::parse("10E3");
495         json const j3c = json::parse("10e3");
496 
497         // class to create a locale that would use a comma for decimals
498         class CommaDecimalSeparator : public std::numpunct<char>
499         {
500           protected:
do_decimal_point() const501             char do_decimal_point() const override
502             {
503                 return ',';
504             }
505 
do_thousands_sep() const506             char do_thousands_sep() const override
507             {
508                 return '.';
509             }
510 
do_grouping() const511             std::string do_grouping() const override
512             {
513                 return "\03";
514             }
515         };
516 
517         // change locale to mess with decimal points
518         auto orig_locale = std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator));
519 
520         CHECK(j1a.dump() == "2312.42");
521         CHECK(j1b.dump() == "2312.42");
522 
523         // check if locale is properly reset
524         std::stringstream ss;
525         ss.imbue(std::locale(std::locale(), new CommaDecimalSeparator));
526         ss << 4712.11;
527         CHECK(ss.str() == "4.712,11");
528         ss << j1a;
529         CHECK(ss.str() == "4.712,112312.42");
530         ss << 47.11;
531         CHECK(ss.str() == "4.712,112312.4247,11");
532 
533         CHECK(j2a.dump() == "23.42");
534         //issue #230
535         //CHECK(j2b.dump() == "23.42");
536 
537         CHECK(j3a.dump() == "10000.0");
538         CHECK(j3b.dump() == "10000.0");
539         CHECK(j3c.dump() == "10000.0");
540         //CHECK(j3b.dump() == "1E04"); // roundtrip error
541         //CHECK(j3c.dump() == "1e04"); // roundtrip error
542 
543         std::locale::global(orig_locale);
544     }
545 
546     SECTION("issue #378 - locale-independent num-to-str")
547     {
548         static_cast<void>(setlocale(LC_NUMERIC, "de_DE.UTF-8"));
549 
550         // verify that dumped correctly with '.' and no grouping
551         const json j1 = 12345.67;
552         CHECK(json(12345.67).dump() == "12345.67");
553         static_cast<void>(setlocale(LC_NUMERIC, "C"));
554     }
555 
556     SECTION("issue #379 - locale-independent str-to-num")
557     {
558         static_cast<void>(setlocale(LC_NUMERIC, "de_DE.UTF-8"));
559 
560         // verify that parsed correctly despite using strtod internally
561         CHECK(json::parse("3.14").get<double>() == 3.14);
562 
563         // check a different code path
564         CHECK(json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000").get<double>() == 1.0);
565     }
566 
567     SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator")
568     {
569         json source = {"a", "b", "c"};
570         json expected = {"a", "b"};
571         json dest;
572 
573         std::copy_n(std::make_move_iterator(source.begin()), 2, std::back_inserter(dest));
574 
575         CHECK(dest == expected);
576     }
577 
578     SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='")
579     {
580         json data = {{"key", "value"}};
581         data.push_back({"key2", "value2"});
582         data += {"key3", "value3"};
583 
584         CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}}));
585     }
586 
587     SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements")
588     {
589         json const doc = R"( { "arr1": [1, 2, 3, 4] } )"_json;
590         json expected = R"( { "arr1": [1, 2] } )"_json;
591 
592         // check roundtrip
593         CHECK(doc.patch(json::diff(doc, expected)) == expected);
594     }
595 
596     SECTION("issue #283 - value() does not work with _json_pointer types")
597     {
598         json j =
599         {
600             {"object", {{"key1", 1}, {"key2", 2}}},
601         };
602 
603         int at_integer{j.at("/object/key2"_json_pointer)};
604         int val_integer = j.value("/object/key2"_json_pointer, 0);
605 
606         CHECK(at_integer == val_integer);
607     }
608 
609     SECTION("issue #304 - Unused variable warning")
610     {
611         // code triggered a "warning: unused variable" warning and is left
612         // here to avoid the warning in the future
613         json object;
614         json const patch = json::array();
615         object = object.patch(patch);
616     }
617 
618     SECTION("issue #306 - Parsing fails without space at end of file")
619     {
620         for (const auto* filename :
621                 {
622                     TEST_DATA_DIRECTORY "/regression/broken_file.json",
623                     TEST_DATA_DIRECTORY "/regression/working_file.json"
624                 })
625         {
626             CAPTURE(filename)
627             json j;
628             std::ifstream f(filename);
629             CHECK_NOTHROW(f >> j);
630         }
631     }
632 
633     SECTION("issue #310 - make json_benchmarks no longer working in 2.0.4")
634     {
635         for (const auto* filename :
636                 {
637                     TEST_DATA_DIRECTORY "/regression/floats.json",
638                     TEST_DATA_DIRECTORY "/regression/signed_ints.json",
639                     TEST_DATA_DIRECTORY "/regression/unsigned_ints.json",
640                     TEST_DATA_DIRECTORY "/regression/small_signed_ints.json"
641                 })
642         {
643             CAPTURE(filename)
644             json j;
645             std::ifstream f(filename);
646             CHECK_NOTHROW(f >> j);
647         }
648     }
649 
650     SECTION("issue #323 - add nested object capabilities to pointers")
651     {
652         json j;
653         j["/this/that/2"_json_pointer] = 27;
654         CHECK(j == json({{"this", {{"that", {nullptr, nullptr, 27}}}}}));
655     }
656 
657     SECTION("issue #329 - serialized value not always can be parsed")
658     {
659         json _;
660         CHECK_THROWS_WITH_AS(_ = json::parse("22e2222"), "[json.exception.out_of_range.406] number overflow parsing '22e2222'", json::out_of_range&);
661     }
662 
663     SECTION("issue #360 - Loss of precision when serializing <double>")
664     {
665         auto check_roundtrip = [](double number)
__anon525045f40502(double number) 666         {
667             CAPTURE(number)
668 
669             json j = number;
670             CHECK(j.is_number_float());
671 
672             std::stringstream ss;
673             ss << j;
674 
675             CHECK_NOTHROW(ss >> j);
676             CHECK(j.is_number_float());
677             CHECK(j.get<json::number_float_t>() == number);
678         };
679 
680         check_roundtrip(100000000000.1236);
681         check_roundtrip((std::numeric_limits<json::number_float_t>::max)());
682 
683         // Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
684         check_roundtrip(1.541888611948064e-17);
685         check_roundtrip(5.418771028591015e-16);
686         check_roundtrip(9.398685592608595e-15);
687         check_roundtrip(8.826843952762347e-14);
688         check_roundtrip(8.143291313475335e-13);
689         check_roundtrip(4.851328172762508e-12);
690         check_roundtrip(6.677850998084358e-11);
691         check_roundtrip(3.995398518174525e-10);
692         check_roundtrip(1.960452605645124e-9);
693         check_roundtrip(3.551812586302883e-8);
694         check_roundtrip(2.947988411689261e-7);
695         check_roundtrip(8.210166748056192e-6);
696         check_roundtrip(6.104889704266753e-5);
697         check_roundtrip(0.0008629954631330876);
698         check_roundtrip(0.004936993881051611);
699         check_roundtrip(0.08309725102608073);
700         check_roundtrip(0.5210494268499783);
701         check_roundtrip(6.382927930939767);
702         check_roundtrip(59.94947245358671);
703         check_roundtrip(361.0838651266122);
704         check_roundtrip(4678.354596181877);
705         check_roundtrip(61412.17658956043);
706         check_roundtrip(725696.0799057782);
707         check_roundtrip(2811732.583399828);
708         check_roundtrip(30178351.07533605);
709         check_roundtrip(689684880.3235844);
710         check_roundtrip(5714887673.555147);
711         check_roundtrip(84652038821.18808);
712         check_roundtrip(156510583431.7721);
713         check_roundtrip(5938450569021.732);
714         check_roundtrip(83623297654460.33);
715         check_roundtrip(701466573254773.6);
716         check_roundtrip(1369013370304513);
717         check_roundtrip(96963648023094720); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
718         check_roundtrip(3.478237409280108e+17);
719     }
720 
721     SECTION("issue #366 - json::parse on failed stream gets stuck")
722     {
723         std::ifstream f("file_not_found.json");
724         json _;
725         CHECK_THROWS_WITH_AS(_ = json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
726     }
727 
728     SECTION("issue #367 - calling stream at EOF")
729     {
730         std::stringstream ss;
731         json j;
732         ss << "123";
733         CHECK_NOTHROW(ss >> j);
734 
735         // see https://github.com/nlohmann/json/issues/367#issuecomment-262841893:
736         // ss is not at EOF; this yielded an error before the fix
737         // (threw basic_string::append). No, it should just throw
738         // a parse error because of the EOF.
739         CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
740     }
741 
742     SECTION("issue #367 - behavior of operator>> should more closely resemble that of built-in overloads")
743     {
744         SECTION("(empty)")
745         {
746             std::stringstream ss;
747             json j;
748             CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
749         }
750 
751         SECTION("(whitespace)")
752         {
753             std::stringstream ss;
754             ss << "   ";
755             json j;
756             CHECK_THROWS_WITH_AS(ss >> j,
757                                  "[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&);
758         }
759 
760         SECTION("one value")
761         {
762             std::stringstream ss;
763             ss << "111";
764             json j;
765             CHECK_NOTHROW(ss >> j);
766             CHECK(j == 111);
767 
768             CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
769         }
770 
771         SECTION("one value + whitespace")
772         {
773             std::stringstream ss;
774             ss << "222 \t\n";
775             json j;
776             CHECK_NOTHROW(ss >> j);
777             CHECK(j == 222);
778 
779             CHECK_THROWS_WITH_AS(ss >> j,
780                                  "[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&);
781         }
782 
783         SECTION("whitespace + one value")
784         {
785             std::stringstream ss;
786             ss << "\n\t 333";
787             json j;
788             CHECK_NOTHROW(ss >> j);
789             CHECK(j == 333);
790 
791             CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
792         }
793 
794         SECTION("three values")
795         {
796             std::stringstream ss;
797             ss << " 111 \n222\n \n  333";
798             json j;
799             CHECK_NOTHROW(ss >> j);
800             CHECK(j == 111);
801             CHECK_NOTHROW(ss >> j);
802             CHECK(j == 222);
803             CHECK_NOTHROW(ss >> j);
804             CHECK(j == 333);
805 
806             CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
807         }
808 
809         SECTION("literals without whitespace")
810         {
811             std::stringstream ss;
812             ss << "truefalsenull\"\"";
813             json j;
814             CHECK_NOTHROW(ss >> j);
815             CHECK(j == true);
816             CHECK_NOTHROW(ss >> j);
817             CHECK(j == false);
818             CHECK_NOTHROW(ss >> j);
819             CHECK(j == nullptr);
820             CHECK_NOTHROW(ss >> j);
821             CHECK(j == "");
822 
823             CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
824         }
825 
826         SECTION("example from #529")
827         {
828             std::stringstream ss;
829             ss << "{\n    \"one\"   : 1,\n    \"two\"   : 2\n}\n{\n    \"three\" : 3\n}";
830             json j;
831             CHECK_NOTHROW(ss >> j);
832             CHECK(j == json({{"one", 1}, {"two", 2}}));
833             CHECK_NOTHROW(ss >> j);
834             CHECK(j == json({{"three", 3}}));
835 
836             CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
837         }
838 
839         SECTION("second example from #529")
840         {
841             std::string const str = "{\n\"one\"   : 1,\n\"two\"   : 2\n}\n{\n\"three\" : 3\n}";
842 
843             {
844                 std::ofstream file("test.json");
845                 file << str;
846             }
847 
848             std::ifstream stream("test.json", std::ifstream::in);
849             json val;
850 
851             size_t i = 0;
852             while (stream.peek() != EOF)
853             {
854                 CAPTURE(i)
855                 CHECK_NOTHROW(stream >> val);
856 
857                 CHECK(i < 2);
858 
859                 if (i == 0)
860                 {
861                     CHECK(val == json({{"one", 1}, {"two", 2}}));
862                 }
863 
864                 if (i == 1)
865                 {
866                     CHECK(val == json({{"three", 3}}));
867                 }
868 
869                 ++i;
870             }
871 
872             static_cast<void>(std::remove("test.json"));
873         }
874     }
875 
876     SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
877     {
878         // original test case
879         json const j1 = json::parse("-9223372036854775808");
880         CHECK(j1.is_number_integer());
881         CHECK(j1.get<json::number_integer_t>() == (std::numeric_limits<std::int64_t>::min)());
882 
883         // edge case (+1; still an integer)
884         json const j2 = json::parse("-9223372036854775807");
885         CHECK(j2.is_number_integer());
886         CHECK(j2.get<json::number_integer_t>() == (std::numeric_limits<std::int64_t>::min)() + 1);
887 
888         // edge case (-1; overflow -> floats)
889         json const j3 = json::parse("-9223372036854775809");
890         CHECK(j3.is_number_float());
891     }
892 
893     SECTION("issue #380 - bug in overflow detection when parsing integers")
894     {
895         json const j = json::parse("166020696663385964490");
896         CHECK(j.is_number_float());
897         CHECK(j.get<json::number_float_t>() == 166020696663385964490.0);
898     }
899 
900     SECTION("issue #405 - Heap-buffer-overflow (OSS-Fuzz issue 342)")
901     {
902         // original test case
903         std::vector<uint8_t> const vec {0x65, 0xf5, 0x0a, 0x48, 0x21};
904         json _;
905         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&);
906     }
907 
908     SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)")
909     {
910         json _;
911 
912         // original test case: incomplete float64
913         std::vector<uint8_t> const vec1 {0xcb, 0x8f, 0x0a};
914         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&);
915 
916         // related test case: incomplete float32
917         std::vector<uint8_t> const vec2 {0xca, 0x8f, 0x0a};
918         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&);
919 
920         // related test case: incomplete Half-Precision Float (CBOR)
921         std::vector<uint8_t> const vec3 {0xf9, 0x8f};
922         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&);
923 
924         // related test case: incomplete Single-Precision Float (CBOR)
925         std::vector<uint8_t> const vec4 {0xfa, 0x8f, 0x0a};
926         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&);
927 
928         // related test case: incomplete Double-Precision Float (CBOR)
929         std::vector<uint8_t> const vec5 {0xfb, 0x8f, 0x0a};
930         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&);
931     }
932 
933     SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)")
934     {
935         json _;
936 
937         // original test case
938         std::vector<uint8_t> const vec1 {0x87};
939         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&);
940 
941         // more test cases for MessagePack
942         for (auto b :
943                 {
944                     0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap
945                     0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray
946                     0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // fixstr
947                     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
948                 })
949         {
950             std::vector<uint8_t> const vec(1, static_cast<uint8_t>(b));
951             CHECK_THROWS_AS(_ = json::from_msgpack(vec), json::parse_error&);
952         }
953 
954         // more test cases for CBOR
955         for (auto b :
956                 {
957                     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
958                     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string
959                     0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
960                     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // array
961                     0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
962                     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map
963                 })
964         {
965             std::vector<uint8_t> const vec(1, static_cast<uint8_t>(b));
966             CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&);
967         }
968 
969         // special case: empty input
970         std::vector<uint8_t> const vec2;
971         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&);
972         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&);
973     }
974 
975     SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)")
976     {
977         json _;
978 
979         // original test case: empty UTF-8 string (indefinite length)
980         std::vector<uint8_t> const vec1 {0x7f};
981         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&);
982 
983         // related test case: empty array (indefinite length)
984         std::vector<uint8_t> const vec2 {0x9f};
985         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&);
986 
987         // related test case: empty map (indefinite length)
988         std::vector<uint8_t> const vec3 {0xbf};
989         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&);
990     }
991 
992     SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)")
993     {
994         // original test case
995         std::vector<uint8_t> const vec
996         {
997             0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
998             0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00,
999             0x60, 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
1000             0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00,
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, 0x60, 0x60,
1007             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xa0, 0x9f,
1008             0x9f, 0x97, 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             0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60
1014         };
1015 
1016         json _;
1017         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&);
1018 
1019         // related test case: nonempty UTF-8 string (indefinite length)
1020         std::vector<uint8_t> const vec1 {0x7f, 0x61, 0x61};
1021         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&);
1022 
1023         // related test case: nonempty array (indefinite length)
1024         std::vector<uint8_t> const vec2 {0x9f, 0x01};
1025         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&);
1026 
1027         // related test case: nonempty map (indefinite length)
1028         std::vector<uint8_t> const vec3 {0xbf, 0x61, 0x61, 0x01};
1029         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&);
1030     }
1031 
1032     SECTION("issue #414 - compare with literal 0)")
1033     {
1034 #define CHECK_TYPE(v) \
1035     CHECK((json(v) == (v)));\
1036     CHECK(((v) == json(v)));\
1037     CHECK_FALSE((json(v) != (v)));\
1038     CHECK_FALSE(((v) != json(v)));
1039 
1040         CHECK_TYPE(nullptr)
1041         CHECK_TYPE(0)
1042         CHECK_TYPE(0u)
1043         CHECK_TYPE(0L)
1044         CHECK_TYPE(0.0)
1045         CHECK_TYPE("") // NOLINT(readability-container-size-empty)
1046 
1047 #undef CHECK_TYPE
1048     }
1049 
1050     SECTION("issue #416 - Use-of-uninitialized-value (OSS-Fuzz issue 377)")
1051     {
1052         // original test case
1053         std::vector<uint8_t> const vec1
1054         {
1055             0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1056             0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
1057             0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71,
1058             0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a,
1059             0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
1060             0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa
1061         };
1062 
1063         json _;
1064         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&);
1065 
1066         // related test case: double-precision
1067         std::vector<uint8_t> const vec2
1068         {
1069             0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1070             0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
1071             0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71,
1072             0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a,
1073             0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
1074             0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
1075         };
1076         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&);
1077     }
1078 
1079     SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
1080     {
1081         std::vector<uint8_t> const vec = {'-', '0', '1', '2', '2', '7', '4'};
1082         json _;
1083         CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&);
1084     }
1085 
1086     SECTION("issue #454 - doubles are printed as integers")
1087     {
1088         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;
1089         CHECK(j["double_value"].is_number_float());
1090     }
1091 
1092 #if JSON_USE_IMPLICIT_CONVERSIONS
1093     SECTION("issue #464 - VS2017 implicit to std::string conversion fix")
1094     {
1095         json v = "test";
1096         std::string test;
1097         test = v;
1098         CHECK(v == "test");
1099     }
1100 #endif
1101 
1102     SECTION("issue #465 - roundtrip error while parsing 1000000000000000010E5")
1103     {
1104         json const j1 = json::parse("1000000000000000010E5");
1105         std::string s1 = j1.dump();
1106         json const j2 = json::parse(s1);
1107         std::string s2 = j2.dump();
1108         CHECK(s1 == s2);
1109     }
1110 
1111 #if JSON_USE_IMPLICIT_CONVERSIONS
1112     SECTION("issue #473 - inconsistent behavior in conversion to array type")
1113     {
1114         json const j_array = {1, 2, 3, 4};
1115         json const j_number = 42;
1116         json const j_null = nullptr;
1117 
1118         SECTION("std::vector")
1119         {
1120             auto create = [](const json & j)
__anon525045f40602(const json & j) 1121             {
1122                 std::vector<int> const v = j;
1123             };
1124 
1125             CHECK_NOTHROW(create(j_array));
1126             CHECK_THROWS_WITH_AS(create(j_number), "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
1127             CHECK_THROWS_WITH_AS(create(j_null), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1128         }
1129 
1130         SECTION("std::list")
1131         {
1132             auto create = [](const json & j)
__anon525045f40702(const json & j) 1133             {
1134                 std::list<int> const v = j;
1135             };
1136 
1137             CHECK_NOTHROW(create(j_array));
1138             CHECK_THROWS_WITH_AS(create(j_number), "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
1139             CHECK_THROWS_WITH_AS(create(j_null), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1140         }
1141 
1142         SECTION("std::forward_list")
1143         {
1144             auto create = [](const json & j)
__anon525045f40802(const json & j) 1145             {
1146                 std::forward_list<int> const v = j;
1147             };
1148 
1149             CHECK_NOTHROW(create(j_array));
1150             CHECK_THROWS_WITH_AS(create(j_number), "[json.exception.type_error.302] type must be array, but is number", json::type_error&);
1151             CHECK_THROWS_WITH_AS(create(j_null), "[json.exception.type_error.302] type must be array, but is null", json::type_error&);
1152         }
1153     }
1154 #endif
1155 
1156     SECTION("issue #486 - json::value_t can't be a map's key type in VC++ 2015")
1157     {
1158         // the code below must compile with MSVC
1159         std::map<json::value_t, std::string> jsonTypes ;
1160         jsonTypes[json::value_t::array] = "array";
1161     }
1162 
1163     SECTION("issue #494 - conversion from vector<bool> to json fails to build")
1164     {
1165         std::vector<bool> const boolVector = {false, true, false, false};
1166         json j;
1167         j["bool_vector"] = boolVector;
1168 
1169         CHECK(j["bool_vector"].dump() == "[false,true,false,false]");
1170     }
1171 
1172     SECTION("issue #504 - assertion error (OSS-Fuzz 856)")
1173     {
1174         std::vector<uint8_t> const vec1 = {0xf9, 0xff, 0xff, 0x4a, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x37, 0x02, 0x38};
1175         json const j1 = json::from_cbor(vec1, false);
1176 
1177         // step 2: round trip
1178         std::vector<uint8_t> vec2 = json::to_cbor(j1);
1179 
1180         // parse serialization
1181         json const j2 = json::from_cbor(vec2);
1182 
1183         // NaN is dumped to "null"
1184         CHECK(j2.is_number_float());
1185         CHECK(std::isnan(j2.get<json::number_float_t>()));
1186         CHECK(j2.dump() == "null");
1187 
1188         // check if serializations match
1189         CHECK(json::to_cbor(j2) == vec2);
1190     }
1191 
1192     SECTION("issue #512 - use of overloaded operator '<=' is ambiguous")
1193     {
1194         json j;
1195         j["a"] = 5;
1196 
1197         // json op scalar
1198         CHECK(j["a"] == 5);
1199         CHECK(j["a"] != 4);
1200 
1201         CHECK(j["a"] <= 7);
1202         CHECK(j["a"] <  7);
1203         CHECK(j["a"] >= 3);
1204         CHECK(j["a"] >  3);
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> const 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 const 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 const 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> const 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 const key1_str(reinterpret_cast<char*>(key1.data()));
1368         json const 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> const 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 const cb = [](int /*depth*/, json::parse_event_t event, json & parsed)
__anon525045f40902(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 const 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 const 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