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