1 /*
2     __ _____ _____ _____
3  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4 |  |  |__   |  |  | | | |  version 3.7.3
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10 
11 Permission is hereby  granted, free of charge, to any  person obtaining a copy
12 of this software and associated  documentation files (the "Software"), to deal
13 in the Software  without restriction, including without  limitation the rights
14 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 
30 #include "doctest_compatibility.h"
31 DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
32 
33 #include <nlohmann/json.hpp>
34 using nlohmann::json;
35 
36 TEST_CASE("reference access")
37 {
38     // create a JSON value with different types
39     json json_types =
40     {
41         {"boolean", true},
42         {
43             "number", {
44                 {"integer", 42},
45                 {"floating-point", 17.23}
46             }
47         },
48         {"string", "Hello, world!"},
49         {"array", {1, 2, 3, 4, 5}},
50         {"null", nullptr}
51     };
52 
53     SECTION("reference access to object_t")
54     {
55         using test_type = json::object_t;
56         json value = {{"one", 1}, {"two", 2}};
57 
58         // check if references are returned correctly
59         test_type& p1 = value.get_ref<test_type&>();
60         CHECK(&p1 == value.get_ptr<test_type*>());
61         CHECK(p1 == value.get<test_type>());
62 
63         const test_type& p2 = value.get_ref<const test_type&>();
64         CHECK(&p2 == value.get_ptr<const test_type*>());
65         CHECK(p2 == value.get<test_type>());
66 
67         // check if mismatching references throw correctly
68         CHECK_NOTHROW(value.get_ref<json::object_t&>());
69         CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error&);
70         CHECK_THROWS_WITH(value.get_ref<json::array_t&>(),
71                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object");
72         CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error&);
73         CHECK_THROWS_WITH(value.get_ref<json::string_t&>(),
74                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object");
75         CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error&);
76         CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(),
77                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object");
78         CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error&);
79         CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(),
80                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object");
81         CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error&);
82         CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(),
83                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object");
84         CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error&);
85         CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(),
86                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object");
87     }
88 
89     SECTION("const reference access to const object_t")
90     {
91         using test_type = json::object_t;
92         const json value = {{"one", 1}, {"two", 2}};
93 
94         // this should not compile
95         // test_type& p1 = value.get_ref<test_type&>();
96 
97         // check if references are returned correctly
98         const test_type& p2 = value.get_ref<const test_type&>();
99         CHECK(&p2 == value.get_ptr<const test_type*>());
100         CHECK(p2 == value.get<test_type>());
101     }
102 
103     SECTION("reference access to array_t")
104     {
105         using test_type = json::array_t;
106         json value = {1, 2, 3, 4};
107 
108         // check if references are returned correctly
109         test_type& p1 = value.get_ref<test_type&>();
110         CHECK(&p1 == value.get_ptr<test_type*>());
111         CHECK(p1 == value.get<test_type>());
112 
113         const test_type& p2 = value.get_ref<const test_type&>();
114         CHECK(&p2 == value.get_ptr<const test_type*>());
115         CHECK(p2 == value.get<test_type>());
116 
117         // check if mismatching references throw correctly
118         CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error&);
119         CHECK_THROWS_WITH(value.get_ref<json::object_t&>(),
120                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array");
121         CHECK_NOTHROW(value.get_ref<json::array_t&>());
122         CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error&);
123         CHECK_THROWS_WITH(value.get_ref<json::string_t&>(),
124                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array");
125         CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error&);
126         CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(),
127                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array");
128         CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error&);
129         CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(),
130                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array");
131         CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error&);
132         CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(),
133                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array");
134         CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error&);
135         CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(),
136                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is array");
137     }
138 
139     SECTION("reference access to string_t")
140     {
141         using test_type = json::string_t;
142         json value = "hello";
143 
144         // check if references are returned correctly
145         test_type& p1 = value.get_ref<test_type&>();
146         CHECK(&p1 == value.get_ptr<test_type*>());
147         CHECK(p1 == value.get<test_type>());
148 
149         const test_type& p2 = value.get_ref<const test_type&>();
150         CHECK(&p2 == value.get_ptr<const test_type*>());
151         CHECK(p2 == value.get<test_type>());
152 
153         // check if mismatching references throw correctly
154         CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error&);
155         CHECK_THROWS_WITH(value.get_ref<json::object_t&>(),
156                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string");
157         CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error&);
158         CHECK_THROWS_WITH(value.get_ref<json::array_t&>(),
159                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string");
160         CHECK_NOTHROW(value.get_ref<json::string_t&>());
161         CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error&);
162         CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(),
163                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string");
164         CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error&);
165         CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(),
166                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string");
167         CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error&);
168         CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(),
169                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string");
170         CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error&);
171         CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(),
172                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is string");
173     }
174 
175     SECTION("reference access to boolean_t")
176     {
177         using test_type = json::boolean_t;
178         json value = false;
179 
180         // check if references are returned correctly
181         test_type& p1 = value.get_ref<test_type&>();
182         CHECK(&p1 == value.get_ptr<test_type*>());
183         CHECK(p1 == value.get<test_type>());
184 
185         const test_type& p2 = value.get_ref<const test_type&>();
186         CHECK(&p2 == value.get_ptr<const test_type*>());
187         CHECK(p2 == value.get<test_type>());
188 
189         // check if mismatching references throw correctly
190         CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error&);
191         CHECK_THROWS_WITH(value.get_ref<json::object_t&>(),
192                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean");
193         CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error&);
194         CHECK_THROWS_WITH(value.get_ref<json::array_t&>(),
195                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean");
196         CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error&);
197         CHECK_THROWS_WITH(value.get_ref<json::string_t&>(),
198                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean");
199         CHECK_NOTHROW(value.get_ref<json::boolean_t&>());
200         CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error&);
201         CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(),
202                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean");
203         CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error&);
204         CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(),
205                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean");
206         CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error&);
207         CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(),
208                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is boolean");
209     }
210 
211     SECTION("reference access to number_integer_t")
212     {
213         using test_type = json::number_integer_t;
214         json value = -23;
215 
216         // check if references are returned correctly
217         test_type& p1 = value.get_ref<test_type&>();
218         CHECK(&p1 == value.get_ptr<test_type*>());
219         CHECK(p1 == value.get<test_type>());
220 
221         const test_type& p2 = value.get_ref<const test_type&>();
222         CHECK(&p2 == value.get_ptr<const test_type*>());
223         CHECK(p2 == value.get<test_type>());
224 
225         // check if mismatching references throw correctly
226         CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error&);
227         CHECK_THROWS_WITH(value.get_ref<json::object_t&>(),
228                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
229         CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error&);
230         CHECK_THROWS_WITH(value.get_ref<json::array_t&>(),
231                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
232         CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error&);
233         CHECK_THROWS_WITH(value.get_ref<json::string_t&>(),
234                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
235         CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error&);
236         CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(),
237                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
238         CHECK_NOTHROW(value.get_ref<json::number_integer_t&>());
239         CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error&);
240         CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(),
241                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
242         CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error&);
243         CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(),
244                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
245     }
246 
247     SECTION("reference access to number_unsigned_t")
248     {
249         using test_type = json::number_unsigned_t;
250         json value = 23u;
251 
252         // check if references are returned correctly
253         test_type& p1 = value.get_ref<test_type&>();
254         CHECK(&p1 == value.get_ptr<test_type*>());
255         CHECK(p1 == value.get<test_type>());
256 
257         const test_type& p2 = value.get_ref<const test_type&>();
258         CHECK(&p2 == value.get_ptr<const test_type*>());
259         CHECK(p2 == value.get<test_type>());
260 
261         // check if mismatching references throw correctly
262         CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error&);
263         CHECK_THROWS_WITH(value.get_ref<json::object_t&>(),
264                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
265         CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error&);
266         CHECK_THROWS_WITH(value.get_ref<json::array_t&>(),
267                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
268         CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error&);
269         CHECK_THROWS_WITH(value.get_ref<json::string_t&>(),
270                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
271         CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error&);
272         CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(),
273                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
274         //CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error&);
275         //CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(),
276         //    "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
277         CHECK_NOTHROW(value.get_ref<json::number_unsigned_t&>());
278         CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error&);
279         CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(),
280                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
281     }
282 
283     SECTION("reference access to number_float_t")
284     {
285         using test_type = json::number_float_t;
286         json value = 42.23;
287 
288         // check if references are returned correctly
289         test_type& p1 = value.get_ref<test_type&>();
290         CHECK(&p1 == value.get_ptr<test_type*>());
291         CHECK(p1 == value.get<test_type>());
292 
293         const test_type& p2 = value.get_ref<const test_type&>();
294         CHECK(&p2 == value.get_ptr<const test_type*>());
295         CHECK(p2 == value.get<test_type>());
296 
297         // check if mismatching references throw correctly
298         CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error&);
299         CHECK_THROWS_WITH(value.get_ref<json::object_t&>(),
300                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
301         CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error&);
302         CHECK_THROWS_WITH(value.get_ref<json::array_t&>(),
303                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
304         CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error&);
305         CHECK_THROWS_WITH(value.get_ref<json::string_t&>(),
306                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
307         CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error&);
308         CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(),
309                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
310         CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error&);
311         CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(),
312                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
313         CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error&);
314         CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(),
315                           "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number");
316         CHECK_NOTHROW(value.get_ref<json::number_float_t&>());
317     }
318 }
319