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 
32 #include <nlohmann/json.hpp>
33 using nlohmann::json;
34 
35 TEST_CASE("element access 1")
36 {
37     SECTION("array")
38     {
39         json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
40         const json j_const = j;
41 
42         SECTION("access specified element with bounds checking")
43         {
44             SECTION("access within bounds")
45             {
46                 CHECK(j.at(0) == json(1));
47                 CHECK(j.at(1) == json(1u));
48                 CHECK(j.at(2) == json(true));
49                 CHECK(j.at(3) == json(nullptr));
50                 CHECK(j.at(4) == json("string"));
51                 CHECK(j.at(5) == json(42.23));
52                 CHECK(j.at(6) == json::object());
53                 CHECK(j.at(7) == json({1, 2, 3}));
54 
55                 CHECK(j_const.at(0) == json(1));
56                 CHECK(j_const.at(1) == json(1u));
57                 CHECK(j_const.at(2) == json(true));
58                 CHECK(j_const.at(3) == json(nullptr));
59                 CHECK(j_const.at(4) == json("string"));
60                 CHECK(j_const.at(5) == json(42.23));
61                 CHECK(j_const.at(6) == json::object());
62                 CHECK(j_const.at(7) == json({1, 2, 3}));
63             }
64 
65             SECTION("access outside bounds")
66             {
67                 CHECK_THROWS_AS(j.at(8), json::out_of_range&);
68                 CHECK_THROWS_AS(j_const.at(8), json::out_of_range&);
69 
70                 CHECK_THROWS_WITH(j.at(8),
71                                   "[json.exception.out_of_range.401] array index 8 is out of range");
72                 CHECK_THROWS_WITH(j_const.at(8),
73                                   "[json.exception.out_of_range.401] array index 8 is out of range");
74             }
75 
76             SECTION("access on non-array type")
77             {
78                 SECTION("null")
79                 {
80                     json j_nonarray(json::value_t::null);
81                     const json j_nonarray_const(j_nonarray);
82                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
83                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
84 
85                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with null");
86                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with null");
87                 }
88 
89                 SECTION("boolean")
90                 {
91                     json j_nonarray(json::value_t::boolean);
92                     const json j_nonarray_const(j_nonarray);
93                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
94                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
95 
96                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with boolean");
97                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with boolean");
98                 }
99 
100                 SECTION("string")
101                 {
102                     json j_nonarray(json::value_t::string);
103                     const json j_nonarray_const(j_nonarray);
104                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
105                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
106 
107                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with string");
108                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with string");
109                 }
110 
111                 SECTION("object")
112                 {
113                     json j_nonarray(json::value_t::object);
114                     const json j_nonarray_const(j_nonarray);
115                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
116                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
117 
118                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with object");
119                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with object");
120                 }
121 
122                 SECTION("number (integer)")
123                 {
124                     json j_nonarray(json::value_t::number_integer);
125                     const json j_nonarray_const(j_nonarray);
126                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
127                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
128 
129                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number");
130                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number");
131                 }
132 
133                 SECTION("number (unsigned)")
134                 {
135                     json j_nonarray(json::value_t::number_unsigned);
136                     const json j_nonarray_const(j_nonarray);
137                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
138                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
139 
140                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number");
141                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number");
142                 }
143 
144                 SECTION("number (floating-point)")
145                 {
146                     json j_nonarray(json::value_t::number_float);
147                     const json j_nonarray_const(j_nonarray);
148                     CHECK_THROWS_AS(j_nonarray.at(0), json::type_error&);
149                     CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error&);
150 
151                     CHECK_THROWS_WITH(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number");
152                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number");
153                 }
154             }
155         }
156 
157         SECTION("front and back")
158         {
159             CHECK(j.front() == json(1));
160             CHECK(j_const.front() == json(1));
161             CHECK(j.back() == json({1, 2, 3}));
162             CHECK(j_const.back() == json({1, 2, 3}));
163         }
164 
165         SECTION("access specified element")
166         {
167             SECTION("access within bounds")
168             {
169                 CHECK(j[0] == json(1));
170                 CHECK(j[1] == json(1u));
171                 CHECK(j[2] == json(true));
172                 CHECK(j[3] == json(nullptr));
173                 CHECK(j[4] == json("string"));
174                 CHECK(j[5] == json(42.23));
175                 CHECK(j[6] == json::object());
176                 CHECK(j[7] == json({1, 2, 3}));
177 
178                 CHECK(j_const[0] == json(1));
179                 CHECK(j_const[1] == json(1u));
180                 CHECK(j_const[2] == json(true));
181                 CHECK(j_const[3] == json(nullptr));
182                 CHECK(j_const[4] == json("string"));
183                 CHECK(j_const[5] == json(42.23));
184                 CHECK(j_const[6] == json::object());
185                 CHECK(j_const[7] == json({1, 2, 3}));
186             }
187 
188             SECTION("access on non-array type")
189             {
190                 SECTION("null")
191                 {
192                     SECTION("standard tests")
193                     {
194                         json j_nonarray(json::value_t::null);
195                         const json j_nonarray_const(j_nonarray);
196                         CHECK_NOTHROW(j_nonarray[0]);
197                         CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
198                         CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with null");
199                     }
200 
201                     SECTION("implicit transformation to properly filled array")
202                     {
203                         json j_nonarray;
204                         j_nonarray[3] = 42;
205                         CHECK(j_nonarray == json({nullptr, nullptr, nullptr, 42}));
206                     }
207                 }
208 
209                 SECTION("boolean")
210                 {
211                     json j_nonarray(json::value_t::boolean);
212                     const json j_nonarray_const(j_nonarray);
213                     CHECK_THROWS_AS(j_nonarray[0], json::type_error&);
214                     CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
215                     CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean");
216                     CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean");
217                 }
218 
219                 SECTION("string")
220                 {
221                     json j_nonarray(json::value_t::string);
222                     const json j_nonarray_const(j_nonarray);
223                     CHECK_THROWS_AS(j_nonarray[0], json::type_error&);
224                     CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
225                     CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string");
226                     CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string");
227                 }
228 
229                 SECTION("object")
230                 {
231                     json j_nonarray(json::value_t::object);
232                     const json j_nonarray_const(j_nonarray);
233                     CHECK_THROWS_AS(j_nonarray[0], json::type_error&);
234                     CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
235                     CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object");
236                     CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object");
237                 }
238 
239                 SECTION("number (integer)")
240                 {
241                     json j_nonarray(json::value_t::number_integer);
242                     const json j_nonarray_const(j_nonarray);
243                     CHECK_THROWS_AS(j_nonarray[0], json::type_error&);
244                     CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
245                     CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number");
246                     CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number");
247                 }
248 
249                 SECTION("number (unsigned)")
250                 {
251                     json j_nonarray(json::value_t::number_unsigned);
252                     const json j_nonarray_const(j_nonarray);
253                     CHECK_THROWS_AS(j_nonarray[0], json::type_error&);
254                     CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
255                     CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number");
256                     CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number");
257                 }
258 
259                 SECTION("number (floating-point)")
260                 {
261                     json j_nonarray(json::value_t::number_float);
262                     const json j_nonarray_const(j_nonarray);
263                     CHECK_THROWS_AS(j_nonarray[0], json::type_error&);
264                     CHECK_THROWS_AS(j_nonarray_const[0], json::type_error&);
265                     CHECK_THROWS_WITH(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number");
266                     CHECK_THROWS_WITH(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number");
267                 }
268             }
269         }
270 
271         SECTION("remove specified element")
272         {
273             SECTION("remove element by index")
274             {
275                 {
276                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
277                     jarray.erase(0);
278                     CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
279                 }
280                 {
281                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
282                     jarray.erase(1);
283                     CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
284                 }
285                 {
286                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
287                     jarray.erase(2);
288                     CHECK(jarray == json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
289                 }
290                 {
291                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
292                     jarray.erase(3);
293                     CHECK(jarray == json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
294                 }
295                 {
296                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
297                     jarray.erase(4);
298                     CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
299                 }
300                 {
301                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
302                     jarray.erase(5);
303                     CHECK(jarray == json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
304                 }
305                 {
306                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
307                     jarray.erase(6);
308                     CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
309                 }
310                 {
311                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
312                     jarray.erase(7);
313                     CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
314                 }
315                 {
316                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
317                     CHECK_THROWS_AS(jarray.erase(8), json::out_of_range&);
318                     CHECK_THROWS_WITH(jarray.erase(8),
319                                       "[json.exception.out_of_range.401] array index 8 is out of range");
320                 }
321             }
322 
323             SECTION("remove element by iterator")
324             {
325                 SECTION("erase(begin())")
326                 {
327                     {
328                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
329                         json::iterator it2 = jarray.erase(jarray.begin());
330                         CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
331                         CHECK(*it2 == json(1u));
332                     }
333                     {
334                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
335                         json::const_iterator it2 = jarray.erase(jarray.cbegin());
336                         CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
337                         CHECK(*it2 == json(1u));
338                     }
339                 }
340 
341                 SECTION("erase(begin(), end())")
342                 {
343                     {
344                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
345                         json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
346                         CHECK(jarray == json::array());
347                         CHECK(it2 == jarray.end());
348                     }
349                     {
350                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
351                         json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
352                         CHECK(jarray == json::array());
353                         CHECK(it2 == jarray.cend());
354                     }
355                 }
356 
357                 SECTION("erase(begin(), begin())")
358                 {
359                     {
360                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
361                         json::iterator it2 = jarray.erase(jarray.begin(), jarray.begin());
362                         CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
363                         CHECK(*it2 == json(1));
364                     }
365                     {
366                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
367                         json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
368                         CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
369                         CHECK(*it2 == json(1));
370                     }
371                 }
372 
373                 SECTION("erase at offset")
374                 {
375                     {
376                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
377                         json::iterator it = jarray.begin() + 4;
378                         json::iterator it2 = jarray.erase(it);
379                         CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
380                         CHECK(*it2 == json(42.23));
381                     }
382                     {
383                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
384                         json::const_iterator it = jarray.cbegin() + 4;
385                         json::const_iterator it2 = jarray.erase(it);
386                         CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
387                         CHECK(*it2 == json(42.23));
388                     }
389                 }
390 
391                 SECTION("erase subrange")
392                 {
393                     {
394                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
395                         json::iterator it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
396                         CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
397                         CHECK(*it2 == json::object());
398                     }
399                     {
400                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
401                         json::const_iterator it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
402                         CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
403                         CHECK(*it2 == json::object());
404                     }
405                 }
406 
407                 SECTION("different arrays")
408                 {
409                     {
410                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
411                         json jarray2 = {"foo", "bar"};
412                         CHECK_THROWS_AS(jarray.erase(jarray2.begin()), json::invalid_iterator&);
413                         CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), json::invalid_iterator&);
414                         CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), json::invalid_iterator&);
415                         CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), json::invalid_iterator&);
416 
417                         CHECK_THROWS_WITH(jarray.erase(jarray2.begin()),
418                                           "[json.exception.invalid_iterator.202] iterator does not fit current value");
419                         CHECK_THROWS_WITH(jarray.erase(jarray.begin(), jarray2.end()),
420                                           "[json.exception.invalid_iterator.203] iterators do not fit current value");
421                         CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray.end()),
422                                           "[json.exception.invalid_iterator.203] iterators do not fit current value");
423                         CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray2.end()),
424                                           "[json.exception.invalid_iterator.203] iterators do not fit current value");
425                     }
426                     {
427                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
428                         json jarray2 = {"foo", "bar"};
429                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), json::invalid_iterator&);
430                         CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), json::invalid_iterator&);
431                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), json::invalid_iterator&);
432                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), json::invalid_iterator&);
433 
434                         CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()),
435                                           "[json.exception.invalid_iterator.202] iterator does not fit current value");
436                         CHECK_THROWS_WITH(jarray.erase(jarray.cbegin(), jarray2.cend()),
437                                           "[json.exception.invalid_iterator.203] iterators do not fit current value");
438                         CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray.cend()),
439                                           "[json.exception.invalid_iterator.203] iterators do not fit current value");
440                         CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray2.cend()),
441                                           "[json.exception.invalid_iterator.203] iterators do not fit current value");
442                     }
443                 }
444             }
445 
446             SECTION("remove element by index in non-array type")
447             {
448                 SECTION("null")
449                 {
450                     json j_nonobject(json::value_t::null);
451                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
452                     CHECK_THROWS_WITH(j_nonobject.erase(0),
453                                       "[json.exception.type_error.307] cannot use erase() with null");
454                 }
455 
456                 SECTION("boolean")
457                 {
458                     json j_nonobject(json::value_t::boolean);
459                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
460                     CHECK_THROWS_WITH(j_nonobject.erase(0),
461                                       "[json.exception.type_error.307] cannot use erase() with boolean");
462                 }
463 
464                 SECTION("string")
465                 {
466                     json j_nonobject(json::value_t::string);
467                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
468                     CHECK_THROWS_WITH(j_nonobject.erase(0),
469                                       "[json.exception.type_error.307] cannot use erase() with string");
470                 }
471 
472                 SECTION("object")
473                 {
474                     json j_nonobject(json::value_t::object);
475                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
476                     CHECK_THROWS_WITH(j_nonobject.erase(0),
477                                       "[json.exception.type_error.307] cannot use erase() with object");
478                 }
479 
480                 SECTION("number (integer)")
481                 {
482                     json j_nonobject(json::value_t::number_integer);
483                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
484                     CHECK_THROWS_WITH(j_nonobject.erase(0),
485                                       "[json.exception.type_error.307] cannot use erase() with number");
486                 }
487 
488                 SECTION("number (unsigned)")
489                 {
490                     json j_nonobject(json::value_t::number_unsigned);
491                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
492                     CHECK_THROWS_WITH(j_nonobject.erase(0),
493                                       "[json.exception.type_error.307] cannot use erase() with number");
494                 }
495 
496                 SECTION("number (floating-point)")
497                 {
498                     json j_nonobject(json::value_t::number_float);
499                     CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error&);
500                     CHECK_THROWS_WITH(j_nonobject.erase(0),
501                                       "[json.exception.type_error.307] cannot use erase() with number");
502                 }
503             }
504         }
505     }
506 
507     SECTION("other values")
508     {
509         SECTION("front and back")
510         {
511             SECTION("null")
512             {
513                 {
514                     json j;
515                     CHECK_THROWS_AS(j.front(), json::invalid_iterator&);
516                     CHECK_THROWS_AS(j.back(), json::invalid_iterator&);
517                     CHECK_THROWS_WITH(j.front(), "[json.exception.invalid_iterator.214] cannot get value");
518                     CHECK_THROWS_WITH(j.back(), "[json.exception.invalid_iterator.214] cannot get value");
519                 }
520                 {
521                     const json j{};
522                     CHECK_THROWS_AS(j.front(), json::invalid_iterator&);
523                     CHECK_THROWS_AS(j.back(), json::invalid_iterator&);
524                     CHECK_THROWS_WITH(j.front(), "[json.exception.invalid_iterator.214] cannot get value");
525                     CHECK_THROWS_WITH(j.back(), "[json.exception.invalid_iterator.214] cannot get value");
526                 }
527             }
528 
529             SECTION("string")
530             {
531                 {
532                     json j = "foo";
533                     CHECK(j.front() == j);
534                     CHECK(j.back() == j);
535                 }
536                 {
537                     const json j = "bar";
538                     CHECK(j.front() == j);
539                     CHECK(j.back() == j);
540                 }
541             }
542 
543             SECTION("number (boolean)")
544             {
545                 {
546                     json j = false;
547                     CHECK(j.front() == j);
548                     CHECK(j.back() == j);
549                 }
550                 {
551                     const json j = true;
552                     CHECK(j.front() == j);
553                     CHECK(j.back() == j);
554                 }
555             }
556 
557             SECTION("number (integer)")
558             {
559                 {
560                     json j = 17;
561                     CHECK(j.front() == j);
562                     CHECK(j.back() == j);
563                 }
564                 {
565                     const json j = 17;
566                     CHECK(j.front() == j);
567                     CHECK(j.back() == j);
568                 }
569             }
570 
571             SECTION("number (unsigned)")
572             {
573                 {
574                     json j = 17u;
575                     CHECK(j.front() == j);
576                     CHECK(j.back() == j);
577                 }
578                 {
579                     const json j = 17u;
580                     CHECK(j.front() == j);
581                     CHECK(j.back() == j);
582                 }
583             }
584 
585             SECTION("number (floating point)")
586             {
587                 {
588                     json j = 23.42;
589                     CHECK(j.front() == j);
590                     CHECK(j.back() == j);
591                 }
592                 {
593                     const json j = 23.42;
594                     CHECK(j.front() == j);
595                     CHECK(j.back() == j);
596                 }
597             }
598         }
599 
600         SECTION("erase with one valid iterator")
601         {
602             SECTION("null")
603             {
604                 {
605                     json j;
606                     CHECK_THROWS_AS(j.erase(j.begin()), json::type_error&);
607                     CHECK_THROWS_WITH(j.erase(j.begin()),
608                                       "[json.exception.type_error.307] cannot use erase() with null");
609                 }
610                 {
611                     json j;
612                     CHECK_THROWS_AS(j.erase(j.cbegin()), json::type_error&);
613                     CHECK_THROWS_WITH(j.erase(j.begin()),
614                                       "[json.exception.type_error.307] cannot use erase() with null");
615                 }
616             }
617 
618             SECTION("string")
619             {
620                 {
621                     json j = "foo";
622                     json::iterator it = j.erase(j.begin());
623                     CHECK(j.type() == json::value_t::null);
624                     CHECK(it == j.end());
625                 }
626                 {
627                     json j = "bar";
628                     json::const_iterator it = j.erase(j.cbegin());
629                     CHECK(j.type() == json::value_t::null);
630                     CHECK(it == j.end());
631                 }
632             }
633 
634             SECTION("number (boolean)")
635             {
636                 {
637                     json j = false;
638                     json::iterator it = j.erase(j.begin());
639                     CHECK(j.type() == json::value_t::null);
640                     CHECK(it == j.end());
641                 }
642                 {
643                     json j = true;
644                     json::const_iterator it = j.erase(j.cbegin());
645                     CHECK(j.type() == json::value_t::null);
646                     CHECK(it == j.end());
647                 }
648             }
649 
650             SECTION("number (integer)")
651             {
652                 {
653                     json j = 17;
654                     json::iterator it = j.erase(j.begin());
655                     CHECK(j.type() == json::value_t::null);
656                     CHECK(it == j.end());
657                 }
658                 {
659                     json j = 17;
660                     json::const_iterator it = j.erase(j.cbegin());
661                     CHECK(j.type() == json::value_t::null);
662                     CHECK(it == j.end());
663                 }
664             }
665 
666             SECTION("number (unsigned)")
667             {
668                 {
669                     json j = 17u;
670                     json::iterator it = j.erase(j.begin());
671                     CHECK(j.type() == json::value_t::null);
672                     CHECK(it == j.end());
673                 }
674                 {
675                     json j = 17u;
676                     json::const_iterator it = j.erase(j.cbegin());
677                     CHECK(j.type() == json::value_t::null);
678                     CHECK(it == j.end());
679                 }
680             }
681 
682             SECTION("number (floating point)")
683             {
684                 {
685                     json j = 23.42;
686                     json::iterator it = j.erase(j.begin());
687                     CHECK(j.type() == json::value_t::null);
688                     CHECK(it == j.end());
689                 }
690                 {
691                     json j = 23.42;
692                     json::const_iterator it = j.erase(j.cbegin());
693                     CHECK(j.type() == json::value_t::null);
694                     CHECK(it == j.end());
695                 }
696             }
697         }
698 
699         SECTION("erase with one invalid iterator")
700         {
701             SECTION("string")
702             {
703                 {
704                     json j = "foo";
705                     CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&);
706                     CHECK_THROWS_WITH(j.erase(j.end()),
707                                       "[json.exception.invalid_iterator.205] iterator out of range");
708                 }
709                 {
710                     json j = "bar";
711                     CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&);
712                     CHECK_THROWS_WITH(j.erase(j.cend()),
713                                       "[json.exception.invalid_iterator.205] iterator out of range");
714                 }
715             }
716 
717             SECTION("number (boolean)")
718             {
719                 {
720                     json j = false;
721                     CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&);
722                     CHECK_THROWS_WITH(j.erase(j.end()),
723                                       "[json.exception.invalid_iterator.205] iterator out of range");
724                 }
725                 {
726                     json j = true;
727                     CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&);
728                     CHECK_THROWS_WITH(j.erase(j.cend()),
729                                       "[json.exception.invalid_iterator.205] iterator out of range");
730                 }
731             }
732 
733             SECTION("number (integer)")
734             {
735                 {
736                     json j = 17;
737                     CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&);
738                     CHECK_THROWS_WITH(j.erase(j.end()),
739                                       "[json.exception.invalid_iterator.205] iterator out of range");
740                 }
741                 {
742                     json j = 17;
743                     CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&);
744                     CHECK_THROWS_WITH(j.erase(j.cend()),
745                                       "[json.exception.invalid_iterator.205] iterator out of range");
746                 }
747             }
748 
749             SECTION("number (unsigned)")
750             {
751                 {
752                     json j = 17u;
753                     CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&);
754                     CHECK_THROWS_WITH(j.erase(j.end()),
755                                       "[json.exception.invalid_iterator.205] iterator out of range");
756                 }
757                 {
758                     json j = 17u;
759                     CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&);
760                     CHECK_THROWS_WITH(j.erase(j.cend()),
761                                       "[json.exception.invalid_iterator.205] iterator out of range");
762                 }
763             }
764 
765             SECTION("number (floating point)")
766             {
767                 {
768                     json j = 23.42;
769                     CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator&);
770                     CHECK_THROWS_WITH(j.erase(j.end()),
771                                       "[json.exception.invalid_iterator.205] iterator out of range");
772                 }
773                 {
774                     json j = 23.42;
775                     CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator&);
776                     CHECK_THROWS_WITH(j.erase(j.cend()),
777                                       "[json.exception.invalid_iterator.205] iterator out of range");
778                 }
779             }
780         }
781 
782         SECTION("erase with two valid iterators")
783         {
784             SECTION("null")
785             {
786                 {
787                     json j;
788                     CHECK_THROWS_AS(j.erase(j.begin(), j.end()), json::type_error&);
789                     CHECK_THROWS_WITH(j.erase(j.begin(), j.end()),
790                                       "[json.exception.type_error.307] cannot use erase() with null");
791                 }
792                 {
793                     json j;
794                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), json::type_error&);
795                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()),
796                                       "[json.exception.type_error.307] cannot use erase() with null");
797                 }
798             }
799 
800             SECTION("string")
801             {
802                 {
803                     json j = "foo";
804                     json::iterator it = j.erase(j.begin(), j.end());
805                     CHECK(j.type() == json::value_t::null);
806                     CHECK(it == j.end());
807                 }
808                 {
809                     json j = "bar";
810                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
811                     CHECK(j.type() == json::value_t::null);
812                     CHECK(it == j.end());
813                 }
814             }
815 
816             SECTION("number (boolean)")
817             {
818                 {
819                     json j = false;
820                     json::iterator it = j.erase(j.begin(), j.end());
821                     CHECK(j.type() == json::value_t::null);
822                     CHECK(it == j.end());
823                 }
824                 {
825                     json j = true;
826                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
827                     CHECK(j.type() == json::value_t::null);
828                     CHECK(it == j.end());
829                 }
830             }
831 
832             SECTION("number (integer)")
833             {
834                 {
835                     json j = 17;
836                     json::iterator it = j.erase(j.begin(), j.end());
837                     CHECK(j.type() == json::value_t::null);
838                     CHECK(it == j.end());
839                 }
840                 {
841                     json j = 17;
842                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
843                     CHECK(j.type() == json::value_t::null);
844                     CHECK(it == j.end());
845                 }
846             }
847 
848             SECTION("number (unsigned)")
849             {
850                 {
851                     json j = 17u;
852                     json::iterator it = j.erase(j.begin(), j.end());
853                     CHECK(j.type() == json::value_t::null);
854                     CHECK(it == j.end());
855                 }
856                 {
857                     json j = 17u;
858                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
859                     CHECK(j.type() == json::value_t::null);
860                     CHECK(it == j.end());
861                 }
862             }
863 
864             SECTION("number (floating point)")
865             {
866                 {
867                     json j = 23.42;
868                     json::iterator it = j.erase(j.begin(), j.end());
869                     CHECK(j.type() == json::value_t::null);
870                     CHECK(it == j.end());
871                 }
872                 {
873                     json j = 23.42;
874                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
875                     CHECK(j.type() == json::value_t::null);
876                     CHECK(it == j.end());
877                 }
878             }
879         }
880 
881         SECTION("erase with two invalid iterators")
882         {
883             SECTION("string")
884             {
885                 {
886                     json j = "foo";
887                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&);
888                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&);
889                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
890                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
891                 }
892                 {
893                     json j = "bar";
894                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&);
895                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&);
896                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
897                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
898                 }
899             }
900 
901             SECTION("number (boolean)")
902             {
903                 {
904                     json j = false;
905                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&);
906                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&);
907                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
908                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
909                 }
910                 {
911                     json j = true;
912                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&);
913                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&);
914                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
915                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
916                 }
917             }
918 
919             SECTION("number (integer)")
920             {
921                 {
922                     json j = 17;
923                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&);
924                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&);
925                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
926                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
927                 }
928                 {
929                     json j = 17;
930                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&);
931                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&);
932                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
933                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
934                 }
935             }
936 
937             SECTION("number (unsigned)")
938             {
939                 {
940                     json j = 17u;
941                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&);
942                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&);
943                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
944                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
945                 }
946                 {
947                     json j = 17u;
948                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&);
949                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&);
950                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
951                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
952                 }
953             }
954 
955             SECTION("number (floating point)")
956             {
957                 {
958                     json j = 23.42;
959                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator&);
960                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator&);
961                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
962                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
963                 }
964                 {
965                     json j = 23.42;
966                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator&);
967                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator&);
968                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
969                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
970                 }
971             }
972         }
973     }
974 }
975