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