lsnes rr2-β24
[lsnes.git] / src / test / json-test.cpp
blob065356e664bf8015686c075db0f6c76de40517d2
1 #include "json.hpp"
2 #include "string.hpp"
4 struct test_x
6 const char* title;
7 bool (*dotest)();
8 JSON::errorcode expect;
9 };
11 test_x tests[] = {
12 {"Default constructor", []() {
13 JSON::node x;
14 return (x.type() == JSON::null);
15 }},{"Explicit null constructor", []() {
16 JSON::node x(JSON::null);
17 return (x.type() == JSON::null);
18 }},{"Explicit boolean constructor #1", []() {
19 JSON::node x(JSON::boolean, false);
20 return (x.type() == JSON::boolean);
21 }},{"Explicit boolean constructor #2", []() {
22 JSON::node x(JSON::boolean, true);
23 return (x.type() == JSON::boolean);
24 }},{"Explicit boolean constructor #3", []() {
25 JSON::node x(JSON::boolean, false);
26 return !x.as_bool();
27 }},{"Explicit boolean constructor #4", []() {
28 JSON::node x(JSON::boolean, true);
29 return x.as_bool();
30 }},{"Explicit string constructor #1", []() {
31 JSON::node x(JSON::string, U"foo");
32 return (x.type() == JSON::string);
33 }},{"Explicit string constructor #2", []() {
34 JSON::node x(JSON::string, U"bar");
35 return x.as_string() == U"bar";
36 }},{"Numeric types #1", []() {
37 JSON::node x(JSON::number, (double)0.0);
38 return (x.type() == JSON::number);
39 }},{"Numeric types #2", []() {
40 JSON::node x(JSON::number, (uint64_t)0);
41 return (x.type() == JSON::number);
42 }},{"Numeric types #3", []() {
43 JSON::node x(JSON::number, (int64_t)0);
44 return (x.type() == JSON::number);
45 }},{"Numeric conversions #1", []() {
46 JSON::node x(JSON::number, (double)123.45);
47 return x.as_double() == 123.45;
48 }},{"Numeric conversions #2", []() {
49 JSON::node x(JSON::number, (uint64_t)9223372036854775809ULL);
50 return x.as_uint() == 9223372036854775809ULL;
51 }},{"Numeric conversions #3", []() {
52 JSON::node x(JSON::number, (int64_t)-36028797018963969LL);
53 return x.as_int() == -36028797018963969LL;
54 }},{"Numeric conversions #4", []() {
55 JSON::node x(JSON::number, (double)123.0);
56 return x.as_uint() == 123;
57 }},{"Numeric conversions #5", []() {
58 JSON::node x(JSON::number, (uint64_t)12345);
59 return x.as_int() == 12345;
60 }},{"Numeric conversions #6", []() {
61 JSON::node x(JSON::number, (int64_t)-456);
62 return x.as_double() == -456;
63 }},{"Numeric conversions #7", []() {
64 JSON::node x(JSON::number, (double)-1234.0);
65 return x.as_int() == -1234;
66 }},{"Numeric conversions #8", []() {
67 JSON::node x(JSON::number, (uint64_t)12345);
68 return x.as_double() == 12345.0;
69 }},{"Numeric conversions #9", []() {
70 JSON::node x(JSON::number, (int64_t)456);
71 return x.as_uint() == 456;
72 }},{"Explicit array constructor", []() {
73 JSON::node x(JSON::array);
74 return (x.type() == JSON::array);
75 }},{"Explicit object constructor", []() {
76 JSON::node x(JSON::object);
77 return (x.type() == JSON::object);
78 }},{"Explicit set null", []() {
79 JSON::node x(JSON::object);
80 x.set(JSON::null);
81 return (x.type() == JSON::null);
82 }},{"Explicit set boolean #1", []() {
83 JSON::node x(JSON::object);
84 x.set(JSON::boolean, false);
85 return (x.type() == JSON::boolean);
86 }},{"Explicit set boolean #2", []() {
87 JSON::node x(JSON::object);
88 x.set(JSON::boolean, true);
89 return (x.type() == JSON::boolean);
90 }},{"Explicit set boolean #3", []() {
91 JSON::node x(JSON::object);
92 x.set(JSON::boolean, false);
93 return !x.as_bool();
94 }},{"Explicit set boolean #4", []() {
95 JSON::node x(JSON::object);
96 x.set(JSON::boolean, true);
97 return x.as_bool();
98 }},{"Explicit set number #1", []() {
99 JSON::node x(JSON::object);
100 x.set(JSON::number, (double)123.45);
101 return (x.type() == JSON::number);
102 }},{"Explicit set number #2", []() {
103 JSON::node x(JSON::object);
104 x.set(JSON::number, (uint64_t)9223372036854775809ULL);
105 return (x.type() == JSON::number);
106 }},{"Explicit set number #3", []() {
107 JSON::node x(JSON::object);
108 x.set(JSON::number, (int64_t)-123);
109 return (x.type() == JSON::number);
110 }},{"Explicit set number #4", []() {
111 JSON::node x(JSON::object);
112 x.set(JSON::number, (double)123.45);
113 return (x.as_double() == 123.45);
114 }},{"Explicit set number #5", []() {
115 JSON::node x(JSON::object);
116 x.set(JSON::number, (uint64_t)9223372036854775809ULL);
117 return (x.as_uint() == 9223372036854775809ULL);
118 }},{"Explicit set number #6", []() {
119 JSON::node x(JSON::object);
120 x.set(JSON::number, (int64_t)-36028797018963969LL);
121 return (x.as_int() == -36028797018963969LL);
122 }},{"Explicit set string #1", []() {
123 JSON::node x(JSON::object);
124 x.set(JSON::string, U"qux");
125 return (x.type() == JSON::string);
126 }},{"Explicit set string #2", []() {
127 JSON::node x(JSON::object);
128 x.set(JSON::string, U"zot");
129 return (x.as_string() == U"zot");
130 }},{"Non-string as string", []() {
131 JSON::node x(JSON::object);
132 x.as_string();
133 return false;
134 }, JSON::ERR_NOT_A_STRING},{"Non-boolean as boolean", []() {
135 JSON::node x(JSON::object);
136 x.as_bool();
137 return false;
138 }, JSON::ERR_NOT_A_BOOLEAN},{"Non-number as number #1", []() {
139 JSON::node x(JSON::object);
140 x.as_double();
141 return false;
142 }, JSON::ERR_NOT_A_NUMBER},{"Non-number as number #2", []() {
143 JSON::node x(JSON::object);
144 x.as_int();
145 return false;
146 }, JSON::ERR_NOT_A_NUMBER},{"Non-number as number #3", []() {
147 JSON::node x(JSON::object);
148 x.as_uint();
149 return false;
150 }, JSON::ERR_NOT_A_NUMBER},{"Index count of non-array", []() {
151 JSON::node x(JSON::object);
152 x.index_count();
153 return false;
154 }, JSON::ERR_NOT_AN_ARRAY},{"Index of non-array", []() {
155 JSON::node x(JSON::object);
156 x.index(0);
157 return false;
158 }, JSON::ERR_NOT_AN_ARRAY},{"Index of non-array (const)", []() {
159 JSON::node x(JSON::object);
160 const JSON::node& y = x;
161 y.index(0);
162 return false;
163 }, JSON::ERR_NOT_AN_ARRAY},{"Index count of array #1", []() {
164 JSON::node x("[]");
165 return (x.index_count() == 0);
166 }},{"Index count of array #2", []() {
167 JSON::node x("[null]");
168 return (x.index_count() == 1);
169 }},{"Index count of array #3", []() {
170 JSON::node x("[null,false,true]");
171 return (x.index_count() == 3);
172 }},{"Index count of array #4", []() {
173 JSON::node x("[null,[false,true]]");
174 return (x.index_count() == 2);
175 }},{"Indexing array #1", []() {
176 JSON::node x("[null,false,true]");
177 return (x.index(0).type() == JSON::null);
178 }},{"Indexing array #2", []() {
179 JSON::node x("[null,false,true]");
180 return !x.index(1).as_bool();
181 }},{"Indexing array #3", []() {
182 JSON::node x("[null,false,true]");
183 return x.index(2).as_bool();
184 }},{"Indexing array out-of-bounds #1", []() {
185 JSON::node x("[null,false,true]");
186 x.index(3);
187 return false;
188 }, JSON::ERR_INDEX_INVALID},{"Indexing array out-of-bounds #2", []() {
189 JSON::node x("[null,false,true]");
190 x.index(12466);
191 return false;
192 }, JSON::ERR_INDEX_INVALID},{"Indexing array out-of-bounds #3", []() {
193 JSON::node x("[]");
194 x.index(0);
195 return false;
196 }, JSON::ERR_INDEX_INVALID},{"Indexing array #1 (const)", []() {
197 JSON::node x("[null,false,true]");
198 const JSON::node& y = x;
199 return (y.index(0).type() == JSON::null);
200 }},{"Indexing array #2 (const)", []() {
201 JSON::node x("[null,false,true]");
202 const JSON::node& y = x;
203 return !y.index(1).as_bool();
204 }},{"Indexing array #3 (const)", []() {
205 JSON::node x("[null,false,true]");
206 const JSON::node& y = x;
207 return y.index(2).as_bool();
208 }},{"Indexing array out-of-bounds #1 (const)", []() {
209 JSON::node x("[null,false,true]");
210 const JSON::node& y = x;
211 y.index(3);
212 return false;
213 }, JSON::ERR_INDEX_INVALID},{"Indexing array out-of-bounds #2 (const)", []() {
214 JSON::node x("[null,false,true]");
215 const JSON::node& y = x;
216 y.index(12466);
217 return false;
218 }, JSON::ERR_INDEX_INVALID},{"Indexing array out-of-bounds #3 (const)", []() {
219 JSON::node x("[]");
220 const JSON::node& y = x;
221 y.index(0);
222 return false;
223 }, JSON::ERR_INDEX_INVALID},{"Field count of non-object", []() {
224 JSON::node x("[null,false,true]");
225 x.field_count(U"foo");
226 return false;
227 }, JSON::ERR_NOT_AN_OBJECT},{"Field exists of non-object", []() {
228 JSON::node x("[null,false,true]");
229 x.field_exists(U"foo");
230 return false;
231 }, JSON::ERR_NOT_AN_OBJECT},{"Field count of found object", []() {
232 JSON::node x(JSON::object);
233 x.insert(U"foo", JSON::node(JSON::null));
234 return (x.field_count(U"foo") == 1);
235 }},{"Field count of non-found object #1", []() {
236 JSON::node x(JSON::object);
237 x.insert(U"foo", JSON::node(JSON::null));
238 return (x.field_count(U"bar") == 0);
239 }},{"Field count of non-found object #2", []() {
240 JSON::node x(JSON::object);
241 x.insert(U"foo", JSON::node(JSON::null));
242 return (x.field_count(U"qux") == 0);
243 }},{"Field exists of found object", []() {
244 JSON::node x(JSON::object);
245 x.insert(U"foo", JSON::node(JSON::null));
246 return x.field_exists(U"foo");
247 }},{"Field exists of non-found object #1", []() {
248 JSON::node x(JSON::object);
249 x.insert(U"foo", JSON::node(JSON::null));
250 return !x.field_exists(U"bar");
251 }},{"Field exists of non-found object #2", []() {
252 JSON::node x(JSON::object);
253 x.insert(U"foo", JSON::node(JSON::null));
254 return !x.field_exists(U"qux");
255 }},{"Field count of duplicate object #1", []() {
256 JSON::node x(JSON::object);
257 x.insert(U"foo", JSON::node(JSON::null));
258 x.insert(U"foo", JSON::node(JSON::boolean, false));
259 return (x.field_count(U"foo") == 2);
260 }},{"Field count of duplicate object #2", []() {
261 JSON::node x(JSON::object);
262 x.insert(U"foo", JSON::node(JSON::null));
263 x.insert(U"foo", JSON::node(JSON::boolean, false));
264 x.insert(U"foo", JSON::node(JSON::boolean, true));
265 return (x.field_count(U"foo") == 3);
266 }},{"Field exists of duplicate object #1", []() {
267 JSON::node x(JSON::object);
268 x.insert(U"foo", JSON::node(JSON::null));
269 x.insert(U"foo", JSON::node(JSON::boolean, false));
270 return x.field_exists(U"foo");
271 }},{"Field exists of duplicate object #2", []() {
272 JSON::node x(JSON::object);
273 x.insert(U"foo", JSON::node(JSON::null));
274 x.insert(U"foo", JSON::node(JSON::boolean, false));
275 x.insert(U"foo", JSON::node(JSON::boolean, true));
276 return x.field_exists(U"foo");
277 }},{"Field access of non-object", []() {
278 JSON::node x("[null,false,true]");
279 x.field(U"foo");
280 return false;
281 }, JSON::ERR_NOT_AN_OBJECT},{"Field access #1", []() {
282 JSON::node x(JSON::object);
283 x.insert(U"foo", JSON::node(JSON::null));
284 x.insert(U"bar", JSON::node(JSON::boolean, false));
285 return (x.field(U"foo").type() == JSON::null);
286 }},{"Field access #2", []() {
287 JSON::node x(JSON::object);
288 x.insert(U"foo", JSON::node(JSON::null));
289 x.insert(U"bar", JSON::node(JSON::boolean, false));
290 return !x.field(U"bar").as_bool();
291 }},{"Field access #3", []() {
292 JSON::node x(JSON::object);
293 x.insert(U"foo", JSON::node(JSON::null));
294 x.insert(U"foo", JSON::node(JSON::boolean, false));
295 return (x.field(U"foo").type() == JSON::null);
296 }},{"Field access #4", []() {
297 JSON::node x(JSON::object);
298 x.insert(U"foo", JSON::node(JSON::null));
299 x.insert(U"foo", JSON::node(JSON::boolean, false));
300 return !x.field(U"foo", 1).as_bool();
301 }},{"Field access to invalid key", []() {
302 JSON::node x(JSON::object);
303 x.insert(U"foo", JSON::node(JSON::null));
304 x.insert(U"bar", JSON::node(JSON::boolean, false));
305 x.field(U"baz");
306 return false;
307 }, JSON::ERR_KEY_INVALID},{"Field access to invalid index #1", []() {
308 JSON::node x(JSON::object);
309 x.insert(U"foo", JSON::node(JSON::null));
310 x.insert(U"bar", JSON::node(JSON::boolean, false));
311 x.field(U"bar", 1);
312 return false;
313 }, JSON::ERR_INSTANCE_INVALID},{"Field access to invalid index #2", []() {
314 JSON::node x(JSON::object);
315 x.insert(U"foo", JSON::node(JSON::null));
316 x.insert(U"foo", JSON::node(JSON::boolean, false));
317 x.field(U"foo", 2);
318 return false;
319 }, JSON::ERR_INSTANCE_INVALID},{"Field access of non-object (const)", []() {
320 JSON::node x("[null,false,true]");
321 const JSON::node& y = x;
322 y.field(U"foo");
323 return false;
324 }, JSON::ERR_NOT_AN_OBJECT},{"Field access #1 (const)", []() {
325 JSON::node x(JSON::object);
326 x.insert(U"foo", JSON::node(JSON::null));
327 x.insert(U"bar", JSON::node(JSON::boolean, false));
328 const JSON::node& y = x;
329 return (y.field(U"foo").type() == JSON::null);
330 }},{"Field access #2 (const)", []() {
331 JSON::node x(JSON::object);
332 x.insert(U"foo", JSON::node(JSON::null));
333 x.insert(U"bar", JSON::node(JSON::boolean, false));
334 const JSON::node& y = x;
335 return !y.field(U"bar").as_bool();
336 }},{"Field access #3 (const)", []() {
337 JSON::node x(JSON::object);
338 x.insert(U"foo", JSON::node(JSON::null));
339 x.insert(U"foo", JSON::node(JSON::boolean, false));
340 const JSON::node& y = x;
341 return (y.field(U"foo").type() == JSON::null);
342 }},{"Field access #4 (const)", []() {
343 JSON::node x(JSON::object);
344 x.insert(U"foo", JSON::node(JSON::null));
345 x.insert(U"foo", JSON::node(JSON::boolean, false));
346 const JSON::node& y = x;
347 return !y.field(U"foo", 1).as_bool();
348 }},{"Field access to invalid key (const)", []() {
349 JSON::node x(JSON::object);
350 x.insert(U"foo", JSON::node(JSON::null));
351 x.insert(U"bar", JSON::node(JSON::boolean, false));
352 const JSON::node& y = x;
353 y.field(U"baz");
354 return false;
355 }, JSON::ERR_KEY_INVALID},{"Field access to invalid index #1 (const)", []() {
356 JSON::node x(JSON::object);
357 x.insert(U"foo", JSON::node(JSON::null));
358 x.insert(U"bar", JSON::node(JSON::boolean, false));
359 const JSON::node& y = x;
360 y.field(U"bar", 1);
361 return false;
362 }, JSON::ERR_INSTANCE_INVALID},{"Field access to invalid index #2 (const)", []() {
363 JSON::node x(JSON::object);
364 x.insert(U"foo", JSON::node(JSON::null));
365 x.insert(U"foo", JSON::node(JSON::boolean, false));
366 const JSON::node& y = x;
367 y.field(U"foo", 2);
368 return false;
369 }, JSON::ERR_INSTANCE_INVALID},{"Append of non-array", []() {
370 JSON::node x(JSON::object);
371 x.append(JSON::node(JSON::null));
372 return false;
373 }, JSON::ERR_NOT_AN_ARRAY},{"Insert of non-object", []() {
374 JSON::node x("[null,false,true]");
375 x.insert(U"foo", JSON::node(JSON::boolean, true));
376 return false;
377 }, JSON::ERR_NOT_AN_OBJECT},{"Follow #1", []() {
378 JSON::node x("[null,[false,true]]");
379 return (x.follow(U"0").type() == JSON::null);
380 }},{"Follow #2", []() {
381 JSON::node x("[null,[false,true]]");
382 return (x.follow(U"1").type() == JSON::array);
383 }},{"Follow #3", []() {
384 JSON::node x("[null,[false,true]]");
385 return !x.follow(U"1/0").as_bool();
386 }},{"Follow #4", []() {
387 JSON::node x("[null,[false,true]]");
388 return x.follow(U"1/1").as_bool();
389 }},{"Follow invalid pointer #1", []() {
390 JSON::node x("[null,[false,true]]");
391 x.follow(U"2");
392 return false;
393 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #2", []() {
394 JSON::node x("[null,[false,true]]");
395 x.follow(U"0/1");
396 return false;
397 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Follow invalid pointer #3", []() {
398 JSON::node x("[null,[false,true]]");
399 x.follow(U"1/2");
400 return false;
401 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #4", []() {
402 JSON::node x("[null,[false,true]]");
403 x.follow(U"foo");
404 return false;
405 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #5", []() {
406 JSON::node x("[null,[false,true]]");
407 x.follow(U"1/foo");
408 return false;
409 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #6", []() {
410 JSON::node x("[null,[false,true]]");
411 x.follow(U"0/foo");
412 return false;
413 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Follow invalid pointer #7", []() {
414 JSON::node x("[null,[false,true]]");
415 x.follow(U"2/0");
416 return false;
417 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #8", []() {
418 JSON::node x("[null,[false,true]]");
419 x.follow(U"2/foo");
420 return false;
421 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #9", []() {
422 JSON::node x("[null,[false,true]]");
423 x.follow(U"foo/0");
424 return false;
425 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #10", []() {
426 JSON::node x("[null,[false,true]]");
427 x.follow(U"1~10");
428 return false;
429 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #11", []() {
430 JSON::node x("[null,[false,true]]");
431 x.follow(U"~2");
432 return false;
433 }, JSON::ERR_POINTER_INVALID_ESCAPE},{"Follow invalid pointer #12", []() {
434 JSON::node x("[null,[false,true]]");
435 x.follow(U"1~");
436 return false;
437 }, JSON::ERR_POINTER_TRAILING_ESCAPE},{"Follow invalid pointer #13", []() {
438 JSON::node x("[null,[false,true]]");
439 x.follow(U"-");
440 return false;
441 }, JSON::ERR_POINTER_BAD_APPEND},{"Follow #1 (const)", []() {
442 JSON::node x("[null,[false,true]]");
443 const JSON::node& y = x;
444 return (y.follow(U"0").type() == JSON::null);
445 }},{"Follow #2 (const)", []() {
446 JSON::node x("[null,[false,true]]");
447 const JSON::node& y = x;
448 return (y.follow(U"1").type() == JSON::array);
449 }},{"Follow #3 (const)", []() {
450 JSON::node x("[null,[false,true]]");
451 const JSON::node& y = x;
452 return !y.follow(U"1/0").as_bool();
453 }},{"Follow #4 (const)", []() {
454 JSON::node x("[null,[false,true]]");
455 const JSON::node& y = x;
456 return y.follow(U"1/1").as_bool();
457 }},{"Follow invalid pointer #1 (const)", []() {
458 JSON::node x("[null,[false,true]]");
459 const JSON::node& y = x;
460 y.follow(U"2");
461 return false;
462 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #2 (const)", []() {
463 JSON::node x("[null,[false,true]]");
464 const JSON::node& y = x;
465 y.follow(U"0/1");
466 return false;
467 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Follow invalid pointer #3 (const)", []() {
468 JSON::node x("[null,[false,true]]");
469 const JSON::node& y = x;
470 y.follow(U"1/2");
471 return false;
472 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #4 (const)", []() {
473 JSON::node x("[null,[false,true]]");
474 const JSON::node& y = x;
475 y.follow(U"foo");
476 return false;
477 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #5 (const)", []() {
478 JSON::node x("[null,[false,true]]");
479 const JSON::node& y = x;
480 y.follow(U"1/foo");
481 return false;
482 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #6 (const)", []() {
483 JSON::node x("[null,[false,true]]");
484 const JSON::node& y = x;
485 y.follow(U"0/foo");
486 return false;
487 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Follow invalid pointer #7 (const)", []() {
488 JSON::node x("[null,[false,true]]");
489 const JSON::node& y = x;
490 y.follow(U"2/0");
491 return false;
492 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #8 (const)", []() {
493 JSON::node x("[null,[false,true]]");
494 const JSON::node& y = x;
495 y.follow(U"2/foo");
496 return false;
497 }, JSON::ERR_INDEX_INVALID},{"Follow invalid pointer #9 (const)", []() {
498 JSON::node x("[null,[false,true]]");
499 const JSON::node& y = x;
500 y.follow(U"foo/0");
501 return false;
502 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #10 (const)", []() {
503 JSON::node x("[null,[false,true]]");
504 const JSON::node& y = x;
505 y.follow(U"1~10");
506 return false;
507 }, JSON::ERR_POINTER_BAD_INDEX},{"Follow invalid pointer #11 (const)", []() {
508 JSON::node x("[null,[false,true]]");
509 const JSON::node& y = x;
510 y.follow(U"~2");
511 return false;
512 }, JSON::ERR_POINTER_INVALID_ESCAPE},{"Follow invalid pointer #12 (const)", []() {
513 JSON::node x("[null,[false,true]]");
514 const JSON::node& y = x;
515 y.follow(U"1~");
516 return false;
517 }, JSON::ERR_POINTER_TRAILING_ESCAPE},{"Follow invalid pointer #13 (const)", []() {
518 JSON::node x("[null,[false,true]]");
519 const JSON::node& y = x;
520 y.follow(U"-");
521 return false;
522 }, JSON::ERR_POINTER_BAD_APPEND},{"Follow ~", []() {
523 JSON::node x(JSON::object);
524 x.insert(U"~", JSON::node(JSON::boolean, true));
525 return x.follow(U"~0").as_bool();
526 }},{"Follow ~ (const)", []() {
527 JSON::node x(JSON::object);
528 x.insert(U"~", JSON::node(JSON::boolean, true));
529 const JSON::node& y = x;
530 return y.follow(U"~0").as_bool();
531 }},{"Follow nonexistent", []() {
532 JSON::node x(JSON::object);
533 x.insert(U"~x", JSON::node(JSON::boolean, true));
534 x.follow(U"~0").as_bool();
535 return false;
536 }, JSON::ERR_KEY_INVALID},{"Follow nonexistent (const)", []() {
537 JSON::node x(JSON::object);
538 x.insert(U"~x", JSON::node(JSON::boolean, true));
539 const JSON::node& y = x;
540 y.follow(U"~0").as_bool();
541 return false;
542 }, JSON::ERR_KEY_INVALID},{"Empty string token", []() {
543 JSON::node x("\"\"");
544 return (x.as_string() == U"");
545 }},{"Simple string token", []() {
546 JSON::node x("\"hello\"");
547 std::cout << utf8::to8(x.as_string()) << "..." << std::flush;
548 return (x.as_string() == U"hello");
549 }},{"Simple number token #1", []() {
550 JSON::node x("123");
551 return (x.as_int() == 123);
552 }},{"Simple number token #2", []() {
553 JSON::node x("-123");
554 return (x.as_int() == -123);
555 }},{"Simple number token #3", []() {
556 JSON::node x("-123.45e2");
557 return (x.as_int() == -12345);
558 }},{"Simple number token #4", []() {
559 JSON::node x("-123e2");
560 return (x.as_int() == -12300);
561 }},{"Bad number token #1", []() {
562 JSON::node x("123f3");
563 return false;
564 }, JSON::ERR_GARBAGE_AFTER_END},{"Bad number token #2", []() {
565 JSON::node x("123e3e3");
566 return false;
567 }, JSON::ERR_GARBAGE_AFTER_END},{"Bad number token #3", []() {
568 JSON::node x("123e3.3");
569 return false;
570 }, JSON::ERR_GARBAGE_AFTER_END},{"Bad number token #4", []() {
571 JSON::node x("123.3.3");
572 return false;
573 }, JSON::ERR_GARBAGE_AFTER_END},{"Bad number token #5", []() {
574 JSON::node x("-");
575 return false;
576 }, JSON::ERR_INVALID_NUMBER},{"Bad number token #6", []() {
577 JSON::node x("-0.");
578 return false;
579 }, JSON::ERR_INVALID_NUMBER},{"Bad number token #7", []() {
580 JSON::node x("-e+6");
581 return false;
582 }, JSON::ERR_INVALID_NUMBER},{"Bad number token #8", []() {
583 JSON::node x("-0.5e+");
584 return false;
585 }, JSON::ERR_INVALID_NUMBER},{"Bad number token #9", []() {
586 JSON::node x("-0.5e-");
587 return false;
588 }, JSON::ERR_INVALID_NUMBER},{"Bad number token #10", []() {
589 JSON::node x("-01");
590 return false;
591 }, JSON::ERR_GARBAGE_AFTER_END},{"Hex string escapes", []() {
592 JSON::node x("\"\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef00\"");
593 return (x.as_string() == U"\U00000123\U00004567\U000089ab\U0000cdef\U0000abcd\U0000ef00");
594 }},{"Surrogate escape #1", []() {
595 JSON::node x("\"\\uD800\\uDC00\"");
596 return (x.as_string() == U"\U00010000");
597 }},{"Surrogate escape #2", []() {
598 JSON::node x("\"\\uD800\\uDC01\"");
599 return (x.as_string() == U"\U00010001");
600 }},{"Surrogate escape #3", []() {
601 JSON::node x("\"\\uD801\\uDC02\"");
602 return (x.as_string() == U"\U00010402");
603 }},{"Bad hex character", []() {
604 JSON::node x("\"\\u01g5\"");
605 return false;
606 }, JSON::ERR_BAD_HEX},{"Bad surrogate escape #1", []() {
607 JSON::node x("\"\\uD800\"");
608 return false;
609 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #2", []() {
610 JSON::node x("\"\\uD800\\n\"");
611 return false;
612 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #3", []() {
613 JSON::node x("\"\\uD800\\u0000\"");
614 return false;
615 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #4", []() {
616 JSON::node x("\"\\uDC00\\uD800\"");
617 return false;
618 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #5", []() {
619 JSON::node x("\"\\uDC00\"");
620 return false;
621 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #6", []() {
622 JSON::node x("\"\\uDC00\\uDC00\"");
623 return false;
624 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #7", []() {
625 JSON::node x("\"\\uD800Hi\"");
626 return false;
627 }, JSON::ERR_INVALID_SURROGATE},{"Bad surrogate escape #8", []() {
628 JSON::node x("\"\\uDC800\"");
629 return false;
630 }, JSON::ERR_INVALID_SURROGATE},{"Bad string expression #1", []() {
631 JSON::node x("\"Hi");
632 return false;
633 }, JSON::ERR_TRUNCATED_STRING},{"Bad string expression #2", []() {
634 JSON::node x("\"\\n");
635 return false;
636 }, JSON::ERR_TRUNCATED_STRING},{"Bad escape", []() {
637 JSON::node x("\"\\e\"");
638 return false;
639 }, JSON::ERR_INVALID_ESCAPE},{"Escapes", []() {
640 JSON::node x("\"\\\"\\\\\\/\\b\\f\\r\\n\\t\"");
641 return (x.as_string() == U"\"\\/\b\f\r\n\t");
642 }},{"Whitespace", []() {
643 JSON::node x(" [\t123,\n456,\r789]");
644 return (x.follow(U"2").as_int() == 789);
645 }},{"Trailing whitespace", []() {
646 JSON::node x("123 ");
647 return (x.as_int() == 123);
648 }},{"Bad string character", []() {
649 JSON::node x("\"\n\"]");
650 return false;
651 }, JSON::ERR_CONTROL_CHARACTER},{"Incomplete array #1", []() {
652 JSON::node x("[");
653 return false;
654 }, JSON::ERR_TRUNCATED_JSON},{"Incomplete array #2", []() {
655 JSON::node x("[123");
656 return false;
657 }, JSON::ERR_TRUNCATED_JSON},{"Incomplete array #3", []() {
658 JSON::node x("[123,");
659 return false;
660 }, JSON::ERR_TRUNCATED_JSON},{"Incomplete array #4", []() {
661 JSON::node x("[123,456");
662 return false;
663 }, JSON::ERR_TRUNCATED_JSON},{"Incomplete object", []() {
664 JSON::node x("{");
665 return false;
666 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #1", []() {
667 JSON::node x("{\"hi\"");
668 return false;
669 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #2", []() {
670 JSON::node x("{\"hi\"}");
671 return false;
672 }, JSON::ERR_EXPECTED_COLON},{"Bad object #3", []() {
673 JSON::node x("{\"hi\":");
674 return false;
675 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #4", []() {
676 JSON::node x("{\"hi\"}");
677 return false;
678 }, JSON::ERR_EXPECTED_COLON},{"Bad object #5", []() {
679 JSON::node x("{\"hi\":123");
680 return false;
681 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #6", []() {
682 JSON::node x("{\"hi\":123,");
683 return false;
684 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #7", []() {
685 JSON::node x("{\"hi\":123,}");
686 return false;
687 }, JSON::ERR_EXPECTED_STRING_KEY},{"Bad object #8", []() {
688 JSON::node x("{\"hi\":123,\"fu\"");
689 return false;
690 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #9", []() {
691 JSON::node x("{\"hi\":123,\"fu\"}");
692 return false;
693 }, JSON::ERR_EXPECTED_COLON},{"Bad object #10", []() {
694 JSON::node x("{\"hi\":123,\"fu\":");
695 return false;
696 }, JSON::ERR_TRUNCATED_JSON},{"Bad object #11", []() {
697 JSON::node x("{\"hi\":123,\"fu\":}");
698 return false;
699 }, JSON::ERR_UNEXPECTED_RIGHT_BRACE},{"Bad object #12", []() {
700 JSON::node x("{\"hi\",123}");
701 return false;
702 }, JSON::ERR_EXPECTED_COLON},{"Bad object #13", []() {
703 JSON::node x("{\"hi\"123}");
704 return false;
705 }, JSON::ERR_EXPECTED_COLON},{"Bad object #14", []() {
706 JSON::node x("{\"hi\":123:\"fu\":null}");
707 return false;
708 }, JSON::ERR_EXPECTED_COMMA},{"Bad array", []() {
709 JSON::node x("[1\"hi\"]");
710 return false;
711 }, JSON::ERR_EXPECTED_COMMA},{"Bad array #2", []() {
712 JSON::node x("[123,]");
713 return false;
714 }, JSON::ERR_UNEXPECTED_RIGHT_BRACKET},{"Bad token #1", []() {
715 JSON::node x("+123");
716 return false;
717 }, JSON::ERR_UNKNOWN_CHARACTER},{"Bad token #2", []() {
718 JSON::node x(",");
719 return false;
720 }, JSON::ERR_UNEXPECTED_COMMA},{"Bad token #3", []() {
721 JSON::node x("}");
722 return false;
723 }, JSON::ERR_UNEXPECTED_RIGHT_BRACE},{"Bad token #4", []() {
724 JSON::node x("]");
725 return false;
726 }, JSON::ERR_UNEXPECTED_RIGHT_BRACKET},{"Bad token #5", []() {
727 JSON::node x(":");
728 return false;
729 }, JSON::ERR_UNEXPECTED_COLON},{"Bad token #6", []() {
730 JSON::node x("[}");
731 return false;
732 }, JSON::ERR_UNEXPECTED_RIGHT_BRACE},{"Bad token #7", []() {
733 JSON::node x("{]");
734 return false;
735 }, JSON::ERR_EXPECTED_STRING_KEY},{"Empty object", []() {
736 JSON::node x("{}");
737 return (x.type() == JSON::object);
738 }},{"Simple object", []() {
739 JSON::node x("{\"foo\":\"bar\"}");
740 return (x.follow(U"foo").as_string() == U"bar");
741 }},{"Nested object", []() {
742 JSON::node x("{\"foo\":{\"bar\":\"baz\"}}");
743 return (x.follow(U"foo/bar").as_string() == U"baz");
744 }},{"Simple object follow escape #1", []() {
745 JSON::node x("{\"foo~\":\"bar\"}");
746 return (x.follow(U"foo~0").as_string() == U"bar");
747 }},{"Simple object follow escape #2", []() {
748 JSON::node x("{\"foo/\":\"bar\"}");
749 return (x.follow(U"foo~1").as_string() == U"bar");
750 }},{"Simple object follow escape #3", []() {
751 JSON::node x("{\"foo~1\":\"bar\"}");
752 return (x.follow(U"foo~01").as_string() == U"bar");
753 }},{"Negative number", []() {
754 JSON::node x("-123");
755 return (x.as_int() == -123);
756 }},{"Serialize null", []() {
757 JSON::node x(JSON::null);
758 return (x.serialize() == "null");
759 }},{"Serialize true", []() {
760 JSON::node x(JSON::boolean, true);
761 return (x.serialize() == "true");
762 }},{"Serialize false", []() {
763 JSON::node x(JSON::boolean, false);
764 return (x.serialize() == "false");
765 }},{"Serialize number #1", []() {
766 JSON::node x(JSON::number, (int64_t)-123);
767 return (x.serialize() == "-123");
768 }},{"Serialize number #2", []() {
769 JSON::node x(JSON::number, (uint64_t)456);
770 return (x.serialize() == "456");
771 }},{"Serialize number #3", []() {
772 JSON::node x(JSON::number, (double)-12345.7);
773 return (x.serialize() == "-12345.7");
774 }},{"Serialize simple string", []() {
775 JSON::node x(JSON::string, U"Hello");
776 return (x.serialize() == "\"Hello\"");
777 }},{"Serialize control characters", []() {
778 JSON::node x(JSON::string, U"\n");
779 return (x.serialize() == "\"\\n\"");
780 }},{"Serialize backslash", []() {
781 JSON::node x(JSON::string, U"hello\\world");
782 return (x.serialize() == "\"hello\\\\world\"");
783 }},{"Serialize doublequote", []() {
784 JSON::node x(JSON::string, U"hello\"world");
785 return (x.serialize() == "\"hello\\\"world\"");
786 }},{"String with 2-byte character", []() {
787 JSON::node x("\"hello\\u00a4\"");
788 return (x.serialize() == "\"hello\302\244\"");
789 }},{"String with 3-byte character", []() {
790 JSON::node x("\"hello\\u1234\"");
791 return (x.serialize() == "\"hello\341\210\264\"");
792 }},{"String with 4-byte character", []() {
793 JSON::node x(JSON::string, U"hello\U00045678");
794 return (x.serialize() == "\"hello\361\205\231\270\"");
795 }},{"Serialize empty array", []() {
796 JSON::node x(JSON::array);
797 return (x.serialize() == "[]");
798 }},{"Serialize one-element array", []() {
799 JSON::node x(JSON::array);
800 x.append(JSON::node(JSON::boolean, true));
801 return (x.serialize() == "[true]");
802 }},{"Serialize two-element array", []() {
803 JSON::node x(JSON::array);
804 x.append(JSON::node(JSON::boolean, true));
805 x.append(JSON::node(JSON::boolean, false));
806 return (x.serialize() == "[true,false]");
807 }},{"Serialize three-element array", []() {
808 JSON::node x(JSON::array);
809 x.append(JSON::node(JSON::boolean, true));
810 x.append(JSON::node(JSON::boolean, false));
811 x.append(JSON::node(JSON::null));
812 return (x.serialize() == "[true,false,null]");
813 }},{"Serialize empty object", []() {
814 JSON::node x(JSON::object);
815 return (x.serialize() == "{}");
816 }},{"Serialize one-element object", []() {
817 JSON::node x(JSON::object);
818 x.insert(U"foo", JSON::node(JSON::boolean, true));
819 return (x.serialize() == "{\"foo\":true}");
820 }},{"Serialize two-element object", []() {
821 JSON::node x(JSON::object);
822 x.insert(U"foo", JSON::node(JSON::boolean, true));
823 x.insert(U"bar", JSON::node(JSON::boolean, false));
824 return (x.serialize() == "{\"bar\":false,\"foo\":true}");
825 }},{"Serialize three-element object", []() {
826 JSON::node x(JSON::object);
827 x.insert(U"foo", JSON::node(JSON::boolean, true));
828 x.insert(U"bar", JSON::node(JSON::boolean, false));
829 x.insert(U"baz", JSON::node(JSON::null));
830 return (x.serialize() == "{\"bar\":false,\"baz\":null,\"foo\":true}");
831 }},{"Self-Assignment", []() {
832 JSON::node x("true");
833 x = x;
834 return x.as_bool();
835 }},{"Create node #1", []() {
836 JSON::node x("{}");
837 x["foo"] = JSON::node(JSON::string, U"bar");
838 return (x["foo"].as_string() == U"bar");
839 }},{"Create node #2", []() {
840 JSON::node x("[]");
841 x["0"] = JSON::node(JSON::string, U"bar");
842 return (x["0"].as_string() == U"bar");
843 }},{"Create node #3", []() {
844 JSON::node x("[]");
845 x["-"] = JSON::node(JSON::string, U"bar");
846 return (x["0"].as_string() == U"bar");
847 }},{"Create node error #1", []() {
848 JSON::node x("[]");
849 x["-/0"] = JSON::node(JSON::string, U"bar");
850 return false;
851 }, JSON::ERR_POINTER_BAD_APPEND},{"Create node error #2", []() {
852 JSON::node x("[]");
853 x["1"] = JSON::node(JSON::string, U"bar");
854 return false;
855 }, JSON::ERR_POINTER_BAD_APPEND},{"Create node error #3", []() {
856 JSON::node x("false");
857 x["0"] = JSON::node(JSON::string, U"bar");
858 return false;
859 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Parsing one null", []() {
860 JSON::node x("null");
861 return (x.type() == JSON::null);
862 }},{"Type of false", []() {
863 JSON::node x("false");
864 return (x.type() == JSON::boolean);
865 }},{"Type of true", []() {
866 JSON::node x("true");
867 return (x.type() == JSON::boolean);
868 }},{"Value of false", []() {
869 JSON::node x("false");
870 return !x.as_bool();
871 }},{"Value of true", []() {
872 JSON::node x("true");
873 return x.as_bool();
874 }},{"n()", []() {
875 JSON::node x = JSON::n();
876 return (x.type() == JSON::null);
877 }},{"_bool()", []() {
878 JSON::node x = JSON::b(true);
879 return x.as_bool();
880 }},{"_double()", []() {
881 JSON::node x = JSON::f(123.45);
882 return (x.as_double() == 123.45);
883 }},{"_int()", []() {
884 JSON::node x = JSON::i(-36028797018963969LL);
885 return (x.as_int() == -36028797018963969LL);
886 }},{"_uint()", []() {
887 JSON::node x = JSON::u(9223372036854775809ULL);
888 return (x.as_uint() == 9223372036854775809ULL);
889 }},{"_string()", []() {
890 JSON::node x = JSON::s(U"foo");
891 return (x.as_string() == U"foo");
892 }},{"array()", []() {
893 JSON::node x = JSON::array();
894 return (x.type() == JSON::array);
895 }},{"object()", []() {
896 JSON::node x = JSON::object();
897 return (x.type() == JSON::object);
898 }},{"Array iteration", []() {
899 JSON::node x("[\"ABC\",\"DEF\",\"GHI\"]");
900 std::u32string y;
901 for(auto i : x) {
902 y += i.as_string();
904 return (y == U"ABCDEFGHI");
905 }},{"Object iteration", []() {
906 JSON::node x("{\"2\":\"ABC\",\"1\":\"DEF\",\"0\":\"GHI\"}");
907 std::u32string y;
908 for(auto i : x) {
909 y += i.as_string();
911 return (y == U"GHIDEFABC");
912 }},{"Empty Array iteration", []() {
913 JSON::node x("[]");
914 std::u32string y;
915 for(auto i : x) {
916 y += i.as_string();
918 return (y == U"");
919 }},{"Empty Object iteration", []() {
920 JSON::node x("{}");
921 std::u32string y;
922 for(auto i : x) {
923 y += i.as_string();
925 return (y == U"");
926 }},{"Boolean iteration", []() {
927 JSON::node x("false");
928 for(auto i : x);
929 return false;
930 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Array iteration (const)", []() {
931 JSON::node _x("[\"ABC\",\"DEF\",\"GHI\"]");
932 const JSON::node& x = _x;
933 std::u32string y;
934 for(auto i : x) {
935 y += i.as_string();
937 return (y == U"ABCDEFGHI");
938 }},{"Object iteration (const)", []() {
939 JSON::node _x("{\"2\":\"ABC\",\"1\":\"DEF\",\"0\":\"GHI\"}");
940 const JSON::node& x = _x;
941 std::u32string y;
942 for(auto i : x) {
943 y += i.as_string();
945 return (y == U"GHIDEFABC");
946 }},{"Empty Array iteration (const)", []() {
947 JSON::node _x("[]");
948 const JSON::node& x = _x;
949 std::u32string y;
950 for(auto i : x) {
951 y += i.as_string();
953 return (y == U"");
954 }},{"Empty Object iteration (const)", []() {
955 JSON::node _x("{}");
956 const JSON::node& x = _x;
957 std::u32string y;
958 for(auto i : x) {
959 y += i.as_string();
961 return (y == U"");
962 }},{"Boolean iteration (const)", []() {
963 JSON::node _x("false");
964 const JSON::node& x = _x;
965 for(auto i : x);
966 return false;
967 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Keyed array iteration", []() {
968 JSON::node x("[\"ABC\",\"DEF\",\"GHI\"]");
969 const char32_t* str[] = {U"ABC", U"DEF", U"GHI"};
970 for(auto i = x.begin(); i != x.end(); i++) {
971 if(i.index() > 2)
972 return false;
973 if(i->as_string() != str[i.index()])
974 return false;
976 return true;
977 }},{"Keyed array iteration (const)", []() {
978 JSON::node _x("[\"ABC\",\"DEF\",\"GHI\"]");
979 const JSON::node& x = _x;
980 const char32_t* str[] = {U"ABC", U"DEF", U"GHI"};
981 for(auto i = x.begin(); i != x.end(); i++) {
982 if(i.index() > 2)
983 return false;
984 if(i->as_string() != str[i.index()])
985 return false;
987 return true;
988 }},{"Keyed object iteration (key)", []() {
989 JSON::node x("{\"ABC\":\"DEF\"}");
990 for(auto i = x.begin(); i != x.end(); i++)
991 return (i.key() == U"ABC");
992 return false;
993 }},{"Keyed object iteration (key, const)", []() {
994 JSON::node _x("{\"ABC\":\"DEF\"}");
995 const JSON::node& x = _x;
996 for(auto i = x.begin(); i != x.end(); i++)
997 return (i.key() == U"ABC");
998 return false;
999 }},{"Keyed array iteration (key)", []() {
1000 JSON::node x("[\"ABC\",\"DEF\"]");
1001 for(auto i = x.begin(); i != x.end(); i++) {
1002 if(i.key() != U"")
1003 return false;
1005 return true;
1006 }},{"Keyed array iteration (key, const)", []() {
1007 JSON::node _x("[\"ABC\",\"DEF\"]");
1008 const JSON::node& x = _x;
1009 for(auto i = x.begin(); i != x.end(); i++) {
1010 if(i.key() != U"")
1011 return false;
1013 return true;
1014 }},{"Keyed object iteration", []() {
1015 JSON::node x("{\"2\":\"ABC\",\"1\":\"DEF\",\"0\":\"GHI\"}");
1016 const char32_t* str[] = {U"GHI", U"DEF", U"ABC"};
1017 for(auto i = x.begin(); i != x.end(); i++) {
1018 size_t idx = parse_value<size_t>(utf8::to8(i.key()));
1019 if(i->as_string() != str[idx])
1020 return false;
1022 return true;
1023 }},{"Keyed object iteration (Const)", []() {
1024 JSON::node _x("{\"2\":\"ABC\",\"1\":\"DEF\",\"0\":\"GHI\"}");
1025 const JSON::node& x = _x;
1026 const char32_t* str[] = {U"GHI", U"DEF", U"ABC"};
1027 for(auto i = x.begin(); i != x.end(); i++) {
1028 size_t idx = parse_value<size_t>(utf8::to8(i.key()));
1029 if(i->as_string() != str[idx])
1030 return false;
1032 return true;
1033 }},{"End-of-object iterator (array)", []() {
1034 JSON::node x("[]");
1035 auto i = x.begin();
1036 try { i.key(); return false; } catch(...) {}
1037 try { i.index(); return false; } catch(...) {}
1038 try { *i; return false; } catch(...) {}
1039 try { i->type(); return false; } catch(...) {}
1040 try { i++; return false; } catch(...) {}
1041 try { ++i; return false; } catch(...) {}
1042 return (i == x.end()) && !(i != x.end());
1043 }},{"End-of-object iterator (object)", []() {
1044 JSON::node x("{}");
1045 auto i = x.begin();
1046 try { i.key(); return false; } catch(...) {}
1047 try { i.index(); return false; } catch(...) {}
1048 try { *i; return false; } catch(...) {}
1049 try { i->type(); return false; } catch(...) {}
1050 try { i++; return false; } catch(...) {}
1051 try { ++i; return false; } catch(...) {}
1052 return (i == x.end()) && !(i != x.end());
1053 }},{"End-of-object iterator (array, const)", []() {
1054 JSON::node _x("[]");
1055 const JSON::node& x = _x;
1056 auto i = x.begin();
1057 try { i.key(); return false; } catch(...) {}
1058 try { i.index(); return false; } catch(...) {}
1059 try { *i; return false; } catch(...) {}
1060 try { i->type(); return false; } catch(...) {}
1061 try { i++; return false; } catch(...) {}
1062 try { ++i; return false; } catch(...) {}
1063 return (i == x.end()) && !(i != x.end());
1064 }},{"End-of-object iterator (object, const)", []() {
1065 JSON::node _x("{}");
1066 const JSON::node& x = _x;
1067 auto i = x.begin();
1068 try { i.key(); return false; } catch(...) {}
1069 try { i.index(); return false; } catch(...) {}
1070 try { *i; return false; } catch(...) {}
1071 try { i->type(); return false; } catch(...) {}
1072 try { i++; return false; } catch(...) {}
1073 try { ++i; return false; } catch(...) {}
1074 return (i == x.end()) && !(i != x.end());
1075 }},{"Iterators to different objects are not equal", []() {
1076 JSON::node x("[1234]");
1077 JSON::node y("[1234]");
1078 return (x.begin() != y.begin());
1079 }},{"Iterators to different objects are not equal (const)", []() {
1080 JSON::node _x("[1234]");
1081 JSON::node _y("[1234]");
1082 const JSON::node& x = _x;
1083 const JSON::node& y = _y;
1084 return (x.begin() != y.begin());
1085 }},{"Iterators to the same object are equal", []() {
1086 JSON::node x("[1234]");
1087 return (x.begin() == x.begin());
1088 }},{"Iterators to the same object are equal (const)", []() {
1089 JSON::node _x("[1234]");
1090 const JSON::node& x = _x;
1091 return (x.begin() == x.begin());
1092 }},{"Iterators to different elements are not equal", []() {
1093 JSON::node x("[1, 2]");
1094 auto i = x.begin();
1095 auto j = x.begin();
1096 j++;
1097 if(i.key() != U"")
1098 return false;
1099 if(j.key() != U"")
1100 return false;
1101 if(i == x.end())
1102 return false;
1103 if(j == x.end())
1104 return false;
1105 return (i != j);
1106 }},{"Iterators to different elements are not equal (const)", []() {
1107 JSON::node _x("[1, 2]");
1108 const JSON::node& x = _x;
1109 auto i = x.begin();
1110 auto j = x.begin();
1111 j++;
1112 if(i.key() != U"")
1113 return false;
1114 if(j.key() != U"")
1115 return false;
1116 if(i == x.end())
1117 return false;
1118 if(j == x.end())
1119 return false;
1120 return (i != j);
1121 }},{"Iterators to different instances of key are not equal", []() {
1122 JSON::node x("{\"foo\":1,\"foo\":2}");
1123 auto i = x.begin();
1124 auto j = x.begin();
1125 j++;
1126 if(i.key() != U"foo")
1127 return false;
1128 if(j.key() != U"foo")
1129 return false;
1130 if(i == x.end())
1131 return false;
1132 if(j == x.end())
1133 return false;
1134 return (i != j);
1135 }},{"Iterators to different instances of key are not equal (const)", []() {
1136 JSON::node _x("{\"foo\":1,\"foo\":2}");
1137 const JSON::node& x = _x;
1138 auto i = x.begin();
1139 auto j = x.begin();
1140 j++;
1141 if(i.key() != U"foo")
1142 return false;
1143 if(j.key() != U"foo")
1144 return false;
1145 if(i == x.end())
1146 return false;
1147 if(j == x.end())
1148 return false;
1149 return (i != j);
1150 }},{"Iterators to different keys are not equal", []() {
1151 JSON::node x("{\"foo\":1,\"foz\":2}");
1152 auto i = x.begin();
1153 auto j = x.begin();
1154 j++;
1155 if(i.key() != U"foo")
1156 return false;
1157 if(j.key() != U"foz")
1158 return false;
1159 if(i == x.end())
1160 return false;
1161 if(j == x.end())
1162 return false;
1163 return (i != j);
1164 }},{"Iterators to different keys are not equal (const)", []() {
1165 JSON::node _x("{\"foo\":1,\"foz\":2}");
1166 const JSON::node& x = _x;
1167 auto i = x.begin();
1168 auto j = x.begin();
1169 j++;
1170 if(i.key() != U"foo")
1171 return false;
1172 if(j.key() != U"foz")
1173 return false;
1174 if(i == x.end())
1175 return false;
1176 if(j == x.end())
1177 return false;
1178 return (i != j);
1179 }},{"Serialize multiple", []() {
1180 JSON::node x("{\"foo\":1,\"foo\":2}");
1181 return (x.serialize() == "{\"foo\":1,\"foo\":2}");
1182 }},{"Serialize multiple #2", []() {
1183 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1184 return (x.serialize() == "{\"foo\":1,\"foo\":2,\"foz\":3}");
1185 }},{"erase index from end", []() {
1186 JSON::node x("[1,2,3]");
1187 auto i = x.begin();
1188 i++;
1189 i++;
1190 x.erase(i);
1191 return (x.serialize() == "[1,2]");
1192 }},{"erase index from middle", []() {
1193 JSON::node x("[1,2,3]");
1194 auto i = x.begin();
1195 i++;
1196 x.erase(i);
1197 return (x.serialize() == "[1,3]");
1198 }},{"erase index from start", []() {
1199 JSON::node x("[1,2,3]");
1200 auto i = x.begin();
1201 x.erase(i);
1202 return (x.serialize() == "[2,3]");
1203 }},{"erase index from middle and iterate", []() {
1204 JSON::node x("[1,2,3]");
1205 auto i = x.begin();
1206 i++;
1207 i = x.erase(i);
1208 return (i->as_int() == 3);
1209 }},{"erase index from end and iterate", []() {
1210 JSON::node x("[1,2,3]");
1211 auto i = x.begin();
1212 i++;
1213 i++;
1214 i = x.erase(i);
1215 return (i == x.end());
1216 }},{"erase_index past end", []() {
1217 JSON::node x("[1,2,3]");
1218 x.erase_index(3);
1219 return (x.serialize() == "[1,2,3]");
1220 }},{"erase_index on object", []() {
1221 JSON::node x("{}");
1222 x.erase_index(0);
1223 return false;
1224 }, JSON::ERR_NOT_AN_ARRAY},{"erase index on boolean", []() {
1225 JSON::node x("[3]");
1226 auto i = x.begin();
1227 x.set(JSON::boolean, false);
1228 x.erase(i);
1229 return false;
1230 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"erase index from wrong thing", []() {
1231 JSON::node x("[1,2,3]");
1232 JSON::node y("[1,2,3]");
1233 auto i = x.begin();
1234 y.erase(i);
1235 return false;
1236 }, JSON::ERR_WRONG_OBJECT},{"erase field on boolean", []() {
1237 JSON::node x("false");
1238 x.erase_field(U"foo");
1239 return false;
1240 }, JSON::ERR_NOT_AN_OBJECT},{"erase field all on boolean", []() {
1241 JSON::node x("false");
1242 x.erase_field_all(U"foo");
1243 return false;
1244 }, JSON::ERR_NOT_AN_OBJECT},{"erase key", []() {
1245 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1246 auto i = x.begin();
1247 i++;
1248 x.erase(i);
1249 return (x.serialize() == "{\"foo\":1,\"foz\":3}");
1250 }},{"erase_field_all", []() {
1251 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1252 x.erase_field_all(U"foo");
1253 return (x.serialize() == "{\"foz\":3}");
1254 }},{"erase_field_all (does not exist)", []() {
1255 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1256 x.erase_field_all(U"fou");
1257 return (x.serialize() == "{\"foo\":1,\"foo\":2,\"foz\":3}");
1258 }},{"erase_field (does not exist)", []() {
1259 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1260 x.erase_field(U"fou");
1261 return (x.serialize() == "{\"foo\":1,\"foo\":2,\"foz\":3}");
1262 }},{"erase_field (first)", []() {
1263 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1264 x.erase_field(U"foo");
1265 return (x.serialize() == "{\"foo\":2,\"foz\":3}");
1266 }},{"erase_field (second)", []() {
1267 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1268 x.erase_field(U"foo", 1);
1269 return (x.serialize() == "{\"foo\":1,\"foz\":3}");
1270 }},{"erase_field (subsequent)", []() {
1271 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1272 x.erase_field(U"foo", 2);
1273 return (x.serialize() == "{\"foo\":1,\"foo\":2,\"foz\":3}");
1274 }},{"erase key and iterate", []() {
1275 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1276 auto i = x.begin();
1277 i++;
1278 i = x.erase(i);
1279 return (i.key() == U"foz" && i->as_int() == 3);
1280 }},{"erase key (disappears)", []() {
1281 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1282 auto i = x.begin();
1283 i++;
1284 i++;
1285 x.erase(i);
1286 return (x.serialize() == "{\"foo\":1,\"foo\":2}");
1287 }},{"clear object", []() {
1288 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1289 x.clear();
1290 return (x.serialize() == "{}");
1291 }},{"clear array", []() {
1292 JSON::node x("[1,2,3]");
1293 x.clear();
1294 return (x.serialize() == "[]");
1295 }},{"clear boolean", []() {
1296 JSON::node x("false");
1297 x.clear();
1298 return false;
1299 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"iterator on deleted index", []() {
1300 JSON::node x("[1,2,3]");
1301 auto i = x.begin();
1302 i++;
1303 i++;
1304 x.erase_index(2);
1306 return false;
1307 }, JSON::ERR_ITERATOR_DELETED},{"iterator on deleted index (const)", []() {
1308 JSON::node _x("[1,2,3]");
1309 const JSON::node& x = _x;
1310 auto i = x.begin();
1311 i++;
1312 i++;
1313 _x.erase_index(2);
1315 return false;
1316 }, JSON::ERR_ITERATOR_DELETED},{"iterator on deleted key", []() {
1317 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1318 auto i = x.begin();
1319 i++;
1320 i++;
1321 x.erase_field(U"foz");
1323 return false;
1324 }, JSON::ERR_ITERATOR_DELETED},{"iterator on deleted key (const)", []() {
1325 JSON::node _x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1326 const JSON::node& x = _x;
1327 auto i = x.begin();
1328 i++;
1329 i++;
1330 _x.erase_field(U"foz");
1332 return false;
1333 }, JSON::ERR_ITERATOR_DELETED},{"iterator on deleted key-instance", []() {
1334 JSON::node x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1335 auto i = x.begin();
1336 i++;
1337 x.erase_field(U"foo",0);
1339 return false;
1340 }, JSON::ERR_ITERATOR_DELETED},{"iterator on deleted key-instance (const)", []() {
1341 JSON::node _x("{\"foo\":1,\"foo\":2,\"foz\":3}");
1342 const JSON::node& x = _x;
1343 auto i = x.begin();
1344 i++;
1345 _x.erase_field(U"foo",0);
1347 return false;
1348 }, JSON::ERR_ITERATOR_DELETED},{"Illegal character #1", []() {
1349 JSON::node x("\"\\uFFFE\"");
1350 return false;
1351 }, JSON::ERR_ILLEGAL_CHARACTER},{"Illegal character #2", []() {
1352 JSON::node x("\"\\uFFFF\"");
1353 return false;
1354 }, JSON::ERR_ILLEGAL_CHARACTER},{"Illegal character #3", []() {
1355 JSON::node x("\"\\uD87F\\uDFFE\"");
1356 return false;
1357 }, JSON::ERR_ILLEGAL_CHARACTER},{"U+F800", []() {
1358 JSON::node x("\"\\uF800\"");
1359 return true;
1360 }},{"Special escapes", []() {
1361 JSON::node x("\"\\b\\f\\n\\r\\t\\\"\\\\\\u007F\u0080\"");
1362 return (x.serialize() == "\"\\b\\f\\n\\r\\t\\\"\\\\\x7F\xc2\x80\"");
1363 }},{"\\v is not whitespace", []() {
1364 JSON::node x(" [\v123]");
1365 return false;
1366 }, JSON::ERR_UNKNOWN_CHARACTER},{"null==null", []() -> bool {
1367 return JSON::n() == JSON::n();
1368 }},{"false==false", []() -> bool {
1369 return JSON::b(false) == JSON::b(false);
1370 }},{"true==true", []() -> bool {
1371 return JSON::b(true) == JSON::b(true);
1372 }},{"null!=false", []() -> bool {
1373 return JSON::b(false) != JSON::n();
1374 }},{"\"foo\"==\"foo\"", []() -> bool {
1375 return JSON::s("foo") == JSON::s("foo");
1376 }},{"\"foo\"==U\"foo\"", []() -> bool {
1377 return JSON::s("foo") == JSON::s(U"foo");
1378 }},{"\"foo\"!=\"bar\"", []() -> bool {
1379 return JSON::s("foo") != JSON::s("bar");
1380 }},{"1==1", []() -> bool {
1381 return JSON::i(1) == JSON::i(1);
1382 }},{"1==(uint)1", []() -> bool {
1383 return JSON::i(1) == JSON::u(1U);
1384 }},{"1==1.0", []() -> bool {
1385 return JSON::i(1) == JSON::f(1.0);
1386 }},{"-1.25!=-1", []() -> bool {
1387 return JSON::f(-1.25) != JSON::i(-1);
1388 }},{"1.25!=1U", []() -> bool {
1389 return JSON::f(1.25) != JSON::u(1);
1390 }},{"1.25!=1.5", []() -> bool {
1391 return JSON::f(1.25) != JSON::f(1.5);
1392 }},{"(uint)1==1.0", []() -> bool {
1393 return JSON::u(1) == JSON::f(1.0);
1394 }},{"1!=2", []() -> bool {
1395 return JSON::i(1) != JSON::i(2);
1396 }},{"-1!=0xFFFFFFFFFFFFFFFFULL", []() -> bool {
1397 return JSON::i(-1) != JSON::u(0xFFFFFFFFFFFFFFFFULL);
1398 }},{"0xFFFFFFFFFFFFFFFFULL!=-1", []() -> bool {
1399 return JSON::u(0xFFFFFFFFFFFFFFFFULL) != JSON::i(-1);
1400 }},{"1!=\1\1", []() -> bool {
1401 return JSON::i(1) != JSON::s("1");
1402 }},{"false!=0", []() -> bool {
1403 return JSON::b(false) != JSON::i(0);
1404 }},{"true!=1", []() -> bool {
1405 return JSON::b(true) != JSON::i(1);
1406 }},{"{}!=[]", []() -> bool {
1407 return JSON::node("{}") != JSON::node("[]");
1408 }},{"{}=={}", []() -> bool {
1409 return JSON::node("{}") == JSON::node("{}");
1410 }},{"[]==[]", []() -> bool {
1411 return JSON::node("[]") == JSON::node("[]");
1412 }},{"[1,2,3]==[1,2,3]", []() -> bool {
1413 return JSON::node("[1,2,3]") == JSON::node("[1,2,3]");
1414 }},{"[1,2,3]!=[1,2,4]", []() -> bool {
1415 return JSON::node("[1,2,3]") != JSON::node("[1,2,4]");
1416 }},{"[1,2,\"hi\"]==[1,2,\"hi\"]", []() -> bool {
1417 return JSON::node("[1,2,\"hi\"]") == JSON::node("[1,2,\"hi\"]");
1418 }},{"[1,2,[4,5]]==[1,2,[4,5]]", []() -> bool {
1419 return JSON::node("[1,2,[4,5]]") == JSON::node("[1,2,[4,5]]");
1420 }},{"[1,2,[4,6]]!=[1,2,[4,5]]", []() -> bool {
1421 return JSON::node("[1,2,[4,6]]") != JSON::node("[1,2,[4,5]]");
1422 }},{"[1,2,3]!=[1,2]", []() -> bool {
1423 return JSON::node("[1,2,3]") != JSON::node("[1,2]");
1424 }},{"[1,2]!=[1,2,3]", []() -> bool {
1425 return JSON::node("[1,2]") != JSON::node("[1,2,3]");
1426 }},{"{\"foo\": 1}=={\"foo\": 1}", []() -> bool {
1427 return JSON::node("{\"foo\": 1}") == JSON::node("{\"foo\": 1}");
1428 }},{"{\"foo\": [1,2]}=={\"foo\": [1,2]}", []() -> bool {
1429 return JSON::node("{\"foo\": [1,2]}") == JSON::node("{\"foo\": [1,2]}");
1430 }},{"{\"foo\": [1,2]}!={\"foo\": [1,3]}", []() -> bool {
1431 return JSON::node("{\"foo\": [1,2]}") != JSON::node("{\"foo\": [1,3]}");
1432 }},{"{\"foo\": 1}!={\"bar\": 1}", []() -> bool {
1433 return JSON::node("{\"foo\": 1}") != JSON::node("{\"bar\": 1}");
1434 }},{"{\"foo\": 1}!={\"foo\": 1, \"x\": 2}", []() -> bool {
1435 return JSON::node("{\"foo\": 1}") != JSON::node("{\"foo\": 1, \"x\": 2}");
1436 }},{"{\"foo\": 1, \"x\": 2}!={\"foo\": 1}", []() -> bool {
1437 return JSON::node("{\"foo\": 1, \"x\": 2}") != JSON::node("{\"foo\": 1}");
1438 }},{"{\"foo\": 1}!={\"foo\": 2}", []() -> bool {
1439 return JSON::node("{\"foo\": 1}") != JSON::node("{\"foo\": 2}");
1440 }},{"{\"foo\": 1,\"foo\": 2}=={\"foo\": 1,\"foo\": 2}", []() -> bool {
1441 return JSON::node("{\"foo\": 1,\"foo\": 2}") == JSON::node("{\"foo\": 1,\"foo\": 2}");
1442 }},{"{\"foo\": 1,\"foo\": 2}!={\"foo\": 2,\"foo\": 1}", []() -> bool {
1443 return JSON::node("{\"foo\": 1,\"foo\": 2}") != JSON::node("{\"foo\": 2,\"foo\": 1}");
1444 }},{"{\"foo\": 1,\"foo\": 2}!={\"foo\": 1}", []() -> bool {
1445 return JSON::node("{\"foo\": 1,\"foo\": 2}") != JSON::node("{\"foo\": 1}");
1446 }},{"{\"foo\": 1}!={\"foo\": 1,\"foo\": 2}", []() -> bool {
1447 return JSON::node("{\"foo\": 1}") != JSON::node("{\"foo\": 1,\"foo\": 2}");
1448 }},{"Escape U+0012", []() {
1449 JSON::node x("\"\\u0012\"");
1450 return (x.serialize() == "\"\\u0012\"");
1451 }},{"Escape U+001F", []() {
1452 JSON::node x("\"\\u001F\"");
1453 return (x.serialize() == "\"\\u001f\"");
1454 }},{"Compare itself", []() {
1455 JSON::node x("\"\\u001F\"");
1456 return x == x;
1457 }},{"Boolean not null", []() {
1458 JSON::node x("false");
1459 return x.type() != JSON::null;
1460 }},{"Insert_node to empty array with -", []() {
1461 JSON::node x("[]");
1462 x.insert_node("-", JSON::i(1));
1463 return x.serialize() == "[1]";
1464 }},{"Insert_node to empty array with 0", []() {
1465 JSON::node x("[]");
1466 x.insert_node("0", JSON::i(1));
1467 return x.serialize() == "[1]";
1468 }},{"Insert_node to end of non-empty array with -", []() {
1469 JSON::node x("[1,2,3]");
1470 x.insert_node("-", JSON::i(4));
1471 return x.serialize() == "[1,2,3,4]";
1472 }},{"Insert_node to end of non-empty array with index", []() {
1473 JSON::node x("[1,2,3]");
1474 x.insert_node("3", JSON::i(4));
1475 return x.serialize() == "[1,2,3,4]";
1476 }},{"Insert_node to middle of non-empty array", []() {
1477 JSON::node x("[1,2,4]");
1478 x.insert_node("2", JSON::i(3));
1479 return x.serialize() == "[1,2,3,4]";
1480 }},{"Insert_node to middle of nested array", []() {
1481 JSON::node x("[[1,2,4]]");
1482 x.insert_node("0/2", JSON::i(3));
1483 return x.serialize() == "[[1,2,3,4]]";
1484 }},{"Insert_node to invalid array", []() {
1485 JSON::node x("[[1,2,4]]");
1486 x.insert_node("1/2", JSON::i(3));
1487 return false;
1488 }, JSON::ERR_INDEX_INVALID},{"Insert_node to boolean", []() {
1489 JSON::node x("false");
1490 x.insert_node("0", JSON::i(4));
1491 return false;
1492 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Insert_node to empty object", []() {
1493 JSON::node x("{}");
1494 x.insert_node("foo",JSON::i(1));
1495 return x.serialize() == "{\"foo\":1}";
1496 }},{"Insert_node to non-empty object", []() {
1497 JSON::node x("{\"bar\":2}");
1498 x.insert_node("foo", JSON::i(1));
1499 return x.serialize() == "{\"bar\":2,\"foo\":1}";
1500 }},{"Insert_node to replacing entry in object", []() {
1501 JSON::node x("{\"foo\":2}");
1502 x.insert_node("foo", JSON::i(1));
1503 return x.serialize() == "{\"foo\":1}";
1504 }},{"Insert_node to replacing entries in object", []() {
1505 JSON::node x("{\"foo\":1,\"foo\":2}");
1506 x.insert_node("foo", JSON::i(3));
1507 return x.serialize() == "{\"foo\":3,\"foo\":2}";
1508 }},{"Insert_node returns object #1", []() {
1509 JSON::node x("{\"bar\":2}");
1510 JSON::node& y = x.insert_node("foo", JSON::s("TEST"));
1511 return y.serialize() == "\"TEST\"";
1512 }},{"Insert_node returns object #2", []() {
1513 JSON::node x("[]");
1514 JSON::node& y = x.insert_node("0", JSON::s("TEST"));
1515 return y.serialize() == "\"TEST\"";
1516 }},{"Insert_node returns object #3", []() {
1517 JSON::node x("[]");
1518 JSON::node& y = x.insert_node("-", JSON::s("TEST"));
1519 return y.serialize() == "\"TEST\"";
1520 }},{"Insert_node returns object #4", []() {
1521 JSON::node x("[1]");
1522 JSON::node& y = x.insert_node("-", JSON::s("TEST"));
1523 return y.serialize() == "\"TEST\"";
1524 }},{"Insert_node to index too large", []() {
1525 JSON::node x("[[1,2,4]]");
1526 x.insert_node("0/5", JSON::i(5));
1527 return false;
1528 }, JSON::ERR_POINTER_BAD_APPEND},{"delete_node to boolean", []() {
1529 JSON::node x("false");
1530 x.delete_node("0");
1531 return false;
1532 }, JSON::ERR_NOT_ARRAY_NOR_OBJECT},{"Delete_node to middle of non-empty array", []() {
1533 JSON::node x("[1,2,3,4]");
1534 x.delete_node("2");
1535 return x.serialize() == "[1,2,4]";
1536 }},{"Delete_node to middle of nested array", []() {
1537 JSON::node x("[[1,2,3,4]]");
1538 x.delete_node("0/2");
1539 return x.serialize() == "[[1,2,4]]";
1540 }},{"Delete_node to invalid array", []() {
1541 JSON::node x("[[1,2,3,4]]");
1542 x.delete_node("1/2");
1543 return false;
1544 }, JSON::ERR_INDEX_INVALID},{"Delete_node returns object", []() {
1545 JSON::node x("{\"bar\":\"test!\"}");
1546 JSON::node y = x.delete_node("bar");
1547 return y.serialize() == "\"test!\"";
1548 }},{"Delete_node returns object #2", []() {
1549 JSON::node x("[1,\"test!\"]");
1550 JSON::node y = x.delete_node("1");
1551 return y.serialize() == "\"test!\"";
1552 }},{"Delete_node to deleting entry in object", []() {
1553 JSON::node x("{\"bar\":1,\"foo\":2}");
1554 x.delete_node("foo");
1555 return x.serialize() == "{\"bar\":1}";
1556 }},{"Delete_node to deleting entries in object", []() {
1557 JSON::node x("{\"bar\":1,\"foo\":2,\"foo\":3}");
1558 x.delete_node("foo");
1559 return x.serialize() == "{\"bar\":1}";
1560 }},{"Delete_node to invalid key in object", []() {
1561 JSON::node x("{\"bar\":1,\"foo\":2}");
1562 x.delete_node("foz");
1563 return false;
1564 }, JSON::ERR_KEY_INVALID},{"Delete_node to invalid index", []() {
1565 JSON::node x("[1,2,3,4]");
1566 x.delete_node("4");
1567 return false;
1568 }, JSON::ERR_INDEX_INVALID},{"Delete_node to index -", []() {
1569 JSON::node x("[1,2,3,4]");
1570 x.delete_node("-");
1571 return false;
1572 }, JSON::ERR_POINTER_BAD_APPEND},{"operator[] on bad index", []() {
1573 JSON::node x("[1,2,3,4]");
1574 x["f"];
1575 return false;
1576 }, JSON::ERR_POINTER_BAD_INDEX},{"insert_node on bad index", []() {
1577 JSON::node x("[1,2,3,4]");
1578 x.insert_node("f", JSON::b(false));
1579 return false;
1580 }, JSON::ERR_POINTER_BAD_INDEX},{"delete_node on bad index", []() {
1581 JSON::node x("[1,2,3,4]");
1582 x.delete_node("f");
1583 return false;
1584 }, JSON::ERR_POINTER_BAD_INDEX},{"patching with an object", []() {
1585 JSON::node x("[1,2,3,4]");
1586 JSON::node y("{}");
1587 x.patch(y);
1588 return false;
1589 }, JSON::ERR_PATCH_BAD},{"Duplicate op", []() {
1590 JSON::node x("[1,2,3,4]");
1591 JSON::node y("[{\"op\":\"test\",\"path\":\"3\",\"value\":4,\"op\":\"add\"}]");
1592 x.patch(y);
1593 return false;
1594 }, JSON::ERR_PATCH_BAD},{"simple test", []() {
1595 JSON::node x("[1,2,3,4]");
1596 JSON::node y("[{\"op\":\"test\",\"path\":\"3\",\"value\":4}]");
1597 JSON::node z = x.patch(y);
1598 return x == z;
1599 }},{"simple failed test", []() {
1600 JSON::node x("[1,2,3,4]");
1601 JSON::node y("[{\"op\":\"test\",\"path\":\"3\",\"value\":3}]");
1602 x.patch(y);
1603 return false;
1604 }, JSON::ERR_PATCH_TEST_FAILED},{"test dupe path", []() {
1605 JSON::node x("[1,2,3,4]");
1606 JSON::node y("[{\"op\":\"test\",\"path\":\"3\",\"path\":\"2\",\"value\":3}]");
1607 x.patch(y);
1608 return false;
1609 }, JSON::ERR_PATCH_BAD},{"test number path", []() {
1610 JSON::node x("[1,2,3,4]");
1611 JSON::node y("[{\"op\":\"test\",\"path\":3,\"value\":4}]");
1612 x.patch(y);
1613 return false;
1614 }, JSON::ERR_PATCH_BAD},{"test dupe value", []() {
1615 JSON::node x("[1,2,3,4]");
1616 JSON::node y("[{\"op\":\"test\",\"path\":\"3\",\"value\":\"2\",\"value\":3}]");
1617 x.patch(y);
1618 return false;
1619 }, JSON::ERR_PATCH_BAD},{"simple remove", []() {
1620 JSON::node x("[1,2,3,4]");
1621 JSON::node y("[{\"op\":\"remove\",\"path\":\"2\"}]");
1622 JSON::node z = x.patch(y);
1623 return z.serialize() == "[1,2,4]";
1624 }},{"remove dupe path", []() {
1625 JSON::node x("[1,2,3,4]");
1626 JSON::node y("[{\"op\":\"remove\",\"path\":\"2\",\"path\":\"3\"}]");
1627 JSON::node z = x.patch(y);
1628 return false;
1629 }, JSON::ERR_PATCH_BAD},{"remove numeric path", []() {
1630 JSON::node x("[1,2,3,4]");
1631 JSON::node y("[{\"op\":\"remove\",\"path\":2}]");
1632 JSON::node z = x.patch(y);
1633 return false;
1634 }, JSON::ERR_PATCH_BAD},{"simple add", []() {
1635 JSON::node x("[1,2,3,4]");
1636 JSON::node y("[{\"op\":\"add\",\"path\":\"-\",\"value\":5}]");
1637 JSON::node z = x.patch(y);
1638 return z.serialize() == "[1,2,3,4,5]";
1639 }},{"add dupe path", []() {
1640 JSON::node x("[1,2,3,4]");
1641 JSON::node y("[{\"op\":\"add\",\"path\":\"3\",\"path\":\"2\",\"value\":3}]");
1642 x.patch(y);
1643 return false;
1644 }, JSON::ERR_PATCH_BAD},{"add number path", []() {
1645 JSON::node x("[1,2,3,4]");
1646 JSON::node y("[{\"op\":\"add\",\"path\":3,\"value\":4}]");
1647 x.patch(y);
1648 return false;
1649 }, JSON::ERR_PATCH_BAD},{"add dupe value", []() {
1650 JSON::node x("[1,2,3,4]");
1651 JSON::node y("[{\"op\":\"add\",\"path\":\"3\",\"value\":\"2\",\"value\":3}]");
1652 x.patch(y);
1653 return false;
1654 }, JSON::ERR_PATCH_BAD},{"simple replace", []() {
1655 JSON::node x("[1,2,3,4]");
1656 JSON::node y("[{\"op\":\"replace\",\"path\":\"3\",\"value\":5}]");
1657 JSON::node z = x.patch(y);
1658 return z.serialize() == "[1,2,3,5]";
1659 }},{"Replace nonexistent", []() {
1660 JSON::node x("{\"foo\":5}");
1661 JSON::node y("[{\"op\":\"replace\",\"path\":\"foz\",\"value\":5}]");
1662 JSON::node z = x.patch(y);
1663 return false;
1664 }, JSON::ERR_KEY_INVALID},{"replace dupe path", []() {
1665 JSON::node x("[1,2,3,4]");
1666 JSON::node y("[{\"op\":\"replace\",\"path\":\"3\",\"path\":\"2\",\"value\":3}]");
1667 x.patch(y);
1668 return false;
1669 }, JSON::ERR_PATCH_BAD},{"replace number path", []() {
1670 JSON::node x("[1,2,3,4]");
1671 JSON::node y("[{\"op\":\"replace\",\"path\":3,\"value\":4}]");
1672 x.patch(y);
1673 return false;
1674 }, JSON::ERR_PATCH_BAD},{"replace dupe value", []() {
1675 JSON::node x("[1,2,3,4]");
1676 JSON::node y("[{\"op\":\"replace\",\"path\":\"3\",\"value\":\"2\",\"value\":3}]");
1677 x.patch(y);
1678 return false;
1679 }, JSON::ERR_PATCH_BAD},{"simple move", []() {
1680 JSON::node x("[[1,2,3,4],[]]");
1681 JSON::node y("[{\"op\":\"move\",\"from\":\"0/1\",\"path\":\"1/-\"}]");
1682 JSON::node z = x.patch(y);
1683 return z.serialize() == "[[1,3,4],[2]]";
1684 }},{"move within array", []() {
1685 JSON::node x("[1,2,3,4]");
1686 JSON::node y("[{\"op\":\"move\",\"from\":\"1\",\"path\":\"3\"}]");
1687 JSON::node z = x.patch(y);
1688 return z.serialize() == "[1,3,4,2]";
1689 }},{"move nonexistent", []() {
1690 JSON::node x("{\"foo\":5}");
1691 JSON::node y("[{\"op\":\"move\",\"path\":\"for\",\"from\":\"foz\"}]");
1692 JSON::node z = x.patch(y);
1693 return false;
1694 }, JSON::ERR_KEY_INVALID},{"move dupe path", []() {
1695 JSON::node x("[1,2,3,4]");
1696 JSON::node y("[{\"op\":\"move\",\"path\":\"3\",\"path\":\"2\",\"from\":\"3\"}]");
1697 x.patch(y);
1698 return false;
1699 }, JSON::ERR_PATCH_BAD},{"move number path", []() {
1700 JSON::node x("[1,2,3,4]");
1701 JSON::node y("[{\"op\":\"move\",\"path\":3,\"from\":\"4\"}]");
1702 x.patch(y);
1703 return false;
1704 }, JSON::ERR_PATCH_BAD},{"move dupe from", []() {
1705 JSON::node x("[1,2,3,4]");
1706 JSON::node y("[{\"op\":\"move\",\"path\":\"3\",\"from\":\"2\",\"from\":\"3\"}]");
1707 x.patch(y);
1708 return false;
1709 }, JSON::ERR_PATCH_BAD},{"move number from", []() {
1710 JSON::node x("[1,2,3,4]");
1711 JSON::node y("[{\"op\":\"move\",\"path\":\"3\",\"from\":4}]");
1712 x.patch(y);
1713 return false;
1714 }, JSON::ERR_PATCH_BAD},{"move illegal", []() {
1715 JSON::node x("{\"foo\":{}}");
1716 JSON::node y("[{\"op\":\"move\",\"path\":\"foo/bar\",\"from\":\"foo\"}]");
1717 JSON::node z = x.patch(y);
1718 return false;
1719 }, JSON::ERR_PATCH_ILLEGAL_MOVE},{"move self", []() {
1720 JSON::node x("{\"foo\":{}}");
1721 JSON::node y("[{\"op\":\"move\",\"path\":\"foo\",\"from\":\"foo\"}]");
1722 JSON::node z = x.patch(y);
1723 return x == z;
1724 }},{"simple copy", []() {
1725 JSON::node x("[[1,2,3,4],[]]");
1726 JSON::node y("[{\"op\":\"copy\",\"from\":\"0/1\",\"path\":\"1/-\"}]");
1727 JSON::node z = x.patch(y);
1728 return z.serialize() == "[[1,2,3,4],[2]]";
1729 }},{"copy within array", []() {
1730 JSON::node x("[1,2,3,4]");
1731 JSON::node y("[{\"op\":\"copy\",\"from\":\"1\",\"path\":\"3\"}]");
1732 JSON::node z = x.patch(y);
1733 return z.serialize() == "[1,2,3,2,4]";
1734 }},{"copy nonexistent", []() {
1735 JSON::node x("{\"foo\":5}");
1736 JSON::node y("[{\"op\":\"copy\",\"path\":\"for\",\"from\":\"foz\"}]");
1737 JSON::node z = x.patch(y);
1738 return false;
1739 }, JSON::ERR_KEY_INVALID},{"copy dupe path", []() {
1740 JSON::node x("[1,2,3,4]");
1741 JSON::node y("[{\"op\":\"copy\",\"path\":\"3\",\"path\":\"2\",\"from\":\"3\"}]");
1742 x.patch(y);
1743 return false;
1744 }, JSON::ERR_PATCH_BAD},{"copy number path", []() {
1745 JSON::node x("[1,2,3,4]");
1746 JSON::node y("[{\"op\":\"copy\",\"path\":3,\"from\":\"4\"}]");
1747 x.patch(y);
1748 return false;
1749 }, JSON::ERR_PATCH_BAD},{"copy dupe from", []() {
1750 JSON::node x("[1,2,3,4]");
1751 JSON::node y("[{\"op\":\"copy\",\"path\":\"3\",\"from\":\"2\",\"from\":\"3\"}]");
1752 x.patch(y);
1753 return false;
1754 }, JSON::ERR_PATCH_BAD},{"copy number from", []() {
1755 JSON::node x("[1,2,3,4]");
1756 JSON::node y("[{\"op\":\"copy\",\"path\":\"3\",\"from\":4}]");
1757 x.patch(y);
1758 return false;
1759 }, JSON::ERR_PATCH_BAD},{"copy self", []() {
1760 JSON::node x("{\"foo\":{}}");
1761 JSON::node y("[{\"op\":\"copy\",\"path\":\"foo\",\"from\":\"foo\"}]");
1762 JSON::node z = x.patch(y);
1763 return x == z;
1764 }},{"copy idential path", []() {
1765 JSON::node x("[1]");
1766 JSON::node y("[{\"op\":\"copy\",\"path\":\"0\",\"from\":\"0\"}]");
1767 JSON::node z = x.patch(y);
1768 return z.serialize() == "[1,1]";
1769 }},{"unknown patch op", []() {
1770 JSON::node x("[1,2,3,4]");
1771 JSON::node y("[{\"op\":\"foo\",\"path\":\"3\",\"from\":\"4\",\"value\":6}]");
1772 x.patch(y);
1773 return false;
1774 }, JSON::ERR_PATCH_BAD},{"Basic type_of", []() {
1775 JSON::node x("[1,false,null,{\"foo\":\"bar\"}]");
1776 if(x.type_of("0") != JSON::number) return false;
1777 if(x.type_of("1") != JSON::boolean) return false;
1778 if(x.type_of("2") != JSON::null) return false;
1779 if(x.type_of("3") != JSON::object) return false;
1780 if(x.type_of("3/foo") != JSON::string) return false;
1781 if(x.type_of("4") != JSON::none) return false;
1782 if(x.type_of("foo") != JSON::none) return false;
1783 return true;
1784 }},{"Basic type_of_indirect", []() {
1785 JSON::node x("{\"objects\":{\"foo\":\"bar\",\"baz\":true},\"pointers\":[false,\"objects/foo\", "
1786 "\"objects/baz\",\"objects/enone\"]}");
1787 if(x.type_of_indirect("objects/baz") != JSON::boolean) return false;
1788 if(x.type_of_indirect("pointers/0") != JSON::boolean) return false;
1789 if(x.type_of_indirect("pointers/1") != JSON::string) return false;
1790 if(x.type_of_indirect("pointers/2") != JSON::boolean) return false;
1791 if(x.type_of_indirect("pointers/3") != JSON::none) return false;
1792 if(x.type_of_indirect("pointers/4") != JSON::none) return false;
1793 return true;
1794 }},{"Basic resolve_indirect", []() {
1795 JSON::node x("{\"objects\":{\"foo\":\"bar\",\"baz\":true},\"pointers\":[false,\"objects/foo\", "
1796 "\"objects/baz\",\"objects/enone\"]}");
1797 if(x.resolve_indirect("objects/baz") != "objects/baz") return false;
1798 if(x.resolve_indirect("pointers/0") != "pointers/0") return false;
1799 if(x.resolve_indirect("pointers/1") != "objects/foo") return false;
1800 if(x.resolve_indirect("pointers/2") != "objects/baz") return false;
1801 if(x.resolve_indirect("pointers/3") != "objects/enone") return false;
1802 if(x.resolve_indirect("pointers/4") != "pointers/4") return false;
1803 return true;
1804 }},{"Basic pointer obj #1", []() {
1805 JSON::pointer p;
1806 p.field_inplace("foo").field_inplace("bar");
1807 return p.as_string8() == "foo/bar";
1808 }},{"Basic pointer obj #2", []() {
1809 JSON::pointer p("foo/bar");
1810 return p.as_string() == U"foo/bar";
1811 }},{"Basic pointer obj #3", []() {
1812 JSON::pointer p(U"foo/bar");
1813 return p.as_string8() == "foo/bar";
1814 }},{"Basic pointer obj #4", []() {
1815 JSON::pointer p;
1816 p = p.index(5);
1817 p = p.index(3);
1818 return p.as_string8() == "5/3";
1819 }},{"Basic pointer obj #5", []() {
1820 JSON::pointer p;
1821 p.index_inplace(5);
1822 p.index_inplace(3);
1823 return p.as_string8() == "5/3";
1824 }},{"Basic pointer obj #6", []() {
1825 JSON::pointer p;
1826 p.index_inplace(5);
1827 p.index_inplace(3);
1828 p.pastend_inplace();
1829 return p.as_string8() == "5/3/-";
1830 }},{"Basic pointer obj #7", []() {
1831 JSON::pointer p;
1832 p = p.index(5);
1833 p = p.index(3);
1834 p = p.pastend();
1835 return p.as_string8() == "5/3/-";
1836 }},{"Basic pointer obj #8", []() {
1837 JSON::pointer p;
1838 p = p.field("foo").field("bar");
1839 return p.as_string8() == "foo/bar";
1840 }},{"Basic pointer obj #9", []() {
1841 JSON::pointer p;
1842 p = p.field("~").field("/");
1843 return p.as_string8() == "~0/~1";
1844 }},{"Basic pointer obj #10", []() {
1845 JSON::pointer p;
1846 p = p.field("foo").field("bar").field("baz").remove();
1847 return p.as_string8() == "foo/bar";
1848 }},{"Basic pointer obj #11", []() {
1849 JSON::pointer p;
1850 p.field_inplace("foo").field_inplace("bar").field_inplace("baz").remove_inplace();
1851 return p.as_string8() == "foo/bar";
1852 }},{"Basic pointer obj #12", []() {
1853 JSON::pointer p("baz/zot");
1854 std::string x = (stringfmt() << p).str();
1855 return x == "baz/zot";
1856 }},{"Basic pointer obj #13", []() {
1857 JSON::pointer p("baz/zot");
1858 std::basic_ostringstream<char32_t> y;
1859 y << p;
1860 return y.str() == U"baz/zot";
1861 }},{"Basic pointer obj #14", []() {
1862 JSON::pointer p;
1863 p = p.field("foo").remove();
1864 return p.as_string8() == "";
1865 }},{"Basic pointer obj #15", []() {
1866 JSON::pointer p;
1867 p.field_inplace("foo").remove_inplace();
1868 return p.as_string8() == "";
1872 void run_test(unsigned i, size_t& total, size_t& pass, size_t& fail)
1874 try {
1875 std::cout << "#" << (i + 1) << ": " << tests[i].title << "..." << std::flush;
1876 if(tests[i].dotest() && !tests[i].expect) {
1877 std::cout << "\e[32mPASS\e[0m" << std::endl;
1878 pass++;
1879 } else {
1880 std::cout << "\e[31mFAIL\e[0m" << std::endl;
1881 fail++;
1883 } catch(JSON::error& e) {
1884 if(e.get_code() == tests[i].expect) {
1885 std::cout << "\e[32mPASS\e[0m" << std::endl;
1886 pass++;
1887 } else {
1888 std::cout << "\e[31mERR: " << e.what() << "\e[0m" << std::endl;
1889 fail++;
1891 } catch(std::exception& e) {
1892 std::cout << "\e[31mERR: " << e.what() << "\e[0m" << std::endl;
1893 fail++;
1895 total++;
1898 int main(int argc, char** argv)
1900 size_t total = 0;
1901 size_t pass = 0;
1902 size_t fail = 0;
1903 if(argc == 1)
1904 for(size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
1905 run_test(i, total, pass, fail);
1906 else
1907 for(int i = 1; i < argc; i++)
1908 run_test(parse_value<unsigned>(argv[i]) - 1, total, pass, fail);
1909 std::cout << "Total: " << total << " Pass: " << pass << " Fail: " << fail << std::endl;
1910 return (fail != 0);