9662d2106efdcaf17b9976651f66853fdf0fb622
[src/app-framework-binder.git] / src / tests / wrap-json / test-wrap-json.c
1 /*
2  Copyright (C) 2016-2019 "IoT.bzh"
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #include <string.h>
20 #include <limits.h>
21 #include <stdio.h>
22
23 #include "wrap-json.h"
24 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
25 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
26 #endif
27
28
29 void tclone(struct json_object *object)
30 {
31         struct json_object *o;
32
33         o = wrap_json_clone(object);
34         if (!wrap_json_equal(object, o))
35                 printf("ERROR in clone or equal: %s VERSUS %s\n", json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE), json_object_to_json_string_ext(o, JSON_C_TO_STRING_NOSLASHESCAPE));
36         json_object_put(o);
37
38         o = wrap_json_clone_deep(object);
39         if (!wrap_json_equal(object, o))
40                 printf("ERROR in clone_deep or equal: %s VERSUS %s\n", json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE), json_object_to_json_string_ext(o, JSON_C_TO_STRING_NOSLASHESCAPE));
41         json_object_put(o);
42 }
43
44
45 void objcb(void *closure, struct json_object *obj, const char *key)
46 {
47         const char *prefix = closure;
48         printf("  %s {%s} %s\n", prefix ?: "", key ?: "[]", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_NOSLASHESCAPE));
49 }
50
51 void arrcb(void *closure, struct json_object *obj)
52 {
53         objcb(closure, obj, NULL);
54 }
55
56 void tforall(struct json_object *object)
57 {
58         wrap_json_for_all(object, objcb, "wrap_json_for_all");
59         wrap_json_optobject_for_all(object, objcb, "wrap_json_optobject_for_all");
60         wrap_json_object_for_all(object, objcb, "wrap_json_object_for_all");
61         wrap_json_optarray_for_all(object, arrcb, "wrap_json_optarray_for_all");
62         wrap_json_array_for_all(object, arrcb, "wrap_json_array_for_all");
63 }
64
65 struct mix
66 {
67         int n;
68         struct json_object *pair[2];
69 };
70
71 void mixcb(void *closure, struct json_object *obj, const char *key)
72 {
73         struct mix *mix = closure;
74
75         if (!mix->n) {
76                 mix->pair[0] = json_object_new_object();
77                 mix->pair[1] = json_object_new_object();
78         }
79         json_object_object_add(mix->pair[mix->n & 1], key, json_object_get(obj));
80         mix->n++;
81 }
82
83 void tmix(struct json_object *object)
84 {
85         struct json_object *z;
86         struct mix mix = { .n = 0 };
87
88         wrap_json_object_for_all(object, mixcb, &mix);
89         if (mix.n) {
90                 z = wrap_json_object_add(wrap_json_clone(mix.pair[0]), mix.pair[1]);
91                 if (!wrap_json_contains(z, mix.pair[0]))
92                         printf("  ERROR mix/1\n");
93                 if (!wrap_json_contains(z, mix.pair[1]))
94                         printf("  ERROR mix/2\n");
95                 if (!wrap_json_contains(z, object))
96                         printf("  ERROR mix/3\n");
97                 if (!wrap_json_contains(object, z))
98                         printf("  ERROR mix/4\n");
99                 if (!wrap_json_equal(object, z))
100                         printf("  ERROR mix/5\n");
101                 json_object_put(z);
102                 json_object_put(mix.pair[0]);
103                 json_object_put(mix.pair[1]);
104         }
105 }
106
107 void p(const char *desc, ...)
108 {
109         int rc;
110         va_list args;
111         struct json_object *result;
112
113         va_start(args, desc);
114         rc = wrap_json_vpack(&result, desc, args);
115         va_end(args);
116         if (!rc)
117                 printf("  SUCCESS %s\n\n", json_object_to_json_string_ext(result, JSON_C_TO_STRING_NOSLASHESCAPE));
118         else
119                 printf("  ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
120         tclone(result);
121         json_object_put(result);
122 }
123
124 const char *xs[10];
125 int *xi[10];
126 int64_t *xI[10];
127 double *xf[10];
128 struct json_object *xo[10];
129 size_t xz[10];
130 uint8_t *xy[10];
131
132 int extrchk(const char *desc, const char **array, int length, va_list args)
133 {
134         unsigned m, k;
135         int n;
136
137         if (!desc)
138                 return 0;
139
140         n = 0;
141         k = m = 0;
142         while(*desc) {
143                 switch(*desc) {
144                 case '{':
145                 case '[': k = !(*desc - '{'); m = (m << 1) | k; break;
146                 case '}':
147                 case ']': m = m >> 1; k = m&1; break;
148                 case 's':
149                         if (!k)
150                                 (void)va_arg(args, char**);
151                         else {
152                                 if (n > length)
153                                         return -1;
154                                 array[n++] = va_arg(args, const char*);
155                         }
156                         break;
157                 case '%': (void)va_arg(args, size_t*); k = m&1; break;
158                 case 'n': k = m&1; break;
159                 case 'b':
160                 case 'i': (void)va_arg(args, int*); k = m&1; break;
161                 case 'I': (void)va_arg(args, int64_t*); k = m&1; break;
162                 case 'f':
163                 case 'F': (void)va_arg(args, double*); k = m&1; break;
164                 case 'o': (void)va_arg(args, struct json_object**), k = m&1; break;
165                 case 'O': (void)va_arg(args, struct json_object**); k = m&1; break;
166                 case 'y':
167                 case 'Y':
168                         (void)va_arg(args, uint8_t**);
169                         (void)va_arg(args, size_t*);
170                         k = m&1;
171                         break;
172                 default:
173                         break;
174                 }
175                 desc++;
176         }
177         return n;
178 }
179
180 const char *mkeys[5];
181
182 void tchk(struct json_object *object, const char *desc, const char **keys, int length, int qrc)
183 {
184         int rm, rc;
185
186         rm = wrap_json_match(object, desc, keys[0], keys[1], keys[2], keys[3], keys[4]);
187         rc = wrap_json_check(object, desc, keys[0], keys[1], keys[2], keys[3], keys[4]);
188         if (rc != qrc)
189                 printf("  ERROR DIFFERS[char %d err %d] %s\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
190         if (rm != !rc)
191                 printf("  ERROR OF MATCH\n");
192 }
193
194 void u(const char *value, const char *desc, ...)
195 {
196         unsigned m, k;
197         int rc, n;
198         va_list args;
199         const char *d;
200         struct json_object *object, *o;
201
202         memset(xs, 0, sizeof xs);
203         memset(xi, 0, sizeof xi);
204         memset(xI, 0, sizeof xI);
205         memset(xf, 0, sizeof xf);
206         memset(xo, 0, sizeof xo);
207         memset(xy, 0, sizeof xy);
208         memset(xz, 0, sizeof xz);
209         object = json_tokener_parse(value);
210         va_start(args, desc);
211         rc = wrap_json_vunpack(object, desc, args);
212         va_end(args);
213         if (rc)
214                 printf("  ERROR[char %d err %d] %s", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
215         else {
216                 value = NULL;
217                 printf("  SUCCESS");
218                 d = desc;
219                 va_start(args, desc);
220                 k = m = 0;
221                 while(*d) {
222                         switch(*d) {
223                         case '{': m = (m << 1) | 1; k = 1; break;
224                         case '}': m = m >> 1; k = m&1; break;
225                         case '[': m = m << 1; k = 0; break;
226                         case ']': m = m >> 1; k = m&1; break;
227                         case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
228                         case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
229                         case 'n': printf(" n"); k = m&1; break;
230                         case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
231                         case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
232                         case 'I': printf(" I:%lld", (long long int)*va_arg(args, int64_t*)); k = m&1; break;
233                         case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
234                         case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
235                         case 'o': printf(" o:%s", json_object_to_json_string_ext(*va_arg(args, struct json_object**), JSON_C_TO_STRING_NOSLASHESCAPE)); k = m&1; break;
236                         case 'O': o = *va_arg(args, struct json_object**); printf(" O:%s", json_object_to_json_string_ext(o, JSON_C_TO_STRING_NOSLASHESCAPE)); json_object_put(o); k = m&1; break;
237                         case 'y':
238                         case 'Y': {
239                                 uint8_t *p = *va_arg(args, uint8_t**);
240                                 size_t s = *va_arg(args, size_t*);
241                                 printf(" y/%d:%.*s", (int)s, (int)s, (char*)p);
242                                 k = m&1;
243                                 break;
244                                 }
245                         default: break;
246                         }
247                         d++;
248                 }
249                 va_end(args);
250         }
251         printf("\n");
252         va_start(args, desc);
253         n = extrchk(desc, mkeys, (int)(sizeof mkeys / sizeof *mkeys), args);
254         va_end(args);
255         if (n < 0)
256                 printf("  ERROR: too much keys in %s\n", desc);
257         else
258                 tchk(object, desc, mkeys, n, rc);
259         tclone(object);
260         tforall(object);
261         tmix(object);
262         printf("\n");
263         json_object_put(object);
264 }
265
266 void c(const char *sx, const char *sy, int e, int c)
267 {
268         int re, rc;
269         struct json_object *jx, *jy;
270
271         jx = json_tokener_parse(sx);
272         jy = json_tokener_parse(sy);
273
274         re = wrap_json_cmp(jx, jy);
275         rc = wrap_json_contains(jx, jy);
276
277         printf("compare(%s)(%s)\n", sx, sy);
278         printf("   -> %d / %d\n", re, rc);
279
280         if (!re != !!e)
281                 printf("  ERROR should be %s\n", e ? "equal" : "different");
282         if (!rc != !c)
283                 printf("  ERROR should %scontain\n", c ? "" : "not ");
284
285         printf("\n");
286 }
287
288 #define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
289 #define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
290
291 int main()
292 {
293         char buffer[4] = {'t', 'e', 's', 't'};
294
295         P("n");
296         P("b", 1);
297         P("b", 0);
298         P("i", 1);
299         P("I", (uint64_t)0x123456789abcdef);
300         P("f", 3.14);
301         P("s", "test");
302         P("s?", "test");
303         P("s?", NULL);
304         P("s#", "test asdf", 4);
305         P("s%", "test asdf", (size_t)4);
306         P("s#", buffer, 4);
307         P("s%", buffer, (size_t)4);
308         P("s++", "te", "st", "ing");
309         P("s#+#+", "test", 1, "test", 2, "test");
310         P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
311         P("{}", 1.0);
312         P("[]", 1.0);
313         P("o", json_object_new_int(1));
314         P("o?", json_object_new_int(1));
315         P("o?", NULL);
316         P("O", json_object_new_int(1));
317         P("O?", json_object_new_int(1));
318         P("O?", NULL);
319         P("{s:[]}", "foo");
320         P("{s+#+: []}", "foo", "barbar", 3, "baz");
321         P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
322         P("{s:**}", "a", NULL);
323         P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
324         P("[i,i,i]", 0, 1, 2);
325         P("[s,o,O]", NULL, NULL, NULL);
326         P("[**]", NULL);
327         P("[s*,o*,O*]", NULL, NULL, NULL);
328         P(" s ", "test");
329         P("[ ]");
330         P("[ i , i,  i ] ", 1, 2, 3);
331         P("{\n\n1");
332         P("[}");
333         P("{]");
334         P("[");
335         P("{");
336         P("[i]a", 42);
337         P("ia", 42);
338         P("s", NULL);
339         P("+", NULL);
340         P(NULL);
341         P("{s:i}", NULL, 1);
342         P("{ {}: s }", "foo");
343         P("{ s: {},  s:[ii{} }", "foo", "bar", 12, 13);
344         P("[[[[[   [[[[[  [[[[ }]]]] ]]]] ]]]]]");
345         P("y", "???????hello>>>>>>>", (size_t)19);
346         P("Y", "???????hello>>>>>>>", (size_t)19);
347         P("{sy?}", "foo", "hi", (size_t)2);
348         P("{sy?}", "foo", NULL, 0);
349         P("{sy*}", "foo", "hi", (size_t)2);
350         P("{sy*}", "foo", NULL, 0);
351
352         U("true", "b", &xi[0]);
353         U("false", "b", &xi[0]);
354         U("null", "n");
355         U("42", "i", &xi[0]);
356         U("123456789", "I", &xI[0]);
357         U("3.14", "f", &xf[0]);
358         U("12345", "F", &xf[0]);
359         U("3.14", "F", &xf[0]);
360         U("\"foo\"", "s", &xs[0]);
361         U("\"foo\"", "s%", &xs[0], &xz[0]);
362         U("{}", "{}");
363         U("[]", "[]");
364         U("{}", "o", &xo[0]);
365         U("{}", "O", &xo[0]);
366         U("{\"foo\":42}", "{si}", "foo", &xi[0]);
367         U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
368         U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
369         U("42", "z");
370         U("null", "[i]");
371         U("[]", "[}");
372         U("{}", "{]");
373         U("[]", "[");
374         U("{}", "{");
375         U("[42]", "[i]a", &xi[0]);
376         U("42", "ia", &xi[0]);
377         U("[]", NULL);
378         U("\"foo\"", "s", NULL);
379         U("42", "s", NULL);
380         U("42", "n");
381         U("42", "b", NULL);
382         U("42", "f", NULL);
383         U("42", "[i]", NULL);
384         U("42", "{si}", "foo", NULL);
385         U("\"foo\"", "n");
386         U("\"foo\"", "b", NULL);
387         U("\"foo\"", "i", NULL);
388         U("\"foo\"", "I", NULL);
389         U("\"foo\"", "f", NULL);
390         U("\"foo\"", "F", NULL);
391         U("true", "s", NULL);
392         U("true", "n");
393         U("true", "i", NULL);
394         U("true", "I", NULL);
395         U("true", "f", NULL);
396         U("true", "F", NULL);
397         U("[42]", "[ii]", &xi[0], &xi[1]);
398         U("{\"foo\":42}", "{si}", NULL, &xi[0]);
399         U("{\"foo\":42}", "{si}", "baz", &xi[0]);
400         U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
401         U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
402         U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
403         U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
404         U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
405         U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
406         U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
407         U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
408         U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
409         U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
410         U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
411         U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
412         U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
413         U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
414         U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
415         U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
416         U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
417         U("{}", "{s?i}", "foo", &xi[0]);
418         U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
419         U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
420         U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
421         U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
422         U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
423         U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
424         U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
425         U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
426         U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
427
428         U("\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"", "y", &xy[0], &xz[0]);
429         U("\"\"", "y", &xy[0], &xz[0]);
430         U("null", "y", &xy[0], &xz[0]);
431         U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
432         U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
433         U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
434
435         c("null", "null", 1, 1);
436         c("true", "true", 1, 1);
437         c("false", "false", 1, 1);
438         c("1", "1", 1, 1);
439         c("1.0", "1.0", 1, 1);
440         c("\"\"", "\"\"", 1, 1);
441         c("\"hi\"", "\"hi\"", 1, 1);
442         c("{}", "{}", 1, 1);
443         c("{\"a\":true,\"b\":false}", "{\"b\":false,\"a\":true}", 1, 1);
444         c("[]", "[]", 1, 1);
445         c("[1,true,null]", "[1,true,null]", 1, 1);
446
447         c("null", "true", 0, 0);
448         c("null", "false", 0, 0);
449         c("0", "1", 0, 0);
450         c("1", "0", 0, 0);
451         c("0", "true", 0, 0);
452         c("0", "false", 0, 0);
453         c("0", "null", 0, 0);
454
455         c("\"hi\"", "\"hello\"", 0, 0);
456         c("\"hello\"", "\"hi\"", 0, 0);
457
458         c("{}", "null", 0, 0);
459         c("{}", "true", 0, 0);
460         c("{}", "1", 0, 0);
461         c("{}", "1.0", 0, 0);
462         c("{}", "[]", 0, 0);
463         c("{}", "\"x\"", 0, 0);
464
465         c("[1,true,null]", "[1,true]", 0, 1);
466         c("{\"a\":true,\"b\":false}", "{\"a\":true}", 0, 1);
467         c("{\"a\":true,\"b\":false}", "{\"a\":true,\"c\":false}", 0, 0);
468         c("{\"a\":true,\"c\":false}", "{\"a\":true,\"b\":false}", 0, 0);
469
470         return 0;
471 }