]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/third_party/nlohmann-json/test/src/unit-regression2.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / nlohmann-json / test / src / unit-regression2.cpp
1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++ (test suite)
4 | | |__ | | | | | | version 3.10.5
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-2022 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
32 // for some reason including this after the json header leads to linker errors with VS 2017...
33 #include <locale>
34
35 #define JSON_TESTS_PRIVATE
36 #include <nlohmann/json.hpp>
37 using json = nlohmann::json;
38 using ordered_json = nlohmann::ordered_json;
39
40 #include <cstdio>
41 #include <list>
42 #include <type_traits>
43 #include <utility>
44
45 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
46 #define JSON_HAS_CPP_17
47 #endif
48
49 #ifdef JSON_HAS_CPP_17
50 #include <variant>
51
52 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
53 #if defined(__cpp_lib_filesystem)
54 #define JSON_HAS_FILESYSTEM 1
55 #elif defined(__cpp_lib_experimental_filesystem)
56 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
57 #elif !defined(__has_include)
58 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
59 #elif __has_include(<filesystem>)
60 #define JSON_HAS_FILESYSTEM 1
61 #elif __has_include(<experimental/filesystem>)
62 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
63 #endif
64
65 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
66 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
67 #undef JSON_HAS_FILESYSTEM
68 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
69 #endif
70
71 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
72 #if defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)
73 #undef JSON_HAS_FILESYSTEM
74 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
75 #endif
76
77 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
78 #if defined(__clang_major__) && __clang_major__ < 7
79 #undef JSON_HAS_FILESYSTEM
80 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
81 #endif
82
83 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
84 #if defined(_MSC_VER) && _MSC_VER < 1940
85 #undef JSON_HAS_FILESYSTEM
86 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
87 #endif
88
89 // no filesystem support before iOS 13
90 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
91 #undef JSON_HAS_FILESYSTEM
92 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
93 #endif
94
95 // no filesystem support before macOS Catalina
96 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
97 #undef JSON_HAS_FILESYSTEM
98 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
99 #endif
100 #endif
101 #endif
102
103 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
104 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
105 #endif
106
107 #ifndef JSON_HAS_FILESYSTEM
108 #define JSON_HAS_FILESYSTEM 0
109 #endif
110
111 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
112 #include <experimental/filesystem>
113 namespace nlohmann::detail
114 {
115 namespace std_fs = std::experimental::filesystem;
116 } // namespace nlohmann::detail
117 #elif JSON_HAS_FILESYSTEM
118 #include <filesystem>
119 namespace nlohmann::detail
120 {
121 namespace std_fs = std::filesystem;
122 } // namespace nlohmann::detail
123 #endif
124
125
126 #ifdef JSON_HAS_CPP_20
127 #include <span>
128 #endif
129
130 // NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
131 DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
132 DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
133
134 /////////////////////////////////////////////////////////////////////
135 // for #1021
136 /////////////////////////////////////////////////////////////////////
137
138 using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;
139
140 /////////////////////////////////////////////////////////////////////
141 // for #1647
142 /////////////////////////////////////////////////////////////////////
143 namespace
144 {
145 struct NonDefaultFromJsonStruct
146 {};
147
148 inline bool operator==(NonDefaultFromJsonStruct const& /*unused*/, NonDefaultFromJsonStruct const& /*unused*/)
149 {
150 return true;
151 }
152
153 enum class for_1647
154 {
155 one,
156 two
157 };
158
159 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): this is a false positive
160 NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
161 {
162 {for_1647::one, "one"},
163 {for_1647::two, "two"},
164 })
165 } // namespace
166
167 /////////////////////////////////////////////////////////////////////
168 // for #1299
169 /////////////////////////////////////////////////////////////////////
170
171 struct Data
172 {
173 Data() = default;
174 Data(std::string a_, std::string b_)
175 : a(std::move(a_))
176 , b(std::move(b_))
177 {}
178 std::string a{};
179 std::string b{};
180 };
181
182 void from_json(const json& j, Data& data);
183 void from_json(const json& j, Data& data)
184 {
185 j["a"].get_to(data.a);
186 j["b"].get_to(data.b);
187 }
188
189 bool operator==(Data const& lhs, Data const& rhs);
190 bool operator==(Data const& lhs, Data const& rhs)
191 {
192 return lhs.a == rhs.a && lhs.b == rhs.b;
193 }
194
195 //bool operator!=(Data const& lhs, Data const& rhs)
196 //{
197 // return !(lhs == rhs);
198 //}
199
200 namespace nlohmann
201 {
202 template<>
203 struct adl_serializer<NonDefaultFromJsonStruct>
204 {
205 static NonDefaultFromJsonStruct from_json(json const& /*unused*/) noexcept
206 {
207 return {};
208 }
209 };
210 } // namespace nlohmann
211
212 /////////////////////////////////////////////////////////////////////
213 // for #1805
214 /////////////////////////////////////////////////////////////////////
215
216 struct NotSerializableData
217 {
218 int mydata;
219 float myfloat;
220 };
221
222 /////////////////////////////////////////////////////////////////////
223 // for #2574
224 /////////////////////////////////////////////////////////////////////
225
226 struct NonDefaultConstructible
227 {
228 explicit NonDefaultConstructible(int a)
229 : x(a)
230 {}
231 int x;
232 };
233
234 namespace nlohmann
235 {
236 template<>
237 struct adl_serializer<NonDefaultConstructible>
238 {
239 static NonDefaultConstructible from_json(json const& j)
240 {
241 return NonDefaultConstructible(j.get<int>());
242 }
243 };
244 } // namespace nlohmann
245
246 /////////////////////////////////////////////////////////////////////
247 // for #2824
248 /////////////////////////////////////////////////////////////////////
249
250 class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
251 {
252 public:
253 explicit sax_no_exception(json& j)
254 : nlohmann::detail::json_sax_dom_parser<json>(j, false)
255 {}
256
257 static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
258 {
259 error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
260 return false;
261 }
262
263 static std::string* error_string;
264 };
265
266 std::string* sax_no_exception::error_string = nullptr;
267
268 /////////////////////////////////////////////////////////////////////
269 // for #2982
270 /////////////////////////////////////////////////////////////////////
271
272 template<class T>
273 class my_allocator : public std::allocator<T>
274 {};
275
276 /////////////////////////////////////////////////////////////////////
277 // for #3077
278 /////////////////////////////////////////////////////////////////////
279
280 class FooAlloc
281 {};
282
283 class Foo
284 {
285 public:
286 explicit Foo(const FooAlloc& /* unused */ = FooAlloc()) {}
287
288 bool value = false;
289 };
290
291 class FooBar
292 {
293 public:
294 Foo foo{};
295 };
296
297 inline void from_json(const nlohmann::json& j, FooBar& fb)
298 {
299 j.at("value").get_to(fb.foo.value);
300 }
301
302 TEST_CASE("regression tests 2")
303 {
304 SECTION("issue #1001 - Fix memory leak during parser callback")
305 {
306 const auto* geojsonExample = R"(
307 { "type": "FeatureCollection",
308 "features": [
309 { "type": "Feature",
310 "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
311 "properties": {"prop0": "value0"}
312 },
313 { "type": "Feature",
314 "geometry": {
315 "type": "LineString",
316 "coordinates": [
317 [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
318 ]
319 },
320 "properties": {
321 "prop0": "value0",
322 "prop1": 0.0
323 }
324 },
325 { "type": "Feature",
326 "geometry": {
327 "type": "Polygon",
328 "coordinates": [
329 [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
330 [100.0, 1.0], [100.0, 0.0] ]
331 ]
332 },
333 "properties": {
334 "prop0": "value0",
335 "prop1": {"this": "that"}
336 }
337 }
338 ]
339 })";
340
341 json::parser_callback_t cb = [&](int /*level*/, json::parse_event_t event, json & parsed)
342 {
343 // skip uninteresting events
344 if (event == json::parse_event_t::value && !parsed.is_primitive())
345 {
346 return false;
347 }
348
349 switch (event)
350 {
351 case json::parse_event_t::key:
352 {
353 return true;
354 }
355 case json::parse_event_t::value:
356 {
357 return false;
358 }
359 case json::parse_event_t::object_start:
360 {
361 return true;
362 }
363 case json::parse_event_t::object_end:
364 {
365 return false;
366 }
367 case json::parse_event_t::array_start:
368 {
369 return true;
370 }
371 case json::parse_event_t::array_end:
372 {
373 return false;
374 }
375
376 default:
377 {
378 return true;
379 }
380 }
381 };
382
383 auto j = json::parse(geojsonExample, cb, true);
384 CHECK(j == json());
385 }
386
387 SECTION("issue #1021 - to/from_msgpack only works with standard typization")
388 {
389 float_json j = 1000.0;
390 CHECK(float_json::from_cbor(float_json::to_cbor(j)) == j);
391 CHECK(float_json::from_msgpack(float_json::to_msgpack(j)) == j);
392 CHECK(float_json::from_ubjson(float_json::to_ubjson(j)) == j);
393
394 float_json j2 = {1000.0, 2000.0, 3000.0};
395 CHECK(float_json::from_ubjson(float_json::to_ubjson(j2, true, true)) == j2);
396 }
397
398 SECTION("issue #1045 - Using STL algorithms with JSON containers with expected results?")
399 {
400 json diffs = nlohmann::json::array();
401 json m1{{"key1", 42}};
402 json m2{{"key2", 42}};
403 auto p1 = m1.items();
404 auto p2 = m2.items();
405
406 using it_type = decltype(p1.begin());
407
408 std::set_difference(
409 p1.begin(),
410 p1.end(),
411 p2.begin(),
412 p2.end(),
413 std::inserter(diffs, diffs.end()),
414 [&](const it_type & e1, const it_type & e2) -> bool
415 {
416 using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy
417 return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper
418 });
419
420 CHECK(diffs.size() == 1); // Note the change here, was 2
421 }
422
423 #ifdef JSON_HAS_CPP_17
424 SECTION("issue #1292 - Serializing std::variant causes stack overflow")
425 {
426 static_assert(!std::is_constructible<json, std::variant<int, float>>::value, "unexpected value");
427 }
428 #endif
429
430 SECTION("issue #1299 - compile error in from_json converting to container "
431 "with std::pair")
432 {
433 json j =
434 {
435 {"1", {{"a", "testa_1"}, {"b", "testb_1"}}},
436 {"2", {{"a", "testa_2"}, {"b", "testb_2"}}},
437 {"3", {{"a", "testa_3"}, {"b", "testb_3"}}},
438 };
439
440 std::map<std::string, Data> expected
441 {
442 {"1", {"testa_1", "testb_1"}},
443 {"2", {"testa_2", "testb_2"}},
444 {"3", {"testa_3", "testb_3"}},
445 };
446 const auto data = j.get<decltype(expected)>();
447 CHECK(expected == data);
448 }
449
450 SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
451 {
452 SECTION("a bunch of -1, ensure_ascii=true")
453 {
454 const auto length = 300;
455
456 json dump_test;
457 dump_test["1"] = std::string(length, -1);
458
459 std::string expected = R"({"1":")";
460 for (int i = 0; i < length; ++i)
461 {
462 expected += "\\ufffd";
463 }
464 expected += "\"}";
465
466 auto s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
467 CHECK(s == expected);
468 }
469 SECTION("a bunch of -2, ensure_ascii=false")
470 {
471 const auto length = 500;
472
473 json dump_test;
474 dump_test["1"] = std::string(length, -2);
475
476 std::string expected = R"({"1":")";
477 for (int i = 0; i < length; ++i)
478 {
479 expected += "\xEF\xBF\xBD";
480 }
481 expected += "\"}";
482
483 auto s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
484 CHECK(s == expected);
485 }
486 SECTION("test case in issue #1445")
487 {
488 nlohmann::json dump_test;
489 const std::array<int, 108> data =
490 {
491 {109, 108, 103, 125, -122, -53, 115, 18, 3, 0, 102, 19, 1, 15, -110, 13, -3, -1, -81, 32, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -80, 2, 0, 0, 96, -118, 46, -116, 46, 109, -84, -87, 108, 14, 109, -24, -83, 13, -18, -51, -83, -52, -115, 14, 6, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 3, 0, 0, 0, 35, -74, -73, 55, 57, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, -96, -54, -28, -26}
492 };
493 std::string s;
494 for (int i : data)
495 {
496 s += static_cast<char>(i);
497 }
498 dump_test["1"] = s;
499 dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
500 }
501 }
502
503 SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
504 {
505 json j = json::parse("[-9223372036854775808]");
506 CHECK(j.dump() == "[-9223372036854775808]");
507 }
508
509 SECTION("issue #1708 - minimum value of int64_t can be outputted")
510 {
511 constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
512 json j = smallest;
513 CHECK(j.dump() == std::to_string(smallest));
514 }
515
516 SECTION("issue #1727 - Contains with non-const lvalue json_pointer picks the wrong overload")
517 {
518 json j = {{"root", {{"settings", {{"logging", true}}}}}};
519
520 auto jptr1 = "/root/settings/logging"_json_pointer;
521 auto jptr2 = json::json_pointer{"/root/settings/logging"};
522
523 CHECK(j.contains(jptr1));
524 CHECK(j.contains(jptr2));
525 }
526
527 SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type")
528 {
529 {
530 json j;
531 NonDefaultFromJsonStruct x(j);
532 NonDefaultFromJsonStruct y;
533 CHECK(x == y);
534 }
535
536 auto val = nlohmann::json("one").get<for_1647>();
537 CHECK(val == for_1647::one);
538 json j = val;
539 }
540
541 SECTION("issue #1715 - json::from_cbor does not respect allow_exceptions = false when input is string literal")
542 {
543 SECTION("string literal")
544 {
545 json cbor = json::from_cbor("B", true, false);
546 CHECK(cbor.is_discarded());
547 }
548
549 SECTION("string array")
550 {
551 const std::array<char, 2> input = {{'B', 0x00}};
552 json cbor = json::from_cbor(input, true, false);
553 CHECK(cbor.is_discarded());
554 }
555
556 SECTION("std::string")
557 {
558 json cbor = json::from_cbor(std::string("B"), true, false);
559 CHECK(cbor.is_discarded());
560 }
561 }
562
563 SECTION("issue #1805 - A pair<T1, T2> is json constructible only if T1 and T2 are json constructible")
564 {
565 static_assert(!std::is_constructible<json, std::pair<std::string, NotSerializableData>>::value, "unexpected result");
566 static_assert(!std::is_constructible<json, std::pair<NotSerializableData, std::string>>::value, "unexpected result");
567 static_assert(std::is_constructible<json, std::pair<int, std::string>>::value, "unexpected result");
568 }
569 SECTION("issue #1825 - A tuple<Args..> is json constructible only if all T in Args are json constructible")
570 {
571 static_assert(!std::is_constructible<json, std::tuple<std::string, NotSerializableData>>::value, "unexpected result");
572 static_assert(!std::is_constructible<json, std::tuple<NotSerializableData, std::string>>::value, "unexpected result");
573 static_assert(std::is_constructible<json, std::tuple<int, std::string>>::value, "unexpected result");
574 }
575
576 SECTION("issue #1983 - JSON patch diff for op=add formation is not as per standard (RFC 6902)")
577 {
578 const auto source = R"({ "foo": [ "1", "2" ] })"_json;
579 const auto target = R"({"foo": [ "1", "2", "3" ]})"_json;
580 const auto result = json::diff(source, target);
581 CHECK(result.dump() == R"([{"op":"add","path":"/foo/-","value":"3"}])");
582 }
583
584 SECTION("issue #2067 - cannot serialize binary data to text JSON")
585 {
586 const std::array<unsigned char, 23> data = {{0x81, 0xA4, 0x64, 0x61, 0x74, 0x61, 0xC4, 0x0F, 0x33, 0x30, 0x30, 0x32, 0x33, 0x34, 0x30, 0x31, 0x30, 0x37, 0x30, 0x35, 0x30, 0x31, 0x30}};
587 json j = json::from_msgpack(data.data(), data.size());
588 CHECK_NOTHROW(
589 j.dump(4, // Indent
590 ' ', // Indent char
591 false, // Ensure ascii
592 json::error_handler_t::strict // Error
593 ));
594 }
595
596 SECTION("PR #2181 - regression bug with lvalue")
597 {
598 // see https://github.com/nlohmann/json/pull/2181#issuecomment-653326060
599 json j{{"x", "test"}};
600 std::string defval = "default value";
601 auto val = j.value("x", defval);
602 auto val2 = j.value("y", defval);
603 }
604
605 SECTION("issue #2293 - eof doesn't cause parsing to stop")
606 {
607 std::vector<uint8_t> data =
608 {
609 0x7B,
610 0x6F,
611 0x62,
612 0x6A,
613 0x65,
614 0x63,
615 0x74,
616 0x20,
617 0x4F,
618 0x42
619 };
620 json result = json::from_cbor(data, true, false);
621 CHECK(result.is_discarded());
622 }
623
624 SECTION("issue #2315 - json.update and vector<pair>does not work with ordered_json")
625 {
626 nlohmann::ordered_json jsonAnimals = {{"animal", "dog"}};
627 nlohmann::ordered_json jsonCat = {{"animal", "cat"}};
628 jsonAnimals.update(jsonCat);
629 CHECK(jsonAnimals["animal"] == "cat");
630
631 auto jsonAnimals_parsed = nlohmann::ordered_json::parse(jsonAnimals.dump());
632 CHECK(jsonAnimals == jsonAnimals_parsed);
633
634 std::vector<std::pair<std::string, int64_t>> intData = {std::make_pair("aaaa", 11),
635 std::make_pair("bbb", 222)
636 };
637 nlohmann::ordered_json jsonObj;
638 for (const auto& data : intData)
639 {
640 jsonObj[data.first] = data.second;
641 }
642 CHECK(jsonObj["aaaa"] == 11);
643 CHECK(jsonObj["bbb"] == 222);
644 }
645
646 SECTION("issue #2330 - ignore_comment=true fails on multiple consecutive lines starting with comments")
647 {
648 std::string ss = "//\n//\n{\n}\n";
649 json j = json::parse(ss, nullptr, true, true);
650 CHECK(j.dump() == "{}");
651 }
652
653 #ifdef JSON_HAS_CPP_20
654 SECTION("issue #2546 - parsing containers of std::byte")
655 {
656 const char DATA[] = R"("Hello, world!")";
657 const auto s = std::as_bytes(std::span(DATA));
658 json j = json::parse(s);
659 CHECK(j.dump() == "\"Hello, world!\"");
660 }
661 #endif
662
663 SECTION("issue #2574 - Deserialization to std::array, std::pair, and std::tuple with non-default constructable types fails")
664 {
665 SECTION("std::array")
666 {
667 {
668 json j = {7, 4};
669 auto arr = j.get<std::array<NonDefaultConstructible, 2>>();
670 CHECK(arr[0].x == 7);
671 CHECK(arr[1].x == 4);
672 }
673
674 {
675 json j = 7;
676 CHECK_THROWS_AS((j.get<std::array<NonDefaultConstructible, 1>>()), json::type_error);
677 }
678 }
679
680 SECTION("std::pair")
681 {
682 {
683 json j = {3, 8};
684 auto p = j.get<std::pair<NonDefaultConstructible, NonDefaultConstructible>>();
685 CHECK(p.first.x == 3);
686 CHECK(p.second.x == 8);
687 }
688
689 {
690 json j = {4, 1};
691 auto p = j.get<std::pair<int, NonDefaultConstructible>>();
692 CHECK(p.first == 4);
693 CHECK(p.second.x == 1);
694 }
695
696 {
697 json j = {6, 7};
698 auto p = j.get<std::pair<NonDefaultConstructible, int>>();
699 CHECK(p.first.x == 6);
700 CHECK(p.second == 7);
701 }
702
703 {
704 json j = 7;
705 CHECK_THROWS_AS((j.get<std::pair<NonDefaultConstructible, int>>()), json::type_error);
706 }
707 }
708
709 SECTION("std::tuple")
710 {
711 {
712 json j = {9};
713 auto t = j.get<std::tuple<NonDefaultConstructible>>();
714 CHECK(std::get<0>(t).x == 9);
715 }
716
717 {
718 json j = {9, 8, 7};
719 auto t = j.get<std::tuple<NonDefaultConstructible, int, NonDefaultConstructible>>();
720 CHECK(std::get<0>(t).x == 9);
721 CHECK(std::get<1>(t) == 8);
722 CHECK(std::get<2>(t).x == 7);
723 }
724
725 {
726 json j = 7;
727 CHECK_THROWS_AS((j.get<std::tuple<NonDefaultConstructible>>()), json::type_error);
728 }
729 }
730 }
731
732 SECTION("issue #2865 - ASAN detects memory leaks")
733 {
734 // the code below is expected to not leak memory
735 {
736 nlohmann::json o;
737 std::string s = "bar";
738
739 nlohmann::to_json(o["foo"], s);
740
741 nlohmann::json p = o;
742
743 // call to_json with a non-null JSON value
744 nlohmann::to_json(p["foo"], s);
745 }
746
747 {
748 nlohmann::json o;
749 std::string s = "bar";
750
751 nlohmann::to_json(o["foo"], s);
752
753 // call to_json with a non-null JSON value
754 nlohmann::to_json(o["foo"], s);
755 }
756 }
757
758 SECTION("issue #2824 - encoding of json::exception::what()")
759 {
760 json j;
761 sax_no_exception sax(j);
762
763 CHECK(!json::sax_parse("xyz", &sax));
764 CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'");
765 delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
766 }
767
768 SECTION("issue #2825 - Properly constrain the basic_json conversion operator")
769 {
770 static_assert(std::is_copy_assignable<nlohmann::ordered_json>::value, "ordered_json must be copy assignable");
771 }
772
773 SECTION("issue #2958 - Inserting in unordered json using a pointer retains the leading slash")
774 {
775 std::string p = "/root";
776
777 // matching types
778 json test1;
779 test1[json::json_pointer(p)] = json::object();
780 CHECK(test1.dump() == "{\"root\":{}}");
781
782 ordered_json test2;
783 test2[ordered_json::json_pointer(p)] = json::object();
784 CHECK(test2.dump() == "{\"root\":{}}");
785
786 // mixed type - the JSON Pointer is implicitly converted into a string "/root"
787 ordered_json test3;
788 test3[json::json_pointer(p)] = json::object();
789 CHECK(test3.dump() == "{\"/root\":{}}");
790 }
791
792 SECTION("issue #2982 - to_{binary format} does not provide a mechanism for specifying a custom allocator for the returned type")
793 {
794 std::vector<std::uint8_t, my_allocator<std::uint8_t>> my_vector;
795 json j = {1, 2, 3, 4};
796 json::to_cbor(j, my_vector);
797 json k = json::from_cbor(my_vector);
798 CHECK(j == k);
799 }
800
801 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
802 SECTION("issue #3070 - Version 3.10.3 breaks backward-compatibility with 3.10.2 ")
803 {
804 nlohmann::detail::std_fs::path text_path("/tmp/text.txt");
805 json j(text_path);
806
807 const auto j_path = j.get<nlohmann::detail::std_fs::path>();
808 CHECK(j_path == text_path);
809
810 CHECK_THROWS_WITH_AS(nlohmann::detail::std_fs::path(json(1)), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
811 }
812 #endif
813
814 SECTION("issue #3077 - explicit constructor with default does not compile")
815 {
816 json j;
817 j[0]["value"] = true;
818 std::vector<FooBar> foo;
819 j.get_to(foo);
820 }
821
822 SECTION("issue #3108 - ordered_json doesn't support range based erase")
823 {
824 ordered_json j = {1, 2, 2, 4};
825
826 auto last = std::unique(j.begin(), j.end());
827 j.erase(last, j.end());
828
829 CHECK(j.dump() == "[1,2,4]");
830
831 j.erase(std::remove_if(j.begin(), j.end(), [](const ordered_json & val)
832 {
833 return val == 2;
834 }), j.end());
835
836 CHECK(j.dump() == "[1,4]");
837 }
838 }
839
840 DOCTEST_CLANG_SUPPRESS_WARNING_POP