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