• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3 // |  |  |__   |  |  | | | |  version 3.11.3
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8 
9 #include "doctest_compatibility.h"
10 
11 #include <nlohmann/json.hpp>
12 using nlohmann::json;
13 
14 #include <climits> // SIZE_MAX
15 #include <limits> // numeric_limits
16 
17 template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
18 struct trait_test_arg
19 {
20     using of_type = OfType;
21     using type = T;
22     static constexpr bool min_in_range = MinInRange;
23     static constexpr bool max_in_range = MaxInRange;
24 };
25 
26 TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test)
27 {
28     using nlohmann::detail::value_in_range_of;
29 
30     using of_type = typename T::of_type;
31     using type = typename T::type;
32     constexpr bool min_in_range = T::min_in_range;
33     constexpr bool max_in_range = T::max_in_range;
34 
35     type const val_min = std::numeric_limits<type>::min();
36     type const val_min2 = val_min + 1;
37     type const val_max = std::numeric_limits<type>::max();
38     type const val_max2 = val_max - 1;
39 
40     REQUIRE(CHAR_BIT == 8);
41 
42     std::string of_type_str;
43     if (std::is_unsigned<of_type>::value)
44     {
45         of_type_str += "u";
46     }
47     of_type_str += "int";
48     of_type_str += std::to_string(sizeof(of_type) * 8);
49 
50     INFO("of_type := ", of_type_str);
51 
52     std::string type_str;
53     if (std::is_unsigned<type>::value)
54     {
55         type_str += "u";
56     }
57     type_str += "int";
58     type_str += std::to_string(sizeof(type) * 8);
59 
60     INFO("type := ", type_str);
61 
62     CAPTURE(val_min);
63     CAPTURE(min_in_range);
64     CAPTURE(val_max);
65     CAPTURE(max_in_range);
66 
67     if (min_in_range)
68     {
69         CHECK(value_in_range_of<of_type>(val_min));
70         CHECK(value_in_range_of<of_type>(val_min2));
71     }
72     else
73     {
74         CHECK_FALSE(value_in_range_of<of_type>(val_min));
75         CHECK_FALSE(value_in_range_of<of_type>(val_min2));
76     }
77 
78     if (max_in_range)
79     {
80         CHECK(value_in_range_of<of_type>(val_max));
81         CHECK(value_in_range_of<of_type>(val_max2));
82     }
83     else
84     {
85         CHECK_FALSE(value_in_range_of<of_type>(val_max));
86         CHECK_FALSE(value_in_range_of<of_type>(val_max2));
87     }
88 }
89 
90 TEST_CASE("32bit")
91 {
92     REQUIRE(SIZE_MAX == 0xffffffff);
93 }
94 
95 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
96                           trait_test_arg<std::size_t, std::int32_t, false, true>, \
97                           trait_test_arg<std::size_t, std::uint32_t, true, true>, \
98                           trait_test_arg<std::size_t, std::int64_t, false, false>, \
99                           trait_test_arg<std::size_t, std::uint64_t, true, false>);
100 
101 TEST_CASE("BJData")
102 {
103     SECTION("parse errors")
104     {
105         SECTION("array")
106         {
107             SECTION("optimized array: negative size")
108             {
109                 std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
110                 std::vector<uint8_t> const vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'};
111 
112                 json _;
113                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
114                 CHECK(json::from_bjdata(vM, true, false).is_discarded());
115 
116                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
117                 CHECK(json::from_bjdata(vMX, true, false).is_discarded());
118             }
119 
120             SECTION("optimized array: integer value overflow")
121             {
122                 std::vector<uint8_t> const vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F};
123                 std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
124 
125                 json _;
126                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
127                 CHECK(json::from_bjdata(vL, true, false).is_discarded());
128 
129                 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
130                 CHECK(json::from_bjdata(vM, true, false).is_discarded());
131             }
132         }
133     }
134 }
135