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