1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <string.h>
7 #include <zephyr/types.h>
8 #include <stdbool.h>
9 #include <zephyr/ztest.h>
10 #include <zephyr/data/json.h>
11
12 struct test_nested {
13 int nested_int;
14 bool nested_bool;
15 const char *nested_string;
16 int64_t nested_int64;
17 uint64_t nested_uint64;
18 };
19
20 struct test_struct {
21 const char *some_string;
22 int some_int;
23 bool some_bool;
24 int64_t some_int64;
25 int64_t another_int64;
26 int64_t some_uint64;
27 int64_t another_uint64;
28 struct test_nested some_nested_struct;
29 int some_array[16];
30 size_t some_array_len;
31 bool another_bxxl; /* JSON field: "another_b!@l" */
32 bool if_; /* JSON: "if" */
33 int another_array[10]; /* JSON: "another-array" */
34 size_t another_array_len;
35 struct test_nested xnother_nexx; /* JSON: "4nother_ne$+" */
36 struct test_nested nested_obj_array[2];
37 size_t obj_array_len;
38 };
39
40 struct elt {
41 const char *name;
42 int height;
43 };
44
45 struct obj_array {
46 struct elt elements[10];
47 size_t num_elements;
48 };
49
50 struct test_int_limits {
51 int int_max;
52 int int_cero;
53 int int_min;
54 int64_t int64_max;
55 int64_t int64_cero;
56 int64_t int64_min;
57 uint64_t uint64_max;
58 uint64_t uint64_cero;
59 uint64_t uint64_min;
60 };
61
62 static const struct json_obj_descr nested_descr[] = {
63 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int, JSON_TOK_NUMBER),
64 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_bool, JSON_TOK_TRUE),
65 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_string,
66 JSON_TOK_STRING),
67 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int64,
68 JSON_TOK_INT64),
69 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_uint64,
70 JSON_TOK_UINT64),
71 };
72
73 static const struct json_obj_descr test_descr[] = {
74 JSON_OBJ_DESCR_PRIM(struct test_struct, some_string, JSON_TOK_STRING),
75 JSON_OBJ_DESCR_PRIM(struct test_struct, some_int, JSON_TOK_NUMBER),
76 JSON_OBJ_DESCR_PRIM(struct test_struct, some_bool, JSON_TOK_TRUE),
77 JSON_OBJ_DESCR_PRIM(struct test_struct, some_int64,
78 JSON_TOK_INT64),
79 JSON_OBJ_DESCR_PRIM(struct test_struct, another_int64,
80 JSON_TOK_INT64),
81 JSON_OBJ_DESCR_PRIM(struct test_struct, some_uint64,
82 JSON_TOK_UINT64),
83 JSON_OBJ_DESCR_PRIM(struct test_struct, another_uint64,
84 JSON_TOK_UINT64),
85 JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct,
86 nested_descr),
87 JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array,
88 16, some_array_len, JSON_TOK_NUMBER),
89 JSON_OBJ_DESCR_PRIM_NAMED(struct test_struct, "another_b!@l",
90 another_bxxl, JSON_TOK_TRUE),
91 JSON_OBJ_DESCR_PRIM_NAMED(struct test_struct, "if",
92 if_, JSON_TOK_TRUE),
93 JSON_OBJ_DESCR_ARRAY_NAMED(struct test_struct, "another-array",
94 another_array, 10, another_array_len,
95 JSON_TOK_NUMBER),
96 JSON_OBJ_DESCR_OBJECT_NAMED(struct test_struct, "4nother_ne$+",
97 xnother_nexx, nested_descr),
98 JSON_OBJ_DESCR_OBJ_ARRAY(struct test_struct, nested_obj_array, 2,
99 obj_array_len, nested_descr, ARRAY_SIZE(nested_descr)),
100 };
101
102 static const struct json_obj_descr elt_descr[] = {
103 JSON_OBJ_DESCR_PRIM(struct elt, name, JSON_TOK_STRING),
104 JSON_OBJ_DESCR_PRIM(struct elt, height, JSON_TOK_NUMBER),
105 };
106
107 static const struct json_obj_descr obj_array_descr[] = {
108 JSON_OBJ_DESCR_OBJ_ARRAY(struct obj_array, elements, 10, num_elements,
109 elt_descr, ARRAY_SIZE(elt_descr)),
110 };
111
112 static const struct json_obj_descr obj_limits_descr[] = {
113 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int_max, JSON_TOK_NUMBER),
114 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int_cero, JSON_TOK_NUMBER),
115 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int_min, JSON_TOK_NUMBER),
116 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_max, JSON_TOK_INT64),
117 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_cero, JSON_TOK_INT64),
118 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_min, JSON_TOK_INT64),
119 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_max, JSON_TOK_UINT64),
120 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_cero, JSON_TOK_UINT64),
121 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_min, JSON_TOK_UINT64),
122 };
123
124 struct array {
125 struct elt objects;
126 };
127
128 struct obj_array_array {
129 struct array objects_array[4];
130 size_t objects_array_len;
131 };
132
133 static const struct json_obj_descr array_descr[] = {
134 JSON_OBJ_DESCR_OBJECT(struct array, objects, elt_descr),
135 };
136
137 static const struct json_obj_descr array_array_descr[] = {
138 JSON_OBJ_DESCR_ARRAY_ARRAY(struct obj_array_array, objects_array, 4,
139 objects_array_len, array_descr,
140 ARRAY_SIZE(array_descr)),
141 };
142
143 struct obj_array_2dim {
144 struct obj_array objects_array_array[3];
145 size_t objects_array_array_len;
146 };
147
148 static const struct json_obj_descr array_2dim_descr[] = {
149 JSON_OBJ_DESCR_ARRAY_ARRAY(struct obj_array_2dim, objects_array_array, 3,
150 objects_array_array_len, obj_array_descr,
151 ARRAY_SIZE(obj_array_descr)),
152 };
153
154 struct obj_array_2dim_extra {
155 const char *name;
156 int val;
157 struct obj_array_2dim obj_array_2dim;
158 };
159
160 static const struct json_obj_descr array_2dim_extra_descr[] = {
161 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, name, JSON_TOK_STRING),
162 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, val, JSON_TOK_NUMBER),
163 JSON_OBJ_DESCR_ARRAY_ARRAY(struct obj_array_2dim_extra, obj_array_2dim, 3,
164 obj_array_2dim.objects_array_array_len, obj_array_descr,
165 ARRAY_SIZE(obj_array_descr)),
166 };
167
168 static const struct json_obj_descr array_2dim_extra_named_descr[] = {
169 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, name, JSON_TOK_STRING),
170 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, val, JSON_TOK_NUMBER),
171 JSON_OBJ_DESCR_ARRAY_ARRAY_NAMED(struct obj_array_2dim_extra, data, obj_array_2dim, 3,
172 obj_array_2dim.objects_array_array_len, obj_array_descr,
173 ARRAY_SIZE(obj_array_descr)),
174 };
175
176 struct test_json_tok_encoded_obj {
177 const char *encoded_obj;
178 int ok;
179 };
180
181 static const struct json_obj_descr test_json_tok_encoded_obj_descr[] = {
182 JSON_OBJ_DESCR_PRIM(struct test_json_tok_encoded_obj, encoded_obj, JSON_TOK_ENCODED_OBJ),
183 JSON_OBJ_DESCR_PRIM(struct test_json_tok_encoded_obj, ok, JSON_TOK_NUMBER),
184 };
185
186 struct test_element {
187 int int1;
188 int int2;
189 int int3;
190 };
191
192 struct test_outer {
193 struct test_element array[5];
194 size_t num_elements;
195 };
196
197 static const struct json_obj_descr element_descr[] = {
198 JSON_OBJ_DESCR_PRIM(struct test_element, int1, JSON_TOK_NUMBER),
199 JSON_OBJ_DESCR_PRIM(struct test_element, int2, JSON_TOK_NUMBER),
200 JSON_OBJ_DESCR_PRIM(struct test_element, int3, JSON_TOK_NUMBER),
201 };
202
203 static const struct json_obj_descr outer_descr[] = {
204 JSON_OBJ_DESCR_OBJ_ARRAY(struct test_outer, array, 5,
205 num_elements, element_descr, ARRAY_SIZE(element_descr))
206 };
207
ZTEST(lib_json_test,test_json_encoding)208 ZTEST(lib_json_test, test_json_encoding)
209 {
210 struct test_struct ts = {
211 .some_string = "zephyr 123\uABCD",
212 .some_int = 42,
213 .some_int64 = 1152921504606846977,
214 .another_int64 = -2305843009213693937,
215 .some_uint64 = 18446744073709551615U,
216 .another_uint64 = 0,
217 .some_bool = true,
218 .some_nested_struct = {
219 .nested_int = -1234,
220 .nested_bool = false,
221 .nested_string = "this should be escaped: \t",
222 .nested_int64 = 4503599627370496,
223 .nested_uint64 = 18446744073709551610U,
224 },
225 .some_array[0] = 1,
226 .some_array[1] = 4,
227 .some_array[2] = 8,
228 .some_array[3] = 16,
229 .some_array[4] = 32,
230 .some_array_len = 5,
231 .another_bxxl = true,
232 .if_ = false,
233 .another_array[0] = 2,
234 .another_array[1] = 3,
235 .another_array[2] = 5,
236 .another_array[3] = 7,
237 .another_array_len = 4,
238 .xnother_nexx = {
239 .nested_int = 1234,
240 .nested_bool = true,
241 .nested_string = "no escape necessary",
242 .nested_int64 = 4503599627370496,
243 .nested_uint64 = 18446744073709551610U,
244 },
245 .nested_obj_array = {
246 {1, true, "true"},
247 {0, false, "false"}
248 },
249 .obj_array_len = 2
250 };
251 char encoded[] = "{\"some_string\":\"zephyr 123\uABCD\","
252 "\"some_int\":42,\"some_bool\":true,"
253 "\"some_int64\":1152921504606846977,"
254 "\"another_int64\":-2305843009213693937,"
255 "\"some_uint64\":18446744073709551615,"
256 "\"another_uint64\":0,"
257 "\"some_nested_struct\":{\"nested_int\":-1234,"
258 "\"nested_bool\":false,\"nested_string\":"
259 "\"this should be escaped: \\t\","
260 "\"nested_int64\":4503599627370496,"
261 "\"nested_uint64\":18446744073709551610},"
262 "\"some_array\":[1,4,8,16,32],"
263 "\"another_b!@l\":true,"
264 "\"if\":false,"
265 "\"another-array\":[2,3,5,7],"
266 "\"4nother_ne$+\":{\"nested_int\":1234,"
267 "\"nested_bool\":true,"
268 "\"nested_string\":\"no escape necessary\","
269 "\"nested_int64\":4503599627370496,"
270 "\"nested_uint64\":18446744073709551610},"
271 "\"nested_obj_array\":["
272 "{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_int64\":0,\"nested_uint64\":0},"
273 "{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_int64\":0,\"nested_uint64\":0}]"
274 "}";
275 char buffer[sizeof(encoded)];
276 int ret;
277 ssize_t len;
278
279 len = json_calc_encoded_len(test_descr, ARRAY_SIZE(test_descr), &ts);
280 zassert_equal(len, strlen(encoded), "encoded size mismatch");
281
282 ret = json_obj_encode_buf(test_descr, ARRAY_SIZE(test_descr),
283 &ts, buffer, sizeof(buffer));
284 zassert_equal(ret, 0, "Encoding function failed");
285
286 ret = strncmp(buffer, encoded, sizeof(encoded) - 1);
287 zassert_equal(ret, 0, "Encoded contents not consistent");
288 }
289
ZTEST(lib_json_test,test_json_decoding)290 ZTEST(lib_json_test, test_json_decoding)
291 {
292 struct test_struct ts;
293 char encoded[] = "{\"some_string\":\"zephyr 123\\uABCD456\","
294 "\"some_int\":\t42\n,"
295 "\"some_bool\":true \t "
296 "\n"
297 "\r ,"
298 "\"some_int64\":-4611686018427387904,"
299 "\"another_int64\":-2147483648,"
300 "\"some_uint64\":18446744073709551615,"
301 "\"another_uint64\":0,"
302 "\"some_nested_struct\":{ "
303 "\"nested_int\":-1234,\n\n"
304 "\"nested_bool\":false,\t"
305 "\"nested_string\":\"this should be escaped: \\t\","
306 "\"nested_int64\":9223372036854775807,"
307 "\"extra_nested_array\":[0,-1]},"
308 "\"extra_struct\":{\"nested_bool\":false},"
309 "\"extra_bool\":true,"
310 "\"some_array\":[11,22, 33,\t45,\n299],"
311 "\"another_b!@l\":true,"
312 "\"if\":false,"
313 "\"another-array\":[2,3,5,7],"
314 "\"4nother_ne$+\":{\"nested_int\":1234,"
315 "\"nested_bool\":true,"
316 "\"nested_string\":\"no escape necessary\","
317 "\"nested_int64\":-9223372036854775806},"
318 "\"nested_obj_array\":["
319 "{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\"},"
320 "{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\"}]"
321 "}\n";
322 const int expected_array[] = { 11, 22, 33, 45, 299 };
323 const int expected_other_array[] = { 2, 3, 5, 7 };
324 int ret;
325
326 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
327 ARRAY_SIZE(test_descr), &ts);
328
329 zassert_equal(ret, (1 << ARRAY_SIZE(test_descr)) - 1,
330 "Not all fields decoded correctly");
331
332 zassert_str_equal(ts.some_string, "zephyr 123\\uABCD456",
333 "String not decoded correctly");
334 zassert_equal(ts.some_int, 42, "Positive integer not decoded correctly");
335 zassert_equal(ts.some_bool, true, "Boolean not decoded correctly");
336 zassert_equal(ts.some_int64, -4611686018427387904,
337 "int64 not decoded correctly");
338 zassert_equal(ts.another_int64, -2147483648,
339 "int64 not decoded correctly");
340 zassert_equal(ts.some_nested_struct.nested_int, -1234,
341 "Nested negative integer not decoded correctly");
342 zassert_equal(ts.some_nested_struct.nested_int64, 9223372036854775807,
343 "Nested int64 not decoded correctly");
344 zassert_equal(ts.some_nested_struct.nested_bool, false,
345 "Nested boolean value not decoded correctly");
346 zassert_str_equal(ts.some_nested_struct.nested_string,
347 "this should be escaped: \\t",
348 "Nested string not decoded correctly");
349 zassert_equal(ts.some_array_len, 5,
350 "Array doesn't have correct number of items");
351 zassert_true(!memcmp(ts.some_array, expected_array,
352 sizeof(expected_array)),
353 "Array not decoded with expected values");
354 zassert_true(ts.another_bxxl,
355 "Named boolean (special chars) not decoded correctly");
356 zassert_false(ts.if_,
357 "Named boolean (reserved word) not decoded correctly");
358 zassert_equal(ts.another_array_len, 4,
359 "Named array does not have correct number of items");
360 zassert_true(!memcmp(ts.another_array, expected_other_array,
361 sizeof(expected_other_array)),
362 "Decoded named array not with expected values");
363 zassert_equal(ts.xnother_nexx.nested_int, 1234,
364 "Named nested integer not decoded correctly");
365 zassert_equal(ts.xnother_nexx.nested_int64, -9223372036854775806,
366 "Named nested int64 not decoded correctly");
367 zassert_equal(ts.xnother_nexx.nested_bool, true,
368 "Named nested boolean not decoded correctly");
369 zassert_str_equal(ts.xnother_nexx.nested_string,
370 "no escape necessary",
371 "Named nested string not decoded correctly");
372 zassert_equal(ts.obj_array_len, 2,
373 "Array of objects does not have correct number of items");
374 zassert_equal(ts.nested_obj_array[0].nested_int, 1,
375 "Integer in first object array element not decoded correctly");
376 zassert_equal(ts.nested_obj_array[0].nested_bool, true,
377 "Boolean value in first object array element not decoded correctly");
378 zassert_str_equal(ts.nested_obj_array[0].nested_string, "true",
379 "String in first object array element not decoded correctly");
380 zassert_equal(ts.nested_obj_array[1].nested_int, 0,
381 "Integer in second object array element not decoded correctly");
382 zassert_equal(ts.nested_obj_array[1].nested_bool, false,
383 "Boolean value in second object array element not decoded correctly");
384 zassert_str_equal(ts.nested_obj_array[1].nested_string, "false",
385 "String in second object array element not decoded correctly");
386 }
387
ZTEST(lib_json_test,test_json_limits)388 ZTEST(lib_json_test, test_json_limits)
389 {
390 int ret = 0;
391 char encoded[] = "{\"int_max\":2147483647,"
392 "\"int_cero\":0,"
393 "\"int_min\":-2147483648,"
394 "\"int64_max\":9223372036854775807,"
395 "\"int64_cero\":0,"
396 "\"int64_min\":-9223372036854775808,"
397 "\"uint64_max\":18446744073709551615,"
398 "\"uint64_cero\":0,"
399 "\"uint64_min\":0"
400 "}";
401
402 struct test_int_limits limits = {
403 .int_max = INT_MAX,
404 .int_cero = 0,
405 .int_min = INT_MIN,
406 .int64_max = INT64_MAX,
407 .int64_cero = 0,
408 .int64_min = INT64_MIN,
409 .uint64_max = UINT64_MAX,
410 .uint64_cero = 0,
411 .uint64_min = 0,
412 };
413
414 char buffer[sizeof(encoded)];
415 struct test_int_limits limits_decoded = {0};
416
417 ret = json_obj_encode_buf(obj_limits_descr, ARRAY_SIZE(obj_limits_descr),
418 &limits, buffer, sizeof(buffer));
419 ret = json_obj_parse(encoded, sizeof(encoded) - 1, obj_limits_descr,
420 ARRAY_SIZE(obj_limits_descr), &limits_decoded);
421
422 zassert_str_equal(encoded, buffer,
423 "Integer limits not encoded correctly");
424 zassert_true(!memcmp(&limits, &limits_decoded, sizeof(limits)),
425 "Integer limits not decoded correctly");
426 }
427
ZTEST(lib_json_test,test_json_encoding_array_array)428 ZTEST(lib_json_test, test_json_encoding_array_array)
429 {
430 struct obj_array_array obj_array_array_ts = {
431 .objects_array = {
432 [0] = { { .name = "Sim\303\263n Bol\303\255var", .height = 168 } },
433 [1] = { { .name = "Pel\303\251", .height = 173 } },
434 [2] = { { .name = "Usain Bolt", .height = 195 } },
435 },
436 .objects_array_len = 3,
437 };
438 char encoded[] = "{\"objects_array\":["
439 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
440 "{\"name\":\"Pel\303\251\",\"height\":173},"
441 "{\"name\":\"Usain Bolt\",\"height\":195}"
442 "]}";
443 char buffer[sizeof(encoded)];
444 int ret;
445
446 ret = json_obj_encode_buf(array_array_descr, ARRAY_SIZE(array_array_descr),
447 &obj_array_array_ts, buffer, sizeof(buffer));
448 zassert_equal(ret, 0, "Encoding array returned error");
449 zassert_str_equal(buffer, encoded,
450 "Encoded array of objects is not consistent");
451 }
452
ZTEST(lib_json_test,test_json_decoding_array_array)453 ZTEST(lib_json_test, test_json_decoding_array_array)
454 {
455 int ret;
456 struct obj_array_array obj_array_array_ts;
457 char encoded[] = "{\"objects_array\":["
458 "{\"height\":168,\"name\":\"Sim\303\263n Bol\303\255var\"},"
459 "{\"height\":173,\"name\":\"Pel\303\251\"},"
460 "{\"height\":195,\"name\":\"Usain Bolt\"}]"
461 "}";
462
463 ret = json_obj_parse(encoded, sizeof(encoded),
464 array_array_descr,
465 ARRAY_SIZE(array_array_descr),
466 &obj_array_array_ts);
467
468 zassert_equal(ret, 1, "Encoding array of objects returned error");
469 zassert_equal(obj_array_array_ts.objects_array_len, 3,
470 "Array doesn't have correct number of items");
471
472 zassert_str_equal(obj_array_array_ts.objects_array[0].objects.name,
473 "Sim\303\263n Bol\303\255var",
474 "String not decoded correctly");
475 zassert_equal(obj_array_array_ts.objects_array[0].objects.height, 168,
476 "Sim\303\263n Bol\303\255var height not decoded correctly");
477
478 zassert_str_equal(obj_array_array_ts.objects_array[1].objects.name,
479 "Pel\303\251", "String not decoded correctly");
480 zassert_equal(obj_array_array_ts.objects_array[1].objects.height, 173,
481 "Pel\303\251 height not decoded correctly");
482
483 zassert_str_equal(obj_array_array_ts.objects_array[2].objects.name,
484 "Usain Bolt", "String not decoded correctly");
485 zassert_equal(obj_array_array_ts.objects_array[2].objects.height, 195,
486 "Usain Bolt height not decoded correctly");
487 }
488
ZTEST(lib_json_test,test_json_obj_arr_encoding)489 ZTEST(lib_json_test, test_json_obj_arr_encoding)
490 {
491 struct obj_array oa = {
492 .elements = {
493 [0] = { .name = "Sim\303\263n Bol\303\255var", .height = 168 },
494 [1] = { .name = "Muggsy Bogues", .height = 160 },
495 [2] = { .name = "Pel\303\251", .height = 173 },
496 [3] = { .name = "Hakeem Olajuwon", .height = 213 },
497 [4] = { .name = "Alex Honnold", .height = 180 },
498 [5] = { .name = "Hazel Findlay", .height = 157 },
499 [6] = { .name = "Daila Ojeda", .height = 158 },
500 [7] = { .name = "Albert Einstein", .height = 172 },
501 [8] = { .name = "Usain Bolt", .height = 195 },
502 [9] = { .name = "Paavo Nurmi", .height = 174 },
503 },
504 .num_elements = 10,
505 };
506 char encoded[] = "{\"elements\":["
507 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
508 "{\"name\":\"Muggsy Bogues\",\"height\":160},"
509 "{\"name\":\"Pel\303\251\",\"height\":173},"
510 "{\"name\":\"Hakeem Olajuwon\",\"height\":213},"
511 "{\"name\":\"Alex Honnold\",\"height\":180},"
512 "{\"name\":\"Hazel Findlay\",\"height\":157},"
513 "{\"name\":\"Daila Ojeda\",\"height\":158},"
514 "{\"name\":\"Albert Einstein\",\"height\":172},"
515 "{\"name\":\"Usain Bolt\",\"height\":195},"
516 "{\"name\":\"Paavo Nurmi\",\"height\":174}"
517 "]}";
518 char buffer[sizeof(encoded)];
519 int ret;
520
521 ret = json_obj_encode_buf(obj_array_descr, ARRAY_SIZE(obj_array_descr),
522 &oa, buffer, sizeof(buffer));
523 zassert_equal(ret, 0, "Encoding array of object returned error");
524 zassert_str_equal(buffer, encoded,
525 "Encoded array of objects is not consistent");
526 }
527
ZTEST(lib_json_test,test_json_arr_obj_decoding)528 ZTEST(lib_json_test, test_json_arr_obj_decoding)
529 {
530 int ret;
531 struct obj_array obj_array_array_ts;
532 char encoded[] = "[{\"height\":168,\"name\":\"Sim\303\263n Bol\303\255var\"},"
533 "{\"height\":173,\"name\":\"Pel\303\251\"},"
534 "{\"height\":195,\"name\":\"Usain Bolt\"}"
535 "]";
536
537 ret = json_arr_parse(encoded, sizeof(encoded),
538 obj_array_descr,
539 &obj_array_array_ts);
540
541 zassert_equal(ret, 0, "Encoding array of objects returned error %d", ret);
542 zassert_equal(obj_array_array_ts.num_elements, 3,
543 "Array doesn't have correct number of items");
544
545 zassert_str_equal(obj_array_array_ts.elements[0].name,
546 "Sim\303\263n Bol\303\255var",
547 "String not decoded correctly");
548 zassert_equal(obj_array_array_ts.elements[0].height, 168,
549 "Sim\303\263n Bol\303\255var height not decoded correctly");
550
551 zassert_str_equal(obj_array_array_ts.elements[1].name, "Pel\303\251",
552 "String not decoded correctly");
553 zassert_equal(obj_array_array_ts.elements[1].height, 173,
554 "Pel\303\251 height not decoded correctly");
555
556 zassert_str_equal(obj_array_array_ts.elements[2].name, "Usain Bolt",
557 "String not decoded correctly");
558 zassert_equal(obj_array_array_ts.elements[2].height, 195,
559 "Usain Bolt height not decoded correctly");
560 }
561
ZTEST(lib_json_test,test_json_arr_obj_encoding)562 ZTEST(lib_json_test, test_json_arr_obj_encoding)
563 {
564 struct obj_array oa = {
565 .elements = {
566 [0] = { .name = "Sim\303\263n Bol\303\255var", .height = 168 },
567 [1] = { .name = "Muggsy Bogues", .height = 160 },
568 [2] = { .name = "Pel\303\251", .height = 173 },
569 [3] = { .name = "Hakeem Olajuwon", .height = 213 },
570 [4] = { .name = "Alex Honnold", .height = 180 },
571 [5] = { .name = "Hazel Findlay", .height = 157 },
572 [6] = { .name = "Daila Ojeda", .height = 158 },
573 [7] = { .name = "Albert Einstein", .height = 172 },
574 [8] = { .name = "Usain Bolt", .height = 195 },
575 [9] = { .name = "Paavo Nurmi", .height = 174 },
576 },
577 .num_elements = 10,
578 };
579 char encoded[] = "["
580 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
581 "{\"name\":\"Muggsy Bogues\",\"height\":160},"
582 "{\"name\":\"Pel\303\251\",\"height\":173},"
583 "{\"name\":\"Hakeem Olajuwon\",\"height\":213},"
584 "{\"name\":\"Alex Honnold\",\"height\":180},"
585 "{\"name\":\"Hazel Findlay\",\"height\":157},"
586 "{\"name\":\"Daila Ojeda\",\"height\":158},"
587 "{\"name\":\"Albert Einstein\",\"height\":172},"
588 "{\"name\":\"Usain Bolt\",\"height\":195},"
589 "{\"name\":\"Paavo Nurmi\",\"height\":174}"
590 "]";
591 char buffer[sizeof(encoded)];
592 int ret;
593 ssize_t len;
594
595 len = json_calc_encoded_arr_len(obj_array_descr, &oa);
596 zassert_equal(len, strlen(encoded), "encoded size mismatch");
597
598 ret = json_arr_encode_buf(obj_array_descr, &oa, buffer, sizeof(buffer));
599 zassert_equal(ret, 0, "Encoding array of object returned error %d", ret);
600 zassert_str_equal(buffer, encoded,
601 "Encoded array of objects is not consistent");
602 }
603
ZTEST(lib_json_test,test_json_obj_arr_decoding)604 ZTEST(lib_json_test, test_json_obj_arr_decoding)
605 {
606 struct obj_array oa;
607 char encoded[] = "{\"elements\":["
608 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
609 "{\"name\":\"Muggsy Bogues\",\"height\":160},"
610 "{\"name\":\"Pel\303\251\",\"height\":173},"
611 "{\"name\":\"Hakeem Olajuwon\",\"height\":213},"
612 "{\"name\":\"Alex Honnold\",\"height\":180},"
613 "{\"name\":\"Hazel Findlay\",\"height\":157},"
614 "{\"name\":\"Daila Ojeda\",\"height\":158},"
615 "{\"name\":\"Albert Einstein\",\"height\":172},"
616 "{\"name\":\"Usain Bolt\",\"height\":195},"
617 "{\"name\":\"Paavo Nurmi\",\"height\":174}"
618 "]}";
619 const struct obj_array expected = {
620 .elements = {
621 [0] = { .name = "Sim\303\263n Bol\303\255var", .height = 168 },
622 [1] = { .name = "Muggsy Bogues", .height = 160 },
623 [2] = { .name = "Pel\303\251", .height = 173 },
624 [3] = { .name = "Hakeem Olajuwon", .height = 213 },
625 [4] = { .name = "Alex Honnold", .height = 180 },
626 [5] = { .name = "Hazel Findlay", .height = 157 },
627 [6] = { .name = "Daila Ojeda", .height = 158 },
628 [7] = { .name = "Albert Einstein", .height = 172 },
629 [8] = { .name = "Usain Bolt", .height = 195 },
630 [9] = { .name = "Paavo Nurmi", .height = 174 },
631 },
632 .num_elements = 10,
633 };
634 int ret;
635
636 ret = json_obj_parse(encoded, sizeof(encoded) - 1, obj_array_descr,
637 ARRAY_SIZE(obj_array_descr), &oa);
638
639 zassert_equal(ret, (1 << ARRAY_SIZE(obj_array_descr)) - 1,
640 "Array of object fields not decoded correctly");
641 zassert_equal(oa.num_elements, 10,
642 "Number of object fields not decoded correctly");
643
644 for (int i = 0; i < expected.num_elements; i++) {
645 zassert_true(!strcmp(oa.elements[i].name,
646 expected.elements[i].name),
647 "Element %d name not decoded correctly", i);
648 zassert_equal(oa.elements[i].height,
649 expected.elements[i].height,
650 "Element %d height not decoded correctly", i);
651 }
652 }
653
ZTEST(lib_json_test,test_json_2dim_arr_obj_encoding)654 ZTEST(lib_json_test, test_json_2dim_arr_obj_encoding)
655 {
656 struct obj_array_2dim obj_array_array_ts = {
657 .objects_array_array = {
658 [0] = {
659 .elements = {
660 [0] = {
661 .name = "Sim\303\263n Bol\303\255var",
662 .height = 168
663 },
664 [1] = {
665 .name = "Pel\303\251",
666 .height = 173
667 },
668 [2] = {
669 .name = "Usain Bolt",
670 .height = 195
671 },
672 },
673 .num_elements = 3
674 },
675 [1] = {
676 .elements = {
677 [0] = {
678 .name = "Muggsy Bogues",
679 .height = 160
680 },
681 [1] = {
682 .name = "Hakeem Olajuwon",
683 .height = 213
684 },
685 },
686 .num_elements = 2
687 },
688 [2] = {
689 .elements = {
690 [0] = {
691 .name = "Alex Honnold",
692 .height = 180
693 },
694 [1] = {
695 .name = "Hazel Findlay",
696 .height = 157
697 },
698 [2] = {
699 .name = "Daila Ojeda",
700 .height = 158
701 },
702 [3] = {
703 .name = "Albert Einstein",
704 .height = 172
705 },
706 },
707 .num_elements = 4
708 },
709 },
710 .objects_array_array_len = 3,
711 };
712 char encoded[] = "{\"objects_array_array\":["
713 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
714 "{\"name\":\"Pel\303\251\",\"height\":173},"
715 "{\"name\":\"Usain Bolt\",\"height\":195}],"
716 "[{\"name\":\"Muggsy Bogues\",\"height\":160},"
717 "{\"name\":\"Hakeem Olajuwon\",\"height\":213}],"
718 "[{\"name\":\"Alex Honnold\",\"height\":180},"
719 "{\"name\":\"Hazel Findlay\",\"height\":157},"
720 "{\"name\":\"Daila Ojeda\",\"height\":158},"
721 "{\"name\":\"Albert Einstein\",\"height\":172}]"
722 "]}";
723 char buffer[sizeof(encoded)];
724 int ret;
725
726 ret = json_obj_encode_buf(array_2dim_descr, ARRAY_SIZE(array_2dim_descr),
727 &obj_array_array_ts, buffer, sizeof(buffer));
728 zassert_equal(ret, 0, "Encoding two-dimensional array returned error");
729 zassert_str_equal(buffer, encoded,
730 "Encoded two-dimensional array is not consistent");
731 }
732
ZTEST(lib_json_test,test_json_2dim_arr_extra_obj_encoding)733 ZTEST(lib_json_test, test_json_2dim_arr_extra_obj_encoding)
734 {
735 struct obj_array_2dim_extra obj_array_2dim_extra_ts = {
736 .name = "Paavo Nurmi",
737 .val = 123,
738 .obj_array_2dim.objects_array_array = {
739 [0] = {
740 .elements = {
741 [0] = {
742 .name = "Sim\303\263n Bol\303\255var",
743 .height = 168
744 },
745 [1] = {
746 .name = "Pel\303\251",
747 .height = 173
748 },
749 [2] = {
750 .name = "Usain Bolt",
751 .height = 195
752 },
753 },
754 .num_elements = 3
755 },
756 [1] = {
757 .elements = {
758 [0] = {
759 .name = "Muggsy Bogues",
760 .height = 160
761 },
762 [1] = {
763 .name = "Hakeem Olajuwon",
764 .height = 213
765 },
766 },
767 .num_elements = 2
768 },
769 [2] = {
770 .elements = {
771 [0] = {
772 .name = "Alex Honnold",
773 .height = 180
774 },
775 [1] = {
776 .name = "Hazel Findlay",
777 .height = 157
778 },
779 [2] = {
780 .name = "Daila Ojeda",
781 .height = 158
782 },
783 [3] = {
784 .name = "Albert Einstein",
785 .height = 172
786 },
787 },
788 .num_elements = 4
789 },
790 },
791 .obj_array_2dim.objects_array_array_len = 3,
792 };
793
794 char encoded[] = "{\"name\":\"Paavo Nurmi\",\"val\":123,"
795 "\"obj_array_2dim\":["
796 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
797 "{\"name\":\"Pel\303\251\",\"height\":173},"
798 "{\"name\":\"Usain Bolt\",\"height\":195}],"
799 "[{\"name\":\"Muggsy Bogues\",\"height\":160},"
800 "{\"name\":\"Hakeem Olajuwon\",\"height\":213}],"
801 "[{\"name\":\"Alex Honnold\",\"height\":180},"
802 "{\"name\":\"Hazel Findlay\",\"height\":157},"
803 "{\"name\":\"Daila Ojeda\",\"height\":158},"
804 "{\"name\":\"Albert Einstein\",\"height\":172}]"
805 "]}";
806 char buffer[sizeof(encoded)];
807 int ret;
808
809 ret = json_obj_encode_buf(array_2dim_extra_descr, ARRAY_SIZE(array_2dim_extra_descr),
810 &obj_array_2dim_extra_ts, buffer, sizeof(buffer));
811 zassert_equal(ret, 0, "Encoding two-dimensional extra array returned error");
812 zassert_str_equal(buffer, encoded,
813 "Encoded two-dimensional extra array is not consistent");
814 }
815
ZTEST(lib_json_test,test_json_2dim_arr_extra_named_obj_encoding)816 ZTEST(lib_json_test, test_json_2dim_arr_extra_named_obj_encoding)
817 {
818 struct obj_array_2dim_extra obj_array_2dim_extra_ts = {
819 .name = "Paavo Nurmi",
820 .val = 123,
821 .obj_array_2dim.objects_array_array = {
822 [0] = {
823 .elements = {
824 [0] = {
825 .name = "Sim\303\263n Bol\303\255var",
826 .height = 168
827 },
828 [1] = {
829 .name = "Pel\303\251",
830 .height = 173
831 },
832 [2] = {
833 .name = "Usain Bolt",
834 .height = 195
835 },
836 },
837 .num_elements = 3
838 },
839 [1] = {
840 .elements = {
841 [0] = {
842 .name = "Muggsy Bogues",
843 .height = 160
844 },
845 [1] = {
846 .name = "Hakeem Olajuwon",
847 .height = 213
848 },
849 },
850 .num_elements = 2
851 },
852 [2] = {
853 .elements = {
854 [0] = {
855 .name = "Alex Honnold",
856 .height = 180
857 },
858 [1] = {
859 .name = "Hazel Findlay",
860 .height = 157
861 },
862 [2] = {
863 .name = "Daila Ojeda",
864 .height = 158
865 },
866 [3] = {
867 .name = "Albert Einstein",
868 .height = 172
869 },
870 },
871 .num_elements = 4
872 },
873 },
874 .obj_array_2dim.objects_array_array_len = 3,
875 };
876
877 char encoded[] = "{\"name\":\"Paavo Nurmi\",\"val\":123,"
878 "\"data\":["
879 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
880 "{\"name\":\"Pel\303\251\",\"height\":173},"
881 "{\"name\":\"Usain Bolt\",\"height\":195}],"
882 "[{\"name\":\"Muggsy Bogues\",\"height\":160},"
883 "{\"name\":\"Hakeem Olajuwon\",\"height\":213}],"
884 "[{\"name\":\"Alex Honnold\",\"height\":180},"
885 "{\"name\":\"Hazel Findlay\",\"height\":157},"
886 "{\"name\":\"Daila Ojeda\",\"height\":158},"
887 "{\"name\":\"Albert Einstein\",\"height\":172}]"
888 "]}";
889 char buffer[sizeof(encoded)];
890 int ret;
891
892 ret = json_obj_encode_buf(array_2dim_extra_named_descr,
893 ARRAY_SIZE(array_2dim_extra_named_descr),
894 &obj_array_2dim_extra_ts, buffer, sizeof(buffer));
895 zassert_equal(ret, 0, "Encoding two-dimensional extra named array returned error");
896 zassert_str_equal(buffer, encoded,
897 "Encoded two-dimensional extra named array is not consistent");
898 }
899
ZTEST(lib_json_test,test_json_2dim_obj_arr_decoding)900 ZTEST(lib_json_test, test_json_2dim_obj_arr_decoding)
901 {
902 struct obj_array_2dim oaa;
903 char encoded[] = "{\"objects_array_array\":["
904 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"height\":168},"
905 "{\"name\":\"Pel\303\251\",\"height\":173},"
906 "{\"name\":\"Usain Bolt\",\"height\":195}],"
907 "[{\"name\":\"Muggsy Bogues\",\"height\":160},"
908 "{\"name\":\"Hakeem Olajuwon\",\"height\":213}],"
909 "[{\"name\":\"Alex Honnold\",\"height\":180},"
910 "{\"name\":\"Hazel Findlay\",\"height\":157},"
911 "{\"name\":\"Daila Ojeda\",\"height\":158},"
912 "{\"name\":\"Albert Einstein\",\"height\":172}]"
913 "]}";
914 const struct obj_array_2dim expected = {
915 .objects_array_array = {
916 [0] = {
917 .elements = {
918 [0] = {
919 .name = "Sim\303\263n Bol\303\255var",
920 .height = 168
921 },
922 [1] = {
923 .name = "Pel\303\251",
924 .height = 173
925 },
926 [2] = {
927 .name = "Usain Bolt",
928 .height = 195
929 },
930 },
931 .num_elements = 3
932 },
933 [1] = {
934 .elements = {
935 [0] = {
936 .name = "Muggsy Bogues",
937 .height = 160
938 },
939 [1] = {
940 .name = "Hakeem Olajuwon",
941 .height = 213
942 },
943 },
944 .num_elements = 2
945 },
946 [2] = {
947 .elements = {
948 [0] = {
949 .name = "Alex Honnold",
950 .height = 180
951 },
952 [1] = {
953 .name = "Hazel Findlay",
954 .height = 157
955 },
956 [2] = {
957 .name = "Daila Ojeda",
958 .height = 158
959 },
960 [3] = {
961 .name = "Albert Einstein",
962 .height = 172
963 },
964 },
965 .num_elements = 4
966 },
967 },
968 .objects_array_array_len = 3,
969 };
970 int ret;
971
972 ret = json_obj_parse(encoded, sizeof(encoded),
973 array_2dim_descr,
974 ARRAY_SIZE(array_2dim_descr),
975 &oaa);
976
977 zassert_equal(ret, 1, "Array of arrays fields not decoded correctly");
978 zassert_equal(oaa.objects_array_array_len, 3,
979 "Number of subarrays not decoded correctly");
980 zassert_equal(oaa.objects_array_array[0].num_elements, 3,
981 "Number of object fields not decoded correctly");
982 zassert_equal(oaa.objects_array_array[1].num_elements, 2,
983 "Number of object fields not decoded correctly");
984 zassert_equal(oaa.objects_array_array[2].num_elements, 4,
985 "Number of object fields not decoded correctly");
986
987 for (int i = 0; i < expected.objects_array_array_len; i++) {
988 for (int j = 0; j < expected.objects_array_array[i].num_elements; j++) {
989 zassert_true(!strcmp(oaa.objects_array_array[i].elements[j].name,
990 expected.objects_array_array[i].elements[j].name),
991 "Element [%d][%d] name not decoded correctly", i, j);
992 zassert_equal(oaa.objects_array_array[i].elements[j].height,
993 expected.objects_array_array[i].elements[j].height,
994 "Element [%d][%d] height not decoded correctly", i, j);
995 }
996 }
997 }
998
999 struct encoding_test {
1000 char *str;
1001 int result;
1002 };
1003
parse_harness(struct encoding_test encoded[],size_t size)1004 static void parse_harness(struct encoding_test encoded[], size_t size)
1005 {
1006 struct test_struct ts;
1007 int ret;
1008
1009 for (int i = 0; i < size; i++) {
1010 ret = json_obj_parse(encoded[i].str, strlen(encoded[i].str),
1011 test_descr, ARRAY_SIZE(test_descr), &ts);
1012 zassert_equal(ret, encoded[i].result,
1013 "Decoding '%s' result %d, expected %d",
1014 encoded[i].str, ret, encoded[i].result);
1015 }
1016 }
1017
ZTEST(lib_json_test,test_json_invalid_string)1018 ZTEST(lib_json_test, test_json_invalid_string)
1019 {
1020 struct encoding_test encoded[] = {
1021 { "{\"some_string\":\"\\u@@@@\"}", -EINVAL },
1022 { "{\"some_string\":\"\\uA@@@\"}", -EINVAL },
1023 { "{\"some_string\":\"\\uAB@@\"}", -EINVAL },
1024 { "{\"some_string\":\"\\uABC@\"}", -EINVAL },
1025 { "{\"some_string\":\"\\X\"}", -EINVAL }
1026 };
1027
1028 parse_harness(encoded, ARRAY_SIZE(encoded));
1029 }
1030
ZTEST(lib_json_test,test_json_invalid_bool)1031 ZTEST(lib_json_test, test_json_invalid_bool)
1032 {
1033 struct encoding_test encoded[] = {
1034 { "{\"some_bool\":truffle }", -EINVAL},
1035 { "{\"some_bool\":fallacy }", -EINVAL},
1036 };
1037
1038 parse_harness(encoded, ARRAY_SIZE(encoded));
1039 }
1040
ZTEST(lib_json_test,test_json_invalid_null)1041 ZTEST(lib_json_test, test_json_invalid_null)
1042 {
1043 struct encoding_test encoded[] = {
1044 /* Parser will recognize 'null', but refuse to decode it */
1045 { "{\"some_string\":null }", -EINVAL},
1046 /* Null spelled wrong */
1047 { "{\"some_string\":nutella }", -EINVAL},
1048 };
1049
1050 parse_harness(encoded, ARRAY_SIZE(encoded));
1051 }
1052
ZTEST(lib_json_test,test_json_invalid_number)1053 ZTEST(lib_json_test, test_json_invalid_number)
1054 {
1055 struct encoding_test encoded[] = {
1056 { "{\"some_int\":xxx }", -EINVAL},
1057 };
1058
1059 parse_harness(encoded, ARRAY_SIZE(encoded));
1060 }
1061
ZTEST(lib_json_test,test_json_missing_quote)1062 ZTEST(lib_json_test, test_json_missing_quote)
1063 {
1064 struct test_struct ts;
1065 char encoded[] = "{\"some_string";
1066 int ret;
1067
1068 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1069 ARRAY_SIZE(test_descr), &ts);
1070 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1071 }
1072
ZTEST(lib_json_test,test_json_wrong_token)1073 ZTEST(lib_json_test, test_json_wrong_token)
1074 {
1075 struct test_struct ts;
1076 char encoded[] = "{\"some_string\",}";
1077 int ret;
1078
1079 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1080 ARRAY_SIZE(test_descr), &ts);
1081 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1082 }
1083
ZTEST(lib_json_test,test_json_item_wrong_type)1084 ZTEST(lib_json_test, test_json_item_wrong_type)
1085 {
1086 struct test_struct ts;
1087 char encoded[] = "{\"some_string\":false}";
1088 int ret;
1089
1090 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1091 ARRAY_SIZE(test_descr), &ts);
1092 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1093 }
1094
ZTEST(lib_json_test,test_json_key_not_in_descr)1095 ZTEST(lib_json_test, test_json_key_not_in_descr)
1096 {
1097 struct test_struct ts;
1098 char encoded[] = "{\"key_not_in_descr\":123456}";
1099 int ret;
1100
1101 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1102 ARRAY_SIZE(test_descr), &ts);
1103 zassert_equal(ret, 0, "No items should be decoded");
1104 }
1105
ZTEST(lib_json_test,test_json_escape)1106 ZTEST(lib_json_test, test_json_escape)
1107 {
1108 char buf[42];
1109 char string[] = "\"abc"
1110 "\\1`23"
1111 "\bf'oo"
1112 "\fbar"
1113 "\nbaz"
1114 "\rquux"
1115 "\tfred\"";
1116 const char *expected = "\\\"abc"
1117 "\\\\1`23"
1118 "\\bf'oo"
1119 "\\fbar"
1120 "\\nbaz"
1121 "\\rquux"
1122 "\\tfred\\\"";
1123 size_t len;
1124 ssize_t ret;
1125
1126 strncpy(buf, string, sizeof(buf) - 1);
1127 len = strlen(buf);
1128
1129 ret = json_escape(buf, &len, sizeof(buf));
1130 zassert_equal(ret, 0, "Escape did not succeed");
1131 zassert_equal(len, sizeof(buf) - 1,
1132 "Escaped length not computed correctly");
1133 zassert_str_equal(buf, expected, "Escaped value is not correct");
1134 }
1135
1136 /* Edge case: only one character, which must be escaped. */
ZTEST(lib_json_test,test_json_escape_one)1137 ZTEST(lib_json_test, test_json_escape_one)
1138 {
1139 char buf[3] = {'\t', '\0', '\0'};
1140 const char *expected = "\\t";
1141 size_t len = strlen(buf);
1142 ssize_t ret;
1143
1144 ret = json_escape(buf, &len, sizeof(buf));
1145 zassert_equal(ret, 0,
1146 "Escaping one character did not succeed");
1147 zassert_equal(len, sizeof(buf) - 1,
1148 "Escaping one character length is not correct");
1149 zassert_str_equal(buf, expected, "Escaped value is not correct");
1150 }
1151
ZTEST(lib_json_test,test_json_escape_empty)1152 ZTEST(lib_json_test, test_json_escape_empty)
1153 {
1154 char empty[] = "";
1155 size_t len = sizeof(empty) - 1;
1156 ssize_t ret;
1157
1158 ret = json_escape(empty, &len, sizeof(empty));
1159 zassert_equal(ret, 0, "Escaping empty string not successful");
1160 zassert_equal(len, 0, "Length of empty escaped string is not zero");
1161 zassert_equal(empty[0], '\0', "Empty string does not remain empty");
1162 }
1163
ZTEST(lib_json_test,test_json_escape_no_op)1164 ZTEST(lib_json_test, test_json_escape_no_op)
1165 {
1166 char nothing_to_escape[] = "hello,world:!";
1167 const char *expected = "hello,world:!";
1168 size_t len = sizeof(nothing_to_escape) - 1;
1169 ssize_t ret;
1170
1171 ret = json_escape(nothing_to_escape, &len, sizeof(nothing_to_escape));
1172 zassert_equal(ret, 0, "Escape no-op not handled correctly");
1173 zassert_equal(len, sizeof(nothing_to_escape) - 1,
1174 "Changed length of already escaped string");
1175 zassert_str_equal(nothing_to_escape, expected,
1176 "Altered string with nothing to escape");
1177 }
1178
ZTEST(lib_json_test,test_json_escape_bounds_check)1179 ZTEST(lib_json_test, test_json_escape_bounds_check)
1180 {
1181 char not_enough_memory[] = "\tfoo";
1182 size_t len = sizeof(not_enough_memory) - 1;
1183 ssize_t ret;
1184
1185 ret = json_escape(not_enough_memory, &len, sizeof(not_enough_memory));
1186 zassert_equal(ret, -ENOMEM, "Bounds check failed");
1187 }
1188
ZTEST(lib_json_test,test_json_encode_bounds_check)1189 ZTEST(lib_json_test, test_json_encode_bounds_check)
1190 {
1191 struct number {
1192 uint32_t val;
1193 } str = { 0 };
1194 const struct json_obj_descr descr[] = {
1195 JSON_OBJ_DESCR_PRIM(struct number, val, JSON_TOK_NUMBER),
1196 };
1197 /* Encodes to {"val":0}\0 for a total of 10 bytes */
1198 uint8_t buf[10];
1199 ssize_t ret = json_obj_encode_buf(descr, ARRAY_SIZE(descr),
1200 &str, buf, 10);
1201 zassert_equal(ret, 0, "Encoding failed despite large enough buffer");
1202 zassert_equal(strlen(buf), 9, "Encoded string length mismatch");
1203
1204 ret = json_obj_encode_buf(descr, ARRAY_SIZE(descr),
1205 &str, buf, 9);
1206 zassert_equal(ret, -ENOMEM, "Bounds check failed");
1207 }
1208
ZTEST(lib_json_test,test_large_descriptor)1209 ZTEST(lib_json_test, test_large_descriptor)
1210 {
1211 struct large_struct {
1212 int int0;
1213 int int1;
1214 int int2;
1215 int int3;
1216 int int4;
1217 int int5;
1218 int int6;
1219 int int7;
1220 int int8;
1221 int int9;
1222 int int10;
1223 int int11;
1224 int int12;
1225 int int13;
1226 int int14;
1227 int int15;
1228 int int16;
1229 int int17;
1230 int int18;
1231 int int19;
1232 int int20;
1233 int int21;
1234 int int22;
1235 int int23;
1236 int int24;
1237 int int25;
1238 int int26;
1239 int int27;
1240 int int28;
1241 int int29;
1242 int int30;
1243 int int31;
1244 int int32;
1245 int int33;
1246 int int34;
1247 int int35;
1248 int int36;
1249 int int37;
1250 int int38;
1251 int int39;
1252 };
1253
1254 static const struct json_obj_descr large_descr[] = {
1255 JSON_OBJ_DESCR_PRIM(struct large_struct, int0, JSON_TOK_NUMBER),
1256 JSON_OBJ_DESCR_PRIM(struct large_struct, int1, JSON_TOK_NUMBER),
1257 JSON_OBJ_DESCR_PRIM(struct large_struct, int2, JSON_TOK_NUMBER),
1258 JSON_OBJ_DESCR_PRIM(struct large_struct, int3, JSON_TOK_NUMBER),
1259 JSON_OBJ_DESCR_PRIM(struct large_struct, int4, JSON_TOK_NUMBER),
1260 JSON_OBJ_DESCR_PRIM(struct large_struct, int5, JSON_TOK_NUMBER),
1261 JSON_OBJ_DESCR_PRIM(struct large_struct, int6, JSON_TOK_NUMBER),
1262 JSON_OBJ_DESCR_PRIM(struct large_struct, int7, JSON_TOK_NUMBER),
1263 JSON_OBJ_DESCR_PRIM(struct large_struct, int8, JSON_TOK_NUMBER),
1264 JSON_OBJ_DESCR_PRIM(struct large_struct, int9, JSON_TOK_NUMBER),
1265 JSON_OBJ_DESCR_PRIM(struct large_struct, int10, JSON_TOK_NUMBER),
1266 JSON_OBJ_DESCR_PRIM(struct large_struct, int11, JSON_TOK_NUMBER),
1267 JSON_OBJ_DESCR_PRIM(struct large_struct, int12, JSON_TOK_NUMBER),
1268 JSON_OBJ_DESCR_PRIM(struct large_struct, int13, JSON_TOK_NUMBER),
1269 JSON_OBJ_DESCR_PRIM(struct large_struct, int14, JSON_TOK_NUMBER),
1270 JSON_OBJ_DESCR_PRIM(struct large_struct, int15, JSON_TOK_NUMBER),
1271 JSON_OBJ_DESCR_PRIM(struct large_struct, int16, JSON_TOK_NUMBER),
1272 JSON_OBJ_DESCR_PRIM(struct large_struct, int17, JSON_TOK_NUMBER),
1273 JSON_OBJ_DESCR_PRIM(struct large_struct, int18, JSON_TOK_NUMBER),
1274 JSON_OBJ_DESCR_PRIM(struct large_struct, int19, JSON_TOK_NUMBER),
1275 JSON_OBJ_DESCR_PRIM(struct large_struct, int20, JSON_TOK_NUMBER),
1276 JSON_OBJ_DESCR_PRIM(struct large_struct, int21, JSON_TOK_NUMBER),
1277 JSON_OBJ_DESCR_PRIM(struct large_struct, int22, JSON_TOK_NUMBER),
1278 JSON_OBJ_DESCR_PRIM(struct large_struct, int23, JSON_TOK_NUMBER),
1279 JSON_OBJ_DESCR_PRIM(struct large_struct, int24, JSON_TOK_NUMBER),
1280 JSON_OBJ_DESCR_PRIM(struct large_struct, int25, JSON_TOK_NUMBER),
1281 JSON_OBJ_DESCR_PRIM(struct large_struct, int26, JSON_TOK_NUMBER),
1282 JSON_OBJ_DESCR_PRIM(struct large_struct, int27, JSON_TOK_NUMBER),
1283 JSON_OBJ_DESCR_PRIM(struct large_struct, int28, JSON_TOK_NUMBER),
1284 JSON_OBJ_DESCR_PRIM(struct large_struct, int29, JSON_TOK_NUMBER),
1285 JSON_OBJ_DESCR_PRIM(struct large_struct, int30, JSON_TOK_NUMBER),
1286 JSON_OBJ_DESCR_PRIM(struct large_struct, int31, JSON_TOK_NUMBER),
1287 JSON_OBJ_DESCR_PRIM(struct large_struct, int32, JSON_TOK_NUMBER),
1288 JSON_OBJ_DESCR_PRIM(struct large_struct, int33, JSON_TOK_NUMBER),
1289 JSON_OBJ_DESCR_PRIM(struct large_struct, int34, JSON_TOK_NUMBER),
1290 JSON_OBJ_DESCR_PRIM(struct large_struct, int35, JSON_TOK_NUMBER),
1291 JSON_OBJ_DESCR_PRIM(struct large_struct, int36, JSON_TOK_NUMBER),
1292 JSON_OBJ_DESCR_PRIM(struct large_struct, int37, JSON_TOK_NUMBER),
1293 JSON_OBJ_DESCR_PRIM(struct large_struct, int38, JSON_TOK_NUMBER),
1294 JSON_OBJ_DESCR_PRIM(struct large_struct, int39, JSON_TOK_NUMBER),
1295 };
1296 char encoded[] = "{"
1297 "\"int1\": 1,"
1298 "\"int21\": 21,"
1299 "\"int31\": 31,"
1300 "\"int39\": 39"
1301 "}";
1302
1303 struct large_struct ls;
1304
1305 int64_t ret = json_obj_parse(encoded, sizeof(encoded) - 1, large_descr,
1306 ARRAY_SIZE(large_descr), &ls);
1307
1308 zassert_false(ret < 0, "json_obj_parse returned error %d", ret);
1309 zassert_false(ret & ((int64_t)1 << 2), "Field int2 erroneously decoded");
1310 zassert_false(ret & ((int64_t)1 << 35), "Field int35 erroneously decoded");
1311 zassert_true(ret & ((int64_t)1 << 1), "Field int1 not decoded");
1312 zassert_true(ret & ((int64_t)1 << 21), "Field int21 not decoded");
1313 zassert_true(ret & ((int64_t)1 << 31), "Field int31 not decoded");
1314 zassert_true(ret & ((int64_t)1 << 39), "Field int39 not decoded");
1315 }
1316
ZTEST(lib_json_test,test_json_encoded_object_tok_encoding)1317 ZTEST(lib_json_test, test_json_encoded_object_tok_encoding)
1318 {
1319 static const char encoded[] =
1320 "{\"encoded_obj\":{\"test\":{\"nested\":\"yes\"}},\"ok\":1234}";
1321 const struct test_json_tok_encoded_obj obj = {
1322 .encoded_obj = "{\"test\":{\"nested\":\"yes\"}}",
1323 .ok = 1234,
1324 };
1325 char buffer[sizeof(encoded)];
1326 int ret;
1327
1328 ret = json_obj_encode_buf(test_json_tok_encoded_obj_descr,
1329 ARRAY_SIZE(test_json_tok_encoded_obj_descr), &obj, buffer,
1330 sizeof(buffer));
1331
1332 zassert_equal(ret, 0, "Encoding function failed");
1333 zassert_mem_equal(buffer, encoded, sizeof(encoded), "Encoded contents not consistent");
1334 }
1335
ZTEST(lib_json_test,test_json_array_alignment)1336 ZTEST(lib_json_test, test_json_array_alignment)
1337 {
1338 char encoded[] = "{"
1339 "\"array\": [ "
1340 "{ \"int1\": 1, "
1341 "\"int2\": 2, "
1342 "\"int3\": 3 }, "
1343 "{ \"int1\": 4, "
1344 "\"int2\": 5, "
1345 "\"int3\": 6 } "
1346 "] "
1347 "}";
1348
1349 struct test_outer o;
1350 int64_t ret = json_obj_parse(encoded, sizeof(encoded) - 1, outer_descr,
1351 ARRAY_SIZE(outer_descr), &o);
1352
1353 zassert_false(ret < 0, "json_obj_parse returned error %d", ret);
1354 zassert_equal(o.num_elements, 2, "Number of elements not decoded correctly");
1355
1356 zassert_equal(o.array[0].int1, 1, "Element 0 int1 not decoded correctly");
1357 zassert_equal(o.array[0].int2, 2, "Element 0 int2 not decoded correctly");
1358 zassert_equal(o.array[0].int3, 3, "Element 0 int3 not decoded correctly");
1359
1360 zassert_equal(o.array[1].int1, 4, "Element 1 int1 not decoded correctly");
1361 zassert_equal(o.array[1].int2, 5, "Element 1 int2 not decoded correctly");
1362 zassert_equal(o.array[1].int3, 6, "Element 1 int3 not decoded correctly");
1363 }
1364
1365 ZTEST_SUITE(lib_json_test, NULL, NULL, NULL, NULL, NULL);
1366