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