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