1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <string.h>
7 #include <float.h>
8 #include <math.h>
9 #include <zephyr/types.h>
10 #include <stdbool.h>
11 #include <zephyr/ztest.h>
12 #include <zephyr/data/json.h>
13
14 struct test_nested {
15 int nested_int;
16 bool nested_bool;
17 const char *nested_string;
18 char nested_string_buf[10];
19 int8_t nested_int8;
20 uint8_t nested_uint8;
21 int64_t nested_int64;
22 uint64_t nested_uint64;
23 };
24
25 struct test_struct {
26 const char *some_string;
27 char some_string_buf[10];
28 int some_int;
29 bool some_bool;
30 int16_t some_int16;
31 int64_t some_int64;
32 int64_t another_int64;
33 int64_t some_uint64;
34 int64_t another_uint64;
35 struct test_nested some_nested_struct;
36 int some_array[16];
37 size_t some_array_len;
38 bool another_bxxl; /* JSON field: "another_b!@l" */
39 bool if_; /* JSON: "if" */
40 int another_array[10]; /* JSON: "another-array" */
41 size_t another_array_len;
42 struct test_nested xnother_nexx; /* JSON: "4nother_ne$+" */
43 struct test_nested nested_obj_array[2];
44 size_t obj_array_len;
45 };
46
47 struct elt {
48 const char *name;
49 const char name_buf[10];
50 int height;
51 };
52
53 struct obj_array {
54 struct elt elements[10];
55 size_t num_elements;
56 };
57
58 struct test_int_limits {
59 int int_max;
60 int int_cero;
61 int int_min;
62 int64_t int64_max;
63 int64_t int64_cero;
64 int64_t int64_min;
65 uint64_t uint64_max;
66 uint64_t uint64_cero;
67 uint64_t uint64_min;
68 uint32_t uint32_max;
69 uint32_t uint32_cero;
70 uint32_t uint32_min;
71 int16_t int16_max;
72 int16_t int16_cero;
73 int16_t int16_min;
74 uint16_t uint16_max;
75 uint16_t uint16_cero;
76 uint16_t uint16_min;
77 int8_t int8_max;
78 int8_t int8_cero;
79 int8_t int8_min;
80 uint8_t uint8_max;
81 uint8_t uint8_cero;
82 uint8_t uint8_min;
83 };
84
85 struct test_float {
86 float some_float;
87 float another_float;
88 float some_array[16];
89 size_t some_array_len;
90 };
91
92 struct test_float_limits {
93 float float_max;
94 float float_cero;
95 float float_min;
96 };
97
98 struct test_double {
99 double some_double;
100 double another_double;
101 double some_array[16];
102 size_t some_array_len;
103 };
104
105 struct test_double_limits {
106 double double_max;
107 double double_cero;
108 double double_min;
109 };
110
111 struct escape_test_data {
112 char string_value[128];
113 char string_buf[64];
114 int integer_value;
115 };
116
117 static const struct json_obj_descr escape_test_descr[] = {
118 JSON_OBJ_DESCR_PRIM(struct escape_test_data, string_value, JSON_TOK_STRING_BUF),
119 JSON_OBJ_DESCR_PRIM(struct escape_test_data, string_buf, JSON_TOK_STRING_BUF),
120 JSON_OBJ_DESCR_PRIM(struct escape_test_data, integer_value, JSON_TOK_NUMBER),
121 };
122
123 static const struct json_obj_descr nested_descr[] = {
124 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int, JSON_TOK_NUMBER),
125 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_bool, JSON_TOK_TRUE),
126 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_string,
127 JSON_TOK_STRING),
128 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_string_buf,
129 JSON_TOK_STRING_BUF),
130 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int8, JSON_TOK_INT),
131 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_uint8, JSON_TOK_UINT),
132 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int64,
133 JSON_TOK_INT64),
134 JSON_OBJ_DESCR_PRIM(struct test_nested, nested_uint64,
135 JSON_TOK_UINT64),
136 };
137
138 static const struct json_obj_descr test_descr[] = {
139 JSON_OBJ_DESCR_PRIM(struct test_struct, some_string, JSON_TOK_STRING),
140 JSON_OBJ_DESCR_PRIM(struct test_struct, some_string_buf, JSON_TOK_STRING_BUF),
141 JSON_OBJ_DESCR_PRIM(struct test_struct, some_int, JSON_TOK_NUMBER),
142 JSON_OBJ_DESCR_PRIM(struct test_struct, some_bool, JSON_TOK_TRUE),
143 JSON_OBJ_DESCR_PRIM(struct test_struct, some_int16, JSON_TOK_INT),
144 JSON_OBJ_DESCR_PRIM(struct test_struct, some_int64,
145 JSON_TOK_INT64),
146 JSON_OBJ_DESCR_PRIM(struct test_struct, another_int64,
147 JSON_TOK_INT64),
148 JSON_OBJ_DESCR_PRIM(struct test_struct, some_uint64,
149 JSON_TOK_UINT64),
150 JSON_OBJ_DESCR_PRIM(struct test_struct, another_uint64,
151 JSON_TOK_UINT64),
152 JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct,
153 nested_descr),
154 JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array,
155 16, some_array_len, JSON_TOK_NUMBER),
156 JSON_OBJ_DESCR_PRIM_NAMED(struct test_struct, "another_b!@l",
157 another_bxxl, JSON_TOK_TRUE),
158 JSON_OBJ_DESCR_PRIM_NAMED(struct test_struct, "if",
159 if_, JSON_TOK_TRUE),
160 JSON_OBJ_DESCR_ARRAY_NAMED(struct test_struct, "another-array",
161 another_array, 10, another_array_len,
162 JSON_TOK_NUMBER),
163 JSON_OBJ_DESCR_OBJECT_NAMED(struct test_struct, "4nother_ne$+",
164 xnother_nexx, nested_descr),
165 JSON_OBJ_DESCR_OBJ_ARRAY(struct test_struct, nested_obj_array, 2,
166 obj_array_len, nested_descr, ARRAY_SIZE(nested_descr)),
167 };
168
169 static const struct json_obj_descr elt_descr[] = {
170 JSON_OBJ_DESCR_PRIM(struct elt, name, JSON_TOK_STRING),
171 JSON_OBJ_DESCR_PRIM(struct elt, name_buf, JSON_TOK_STRING_BUF),
172 JSON_OBJ_DESCR_PRIM(struct elt, height, JSON_TOK_NUMBER),
173 };
174
175 static const struct json_obj_descr obj_array_descr[] = {
176 JSON_OBJ_DESCR_OBJ_ARRAY(struct obj_array, elements, 10, num_elements,
177 elt_descr, ARRAY_SIZE(elt_descr)),
178 };
179
180 static const struct json_obj_descr obj_limits_descr[] = {
181 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int_max, JSON_TOK_NUMBER),
182 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int_cero, JSON_TOK_NUMBER),
183 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int_min, JSON_TOK_NUMBER),
184 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_max, JSON_TOK_INT64),
185 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_cero, JSON_TOK_INT64),
186 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_min, JSON_TOK_INT64),
187 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_max, JSON_TOK_UINT64),
188 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_cero, JSON_TOK_UINT64),
189 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_min, JSON_TOK_UINT64),
190 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint32_max, JSON_TOK_UINT),
191 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint32_cero, JSON_TOK_UINT),
192 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint32_min, JSON_TOK_UINT),
193 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int16_max, JSON_TOK_INT),
194 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int16_cero, JSON_TOK_INT),
195 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int16_min, JSON_TOK_INT),
196 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint16_max, JSON_TOK_UINT),
197 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint16_cero, JSON_TOK_UINT),
198 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint16_min, JSON_TOK_UINT),
199 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int8_max, JSON_TOK_INT),
200 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int8_cero, JSON_TOK_INT),
201 JSON_OBJ_DESCR_PRIM(struct test_int_limits, int8_min, JSON_TOK_INT),
202 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint8_max, JSON_TOK_UINT),
203 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint8_cero, JSON_TOK_UINT),
204 JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint8_min, JSON_TOK_UINT),
205 };
206
207 static const struct json_obj_descr obj_float_descr[] = {
208 JSON_OBJ_DESCR_PRIM(struct test_float, some_float, JSON_TOK_FLOAT_FP),
209 JSON_OBJ_DESCR_PRIM(struct test_float, another_float, JSON_TOK_FLOAT_FP),
210 JSON_OBJ_DESCR_ARRAY(struct test_float, some_array,
211 16, some_array_len, JSON_TOK_FLOAT_FP),
212 };
213
214 static const struct json_obj_descr obj_float_limits_descr[] = {
215 JSON_OBJ_DESCR_PRIM(struct test_float_limits, float_max, JSON_TOK_FLOAT_FP),
216 JSON_OBJ_DESCR_PRIM(struct test_float_limits, float_cero, JSON_TOK_FLOAT_FP),
217 JSON_OBJ_DESCR_PRIM(struct test_float_limits, float_min, JSON_TOK_FLOAT_FP),
218 };
219
220 static const struct json_obj_descr obj_double_descr[] = {
221 JSON_OBJ_DESCR_PRIM(struct test_double, some_double, JSON_TOK_DOUBLE_FP),
222 JSON_OBJ_DESCR_PRIM(struct test_double, another_double, JSON_TOK_DOUBLE_FP),
223 JSON_OBJ_DESCR_ARRAY(struct test_double, some_array,
224 16, some_array_len, JSON_TOK_DOUBLE_FP),
225 };
226
227 static const struct json_obj_descr obj_double_limits_descr[] = {
228 JSON_OBJ_DESCR_PRIM(struct test_double_limits, double_max, JSON_TOK_DOUBLE_FP),
229 JSON_OBJ_DESCR_PRIM(struct test_double_limits, double_cero, JSON_TOK_DOUBLE_FP),
230 JSON_OBJ_DESCR_PRIM(struct test_double_limits, double_min, JSON_TOK_DOUBLE_FP),
231 };
232
233 struct array {
234 struct elt objects;
235 };
236
237 struct obj_array_array {
238 struct array objects_array[4];
239 size_t objects_array_len;
240 };
241
242 static const struct json_obj_descr array_descr[] = {
243 JSON_OBJ_DESCR_OBJECT(struct array, objects, elt_descr),
244 };
245
246 static const struct json_obj_descr array_array_descr[] = {
247 JSON_OBJ_DESCR_ARRAY_ARRAY(struct obj_array_array, objects_array, 4,
248 objects_array_len, array_descr,
249 ARRAY_SIZE(array_descr)),
250 };
251
252 struct obj_array_2dim {
253 struct obj_array objects_array_array[3];
254 size_t objects_array_array_len;
255 };
256
257 static const struct json_obj_descr array_2dim_descr[] = {
258 JSON_OBJ_DESCR_ARRAY_ARRAY(struct obj_array_2dim, objects_array_array, 3,
259 objects_array_array_len, obj_array_descr,
260 ARRAY_SIZE(obj_array_descr)),
261 };
262
263 struct obj_array_2dim_extra {
264 const char *name;
265 int val;
266 struct obj_array_2dim obj_array_2dim;
267 };
268
269 static const struct json_obj_descr array_2dim_extra_descr[] = {
270 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, name, JSON_TOK_STRING),
271 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, val, JSON_TOK_NUMBER),
272 JSON_OBJ_DESCR_ARRAY_ARRAY(struct obj_array_2dim_extra, obj_array_2dim, 3,
273 obj_array_2dim.objects_array_array_len, obj_array_descr,
274 ARRAY_SIZE(obj_array_descr)),
275 };
276
277 static const struct json_obj_descr array_2dim_extra_named_descr[] = {
278 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, name, JSON_TOK_STRING),
279 JSON_OBJ_DESCR_PRIM(struct obj_array_2dim_extra, val, JSON_TOK_NUMBER),
280 JSON_OBJ_DESCR_ARRAY_ARRAY_NAMED(struct obj_array_2dim_extra, data, obj_array_2dim, 3,
281 obj_array_2dim.objects_array_array_len, obj_array_descr,
282 ARRAY_SIZE(obj_array_descr)),
283 };
284
285 struct test_json_tok_encoded_obj {
286 const char *encoded_obj;
287 const char *encoded_obj_array[3];
288 size_t encoded_obj_array_len;
289 int ok;
290 };
291
292 static const struct json_obj_descr test_json_tok_encoded_obj_descr[] = {
293 JSON_OBJ_DESCR_PRIM(struct test_json_tok_encoded_obj, encoded_obj, JSON_TOK_ENCODED_OBJ),
294 JSON_OBJ_DESCR_ARRAY(struct test_json_tok_encoded_obj, encoded_obj_array,
295 3, encoded_obj_array_len, JSON_TOK_ENCODED_OBJ),
296 JSON_OBJ_DESCR_PRIM(struct test_json_tok_encoded_obj, ok, JSON_TOK_NUMBER),
297 };
298
299 struct test_element {
300 int int1;
301 int int2;
302 int int3;
303 };
304
305 struct test_outer {
306 struct test_element array[5];
307 size_t num_elements;
308 };
309
310 static const struct json_obj_descr element_descr[] = {
311 JSON_OBJ_DESCR_PRIM(struct test_element, int1, JSON_TOK_NUMBER),
312 JSON_OBJ_DESCR_PRIM(struct test_element, int2, JSON_TOK_NUMBER),
313 JSON_OBJ_DESCR_PRIM(struct test_element, int3, JSON_TOK_NUMBER),
314 };
315
316 static const struct json_obj_descr outer_descr[] = {
317 JSON_OBJ_DESCR_OBJ_ARRAY(struct test_outer, array, 5,
318 num_elements, element_descr, ARRAY_SIZE(element_descr))
319 };
320
321 struct test_alignment_nested {
322 bool bool1;
323 int int1;
324 bool bool2;
325 };
326
327 struct test_alignment_bool {
328 struct test_alignment_nested array[3];
329 size_t num_elements;
330 };
331
332 static const struct json_obj_descr alignment_nested_descr[] = {
333 JSON_OBJ_DESCR_PRIM(struct test_alignment_nested, bool1, JSON_TOK_TRUE),
334 JSON_OBJ_DESCR_PRIM(struct test_alignment_nested, int1, JSON_TOK_NUMBER),
335 JSON_OBJ_DESCR_PRIM(struct test_alignment_nested, bool2, JSON_TOK_TRUE),
336 };
337
338 static const struct json_obj_descr alignment_bool_descr[] = {
339 JSON_OBJ_DESCR_OBJ_ARRAY(struct test_alignment_bool, array, 3, num_elements,
340 alignment_nested_descr, ARRAY_SIZE(alignment_nested_descr)) };
341
342 enum int8_enum { I8_MIN = INT8_MIN, I8_MAX = INT8_MAX };
343 enum uint8_enum { U8_MIN = 0, U8_MAX = UINT8_MAX };
344 enum int16_enum { I16_MIN = INT16_MIN, I16_MAX = INT16_MAX };
345 enum uint16_enum { U16_MIN = 0, U16_MAX = UINT16_MAX };
346 enum int32_enum { I32_MIN = INT32_MIN, I32_MAX = INT32_MAX };
347 enum uint32_enum { U32_MIN = 0, U32_MAX = UINT32_MAX };
348
349 struct test_enums {
350 enum int8_enum i8;
351 enum uint8_enum u8;
352 enum int16_enum i16;
353 enum uint16_enum u16;
354 enum int32_enum i32;
355 enum uint32_enum u32;
356 };
357
358 static const struct json_obj_descr enums_descr[] = {
359 JSON_OBJ_DESCR_PRIM(struct test_enums, i8, JSON_TOK_INT),
360 JSON_OBJ_DESCR_PRIM(struct test_enums, u8, JSON_TOK_UINT),
361 JSON_OBJ_DESCR_PRIM(struct test_enums, i16, JSON_TOK_INT),
362 JSON_OBJ_DESCR_PRIM(struct test_enums, u16, JSON_TOK_UINT),
363 JSON_OBJ_DESCR_PRIM(struct test_enums, i32, JSON_TOK_INT),
364 JSON_OBJ_DESCR_PRIM(struct test_enums, u32, JSON_TOK_UINT),
365 };
366
367 struct test_mixed_arr {
368 const char *msg_type;
369 uint64_t dev_id;
370 struct test_nested nested;
371 int arr[3];
372 size_t arr_len;
373 char status_buf[10];
374 size_t count;
375 };
376
377 static const struct json_obj_descr test_mixed_arr_descr_arr[] = {
378 JSON_OBJ_DESCR_ARRAY(struct test_mixed_arr, arr, 3, arr_len, JSON_TOK_NUMBER),
379 };
380
381 static const struct json_mixed_arr_descr test_mixed_arr_descr[] = {
382 JSON_MIXED_ARR_DESCR_PRIM(struct test_mixed_arr, msg_type, JSON_TOK_STRING, count),
383 JSON_MIXED_ARR_DESCR_PRIM(struct test_mixed_arr, dev_id, JSON_TOK_UINT64, count),
384 JSON_MIXED_ARR_DESCR_OBJECT(struct test_mixed_arr, nested, nested_descr, count),
385 JSON_MIXED_ARR_DESCR_ARRAY(struct test_mixed_arr, arr, 3, test_mixed_arr_descr_arr, count),
386 JSON_MIXED_ARR_DESCR_PRIM(struct test_mixed_arr, status_buf, JSON_TOK_STRING_BUF, count),
387 };
388
389
ZTEST(lib_json_test,test_json_encoding)390 ZTEST(lib_json_test, test_json_encoding)
391 {
392 struct test_struct ts = {
393 .some_string = "zephyr 123\uABCD",
394 .some_string_buf = "z 123\uABCD",
395 .some_int = 42,
396 .some_int16 = 16,
397 .some_int64 = 1152921504606846977,
398 .another_int64 = -2305843009213693937,
399 .some_uint64 = 18446744073709551615U,
400 .another_uint64 = 0,
401 .some_bool = true,
402 .some_nested_struct = {
403 .nested_int = -1234,
404 .nested_bool = false,
405 .nested_string = "this should be escaped: \t",
406 .nested_string_buf = "esc: \t",
407 .nested_int8 = -123,
408 .nested_uint8 = 231,
409 .nested_int64 = 4503599627370496,
410 .nested_uint64 = 18446744073709551610U,
411 },
412 .some_array[0] = 1,
413 .some_array[1] = 4,
414 .some_array[2] = 8,
415 .some_array[3] = 16,
416 .some_array[4] = 32,
417 .some_array_len = 5,
418 .another_bxxl = true,
419 .if_ = false,
420 .another_array[0] = 2,
421 .another_array[1] = 3,
422 .another_array[2] = 5,
423 .another_array[3] = 7,
424 .another_array_len = 4,
425 .xnother_nexx = {
426 .nested_int = 1234,
427 .nested_bool = true,
428 .nested_string = "no escape necessary",
429 .nested_string_buf = "no escape",
430 .nested_int8 = 123,
431 .nested_uint8 = 231,
432 .nested_int64 = 4503599627370496,
433 .nested_uint64 = 18446744073709551610U,
434 },
435 .nested_obj_array = {
436 {1, true, "true", "true"},
437 {0, false, "false", "false"}
438 },
439 .obj_array_len = 2
440 };
441 char encoded[] = "{\"some_string\":\"zephyr 123\uABCD\","
442 "\"some_string_buf\":\"z 123\uABCD\","
443 "\"some_int\":42,\"some_bool\":true,\"some_int16\":16,"
444 "\"some_int64\":1152921504606846977,"
445 "\"another_int64\":-2305843009213693937,"
446 "\"some_uint64\":18446744073709551615,"
447 "\"another_uint64\":0,"
448 "\"some_nested_struct\":{\"nested_int\":-1234,"
449 "\"nested_bool\":false,\"nested_string\":"
450 "\"this should be escaped: \\t\","
451 "\"nested_string_buf\":\"esc: \\t\","
452 "\"nested_int8\":-123,"
453 "\"nested_uint8\":231,"
454 "\"nested_int64\":4503599627370496,"
455 "\"nested_uint64\":18446744073709551610},"
456 "\"some_array\":[1,4,8,16,32],"
457 "\"another_b!@l\":true,"
458 "\"if\":false,"
459 "\"another-array\":[2,3,5,7],"
460 "\"4nother_ne$+\":{\"nested_int\":1234,"
461 "\"nested_bool\":true,"
462 "\"nested_string\":\"no escape necessary\","
463 "\"nested_string_buf\":\"no escape\","
464 "\"nested_int8\":123,"
465 "\"nested_uint8\":231,"
466 "\"nested_int64\":4503599627370496,"
467 "\"nested_uint64\":18446744073709551610},"
468 "\"nested_obj_array\":["
469 "{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_string_buf\":\"true\",\"nested_int8\":0,\"nested_uint8\":0,\"nested_int64\":0,\"nested_uint64\":0},"
470 "{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_string_buf\":\"false\",\"nested_int8\":0,\"nested_uint8\":0,\"nested_int64\":0,\"nested_uint64\":0}]"
471 "}";
472 char buffer[sizeof(encoded)];
473 int ret;
474 ssize_t len;
475
476 len = json_calc_encoded_len(test_descr, ARRAY_SIZE(test_descr), &ts);
477 zassert_equal(len, strlen(encoded), "encoded size mismatch");
478
479 ret = json_obj_encode_buf(test_descr, ARRAY_SIZE(test_descr),
480 &ts, buffer, sizeof(buffer));
481 zassert_equal(ret, 0, "Encoding function failed");
482
483 ret = strncmp(buffer, encoded, sizeof(encoded) - 1);
484 zassert_equal(ret, 0, "Encoded contents not consistent");
485 }
486
ZTEST(lib_json_test,test_json_decoding)487 ZTEST(lib_json_test, test_json_decoding)
488 {
489 struct test_struct ts;
490 char encoded[] = "{\"some_string\":\"zephyr 123\\uABCD456\","
491 "\"some_string_buf\":\"z\\uABCD\","
492 "\"some_int\":\t42\n,"
493 "\"some_int16\":\t16\n,"
494 "\"some_bool\":true \t "
495 "\n"
496 "\r ,"
497 "\"some_int64\":-4611686018427387904,"
498 "\"another_int64\":-2147483648,"
499 "\"some_uint64\":18446744073709551615,"
500 "\"another_uint64\":0,"
501 "\"some_nested_struct\":{ "
502 "\"nested_int\":-1234,\n\n"
503 "\"nested_bool\":false,\t"
504 "\"nested_string\":\"this should be escaped: \\t\","
505 "\"nested_string_buf\":\"esc: \\t\","
506 "\"nested_int8\":123,"
507 "\"nested_int64\":9223372036854775807,"
508 "\"extra_nested_array\":[0,-1]},"
509 "\"extra_struct\":{\"nested_bool\":false},"
510 "\"extra_bool\":true,"
511 "\"some_array\":[11,22, 33,\t45,\n299],"
512 "\"another_b!@l\":true,"
513 "\"if\":false,"
514 "\"another-array\":[2,3,5,7],"
515 "\"4nother_ne$+\":{\"nested_int\":1234,"
516 "\"nested_bool\":true,"
517 "\"nested_string\":\"no escape necessary\","
518 "\"nested_string_buf\":\"no escape\","
519 "\"nested_int8\":-123,"
520 "\"nested_int64\":-9223372036854775806},"
521 "\"nested_obj_array\":["
522 "{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_string_buf\":\"true\"},"
523 "{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_string_buf\":\"false\"}]"
524 "}\n";
525 const int expected_array[] = { 11, 22, 33, 45, 299 };
526 const int expected_other_array[] = { 2, 3, 5, 7 };
527 int ret;
528
529 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
530 ARRAY_SIZE(test_descr), &ts);
531
532 zassert_equal(ret, (1 << ARRAY_SIZE(test_descr)) - 1,
533 "Not all fields decoded correctly");
534
535 zassert_str_equal(ts.some_string, "zephyr 123\\uABCD456",
536 "String not decoded correctly");
537 zassert_str_equal(ts.some_string_buf, "z\\uABCD",
538 "String (array) not decoded correctly");
539 zassert_equal(ts.some_int, 42, "Positive integer not decoded correctly");
540 zassert_equal(ts.some_int16, 16, "Positive integer not decoded correctly");
541 zassert_equal(ts.some_bool, true, "Boolean not decoded correctly");
542 zassert_equal(ts.some_int64, -4611686018427387904,
543 "int64 not decoded correctly");
544 zassert_equal(ts.another_int64, -2147483648,
545 "int64 not decoded correctly");
546 zassert_equal(ts.some_nested_struct.nested_int, -1234,
547 "Nested negative integer not decoded correctly");
548 zassert_equal(ts.some_nested_struct.nested_int8, 123,
549 "Nested int8 not decoded correctly");
550 zassert_equal(ts.some_nested_struct.nested_int64, 9223372036854775807,
551 "Nested int64 not decoded correctly");
552 zassert_equal(ts.some_nested_struct.nested_bool, false,
553 "Nested boolean value not decoded correctly");
554 zassert_str_equal(ts.some_nested_struct.nested_string,
555 "this should be escaped: \\t",
556 "Nested string not decoded correctly");
557 zassert_str_equal(ts.some_nested_struct.nested_string_buf, "esc: \t",
558 "Nested string-array not decoded correctly");
559 zassert_equal(ts.some_array_len, 5,
560 "Array doesn't have correct number of items");
561 zassert_true(!memcmp(ts.some_array, expected_array,
562 sizeof(expected_array)),
563 "Array not decoded with expected values");
564 zassert_true(ts.another_bxxl,
565 "Named boolean (special chars) not decoded correctly");
566 zassert_false(ts.if_,
567 "Named boolean (reserved word) not decoded correctly");
568 zassert_equal(ts.another_array_len, 4,
569 "Named array does not have correct number of items");
570 zassert_true(!memcmp(ts.another_array, expected_other_array,
571 sizeof(expected_other_array)),
572 "Decoded named array not with expected values");
573 zassert_equal(ts.xnother_nexx.nested_int, 1234,
574 "Named nested integer not decoded correctly");
575 zassert_equal(ts.xnother_nexx.nested_int8, -123,
576 "Named nested int8 not decoded correctly");
577 zassert_equal(ts.xnother_nexx.nested_int64, -9223372036854775806,
578 "Named nested int64 not decoded correctly");
579 zassert_equal(ts.xnother_nexx.nested_bool, true,
580 "Named nested boolean not decoded correctly");
581 zassert_str_equal(ts.xnother_nexx.nested_string,
582 "no escape necessary",
583 "Named nested string not decoded correctly");
584 zassert_str_equal(ts.xnother_nexx.nested_string_buf,
585 "no escape",
586 "Named nested string-array not decoded correctly");
587 zassert_equal(ts.obj_array_len, 2,
588 "Array of objects does not have correct number of items");
589 zassert_equal(ts.nested_obj_array[0].nested_int, 1,
590 "Integer in first object array element not decoded correctly");
591 zassert_equal(ts.nested_obj_array[0].nested_bool, true,
592 "Boolean value in first object array element not decoded correctly");
593 zassert_str_equal(ts.nested_obj_array[0].nested_string, "true",
594 "String in first object array element not decoded correctly");
595 zassert_str_equal(ts.nested_obj_array[0].nested_string_buf, "true",
596 "String buffer in first object array element not decoded correctly");
597 zassert_equal(ts.nested_obj_array[1].nested_int, 0,
598 "Integer in second object array element not decoded correctly");
599 zassert_equal(ts.nested_obj_array[1].nested_bool, false,
600 "Boolean value in second object array element not decoded correctly");
601 zassert_str_equal(ts.nested_obj_array[1].nested_string, "false",
602 "String in second object array element not decoded correctly");
603 zassert_str_equal(ts.nested_obj_array[1].nested_string_buf, "false",
604 "String buffer in second object array element not decoded correctly");
605 }
606
ZTEST(lib_json_test,test_json_limits)607 ZTEST(lib_json_test, test_json_limits)
608 {
609 int ret = 0;
610 char encoded[] = "{\"int_max\":2147483647,"
611 "\"int_cero\":0,"
612 "\"int_min\":-2147483648,"
613 "\"int64_max\":9223372036854775807,"
614 "\"int64_cero\":0,"
615 "\"int64_min\":-9223372036854775808,"
616 "\"uint64_max\":18446744073709551615,"
617 "\"uint64_cero\":0,"
618 "\"uint64_min\":0,"
619 "\"uint32_max\":4294967295,"
620 "\"uint32_cero\":0,"
621 "\"uint32_min\":0,"
622 "\"int16_max\":32767,"
623 "\"int16_cero\":0,"
624 "\"int16_min\":-32768,"
625 "\"uint16_max\":65535,"
626 "\"uint16_cero\":0,"
627 "\"uint16_min\":0,"
628 "\"int8_max\":127,"
629 "\"int8_cero\":0,"
630 "\"int8_min\":-128,"
631 "\"uint8_max\":255,"
632 "\"uint8_cero\":0,"
633 "\"uint8_min\":0"
634 "}";
635
636 struct test_int_limits limits = {0};
637 struct test_int_limits limits_decoded = {0};
638
639 limits.int_max = INT_MAX;
640 limits.int_cero = 0;
641 limits.int_min = INT_MIN;
642 limits.int64_max = INT64_MAX;
643 limits.int64_cero = 0;
644 limits.int64_min = INT64_MIN;
645 limits.uint64_max = UINT64_MAX;
646 limits.uint64_cero = 0;
647 limits.uint64_min = 0;
648 limits.uint32_max = UINT32_MAX;
649 limits.uint32_cero = 0;
650 limits.uint32_min = 0;
651 limits.int16_max = INT16_MAX;
652 limits.int16_cero = 0;
653 limits.int16_min = INT16_MIN;
654 limits.uint16_max = UINT16_MAX;
655 limits.uint16_cero = 0;
656 limits.uint16_min = 0;
657 limits.int8_max = INT8_MAX;
658 limits.int8_cero = 0;
659 limits.int8_min = INT8_MIN;
660 limits.uint8_max = UINT8_MAX;
661 limits.uint8_cero = 0;
662 limits.uint8_min = 0;
663
664 char buffer[sizeof(encoded)];
665
666 ret = json_obj_encode_buf(obj_limits_descr, ARRAY_SIZE(obj_limits_descr),
667 &limits, buffer, sizeof(buffer));
668 ret = json_obj_parse(encoded, sizeof(encoded) - 1, obj_limits_descr,
669 ARRAY_SIZE(obj_limits_descr), &limits_decoded);
670
671 zassert_str_equal(encoded, buffer,
672 "Integer limits not encoded correctly");
673 zassert_true(!memcmp(&limits, &limits_decoded, sizeof(limits)),
674 "Integer limits not decoded correctly");
675 }
676
ZTEST(lib_json_test,test_json_float)677 ZTEST(lib_json_test, test_json_float)
678 {
679 char encoded[] = "{\"some_float\":-0.000244140625,"
680 "\"another_float\":12345600,"
681 "\"some_array\":[1.5,2.25]"
682 "}";
683
684 struct test_float floats = {
685 .some_float = -0.000244140625,
686 .another_float = 12345600.0,
687 .some_array[0] = 1.5,
688 .some_array[1] = 2.25,
689 .some_array_len = 2,
690 };
691
692 char buffer[sizeof(encoded)];
693 struct test_float floats_decoded = {0};
694 int ret;
695
696 ret = json_obj_encode_buf(obj_float_descr, ARRAY_SIZE(obj_float_descr),
697 &floats, buffer, sizeof(buffer));
698 zassert_equal(ret, 0, "Encoding of float returned error");
699 ret = json_obj_parse(encoded, sizeof(encoded), obj_float_descr,
700 ARRAY_SIZE(obj_float_descr), &floats_decoded);
701 zassert_str_equal(encoded, buffer,
702 "Float not encoded correctly");
703 zassert_true(!memcmp(&floats, &floats_decoded, sizeof(floats)),
704 "Float not decoded correctly");
705 }
706
ZTEST(lib_json_test,test_json_float_format)707 ZTEST(lib_json_test, test_json_float_format)
708 {
709 struct sub_test {
710 float num;
711 char *str;
712 };
713 struct sub_test encoded[] = {
714 { .num = 0, .str = "0" },
715 { .num = 0, .str = "0.0" },
716 { .num = 0, .str = "0e0" },
717 { .num = 0, .str = "0e+0" },
718 { .num = 0, .str = "0e-0" },
719
720 { .num = 12345, .str = "12345" },
721 { .num = 12345, .str = "1.2345e+4" },
722 { .num = 12345, .str = "1.2345e+04" },
723
724 { .num = -12345, .str = "-12345" },
725 { .num = -12345, .str = "-1.2345e+4" },
726 { .num = -12345, .str = "-1.2345e+04" },
727
728 { .num = 0.03125, .str = "0.03125" },
729 { .num = 0.03125, .str = "3.125e-2" },
730 { .num = 0.03125, .str = "3.125e-02" },
731
732 { .num = -0.03125, .str = "-0.03125" },
733 { .num = -0.03125, .str = "-3.125e-2" },
734 { .num = -0.03125, .str = "-3.125e-02" },
735 };
736
737 struct test_float ts;
738 char str_encoded[32];
739
740 for (int i = 0; i < ARRAY_SIZE(encoded); i++) {
741 snprintf(str_encoded, sizeof(str_encoded), "{\"some_float\":%s}", encoded[i].str);
742 int ret = json_obj_parse(str_encoded, strlen(str_encoded),
743 obj_float_descr, ARRAY_SIZE(obj_float_descr), &ts);
744 zassert_equal(ret, 1, "Decoding failed: %s result: %d", str_encoded, ret);
745 zassert_equal(ts.some_float, encoded[i].num,
746 "Decoding failed '%s' float: %g exepcted: %g",
747 str_encoded, (double)ts.some_float, (double)encoded[i].num);
748 }
749 }
750
ZTEST(lib_json_test,test_json_float_nan)751 ZTEST(lib_json_test, test_json_float_nan)
752 {
753 char encoded[] = "{\"some_float\":NaN,"
754 "\"another_float\":NaN,"
755 "\"some_array\":[NaN,NaN]"
756 "}";
757
758 struct test_float floats = {
759 .some_float = NAN,
760 .another_float = NAN,
761 .some_array[0] = NAN,
762 .some_array[1] = NAN,
763 .some_array_len = 2,
764 };
765
766 char buffer[sizeof(encoded)];
767 struct test_float floats_decoded = {0};
768 int ret;
769
770 ret = json_obj_encode_buf(obj_float_descr, ARRAY_SIZE(obj_float_descr),
771 &floats, buffer, sizeof(buffer));
772 zassert_equal(ret, 0, "Encoding of float nan returned error");
773 ret = json_obj_parse(encoded, sizeof(encoded), obj_float_descr,
774 ARRAY_SIZE(obj_float_descr), &floats_decoded);
775 zassert_str_equal(encoded, buffer,
776 "Float not encoded correctly");
777 zassert_true(!memcmp(&floats, &floats_decoded, sizeof(floats)),
778 "Float not decoded correctly");
779 }
780
ZTEST(lib_json_test,test_json_float_infinity)781 ZTEST(lib_json_test, test_json_float_infinity)
782 {
783 char encoded[] = "{\"some_float\":Infinity,"
784 "\"another_float\":-Infinity,"
785 "\"some_array\":[Infinity,-Infinity]"
786 "}";
787
788 struct test_float floats = {
789 .some_float = INFINITY,
790 .another_float = -INFINITY,
791 .some_array[0] = INFINITY,
792 .some_array[1] = -INFINITY,
793 .some_array_len = 2,
794 };
795
796 char buffer[sizeof(encoded)];
797 struct test_float floats_decoded = {0};
798 int ret;
799
800 ret = json_obj_encode_buf(obj_float_descr, ARRAY_SIZE(obj_float_descr),
801 &floats, buffer, sizeof(buffer));
802 zassert_equal(ret, 0, "Encoding of float inf returned error");
803 ret = json_obj_parse(encoded, sizeof(encoded), obj_float_descr,
804 ARRAY_SIZE(obj_float_descr), &floats_decoded);
805 zassert_str_equal(encoded, buffer,
806 "Float not encoded correctly");
807 zassert_true(!memcmp(&floats, &floats_decoded, sizeof(floats)),
808 "Float not decoded correctly");
809 }
810
ZTEST(lib_json_test,test_json_float_limits)811 ZTEST(lib_json_test, test_json_float_limits)
812 {
813 char encoded[] = "{\"float_max\":3.40282347e+38,"
814 "\"float_cero\":0,"
815 "\"float_min\":-3.40282347e+38"
816 "}";
817
818 struct test_float_limits limits = {
819 .float_max = 3.40282347e+38,
820 .float_cero = 0,
821 .float_min = -3.40282347e+38,
822 };
823
824 char buffer[sizeof(encoded)];
825 struct test_float_limits limits_decoded = {0};
826 int ret;
827
828 ret = json_obj_encode_buf(obj_float_limits_descr, ARRAY_SIZE(obj_float_limits_descr),
829 &limits, buffer, sizeof(buffer));
830 zassert_equal(ret, 0, "Encoding of float limits returned error");
831 ret = json_obj_parse(encoded, sizeof(encoded), obj_float_limits_descr,
832 ARRAY_SIZE(obj_float_limits_descr), &limits_decoded);
833 zassert_str_equal(encoded, buffer,
834 "Float limits not encoded correctly");
835 zassert_true(!memcmp(&limits, &limits_decoded, sizeof(limits)),
836 "Float limits not decoded correctly");
837 }
838
ZTEST(lib_json_test,test_json_double)839 ZTEST(lib_json_test, test_json_double)
840 {
841 char encoded[] = "{\"some_double\":-0.000244140625,"
842 "\"another_double\":1234567890000000,"
843 "\"some_array\":[1.5,2.25]"
844 "}";
845
846 struct test_double doubles = {
847 .some_double = -0.000244140625,
848 .another_double = 1234567890000000.0,
849 .some_array[0] = 1.5,
850 .some_array[1] = 2.25,
851 .some_array_len = 2,
852 };
853
854 char buffer[sizeof(encoded)];
855 struct test_double doubles_decoded = {0};
856 int ret;
857
858 ret = json_obj_encode_buf(obj_double_descr, ARRAY_SIZE(obj_double_descr),
859 &doubles, buffer, sizeof(buffer));
860 zassert_equal(ret, 0, "Encoding of double returned error");
861 ret = json_obj_parse(encoded, sizeof(encoded), obj_double_descr,
862 ARRAY_SIZE(obj_double_descr), &doubles_decoded);
863 zassert_str_equal(encoded, buffer,
864 "Double not encoded correctly");
865 zassert_true(!memcmp(&doubles, &doubles_decoded, sizeof(doubles)),
866 "Double not decoded correctly");
867 }
868
ZTEST(lib_json_test,test_json_double_format)869 ZTEST(lib_json_test, test_json_double_format)
870 {
871 struct sub_test {
872 double num;
873 char *str;
874 };
875 struct sub_test encoded[] = {
876 { .num = 0, .str = "0" },
877 { .num = 0, .str = "0.0" },
878 { .num = 0, .str = "0e0" },
879 { .num = 0, .str = "0e+0" },
880 { .num = 0, .str = "0e-0" },
881
882 { .num = 12345, .str = "12345" },
883 { .num = 12345, .str = "1.2345e+4" },
884 { .num = 12345, .str = "1.2345e+04" },
885
886 { .num = -12345, .str = "-12345" },
887 { .num = -12345, .str = "-1.2345e+4" },
888 { .num = -12345, .str = "-1.2345e+04" },
889
890 { .num = 0.03125, .str = "0.03125" },
891 { .num = 0.03125, .str = "3.125e-2" },
892 { .num = 0.03125, .str = "3.125e-02" },
893
894 { .num = -0.03125, .str = "-0.03125" },
895 { .num = -0.03125, .str = "-3.125e-2" },
896 { .num = -0.03125, .str = "-3.125e-02" },
897 };
898
899 struct test_double ts;
900 char str_encoded[32];
901
902 for (int i = 0; i < ARRAY_SIZE(encoded); i++) {
903 snprintf(str_encoded, sizeof(str_encoded), "{\"some_double\":%s}", encoded[i].str);
904 int ret = json_obj_parse(str_encoded, strlen(str_encoded),
905 obj_double_descr, ARRAY_SIZE(obj_double_descr), &ts);
906 zassert_equal(ret, 1, "Decoding failed: %s result: %d", str_encoded, ret);
907 zassert_equal(ts.some_double, encoded[i].num,
908 "Decoding failed '%s' double: %g exepcted: %g",
909 str_encoded, ts.some_double, encoded[i].num);
910 }
911 }
912
913
ZTEST(lib_json_test,test_json_double_nan)914 ZTEST(lib_json_test, test_json_double_nan)
915 {
916 char encoded[] = "{\"some_double\":NaN,"
917 "\"another_double\":NaN,"
918 "\"some_array\":[NaN,NaN]"
919 "}";
920
921 struct test_double doubles = {
922 .some_double = (double)NAN,
923 .another_double = (double)NAN,
924 .some_array[0] = (double)NAN,
925 .some_array[1] = (double)NAN,
926 .some_array_len = 2,
927 };
928
929 char buffer[sizeof(encoded)];
930 struct test_double doubles_decoded = {0};
931 int ret;
932
933 ret = json_obj_encode_buf(obj_double_descr, ARRAY_SIZE(obj_double_descr),
934 &doubles, buffer, sizeof(buffer));
935 zassert_equal(ret, 0, "Encoding of double nan returned error");
936 ret = json_obj_parse(encoded, sizeof(encoded), obj_double_descr,
937 ARRAY_SIZE(obj_double_descr), &doubles_decoded);
938 zassert_str_equal(encoded, buffer,
939 "Double not encoded correctly");
940 zassert_true(!memcmp(&doubles, &doubles_decoded, sizeof(doubles)),
941 "Double not decoded correctly");
942 }
943
ZTEST(lib_json_test,test_json_double_infinity)944 ZTEST(lib_json_test, test_json_double_infinity)
945 {
946 char encoded[] = "{\"some_double\":Infinity,"
947 "\"another_double\":-Infinity,"
948 "\"some_array\":[Infinity,-Infinity]"
949 "}";
950
951 struct test_double doubles = {
952 .some_double = (double)INFINITY,
953 .another_double = (double)-INFINITY,
954 .some_array[0] = (double)INFINITY,
955 .some_array[1] = (double)-INFINITY,
956 .some_array_len = 2,
957 };
958
959 char buffer[sizeof(encoded)];
960 struct test_double doubles_decoded = {0};
961 int ret;
962
963 ret = json_obj_encode_buf(obj_double_descr, ARRAY_SIZE(obj_double_descr),
964 &doubles, buffer, sizeof(buffer));
965 zassert_equal(ret, 0, "Encoding of double inf returned error");
966 ret = json_obj_parse(encoded, sizeof(encoded), obj_double_descr,
967 ARRAY_SIZE(obj_double_descr), &doubles_decoded);
968 zassert_str_equal(encoded, buffer,
969 "Double not encoded correctly");
970 zassert_true(!memcmp(&doubles, &doubles_decoded, sizeof(doubles)),
971 "Double not decoded correctly");
972 }
973
ZTEST(lib_json_test,test_json_doubles_limits)974 ZTEST(lib_json_test, test_json_doubles_limits)
975 {
976 char encoded[] = "{\"double_max\":1.797693134862315e+308,"
977 "\"double_cero\":0,"
978 "\"double_min\":-1.797693134862315e+308"
979 "}";
980
981 struct test_double_limits limits = {
982 .double_max = 1.797693134862315e+308,
983 .double_cero = 0,
984 .double_min = -1.797693134862315e+308,
985 };
986
987 char buffer[sizeof(encoded)];
988 struct test_double_limits limits_decoded = {0};
989 int ret;
990
991 ret = json_obj_encode_buf(obj_double_limits_descr, ARRAY_SIZE(obj_double_limits_descr),
992 &limits, buffer, sizeof(buffer));
993 zassert_equal(ret, 0, "Encoding of double limits returned error");
994 ret = json_obj_parse(encoded, sizeof(encoded), obj_double_limits_descr,
995 ARRAY_SIZE(obj_double_limits_descr), &limits_decoded);
996 zassert_str_equal(encoded, buffer,
997 "Double limits not encoded correctly");
998 zassert_true(!memcmp(&limits, &limits_decoded, sizeof(limits)),
999 "Double limits not decoded correctly");
1000 }
1001
ZTEST(lib_json_test,test_json_encoding_array_array)1002 ZTEST(lib_json_test, test_json_encoding_array_array)
1003 {
1004 struct obj_array_array obj_array_array_ts = {
1005 .objects_array = {
1006 [0] = {{.name = "Sim\303\263n Bol\303\255var",
1007 .name_buf = "Sim\303\263n",
1008 .height = 168}},
1009 [1] = {{.name = "Pel\303\251",
1010 .name_buf = "Pel\303\251",
1011 .height = 173}},
1012 [2] = {{.name = "Usain Bolt",
1013 .name_buf = "Usain",
1014 .height = 195}},
1015 },
1016 .objects_array_len = 3,
1017 };
1018 char encoded[] = "{\"objects_array\":["
1019 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1020 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1021 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195}"
1022 "]}";
1023
1024 char buffer[sizeof(encoded)];
1025 int ret;
1026
1027 ret = json_obj_encode_buf(array_array_descr, ARRAY_SIZE(array_array_descr),
1028 &obj_array_array_ts, buffer, sizeof(buffer));
1029 zassert_equal(ret, 0, "Encoding array returned error");
1030 zassert_str_equal(buffer, encoded,
1031 "Encoded array of objects is not consistent");
1032 }
1033
ZTEST(lib_json_test,test_json_decoding_array_array)1034 ZTEST(lib_json_test, test_json_decoding_array_array)
1035 {
1036 int ret;
1037 struct obj_array_array obj_array_array_ts;
1038 char encoded[] = "{\"objects_array\":["
1039 "{\"height\":168,\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\"},"
1040 "{\"height\":173,\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\"},"
1041 "{\"height\":195,\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\"}]"
1042 "}";
1043
1044 ret = json_obj_parse(encoded, sizeof(encoded),
1045 array_array_descr,
1046 ARRAY_SIZE(array_array_descr),
1047 &obj_array_array_ts);
1048
1049 zassert_equal(ret, 1, "Encoding array of objects returned error");
1050 zassert_equal(obj_array_array_ts.objects_array_len, 3,
1051 "Array doesn't have correct number of items");
1052
1053 zassert_str_equal(obj_array_array_ts.objects_array[0].objects.name,
1054 "Sim\303\263n Bol\303\255var",
1055 "String not decoded correctly");
1056 zassert_str_equal(obj_array_array_ts.objects_array[0].objects.name_buf,
1057 "Sim\303\263n",
1058 "String buffer not decoded correctly");
1059 zassert_equal(obj_array_array_ts.objects_array[0].objects.height, 168,
1060 "Sim\303\263n Bol\303\255var height not decoded correctly");
1061
1062 zassert_str_equal(obj_array_array_ts.objects_array[1].objects.name,
1063 "Pel\303\251", "String not decoded correctly");
1064 zassert_str_equal(obj_array_array_ts.objects_array[1].objects.name_buf,
1065 "Pel\303\251", "String buffer not decoded correctly");
1066 zassert_equal(obj_array_array_ts.objects_array[1].objects.height, 173,
1067 "Pel\303\251 height not decoded correctly");
1068
1069 zassert_str_equal(obj_array_array_ts.objects_array[2].objects.name,
1070 "Usain Bolt", "String not decoded correctly");
1071 zassert_str_equal(obj_array_array_ts.objects_array[2].objects.name_buf,
1072 "Usain", "String buffer not decoded correctly");
1073 zassert_equal(obj_array_array_ts.objects_array[2].objects.height, 195,
1074 "Usain Bolt height not decoded correctly");
1075 }
1076
ZTEST(lib_json_test,test_json_obj_arr_encoding)1077 ZTEST(lib_json_test, test_json_obj_arr_encoding)
1078 {
1079 struct obj_array oa = {
1080 .elements = {
1081 [0] = {
1082 .name = "Sim\303\263n Bol\303\255var",
1083 .name_buf = "Sim\303\263n",
1084 .height = 168 },
1085 [1] = {
1086 .name = "Muggsy Bogues",
1087 .name_buf = "Muggsy",
1088 .height = 160 },
1089 [2] = {
1090 .name = "Pel\303\251",
1091 .name_buf = "Pel\303\251",
1092 .height = 173 },
1093 [3] = {
1094 .name = "Hakeem Olajuwon",
1095 .name_buf = "Hakeem",
1096 .height = 213 },
1097 [4] = {
1098 .name = "Alex Honnold",
1099 .name_buf = "Alex",
1100 .height = 180 },
1101 [5] = {
1102 .name = "Hazel Findlay",
1103 .name_buf = "Hazel",
1104 .height = 157 },
1105 [6] = {
1106 .name = "Daila Ojeda",
1107 .name_buf = "Daila",
1108 .height = 158 },
1109 [7] = {
1110 .name = "Albert Einstein",
1111 .name_buf = "Albert",
1112 .height = 172 },
1113 [8] = {
1114 .name = "Usain Bolt",
1115 .name_buf = "Usain",
1116 .height = 195 },
1117 [9] = {
1118 .name = "Paavo Nurmi",
1119 .name_buf = "Paavo",
1120 .height = 174 },
1121 },
1122 .num_elements = 10,
1123 };
1124 char encoded[] = "{\"elements\":["
1125 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1126 "{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1127 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1128 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213},"
1129 "{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1130 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1131 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1132 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172},"
1133 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195},"
1134 "{\"name\":\"Paavo Nurmi\",\"name_buf\":\"Paavo\",\"height\":174}"
1135 "]}";
1136 char buffer[sizeof(encoded)];
1137 int ret;
1138
1139 ret = json_obj_encode_buf(obj_array_descr, ARRAY_SIZE(obj_array_descr),
1140 &oa, buffer, sizeof(buffer));
1141 zassert_equal(ret, 0, "Encoding array of object returned error");
1142 zassert_str_equal(buffer, encoded,
1143 "Encoded array of objects is not consistent");
1144 }
1145
ZTEST(lib_json_test,test_json_arr_obj_decoding)1146 ZTEST(lib_json_test, test_json_arr_obj_decoding)
1147 {
1148 int ret;
1149 struct obj_array obj_array_array_ts;
1150 char encoded[] = "[{\"height\":168,\"name\":\"Sim\303\263n Bol\303\255var\","
1151 "\"name_buf\":\"Sim\303\263n\"},"
1152 "{\"height\":173,\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\"},"
1153 "{\"height\":195,\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\"}"
1154 "]";
1155
1156 ret = json_arr_parse(encoded, sizeof(encoded),
1157 obj_array_descr,
1158 &obj_array_array_ts);
1159
1160 zassert_equal(ret, 0, "Encoding array of objects returned error %d", ret);
1161 zassert_equal(obj_array_array_ts.num_elements, 3,
1162 "Array doesn't have correct number of items");
1163
1164 zassert_str_equal(obj_array_array_ts.elements[0].name,
1165 "Sim\303\263n Bol\303\255var",
1166 "String not decoded correctly");
1167 zassert_str_equal(obj_array_array_ts.elements[0].name_buf,
1168 "Sim\303\263n",
1169 "String buffer not decoded correctly");
1170 zassert_equal(obj_array_array_ts.elements[0].height, 168,
1171 "Sim\303\263n Bol\303\255var height not decoded correctly");
1172
1173 zassert_str_equal(obj_array_array_ts.elements[1].name, "Pel\303\251",
1174 "String not decoded correctly");
1175 zassert_str_equal(obj_array_array_ts.elements[1].name_buf, "Pel\303\251",
1176 "String buffer not decoded correctly");
1177 zassert_equal(obj_array_array_ts.elements[1].height, 173,
1178 "Pel\303\251 height not decoded correctly");
1179
1180 zassert_str_equal(obj_array_array_ts.elements[2].name, "Usain Bolt",
1181 "String not decoded correctly");
1182 zassert_str_equal(obj_array_array_ts.elements[2].name_buf, "Usain",
1183 "String buffer not decoded correctly");
1184 zassert_equal(obj_array_array_ts.elements[2].height, 195,
1185 "Usain Bolt height not decoded correctly");
1186 }
1187
ZTEST(lib_json_test,test_json_arr_obj_encoding)1188 ZTEST(lib_json_test, test_json_arr_obj_encoding)
1189 {
1190 struct obj_array oa = {
1191 .elements = {
1192 [0] = {
1193 .name = "Sim\303\263n Bol\303\255var",
1194 .name_buf = "Sim\303\263n",
1195 .height = 168 },
1196 [1] = {
1197 .name = "Muggsy Bogues",
1198 .name_buf = "Muggsy",
1199 .height = 160 },
1200 [2] = {
1201 .name = "Pel\303\251",
1202 .name_buf = "Pel\303\251",
1203 .height = 173 },
1204 [3] = {
1205 .name = "Hakeem Olajuwon",
1206 .name_buf = "Hakeem",
1207 .height = 213 },
1208 [4] = {
1209 .name = "Alex Honnold",
1210 .name_buf = "Alex",
1211 .height = 180 },
1212 [5] = {
1213 .name = "Hazel Findlay",
1214 .name_buf = "Hazel",
1215 .height = 157 },
1216 [6] = {
1217 .name = "Daila Ojeda",
1218 .name_buf = "Daila",
1219 .height = 158 },
1220 [7] = {
1221 .name = "Albert Einstein",
1222 .name_buf = "Albert",
1223 .height = 172 },
1224 [8] = {
1225 .name = "Usain Bolt",
1226 .name_buf = "Usain",
1227 .height = 195 },
1228 [9] = {
1229 .name = "Paavo Nurmi",
1230 .name_buf = "Paavo",
1231 .height = 174 },
1232 },
1233 .num_elements = 10,
1234 };
1235 char encoded[] = "["
1236 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1237 "{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1238 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1239 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213},"
1240 "{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1241 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1242 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1243 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172},"
1244 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195},"
1245 "{\"name\":\"Paavo Nurmi\",\"name_buf\":\"Paavo\",\"height\":174}"
1246 "]";
1247 char buffer[sizeof(encoded)];
1248 int ret;
1249 ssize_t len;
1250
1251 len = json_calc_encoded_arr_len(obj_array_descr, &oa);
1252 zassert_equal(len, strlen(encoded), "encoded size mismatch");
1253
1254 ret = json_arr_encode_buf(obj_array_descr, &oa, buffer, sizeof(buffer));
1255 zassert_equal(ret, 0, "Encoding array of object returned error %d", ret);
1256 zassert_str_equal(buffer, encoded,
1257 "Encoded array of objects is not consistent");
1258 }
1259
ZTEST(lib_json_test,test_json_obj_arr_decoding)1260 ZTEST(lib_json_test, test_json_obj_arr_decoding)
1261 {
1262 struct obj_array oa;
1263 char encoded[] = "{\"elements\":["
1264 "{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1265 "{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1266 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1267 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213},"
1268 "{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1269 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1270 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1271 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172},"
1272 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195},"
1273 "{\"name\":\"Paavo Nurmi\",\"name_buf\":\"Paavo\",\"height\":174}"
1274 "]}";
1275 const struct obj_array expected = {
1276 .elements = {
1277 [0] = {
1278 .name = "Sim\303\263n Bol\303\255var",
1279 .name_buf = "Sim\303\263n",
1280 .height = 168 },
1281 [1] = {
1282 .name = "Muggsy Bogues",
1283 .name_buf = "Muggsy",
1284 .height = 160 },
1285 [2] = {
1286 .name = "Pel\303\251",
1287 .name_buf = "Pel\303\251",
1288 .height = 173 },
1289 [3] = {
1290 .name = "Hakeem Olajuwon",
1291 .name_buf = "Hakeem",
1292 .height = 213 },
1293 [4] = {
1294 .name = "Alex Honnold",
1295 .name_buf = "Alex",
1296 .height = 180 },
1297 [5] = {
1298 .name = "Hazel Findlay",
1299 .name_buf = "Hazel",
1300 .height = 157 },
1301 [6] = {
1302 .name = "Daila Ojeda",
1303 .name_buf = "Daila",
1304 .height = 158 },
1305 [7] = {
1306 .name = "Albert Einstein",
1307 .name_buf = "Albert",
1308 .height = 172 },
1309 [8] = {
1310 .name = "Usain Bolt",
1311 .name_buf = "Usain",
1312 .height = 195 },
1313 [9] = {
1314 .name = "Paavo Nurmi",
1315 .name_buf = "Paavo",
1316 .height = 174 },
1317 },
1318 .num_elements = 10,
1319 };
1320 int ret;
1321
1322 ret = json_obj_parse(encoded, sizeof(encoded) - 1, obj_array_descr,
1323 ARRAY_SIZE(obj_array_descr), &oa);
1324
1325 zassert_equal(ret, (1 << ARRAY_SIZE(obj_array_descr)) - 1,
1326 "Array of object fields not decoded correctly");
1327 zassert_equal(oa.num_elements, 10,
1328 "Number of object fields not decoded correctly");
1329
1330 for (int i = 0; i < expected.num_elements; i++) {
1331 zassert_true(!strcmp(oa.elements[i].name,
1332 expected.elements[i].name),
1333 "Element %d name not decoded correctly", i);
1334 zassert_equal(oa.elements[i].height,
1335 expected.elements[i].height,
1336 "Element %d height not decoded correctly", i);
1337 }
1338 }
1339
ZTEST(lib_json_test,test_json_2dim_arr_obj_encoding)1340 ZTEST(lib_json_test, test_json_2dim_arr_obj_encoding)
1341 {
1342 struct obj_array_2dim obj_array_array_ts = {
1343 .objects_array_array = {
1344 [0] = {
1345 .elements = {
1346 [0] = {
1347 .name = "Sim\303\263n Bol\303\255var",
1348 .name_buf = "Sim\303\263n",
1349 .height = 168
1350 },
1351 [1] = {
1352 .name = "Pel\303\251",
1353 .name_buf = "Pel\303\251",
1354 .height = 173
1355 },
1356 [2] = {
1357 .name = "Usain Bolt",
1358 .name_buf = "Usain",
1359 .height = 195
1360 },
1361 },
1362 .num_elements = 3
1363 },
1364 [1] = {
1365 .elements = {
1366 [0] = {
1367 .name = "Muggsy Bogues",
1368 .name_buf = "Muggsy",
1369 .height = 160
1370 },
1371 [1] = {
1372 .name = "Hakeem Olajuwon",
1373 .name_buf = "Hakeem",
1374 .height = 213
1375 },
1376 },
1377 .num_elements = 2
1378 },
1379 [2] = {
1380 .elements = {
1381 [0] = {
1382 .name = "Alex Honnold",
1383 .name_buf = "Alex",
1384 .height = 180
1385 },
1386 [1] = {
1387 .name = "Hazel Findlay",
1388 .name_buf = "Hazel",
1389 .height = 157
1390 },
1391 [2] = {
1392 .name = "Daila Ojeda",
1393 .name_buf = "Daila",
1394 .height = 158
1395 },
1396 [3] = {
1397 .name = "Albert Einstein",
1398 .name_buf = "Albert",
1399 .height = 172
1400 },
1401 },
1402 .num_elements = 4
1403 },
1404 },
1405 .objects_array_array_len = 3,
1406 };
1407 char encoded[] = "{\"objects_array_array\":["
1408 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1409 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1410 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195}],"
1411 "[{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1412 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213}],"
1413 "[{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1414 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1415 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1416 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172}]"
1417 "]}";
1418 char buffer[sizeof(encoded)];
1419 int ret;
1420
1421 ret = json_obj_encode_buf(array_2dim_descr, ARRAY_SIZE(array_2dim_descr),
1422 &obj_array_array_ts, buffer, sizeof(buffer));
1423 zassert_equal(ret, 0, "Encoding two-dimensional array returned error");
1424 zassert_str_equal(buffer, encoded,
1425 "Encoded two-dimensional array is not consistent");
1426 }
1427
ZTEST(lib_json_test,test_json_2dim_arr_extra_obj_encoding)1428 ZTEST(lib_json_test, test_json_2dim_arr_extra_obj_encoding)
1429 {
1430 struct obj_array_2dim_extra obj_array_2dim_extra_ts = {
1431 .name = "Paavo Nurmi",
1432 .val = 123,
1433 .obj_array_2dim.objects_array_array = {
1434 [0] = {
1435 .elements = {
1436 [0] = {
1437 .name = "Sim\303\263n Bol\303\255var",
1438 .name_buf = "Sim\303\263n",
1439 .height = 168
1440 },
1441 [1] = {
1442 .name = "Pel\303\251",
1443 .name_buf = "Pel\303\251",
1444 .height = 173
1445 },
1446 [2] = {
1447 .name = "Usain Bolt",
1448 .name_buf = "Usain",
1449 .height = 195
1450 },
1451 },
1452 .num_elements = 3
1453 },
1454 [1] = {
1455 .elements = {
1456 [0] = {
1457 .name = "Muggsy Bogues",
1458 .name_buf = "Muggsy",
1459 .height = 160
1460 },
1461 [1] = {
1462 .name = "Hakeem Olajuwon",
1463 .name_buf = "Hakeem",
1464 .height = 213
1465 },
1466 },
1467 .num_elements = 2
1468 },
1469 [2] = {
1470 .elements = {
1471 [0] = {
1472 .name = "Alex Honnold",
1473 .name_buf = "Alex",
1474 .height = 180
1475 },
1476 [1] = {
1477 .name = "Hazel Findlay",
1478 .name_buf = "Hazel",
1479 .height = 157
1480 },
1481 [2] = {
1482 .name = "Daila Ojeda",
1483 .name_buf = "Daila",
1484 .height = 158
1485 },
1486 [3] = {
1487 .name = "Albert Einstein",
1488 .name_buf = "Albert",
1489 .height = 172
1490 },
1491 },
1492 .num_elements = 4
1493 },
1494 },
1495 .obj_array_2dim.objects_array_array_len = 3,
1496 };
1497
1498 char encoded[] = "{\"name\":\"Paavo Nurmi\",\"val\":123,"
1499 "\"obj_array_2dim\":["
1500 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1501 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1502 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195}],"
1503 "[{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1504 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213}],"
1505 "[{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1506 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1507 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1508 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172}]"
1509 "]}";
1510 char buffer[sizeof(encoded)];
1511 int ret;
1512
1513 ret = json_obj_encode_buf(array_2dim_extra_descr, ARRAY_SIZE(array_2dim_extra_descr),
1514 &obj_array_2dim_extra_ts, buffer, sizeof(buffer));
1515 zassert_equal(ret, 0, "Encoding two-dimensional extra array returned error");
1516 zassert_str_equal(buffer, encoded,
1517 "Encoded two-dimensional extra array is not consistent");
1518 }
1519
ZTEST(lib_json_test,test_json_2dim_arr_extra_named_obj_encoding)1520 ZTEST(lib_json_test, test_json_2dim_arr_extra_named_obj_encoding)
1521 {
1522 struct obj_array_2dim_extra obj_array_2dim_extra_ts = {
1523 .name = "Paavo Nurmi",
1524 .val = 123,
1525 .obj_array_2dim.objects_array_array = {
1526 [0] = {
1527 .elements = {
1528 [0] = {
1529 .name = "Sim\303\263n Bol\303\255var",
1530 .name_buf = "Sim\303\263n",
1531 .height = 168
1532 },
1533 [1] = {
1534 .name = "Pel\303\251",
1535 .name_buf = "Pel\303\251",
1536 .height = 173
1537 },
1538 [2] = {
1539 .name = "Usain Bolt",
1540 .name_buf = "Usain",
1541 .height = 195
1542 },
1543 },
1544 .num_elements = 3
1545 },
1546 [1] = {
1547 .elements = {
1548 [0] = {
1549 .name = "Muggsy Bogues",
1550 .name_buf = "Muggsy",
1551 .height = 160
1552 },
1553 [1] = {
1554 .name = "Hakeem Olajuwon",
1555 .name_buf = "Hakeem",
1556 .height = 213
1557 },
1558 },
1559 .num_elements = 2
1560 },
1561 [2] = {
1562 .elements = {
1563 [0] = {
1564 .name = "Alex Honnold",
1565 .name_buf = "Alex",
1566 .height = 180
1567 },
1568 [1] = {
1569 .name = "Hazel Findlay",
1570 .name_buf = "Hazel",
1571 .height = 157
1572 },
1573 [2] = {
1574 .name = "Daila Ojeda",
1575 .name_buf = "Daila",
1576 .height = 158
1577 },
1578 [3] = {
1579 .name = "Albert Einstein",
1580 .name_buf = "Albert",
1581 .height = 172
1582 },
1583 },
1584 .num_elements = 4
1585 },
1586 },
1587 .obj_array_2dim.objects_array_array_len = 3,
1588 };
1589
1590 char encoded[] = "{\"name\":\"Paavo Nurmi\",\"val\":123,"
1591 "\"data\":["
1592 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1593 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1594 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195}],"
1595 "[{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1596 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213}],"
1597 "[{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1598 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1599 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1600 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172}]"
1601 "]}";
1602 char buffer[sizeof(encoded)];
1603 int ret;
1604
1605 ret = json_obj_encode_buf(array_2dim_extra_named_descr,
1606 ARRAY_SIZE(array_2dim_extra_named_descr),
1607 &obj_array_2dim_extra_ts, buffer, sizeof(buffer));
1608 zassert_equal(ret, 0, "Encoding two-dimensional extra named array returned error");
1609 zassert_str_equal(buffer, encoded,
1610 "Encoded two-dimensional extra named array is not consistent");
1611 }
1612
ZTEST(lib_json_test,test_json_2dim_obj_arr_decoding)1613 ZTEST(lib_json_test, test_json_2dim_obj_arr_decoding)
1614 {
1615 struct obj_array_2dim oaa;
1616 char encoded[] = "{\"objects_array_array\":["
1617 "[{\"name\":\"Sim\303\263n Bol\303\255var\",\"name_buf\":\"Sim\303\263n\",\"height\":168},"
1618 "{\"name\":\"Pel\303\251\",\"name_buf\":\"Pel\303\251\",\"height\":173},"
1619 "{\"name\":\"Usain Bolt\",\"name_buf\":\"Usain\",\"height\":195}],"
1620 "[{\"name\":\"Muggsy Bogues\",\"name_buf\":\"Muggsy\",\"height\":160},"
1621 "{\"name\":\"Hakeem Olajuwon\",\"name_buf\":\"Hakeem\",\"height\":213}],"
1622 "[{\"name\":\"Alex Honnold\",\"name_buf\":\"Alex\",\"height\":180},"
1623 "{\"name\":\"Hazel Findlay\",\"name_buf\":\"Hazel\",\"height\":157},"
1624 "{\"name\":\"Daila Ojeda\",\"name_buf\":\"Daila\",\"height\":158},"
1625 "{\"name\":\"Albert Einstein\",\"name_buf\":\"Albert\",\"height\":172}]"
1626 "]}";
1627 const struct obj_array_2dim expected = {
1628 .objects_array_array = {
1629 [0] = {
1630 .elements = {
1631 [0] = {
1632 .name = "Sim\303\263n Bol\303\255var",
1633 .name_buf = "Sim\303\263n",
1634 .height = 168
1635 },
1636 [1] = {
1637 .name = "Pel\303\251",
1638 .name_buf = "Pel\303\251",
1639 .height = 173
1640 },
1641 [2] = {
1642 .name = "Usain Bolt",
1643 .name_buf = "Usain",
1644 .height = 195
1645 },
1646 },
1647 .num_elements = 3
1648 },
1649 [1] = {
1650 .elements = {
1651 [0] = {
1652 .name = "Muggsy Bogues",
1653 .name_buf = "Muggsy",
1654 .height = 160
1655 },
1656 [1] = {
1657 .name = "Hakeem Olajuwon",
1658 .name_buf = "Hakeem",
1659 .height = 213
1660 },
1661 },
1662 .num_elements = 2
1663 },
1664 [2] = {
1665 .elements = {
1666 [0] = {
1667 .name = "Alex Honnold",
1668 .name_buf = "Alex",
1669 .height = 180
1670 },
1671 [1] = {
1672 .name = "Hazel Findlay",
1673 .name_buf = "Hazel",
1674 .height = 157
1675 },
1676 [2] = {
1677 .name = "Daila Ojeda",
1678 .name_buf = "Daila",
1679 .height = 158
1680 },
1681 [3] = {
1682 .name = "Albert Einstein",
1683 .name_buf = "Albert",
1684 .height = 172
1685 },
1686 },
1687 .num_elements = 4
1688 },
1689 },
1690 .objects_array_array_len = 3,
1691 };
1692 int ret;
1693
1694 ret = json_obj_parse(encoded, sizeof(encoded),
1695 array_2dim_descr,
1696 ARRAY_SIZE(array_2dim_descr),
1697 &oaa);
1698
1699 zassert_equal(ret, 1, "Array of arrays fields not decoded correctly");
1700 zassert_equal(oaa.objects_array_array_len, 3,
1701 "Number of subarrays not decoded correctly");
1702 zassert_equal(oaa.objects_array_array[0].num_elements, 3,
1703 "Number of object fields not decoded correctly");
1704 zassert_equal(oaa.objects_array_array[1].num_elements, 2,
1705 "Number of object fields not decoded correctly");
1706 zassert_equal(oaa.objects_array_array[2].num_elements, 4,
1707 "Number of object fields not decoded correctly");
1708
1709 for (int i = 0; i < expected.objects_array_array_len; i++) {
1710 for (int j = 0; j < expected.objects_array_array[i].num_elements; j++) {
1711 zassert_true(!strcmp(oaa.objects_array_array[i].elements[j].name,
1712 expected.objects_array_array[i].elements[j].name),
1713 "Element [%d][%d] name not decoded correctly", i, j);
1714 zassert_true(!strcmp(oaa.objects_array_array[i].elements[j].name_buf,
1715 expected.objects_array_array[i].elements[j].name_buf),
1716 "Element [%d][%d] name array not decoded correctly", i, j);
1717 zassert_equal(oaa.objects_array_array[i].elements[j].height,
1718 expected.objects_array_array[i].elements[j].height,
1719 "Element [%d][%d] height not decoded correctly", i, j);
1720 }
1721 }
1722 }
1723
ZTEST(lib_json_test,test_json_string_array_size)1724 ZTEST(lib_json_test, test_json_string_array_size)
1725 {
1726 int ret;
1727 struct elt elt_ts;
1728 char encoded[] = "{\"name_buf\":\"a12345678\"}";
1729
1730 ret = json_obj_parse(encoded, sizeof(encoded),
1731 elt_descr,
1732 ARRAY_SIZE(elt_descr),
1733 &elt_ts);
1734
1735 /* size of name_buf is 10 */
1736 zassert_str_equal(elt_ts.name_buf,
1737 "a12345678", "String not decoded correctly");
1738 }
1739
ZTEST(lib_json_test,test_json_string_array_empty)1740 ZTEST(lib_json_test, test_json_string_array_empty)
1741 {
1742 int ret;
1743 struct elt elt_ts;
1744 char encoded[] = "{\"name_buf\":\"\"}";
1745
1746 ret = json_obj_parse(encoded, sizeof(encoded),
1747 elt_descr,
1748 ARRAY_SIZE(elt_descr),
1749 &elt_ts);
1750
1751 /* size of name_buf is 10 */
1752 zassert_str_equal(elt_ts.name_buf, "", "String not decoded correctly");
1753 }
1754
ZTEST(lib_json_test,test_json_string_array_max)1755 ZTEST(lib_json_test, test_json_string_array_max)
1756 {
1757 int ret;
1758 struct elt elt_ts;
1759 char encoded[] = "{\"name_buf\":\"a123456789\"}";
1760
1761 ret = json_obj_parse(encoded, sizeof(encoded),
1762 elt_descr,
1763 ARRAY_SIZE(elt_descr),
1764 &elt_ts);
1765
1766 /* string does not fit into name_buf */
1767 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1768 }
1769
1770 struct encoding_test {
1771 char *str;
1772 int result;
1773 };
1774
parse_harness(struct encoding_test encoded[],size_t size)1775 static void parse_harness(struct encoding_test encoded[], size_t size)
1776 {
1777 struct test_struct ts;
1778 int ret;
1779
1780 for (int i = 0; i < size; i++) {
1781 ret = json_obj_parse(encoded[i].str, strlen(encoded[i].str),
1782 test_descr, ARRAY_SIZE(test_descr), &ts);
1783 zassert_equal(ret, encoded[i].result,
1784 "Decoding '%s' result %d, expected %d",
1785 encoded[i].str, ret, encoded[i].result);
1786 }
1787 }
1788
ZTEST(lib_json_test,test_json_invalid_string)1789 ZTEST(lib_json_test, test_json_invalid_string)
1790 {
1791 struct encoding_test encoded[] = {
1792 { "{\"some_string\":\"\\u@@@@\"}", -EINVAL },
1793 { "{\"some_string\":\"\\uA@@@\"}", -EINVAL },
1794 { "{\"some_string\":\"\\uAB@@\"}", -EINVAL },
1795 { "{\"some_string\":\"\\uABC@\"}", -EINVAL },
1796 { "{\"some_string\":\"\\X\"}", -EINVAL }
1797 };
1798
1799 parse_harness(encoded, ARRAY_SIZE(encoded));
1800 }
1801
ZTEST(lib_json_test,test_json_invalid_bool)1802 ZTEST(lib_json_test, test_json_invalid_bool)
1803 {
1804 struct encoding_test encoded[] = {
1805 { "{\"some_bool\":truffle }", -EINVAL},
1806 { "{\"some_bool\":fallacy }", -EINVAL},
1807 };
1808
1809 parse_harness(encoded, ARRAY_SIZE(encoded));
1810 }
1811
ZTEST(lib_json_test,test_json_invalid_null)1812 ZTEST(lib_json_test, test_json_invalid_null)
1813 {
1814 struct encoding_test encoded[] = {
1815 /* Parser will recognize 'null', but refuse to decode it */
1816 { "{\"some_string\":null }", -EINVAL},
1817 /* Null spelled wrong */
1818 { "{\"some_string\":nutella }", -EINVAL},
1819 };
1820
1821 parse_harness(encoded, ARRAY_SIZE(encoded));
1822 }
1823
ZTEST(lib_json_test,test_json_invalid_number)1824 ZTEST(lib_json_test, test_json_invalid_number)
1825 {
1826 struct encoding_test encoded[] = {
1827 { "{\"some_int\":xxx }", -EINVAL},
1828 };
1829
1830 parse_harness(encoded, ARRAY_SIZE(encoded));
1831 }
1832
ZTEST(lib_json_test,test_json_missing_quote)1833 ZTEST(lib_json_test, test_json_missing_quote)
1834 {
1835 struct test_struct ts;
1836 char encoded[] = "{\"some_string";
1837 int ret;
1838
1839 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1840 ARRAY_SIZE(test_descr), &ts);
1841 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1842 }
1843
ZTEST(lib_json_test,test_json_wrong_token)1844 ZTEST(lib_json_test, test_json_wrong_token)
1845 {
1846 struct test_struct ts;
1847 char encoded[] = "{\"some_string\",}";
1848 int ret;
1849
1850 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1851 ARRAY_SIZE(test_descr), &ts);
1852 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1853 }
1854
ZTEST(lib_json_test,test_json_item_wrong_type)1855 ZTEST(lib_json_test, test_json_item_wrong_type)
1856 {
1857 struct test_struct ts;
1858 char encoded[] = "{\"some_string\":false}";
1859 int ret;
1860
1861 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1862 ARRAY_SIZE(test_descr), &ts);
1863 zassert_equal(ret, -EINVAL, "Decoding has to fail");
1864 }
1865
ZTEST(lib_json_test,test_json_key_not_in_descr)1866 ZTEST(lib_json_test, test_json_key_not_in_descr)
1867 {
1868 struct test_struct ts;
1869 char encoded[] = "{\"key_not_in_descr\":123456}";
1870 int ret;
1871
1872 ret = json_obj_parse(encoded, sizeof(encoded) - 1, test_descr,
1873 ARRAY_SIZE(test_descr), &ts);
1874 zassert_equal(ret, 0, "No items should be decoded");
1875 }
1876
ZTEST(lib_json_test,test_json_escape)1877 ZTEST(lib_json_test, test_json_escape)
1878 {
1879 char buf[42];
1880 char string[] = "\"abc"
1881 "\\1`23"
1882 "\bf'oo"
1883 "\fbar"
1884 "\nbaz"
1885 "\rquux"
1886 "\tfred\"";
1887 const char *expected = "\\\"abc"
1888 "\\\\1`23"
1889 "\\bf'oo"
1890 "\\fbar"
1891 "\\nbaz"
1892 "\\rquux"
1893 "\\tfred\\\"";
1894 size_t len;
1895 ssize_t ret;
1896
1897 strncpy(buf, string, sizeof(buf) - 1);
1898 len = strlen(buf);
1899
1900 ret = json_escape(buf, &len, sizeof(buf));
1901 zassert_equal(ret, 0, "Escape did not succeed");
1902 zassert_equal(len, sizeof(buf) - 1,
1903 "Escaped length not computed correctly");
1904 zassert_str_equal(buf, expected, "Escaped value is not correct");
1905 }
1906
1907 /* Edge case: only one character, which must be escaped. */
ZTEST(lib_json_test,test_json_escape_one)1908 ZTEST(lib_json_test, test_json_escape_one)
1909 {
1910 char buf[3] = {'\t', '\0', '\0'};
1911 const char *expected = "\\t";
1912 size_t len = strlen(buf);
1913 ssize_t ret;
1914
1915 ret = json_escape(buf, &len, sizeof(buf));
1916 zassert_equal(ret, 0,
1917 "Escaping one character did not succeed");
1918 zassert_equal(len, sizeof(buf) - 1,
1919 "Escaping one character length is not correct");
1920 zassert_str_equal(buf, expected, "Escaped value is not correct");
1921 }
1922
ZTEST(lib_json_test,test_json_escape_empty)1923 ZTEST(lib_json_test, test_json_escape_empty)
1924 {
1925 char empty[] = "";
1926 size_t len = sizeof(empty) - 1;
1927 ssize_t ret;
1928
1929 ret = json_escape(empty, &len, sizeof(empty));
1930 zassert_equal(ret, 0, "Escaping empty string not successful");
1931 zassert_equal(len, 0, "Length of empty escaped string is not zero");
1932 zassert_equal(empty[0], '\0', "Empty string does not remain empty");
1933 }
1934
ZTEST(lib_json_test,test_json_escape_no_op)1935 ZTEST(lib_json_test, test_json_escape_no_op)
1936 {
1937 char nothing_to_escape[] = "hello,world:!";
1938 const char *expected = "hello,world:!";
1939 size_t len = sizeof(nothing_to_escape) - 1;
1940 ssize_t ret;
1941
1942 ret = json_escape(nothing_to_escape, &len, sizeof(nothing_to_escape));
1943 zassert_equal(ret, 0, "Escape no-op not handled correctly");
1944 zassert_equal(len, sizeof(nothing_to_escape) - 1,
1945 "Changed length of already escaped string");
1946 zassert_str_equal(nothing_to_escape, expected,
1947 "Altered string with nothing to escape");
1948 }
1949
ZTEST(lib_json_test,test_json_escape_bounds_check)1950 ZTEST(lib_json_test, test_json_escape_bounds_check)
1951 {
1952 char not_enough_memory[] = "\tfoo";
1953 size_t len = sizeof(not_enough_memory) - 1;
1954 ssize_t ret;
1955
1956 ret = json_escape(not_enough_memory, &len, sizeof(not_enough_memory));
1957 zassert_equal(ret, -ENOMEM, "Bounds check failed");
1958 }
1959
ZTEST(lib_json_test,test_json_encode_bounds_check)1960 ZTEST(lib_json_test, test_json_encode_bounds_check)
1961 {
1962 struct number {
1963 uint32_t val;
1964 } str = { 0 };
1965 const struct json_obj_descr descr[] = {
1966 JSON_OBJ_DESCR_PRIM(struct number, val, JSON_TOK_NUMBER),
1967 };
1968 /* Encodes to {"val":0}\0 for a total of 10 bytes */
1969 uint8_t buf[10];
1970 ssize_t ret = json_obj_encode_buf(descr, ARRAY_SIZE(descr),
1971 &str, buf, 10);
1972 zassert_equal(ret, 0, "Encoding failed despite large enough buffer");
1973 zassert_equal(strlen(buf), 9, "Encoded string length mismatch");
1974
1975 ret = json_obj_encode_buf(descr, ARRAY_SIZE(descr),
1976 &str, buf, 9);
1977 zassert_equal(ret, -ENOMEM, "Bounds check failed");
1978 }
1979
ZTEST(lib_json_test,test_large_descriptor)1980 ZTEST(lib_json_test, test_large_descriptor)
1981 {
1982 struct large_struct {
1983 int int0;
1984 int int1;
1985 int int2;
1986 int int3;
1987 int int4;
1988 int int5;
1989 int int6;
1990 int int7;
1991 int int8;
1992 int int9;
1993 int int10;
1994 int int11;
1995 int int12;
1996 int int13;
1997 int int14;
1998 int int15;
1999 int int16;
2000 int int17;
2001 int int18;
2002 int int19;
2003 int int20;
2004 int int21;
2005 int int22;
2006 int int23;
2007 int int24;
2008 int int25;
2009 int int26;
2010 int int27;
2011 int int28;
2012 int int29;
2013 int int30;
2014 int int31;
2015 int int32;
2016 int int33;
2017 int int34;
2018 int int35;
2019 int int36;
2020 int int37;
2021 int int38;
2022 int int39;
2023 };
2024
2025 static const struct json_obj_descr large_descr[] = {
2026 JSON_OBJ_DESCR_PRIM(struct large_struct, int0, JSON_TOK_NUMBER),
2027 JSON_OBJ_DESCR_PRIM(struct large_struct, int1, JSON_TOK_NUMBER),
2028 JSON_OBJ_DESCR_PRIM(struct large_struct, int2, JSON_TOK_NUMBER),
2029 JSON_OBJ_DESCR_PRIM(struct large_struct, int3, JSON_TOK_NUMBER),
2030 JSON_OBJ_DESCR_PRIM(struct large_struct, int4, JSON_TOK_NUMBER),
2031 JSON_OBJ_DESCR_PRIM(struct large_struct, int5, JSON_TOK_NUMBER),
2032 JSON_OBJ_DESCR_PRIM(struct large_struct, int6, JSON_TOK_NUMBER),
2033 JSON_OBJ_DESCR_PRIM(struct large_struct, int7, JSON_TOK_NUMBER),
2034 JSON_OBJ_DESCR_PRIM(struct large_struct, int8, JSON_TOK_NUMBER),
2035 JSON_OBJ_DESCR_PRIM(struct large_struct, int9, JSON_TOK_NUMBER),
2036 JSON_OBJ_DESCR_PRIM(struct large_struct, int10, JSON_TOK_NUMBER),
2037 JSON_OBJ_DESCR_PRIM(struct large_struct, int11, JSON_TOK_NUMBER),
2038 JSON_OBJ_DESCR_PRIM(struct large_struct, int12, JSON_TOK_NUMBER),
2039 JSON_OBJ_DESCR_PRIM(struct large_struct, int13, JSON_TOK_NUMBER),
2040 JSON_OBJ_DESCR_PRIM(struct large_struct, int14, JSON_TOK_NUMBER),
2041 JSON_OBJ_DESCR_PRIM(struct large_struct, int15, JSON_TOK_NUMBER),
2042 JSON_OBJ_DESCR_PRIM(struct large_struct, int16, JSON_TOK_NUMBER),
2043 JSON_OBJ_DESCR_PRIM(struct large_struct, int17, JSON_TOK_NUMBER),
2044 JSON_OBJ_DESCR_PRIM(struct large_struct, int18, JSON_TOK_NUMBER),
2045 JSON_OBJ_DESCR_PRIM(struct large_struct, int19, JSON_TOK_NUMBER),
2046 JSON_OBJ_DESCR_PRIM(struct large_struct, int20, JSON_TOK_NUMBER),
2047 JSON_OBJ_DESCR_PRIM(struct large_struct, int21, JSON_TOK_NUMBER),
2048 JSON_OBJ_DESCR_PRIM(struct large_struct, int22, JSON_TOK_NUMBER),
2049 JSON_OBJ_DESCR_PRIM(struct large_struct, int23, JSON_TOK_NUMBER),
2050 JSON_OBJ_DESCR_PRIM(struct large_struct, int24, JSON_TOK_NUMBER),
2051 JSON_OBJ_DESCR_PRIM(struct large_struct, int25, JSON_TOK_NUMBER),
2052 JSON_OBJ_DESCR_PRIM(struct large_struct, int26, JSON_TOK_NUMBER),
2053 JSON_OBJ_DESCR_PRIM(struct large_struct, int27, JSON_TOK_NUMBER),
2054 JSON_OBJ_DESCR_PRIM(struct large_struct, int28, JSON_TOK_NUMBER),
2055 JSON_OBJ_DESCR_PRIM(struct large_struct, int29, JSON_TOK_NUMBER),
2056 JSON_OBJ_DESCR_PRIM(struct large_struct, int30, JSON_TOK_NUMBER),
2057 JSON_OBJ_DESCR_PRIM(struct large_struct, int31, JSON_TOK_NUMBER),
2058 JSON_OBJ_DESCR_PRIM(struct large_struct, int32, JSON_TOK_NUMBER),
2059 JSON_OBJ_DESCR_PRIM(struct large_struct, int33, JSON_TOK_NUMBER),
2060 JSON_OBJ_DESCR_PRIM(struct large_struct, int34, JSON_TOK_NUMBER),
2061 JSON_OBJ_DESCR_PRIM(struct large_struct, int35, JSON_TOK_NUMBER),
2062 JSON_OBJ_DESCR_PRIM(struct large_struct, int36, JSON_TOK_NUMBER),
2063 JSON_OBJ_DESCR_PRIM(struct large_struct, int37, JSON_TOK_NUMBER),
2064 JSON_OBJ_DESCR_PRIM(struct large_struct, int38, JSON_TOK_NUMBER),
2065 JSON_OBJ_DESCR_PRIM(struct large_struct, int39, JSON_TOK_NUMBER),
2066 };
2067 char encoded[] = "{"
2068 "\"int1\": 1,"
2069 "\"int21\": 21,"
2070 "\"int31\": 31,"
2071 "\"int39\": 39"
2072 "}";
2073
2074 struct large_struct ls;
2075
2076 int64_t ret = json_obj_parse(encoded, sizeof(encoded) - 1, large_descr,
2077 ARRAY_SIZE(large_descr), &ls);
2078
2079 zassert_false(ret < 0, "json_obj_parse returned error %lld", ret);
2080 zassert_false(ret & ((int64_t)1 << 2), "Field int2 erroneously decoded");
2081 zassert_false(ret & ((int64_t)1 << 35), "Field int35 erroneously decoded");
2082 zassert_true(ret & ((int64_t)1 << 1), "Field int1 not decoded");
2083 zassert_true(ret & ((int64_t)1 << 21), "Field int21 not decoded");
2084 zassert_true(ret & ((int64_t)1 << 31), "Field int31 not decoded");
2085 zassert_true(ret & ((int64_t)1 << 39), "Field int39 not decoded");
2086 }
2087
ZTEST(lib_json_test,test_json_encoded_object_tok_encoding)2088 ZTEST(lib_json_test, test_json_encoded_object_tok_encoding)
2089 {
2090 static const char encoded[] = "{"
2091 "\"encoded_obj\":{\"test\":{\"nested\":\"yes\"}},"
2092 "\"encoded_obj_array\":["
2093 "{\"array_1\":{\"nested\":\"yes\"}},"
2094 "{\"array_2\":{\"nested\":\"yes\"}},"
2095 "{\"array_3\":{\"nested\":\"yes\"}}],"
2096 "\"ok\":1234}";
2097 const struct test_json_tok_encoded_obj obj = {
2098 .encoded_obj = "{\"test\":{\"nested\":\"yes\"}}",
2099 .encoded_obj_array[0] = "{\"array_1\":{\"nested\":\"yes\"}}",
2100 .encoded_obj_array[1] = "{\"array_2\":{\"nested\":\"yes\"}}",
2101 .encoded_obj_array[2] = "{\"array_3\":{\"nested\":\"yes\"}}",
2102 .encoded_obj_array_len = 3,
2103 .ok = 1234,
2104 };
2105 char buffer[sizeof(encoded)];
2106 int ret;
2107
2108 ret = json_obj_encode_buf(test_json_tok_encoded_obj_descr,
2109 ARRAY_SIZE(test_json_tok_encoded_obj_descr), &obj, buffer,
2110 sizeof(buffer));
2111
2112 zassert_equal(ret, 0, "Encoding function failed");
2113 zassert_mem_equal(buffer, encoded, sizeof(encoded), "Encoded contents not consistent");
2114 }
2115
ZTEST(lib_json_test,test_json_array_alignment)2116 ZTEST(lib_json_test, test_json_array_alignment)
2117 {
2118 char encoded[] = "{"
2119 "\"array\": [ "
2120 "{ \"int1\": 1, "
2121 "\"int2\": 2, "
2122 "\"int3\": 3 }, "
2123 "{ \"int1\": 4, "
2124 "\"int2\": 5, "
2125 "\"int3\": 6 } "
2126 "] "
2127 "}";
2128
2129 struct test_outer o;
2130 int64_t ret = json_obj_parse(encoded, sizeof(encoded) - 1, outer_descr,
2131 ARRAY_SIZE(outer_descr), &o);
2132
2133 zassert_false(ret < 0, "json_obj_parse returned error %lld", ret);
2134 zassert_equal(o.num_elements, 2, "Number of elements not decoded correctly");
2135
2136 zassert_equal(o.array[0].int1, 1, "Element 0 int1 not decoded correctly");
2137 zassert_equal(o.array[0].int2, 2, "Element 0 int2 not decoded correctly");
2138 zassert_equal(o.array[0].int3, 3, "Element 0 int3 not decoded correctly");
2139
2140 zassert_equal(o.array[1].int1, 4, "Element 1 int1 not decoded correctly");
2141 zassert_equal(o.array[1].int2, 5, "Element 1 int2 not decoded correctly");
2142 zassert_equal(o.array[1].int3, 6, "Element 1 int3 not decoded correctly");
2143 }
2144
ZTEST(lib_json_test,test_json_array_alignment_bool)2145 ZTEST(lib_json_test, test_json_array_alignment_bool)
2146 {
2147 char encoded[] = "{\"array\":["
2148 "{\"bool1\":true,\"int1\":1,\"bool2\":false},"
2149 "{\"bool1\":true,\"int1\":2,\"bool2\":false}"
2150 "]}";
2151
2152 struct test_alignment_bool o = { 0 };
2153 int64_t ret = json_obj_parse(encoded, sizeof(encoded) - 1, alignment_bool_descr,
2154 ARRAY_SIZE(alignment_bool_descr), &o);
2155
2156 zassert_false(ret < 0, "json_obj_parse returned error %lld", ret);
2157 zassert_equal(o.num_elements, 2, "Number of elements not decoded correctly");
2158
2159 zassert_equal(o.array[0].bool1, true, "Element 0 bool1 not decoded correctly");
2160 zassert_equal(o.array[0].int1, 1, "Element 0 int1 not decoded correctly");
2161 zassert_equal(o.array[0].bool2, false, "Element 0 bool2 not decoded correctly");
2162
2163 zassert_equal(o.array[1].bool1, true, "Element 1 bool1 not decoded correctly");
2164 zassert_equal(o.array[1].int1, 2, "Element 1 int1 not decoded correctly");
2165 zassert_equal(o.array[1].bool2, false, "Element 1 bool2 not decoded correctly");
2166 }
2167
ZTEST(lib_json_test,test_json_invalid_int)2168 ZTEST(lib_json_test, test_json_invalid_int)
2169 {
2170 struct sub_test {
2171 char str[30];
2172 int result;
2173 };
2174 struct sub_test encoded[] = {
2175 { "{\"int8_cero\":128}", -EINVAL },
2176 { "{\"int8_cero\":-129}", -EINVAL },
2177 { "{\"uint8_cero\":257}", -EINVAL },
2178 { "{\"int16_cero\":32768}", -EINVAL },
2179 { "{\"int16_cero\":-32769}", -EINVAL },
2180 { "{\"uint16_cero\":65536}", -EINVAL },
2181 };
2182
2183 struct test_int_limits ts;
2184 int ret;
2185
2186 for (int i = 0; i < ARRAY_SIZE(encoded); i++) {
2187 ret = json_obj_parse(encoded[i].str, strlen(encoded[i].str),
2188 obj_limits_descr, ARRAY_SIZE(obj_limits_descr), &ts);
2189 zassert_equal(ret, encoded[i].result,
2190 "Decoding '%s' result %d, expected %d",
2191 encoded[i].str, ret, encoded[i].result);
2192 }
2193 }
2194
ZTEST(lib_json_test,test_json_enums)2195 ZTEST(lib_json_test, test_json_enums)
2196 {
2197 int ret = 0;
2198 char encoded[] = "{\"i8\":-128,"
2199 "\"u8\":255,"
2200 "\"i16\":-32768,"
2201 "\"u16\":65535,"
2202 "\"i32\":-2147483648,"
2203 "\"u32\":4294967295"
2204 "}";
2205 char buffer[sizeof(encoded)];
2206 struct test_enums enums_decoded = {0};
2207 struct test_enums enums = {0};
2208
2209 enums.i8 = I8_MIN;
2210 enums.u8 = U8_MAX;
2211 enums.i16 = I16_MIN;
2212 enums.u16 = U16_MAX;
2213 enums.i32 = I32_MIN;
2214 enums.u32 = U32_MAX;
2215
2216 ret = json_obj_encode_buf(enums_descr, ARRAY_SIZE(enums_descr),
2217 &enums, buffer, sizeof(buffer));
2218 ret = json_obj_parse(encoded, sizeof(encoded) - 1, enums_descr,
2219 ARRAY_SIZE(enums_descr), &enums_decoded);
2220
2221 zassert_str_equal(encoded, buffer,
2222 "Enums not encoded correctly");
2223 zassert_true(!memcmp(&enums, &enums_decoded, sizeof(enums)),
2224 "Enums not decoded correctly");
2225 }
2226
ZTEST(lib_json_test,test_json_string_nullptr)2227 ZTEST(lib_json_test, test_json_string_nullptr)
2228 {
2229 int ret = 0;
2230
2231 struct test_struct ts = {0};
2232 char *buffer;
2233 size_t len;
2234
2235 len = json_calc_encoded_len(test_descr, ARRAY_SIZE(test_descr), &ts);
2236 zassert(len > 0, "encoded size incorrect");
2237
2238 buffer = alloca(len + 1);
2239 ret = json_obj_encode_buf(test_descr, ARRAY_SIZE(test_descr), &ts, buffer, len + 1);
2240 zassert_equal(ret, 0, "Encoding function failed");
2241
2242 ret = json_obj_parse(buffer, len, test_descr, ARRAY_SIZE(test_descr), &ts);
2243 zassert_equal(ret, (1 << ARRAY_SIZE(test_descr)) - 1, "Not all fields decoded correctly");
2244 zassert_str_equal(ts.some_string, "", "String not decoded correctly");
2245 }
2246
ZTEST(lib_json_test,test_json_mixed_arr_parse)2247 ZTEST(lib_json_test, test_json_mixed_arr_parse)
2248 {
2249 struct test_mixed_arr arr = {0};
2250 char json[] = "[\"msg\", 123456, {\"nested_int\":42,\"nested_bool\":true,"
2251 "\"nested_string\":\"abc\","
2252 "\"nested_string_buf\":\"buf\",\"nested_int8\":1,\"nested_uint8\":2,"
2253 "\"nested_int64\":3,\"nested_uint64\":4}, [10,20,30], \"ok\"]";
2254 int ret = json_mixed_arr_parse(json, strlen(json),
2255 test_mixed_arr_descr,
2256 ARRAY_SIZE(test_mixed_arr_descr), &arr);
2257
2258 zassert_equal(ret, 5, "Should parse 5 elements");
2259 zassert_str_equal(arr.msg_type, "msg", NULL);
2260 zassert_equal(arr.dev_id, 123456, NULL);
2261 zassert_equal(arr.nested.nested_int, 42, NULL);
2262 zassert_equal(arr.arr_len, 3, NULL);
2263 zassert_equal(arr.arr[0], 10, NULL);
2264 zassert_equal(arr.arr[1], 20, NULL);
2265 zassert_equal(arr.arr[2], 30, NULL);
2266 zassert_str_equal(arr.status_buf, "ok", NULL);
2267 }
2268
ZTEST(lib_json_test,test_json_mixed_arr_encode)2269 ZTEST(lib_json_test, test_json_mixed_arr_encode)
2270 {
2271 char buf[256];
2272 struct test_mixed_arr pkt = {0};
2273 struct test_mixed_arr arr = {
2274 .msg_type = "msg",
2275 .dev_id = 123456,
2276 .nested = {
2277 .nested_int = 42,
2278 .nested_bool = true,
2279 .nested_string = "abc",
2280 .nested_string_buf = "buf",
2281 .nested_int8 = 1,
2282 .nested_uint8 = 2,
2283 .nested_int64 = 3,
2284 .nested_uint64 = 4,
2285 },
2286 .arr = {10, 20, 30},
2287 .arr_len = 3,
2288 .status_buf = "ok",
2289 .count = 5
2290 };
2291 int ret = json_mixed_arr_encode_buf(test_mixed_arr_descr,
2292 ARRAY_SIZE(test_mixed_arr_descr),
2293 &arr, buf, sizeof(buf));
2294
2295 zassert_equal(ret, 0, NULL);
2296
2297 ret = json_mixed_arr_parse(buf, strlen(buf),
2298 test_mixed_arr_descr,
2299 ARRAY_SIZE(test_mixed_arr_descr), &pkt);
2300
2301 zassert_equal(ret, 5, NULL);
2302 zassert_str_equal(pkt.msg_type, "msg", NULL);
2303 zassert_equal(pkt.dev_id, 123456, NULL);
2304 zassert_equal(pkt.arr[0], 10, NULL);
2305 zassert_str_equal(pkt.status_buf, "ok", NULL);
2306 }
2307
ZTEST(lib_json_test,test_json_mixed_arr_empty)2308 ZTEST(lib_json_test, test_json_mixed_arr_empty)
2309 {
2310 struct test_mixed_arr arr = {0};
2311 char json[] = "[]";
2312 int ret = json_mixed_arr_parse(json, strlen(json),
2313 test_mixed_arr_descr, 0, &arr);
2314
2315 zassert_equal(ret, 0, NULL);
2316 }
2317
ZTEST(lib_json_test,test_json_mixed_arr_calc_len)2318 ZTEST(lib_json_test, test_json_mixed_arr_calc_len)
2319 {
2320 char buf[256];
2321 ssize_t calc_len;
2322 int ret;
2323 struct test_mixed_arr arr = {
2324 .msg_type = "msg",
2325 .dev_id = 123456,
2326 .nested = {
2327 .nested_int = 42,
2328 .nested_bool = true,
2329 .nested_string = "abc",
2330 .nested_string_buf = "buf",
2331 .nested_int8 = 1,
2332 .nested_uint8 = 2,
2333 .nested_int64 = 3,
2334 .nested_uint64 = 4,
2335 },
2336 .arr = {10, 20, 30},
2337 .arr_len = 3,
2338 .status_buf = "ok",
2339 .count = 5
2340 };
2341
2342 calc_len = json_calc_mixed_arr_len(test_mixed_arr_descr,
2343 ARRAY_SIZE(test_mixed_arr_descr),
2344 &arr);
2345 ret = json_mixed_arr_encode_buf(test_mixed_arr_descr,
2346 ARRAY_SIZE(test_mixed_arr_descr),
2347 &arr, buf, sizeof(buf));
2348 zassert_equal(ret, 0, NULL);
2349
2350 zassert_equal(calc_len, (ssize_t)strlen(buf), "Length mismatch");
2351 }
2352
2353 /**
2354 * @brief Test that escape sequences don't duplicate on encode/decode cycles
2355 *
2356 * This test specifically targets the bug where backslashes in escape sequences
2357 * like \n, \t, etc. get duplicated with each encode/decode cycle.
2358 */
ZTEST(lib_json_test,test_json_escape_sequence_stability)2359 ZTEST(lib_json_test, test_json_escape_sequence_stability)
2360 {
2361 struct escape_test_data original = {
2362 .string_value = "Line1\nLine2\tTabbed",
2363 .integer_value = 42,
2364 };
2365 strncpy(original.string_value, "Line1\nLine2\tTabbed", sizeof(original.string_value) - 1);
2366 strncpy(original.string_buf, "Text with\nnewline and\ttab",
2367 sizeof(original.string_buf) - 1);
2368
2369 char buffer[512];
2370 struct escape_test_data decoded = {0};
2371 int ret;
2372
2373 /* Encode -> Decode -> Encode -> Decode cycle */
2374
2375 /* First encode */
2376 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &original,
2377 buffer, sizeof(buffer));
2378 zassert_equal(ret, 0, "First encoding failed");
2379
2380 /* First decode */
2381 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2382 ARRAY_SIZE(escape_test_descr), &decoded);
2383 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "First decoding failed");
2384
2385 /* Verify first decode matches original */
2386 zassert_str_equal(decoded.string_value, original.string_value,
2387 "String value changed after first decode");
2388 zassert_str_equal(decoded.string_buf, original.string_buf,
2389 "String buffer changed after first decode");
2390 zassert_equal(decoded.integer_value, original.integer_value,
2391 "Integer value changed after first decode");
2392
2393 /* Second encode */
2394 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &decoded,
2395 buffer, sizeof(buffer));
2396 zassert_equal(ret, 0, "Second encoding failed");
2397
2398 /* Second decode */
2399 struct escape_test_data decoded2 = {0};
2400
2401 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2402 ARRAY_SIZE(escape_test_descr), &decoded2);
2403 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "Second decoding failed");
2404
2405 /* CRITICAL: Verify strings remain unchanged after multiple cycles */
2406 zassert_str_equal(decoded2.string_value, original.string_value,
2407 "String value corrupted after encode/decode cycle");
2408 zassert_str_equal(decoded2.string_buf, original.string_buf,
2409 "String buffer corrupted after encode/decode cycle");
2410 zassert_equal(decoded2.integer_value, original.integer_value,
2411 "Integer value changed after encode/decode cycle");
2412 }
2413
2414 /**
2415 * @brief Test specific escape sequences individually
2416 */
ZTEST(lib_json_test,test_json_specific_escape_sequences)2417 ZTEST(lib_json_test, test_json_specific_escape_sequences)
2418 {
2419 struct test_case {
2420 const char *input;
2421 const char *description;
2422 };
2423
2424 struct test_case test_cases[] = {
2425 {"Simple newline\n", "newline"},
2426 {"Multiple\nnew\nlines\n", "multiple newlines"},
2427 {"Tab\tseparated", "tab"},
2428 {"Mixed\n\tboth", "mixed newline and tab"},
2429 {"Backslash\\character", "backslash"},
2430 {"Quote\"test", "quote"},
2431 {"Backspace\btest", "backspace"},
2432 {"Form\ffeed", "form feed"},
2433 {"Carriage\rreturn", "carriage return"},
2434 {"Slash/test", "slash"},
2435 };
2436
2437 for (size_t i = 0; i < ARRAY_SIZE(test_cases); i++) {
2438 struct escape_test_data test_data = {
2439 .integer_value = (int)i,
2440 };
2441 strncpy(test_data.string_value, test_cases[i].input,
2442 sizeof(test_data.string_value) - 1);
2443 strncpy(test_data.string_buf, test_cases[i].input,
2444 sizeof(test_data.string_buf) - 1);
2445
2446 char buffer[256];
2447 struct escape_test_data decoded = {0};
2448 int ret;
2449
2450 /* Encode */
2451 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr),
2452 &test_data, buffer, sizeof(buffer));
2453 zassert_equal(ret, 0, "Encoding failed for %s", test_cases[i].description);
2454
2455 /* Decode */
2456 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2457 ARRAY_SIZE(escape_test_descr), &decoded);
2458 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1,
2459 "Decoding failed for %s", test_cases[i].description);
2460
2461 /* Verify string is preserved */
2462 zassert_str_equal(decoded.string_value, test_data.string_value,
2463 "Escape sequence corrupted for %s", test_cases[i].description);
2464 zassert_str_equal(decoded.string_buf, test_data.string_buf,
2465 "String buffer corrupted for %s", test_cases[i].description);
2466 }
2467 }
2468
2469 /**
2470 * @brief Test that encoded JSON contains proper escape sequences
2471 */
ZTEST(lib_json_test,test_json_escape_encoding_correctness)2472 ZTEST(lib_json_test, test_json_escape_encoding_correctness)
2473 {
2474 struct escape_test_data test_data = {
2475 .string_value = "Test\nLine",
2476 .integer_value = 123,
2477 };
2478 strncpy(test_data.string_buf, "Buffer\tTest", sizeof(test_data.string_buf) - 1);
2479
2480 char buffer[256];
2481 int ret;
2482
2483 /* Encode the data */
2484 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &test_data,
2485 buffer, sizeof(buffer));
2486 zassert_equal(ret, 0, "Encoding failed");
2487
2488 /* Verify the encoded JSON contains proper escape sequences */
2489 zassert_not_null(strstr(buffer, "\\n"), "Newline not properly escaped in JSON");
2490 zassert_not_null(strstr(buffer, "\\t"), "Tab not properly escaped in JSON");
2491
2492 /* The encoded JSON should NOT contain raw control characters */
2493 zassert_is_null(strchr(buffer, '\n'), "Raw newline found in encoded JSON");
2494 zassert_is_null(strchr(buffer, '\t'), "Raw tab found in encoded JSON");
2495 }
2496
2497 /**
2498 * @brief Test multiple encode/decode cycles to catch gradual corruption
2499 */
ZTEST(lib_json_test,test_json_multiple_cycle_stability)2500 ZTEST(lib_json_test, test_json_multiple_cycle_stability)
2501 {
2502 struct escape_test_data original = {
2503 .string_value = "Start\nMiddle\tEnd",
2504 .integer_value = 99,
2505 };
2506 strncpy(original.string_value, "Start\nMiddle\tEnd", sizeof(original.string_value) - 1);
2507 strncpy(original.string_buf, "Cyclic\ntest\tdata", sizeof(original.string_buf) - 1);
2508
2509 char buffer[512];
2510 struct escape_test_data current = {0};
2511 int ret;
2512
2513 /* Initialize current by copying from original */
2514 current.integer_value = original.integer_value;
2515 strncpy(current.string_value, original.string_value, sizeof(current.string_value));
2516 strncpy(current.string_buf, original.string_buf, sizeof(current.string_buf));
2517
2518 /* Run multiple encode/decode cycles */
2519 for (int cycle = 0; cycle < 5; cycle++) {
2520 /* Encode */
2521 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr),
2522 ¤t, buffer, sizeof(buffer));
2523 zassert_equal(ret, 0, "Encoding failed at cycle %d", cycle);
2524
2525 /* Decode into a fresh struct */
2526 struct escape_test_data next = {0};
2527
2528 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2529 ARRAY_SIZE(escape_test_descr), &next);
2530 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1,
2531 "Decoding failed at cycle %d", cycle);
2532
2533 /* Verify no corruption */
2534 zassert_str_equal(next.string_value, original.string_value,
2535 "String corrupted after %d cycles", cycle + 1);
2536 zassert_str_equal(next.string_buf, original.string_buf,
2537 "String buffer corrupted after %d cycles", cycle + 1);
2538 zassert_equal(next.integer_value, original.integer_value,
2539 "Integer corrupted after %d cycles", cycle + 1);
2540
2541 /* Prepare for next cycle */
2542 current.integer_value = next.integer_value;
2543 strncpy(current.string_value, next.string_value, sizeof(current.string_value));
2544 strncpy(current.string_buf, next.string_buf, sizeof(current.string_buf));
2545 }
2546 }
2547
2548 /**
2549 * @brief Test the exact scenario from the bug report
2550 */
ZTEST(lib_json_test,test_json_escape_sequence_regression)2551 ZTEST(lib_json_test, test_json_escape_sequence_regression)
2552 {
2553 /* This test reproduces the exact scenario described in GitHub issue #88552 */
2554 struct escape_test_data config_data = {
2555 .string_value = "some_string\n",
2556 .integer_value = 69,
2557 };
2558 strncpy(config_data.string_value, "some_string\n", sizeof(config_data.string_value) - 1);
2559 strncpy(config_data.string_buf, "config\nvalue", sizeof(config_data.string_buf) - 1);
2560
2561 char encoded_json[256];
2562 struct escape_test_data decoded_data = {0};
2563 int ret;
2564
2565 /* Simulate multiple boot cycles with encode/decode - this is where the bug manifests */
2566 for (int boot_cycle = 0; boot_cycle < 3; boot_cycle++) {
2567 /* Encode (simulate saving to flash) */
2568 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr),
2569 &config_data, encoded_json, sizeof(encoded_json));
2570 zassert_equal(ret, 0, "Encode failed at boot cycle %d", boot_cycle);
2571
2572 /* Decode (simulate reading from flash) */
2573 ret = json_obj_parse(encoded_json, strlen(encoded_json), escape_test_descr,
2574 ARRAY_SIZE(escape_test_descr), &decoded_data);
2575 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1,
2576 "Decode failed at boot cycle %d", boot_cycle);
2577
2578 /* Update for next cycle (simulate config change) */
2579 decoded_data.integer_value++;
2580 config_data = decoded_data;
2581 }
2582
2583 /* After multiple cycles, the string should be unchanged */
2584 zassert_str_equal(config_data.string_value, "some_string\n",
2585 "String value corrupted after multiple boot cycles");
2586 zassert_str_equal(config_data.string_buf, "config\nvalue",
2587 "String buffer corrupted after multiple boot cycles");
2588
2589 /* Additional verification: check that backslashes didn't duplicate */
2590 const char *expected_value = "some_string\n";
2591 const char *expected_buf = "config\nvalue";
2592
2593 zassert_str_equal(config_data.string_value, expected_value,
2594 "Escape sequence regression detected in string_value");
2595 zassert_str_equal(config_data.string_buf, expected_buf,
2596 "Escape sequence regression detected in string_buf");
2597 }
2598
2599 /**
2600 * @brief Test to detect backslash duplication specifically
2601 */
ZTEST(lib_json_test,test_json_backslash_duplication)2602 ZTEST(lib_json_test, test_json_backslash_duplication)
2603 {
2604 /* This test specifically checks for the backslash duplication bug */
2605 struct escape_test_data test_data = {
2606 .string_value = "test\nstring",
2607 .integer_value = 1,
2608 };
2609 strncpy(test_data.string_buf, "buffer\ncontent", sizeof(test_data.string_buf) - 1);
2610
2611 char buffer1[256], buffer2[256];
2612 struct escape_test_data decoded1 = {0}, decoded2 = {0};
2613 int ret;
2614
2615 /* First encode/decode cycle */
2616 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &test_data,
2617 buffer1, sizeof(buffer1));
2618 zassert_equal(ret, 0, "First encode failed");
2619
2620 ret = json_obj_parse(buffer1, strlen(buffer1), escape_test_descr,
2621 ARRAY_SIZE(escape_test_descr), &decoded1);
2622 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "First decode failed");
2623
2624 /* Second encode/decode cycle */
2625 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &decoded1,
2626 buffer2, sizeof(buffer2));
2627 zassert_equal(ret, 0, "Second encode failed");
2628
2629 ret = json_obj_parse(buffer2, strlen(buffer2), escape_test_descr,
2630 ARRAY_SIZE(escape_test_descr), &decoded2);
2631 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "Second decode failed");
2632
2633 /* The critical assertion: strings should be identical across cycles */
2634 zassert_str_equal(decoded1.string_value, decoded2.string_value,
2635 "Backslash duplication detected in string_value");
2636 zassert_str_equal(decoded1.string_buf, decoded2.string_buf,
2637 "Backslash duplication detected in string_buf");
2638 zassert_str_equal(test_data.string_value, decoded2.string_value,
2639 "Original string value not preserved");
2640 zassert_str_equal(test_data.string_buf, decoded2.string_buf,
2641 "Original string buffer not preserved");
2642 }
2643
ZTEST(lib_json_test,test_json_quote_escaping_encoding)2644 ZTEST(lib_json_test, test_json_quote_escaping_encoding)
2645 {
2646 struct escape_test_data test_data = {
2647 .integer_value = 42,
2648 };
2649 strncpy(test_data.string_value, "Text with \"quotes\" inside",
2650 sizeof(test_data.string_value) - 1);
2651 strncpy(test_data.string_buf, "Buffer with \"quotes\"", sizeof(test_data.string_buf) - 1);
2652
2653 char buffer[256];
2654 int ret;
2655
2656 /* Encode the data */
2657 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &test_data,
2658 buffer, sizeof(buffer));
2659 zassert_equal(ret, 0, "Encoding failed");
2660
2661 /* Verify the encoded JSON contains escaped quotes */
2662 zassert_not_null(strstr(buffer, "\\\""), "Quotes not properly escaped in JSON output");
2663
2664 /* The encoded JSON should NOT contain the pattern: "... "..." (unescaped quotes in content)
2665 * Look for the specific escaped quote pattern
2666 */
2667 const char *escaped_quote = strstr(buffer, "\\\"");
2668
2669 zassert_not_null(escaped_quote, "No escaped quotes found in encoded JSON");
2670
2671 /* Make sure we found at least 2 escaped quotes (one for each field) */
2672 const char *second_escaped_quote = strstr(escaped_quote + 1, "\\\"");
2673
2674 zassert_not_null(second_escaped_quote, "Should have multiple escaped quotes in JSON");
2675
2676 /* Verify the overall structure looks correct */
2677 zassert_not_null(strstr(buffer, "\"string_value\""), "string_value field missing");
2678 zassert_not_null(strstr(buffer, "\"string_buf\""), "string_buf field missing");
2679 zassert_not_null(strstr(buffer, "\"integer_value\""), "integer_value field missing");
2680 }
2681
2682 /**
2683 * @brief Test that escaped quotes are properly unescaped during decoding
2684 */
ZTEST(lib_json_test,test_json_quote_unescaping_decoding)2685 ZTEST(lib_json_test, test_json_quote_unescaping_decoding)
2686 {
2687 /* JSON with escaped quotes */
2688 char encoded_json[] = "{\"string_value\":\"Text with \\\"quotes\\\" inside\","
2689 "\"string_buf\":\"Buffer with \\\"quotes\\\"\","
2690 "\"integer_value\":42}";
2691
2692 struct escape_test_data decoded = {0};
2693 int ret;
2694
2695 /* Decode the JSON */
2696 ret = json_obj_parse(encoded_json, strlen(encoded_json), escape_test_descr,
2697 ARRAY_SIZE(escape_test_descr), &decoded);
2698 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "Decoding failed");
2699
2700 /* Verify quotes are properly unescaped */
2701 zassert_str_equal(decoded.string_value, "Text with \"quotes\" inside",
2702 "Quotes not properly unescaped in string_value");
2703 zassert_str_equal(decoded.string_buf, "Buffer with \"quotes\"",
2704 "Quotes not properly unescaped in string_buf");
2705 }
2706
2707 /**
2708 * @brief Test complete round-trip: quote -> escaped -> unescaped -> original
2709 */
ZTEST(lib_json_test,test_json_quote_round_trip)2710 ZTEST(lib_json_test, test_json_quote_round_trip)
2711 {
2712 struct escape_test_data original = {
2713 .string_value = "Start \"middle\" end",
2714 .integer_value = 123,
2715 };
2716 strncpy(original.string_buf, "Quote: \"test\" here", sizeof(original.string_buf) - 1);
2717
2718 char buffer[256];
2719 struct escape_test_data decoded = {0};
2720 int ret;
2721
2722 /* Encode (quotes should become \") */
2723 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &original,
2724 buffer, sizeof(buffer));
2725 zassert_equal(ret, 0, "Encoding failed");
2726
2727 /* Verify encoding produced escaped quotes */
2728 zassert_not_null(strstr(buffer, "\\\""), "Quotes not escaped in encoding");
2729
2730 /* Decode (\" should become ") */
2731 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2732 ARRAY_SIZE(escape_test_descr), &decoded);
2733 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "Decoding failed");
2734
2735 /* Verify we get back the original strings */
2736 zassert_str_equal(decoded.string_value, original.string_value,
2737 "Quote round-trip failed for string_value");
2738 zassert_str_equal(decoded.string_buf, original.string_buf,
2739 "Quote round-trip failed for string_buf");
2740 }
2741
2742 /**
2743 * @brief Test that backslashes don't get duplicated in quote escaping
2744 */
ZTEST(lib_json_test,test_json_quote_no_backslash_duplication)2745 ZTEST(lib_json_test, test_json_quote_no_backslash_duplication)
2746 {
2747 struct escape_test_data test_data = {
2748 .string_value = "Text\"with\"quotes",
2749 .integer_value = 1,
2750 };
2751 strncpy(test_data.string_buf, "More\"quotes\"here", sizeof(test_data.string_buf) - 1);
2752
2753 char buffer1[256], buffer2[256];
2754 struct escape_test_data decoded1 = {0}, decoded2 = {0};
2755 int ret;
2756
2757 /* First encode/decode cycle */
2758 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &test_data,
2759 buffer1, sizeof(buffer1));
2760 zassert_equal(ret, 0, "First encode failed");
2761
2762 ret = json_obj_parse(buffer1, strlen(buffer1), escape_test_descr,
2763 ARRAY_SIZE(escape_test_descr), &decoded1);
2764 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "First decode failed");
2765
2766 /* Second encode/decode cycle */
2767 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &decoded1,
2768 buffer2, sizeof(buffer2));
2769 zassert_equal(ret, 0, "Second encode failed");
2770
2771 ret = json_obj_parse(buffer2, strlen(buffer2), escape_test_descr,
2772 ARRAY_SIZE(escape_test_descr), &decoded2);
2773 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "Second decode failed");
2774
2775 /* Critical: No backslash duplication should occur */
2776 zassert_str_equal(decoded1.string_value, decoded2.string_value,
2777 "Backslash duplication detected in string_value after quote handling");
2778 zassert_str_equal(decoded1.string_buf, decoded2.string_buf,
2779 "Backslash duplication detected in string_buf after quote handling");
2780
2781 /* Verify original content is preserved */
2782 zassert_str_equal(test_data.string_value, decoded2.string_value,
2783 "Original string with quotes not preserved");
2784 zassert_str_equal(test_data.string_buf, decoded2.string_buf,
2785 "Original string buffer with quotes not preserved");
2786 }
2787
2788 /**
2789 * @brief Test mixed escape sequences including quotes
2790 */
ZTEST(lib_json_test,test_json_mixed_escape_sequences_with_quotes)2791 ZTEST(lib_json_test, test_json_mixed_escape_sequences_with_quotes)
2792 {
2793 struct escape_test_data test_data = {
2794 .string_value = "Line1\nTab\tQuote\"End",
2795 .integer_value = 999,
2796 };
2797 strncpy(test_data.string_buf, "Mix\n\t\"\\chars", sizeof(test_data.string_buf) - 1);
2798
2799 char buffer[256];
2800 struct escape_test_data decoded = {0};
2801 int ret;
2802
2803 /* Encode */
2804 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &test_data,
2805 buffer, sizeof(buffer));
2806 zassert_equal(ret, 0, "Encoding failed");
2807
2808 /* Verify all escape sequences are present in encoded form */
2809 zassert_not_null(strstr(buffer, "\\n"), "Newline not escaped");
2810 zassert_not_null(strstr(buffer, "\\t"), "Tab not escaped");
2811 zassert_not_null(strstr(buffer, "\\\""), "Quote not escaped");
2812 zassert_not_null(strstr(buffer, "\\\\"), "Backslash not escaped");
2813
2814 /* Decode */
2815 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2816 ARRAY_SIZE(escape_test_descr), &decoded);
2817 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1, "Decoding failed");
2818
2819 /* Verify all sequences are properly unescaped */
2820 zassert_str_equal(decoded.string_value, "Line1\nTab\tQuote\"End",
2821 "Mixed escape sequences corrupted in string_value");
2822 zassert_str_equal(decoded.string_buf, "Mix\n\t\"\\chars",
2823 "Mixed escape sequences corrupted in string_buf");
2824 }
2825
2826 /**
2827 * @brief Test multiple cycles with quotes to detect gradual corruption
2828 */
ZTEST(lib_json_test,test_json_quote_multiple_cycle_stability)2829 ZTEST(lib_json_test, test_json_quote_multiple_cycle_stability)
2830 {
2831 struct escape_test_data original = {
2832 .string_value = "Config\"value\"here",
2833 .integer_value = 50,
2834 };
2835 strncpy(original.string_value, "Config\"value\"here", sizeof(original.string_value) - 1);
2836 strncpy(original.string_buf, "Setting\"name\"value", sizeof(original.string_buf) - 1);
2837
2838 char buffer[256];
2839 struct escape_test_data current = {0};
2840 int ret;
2841
2842 /* Initialize current by copying from original */
2843 current.integer_value = original.integer_value;
2844 strncpy(current.string_value, original.string_value, sizeof(current.string_value));
2845 strncpy(current.string_buf, original.string_buf, sizeof(current.string_buf));
2846
2847 /* Run multiple encode/decode cycles */
2848 for (int cycle = 0; cycle < 3; cycle++) {
2849 /* Encode */
2850 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr),
2851 ¤t, buffer, sizeof(buffer));
2852 zassert_equal(ret, 0, "Encoding failed at cycle %d", cycle);
2853
2854 /* Decode into fresh struct */
2855 struct escape_test_data next = {0};
2856
2857 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2858 ARRAY_SIZE(escape_test_descr), &next);
2859 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1,
2860 "Decoding failed at cycle %d", cycle);
2861
2862 /* Verify no corruption of quotes */
2863 zassert_str_equal(next.string_value, original.string_value,
2864 "Quote string corrupted after %d cycles", cycle + 1);
2865 zassert_str_equal(next.string_buf, original.string_buf,
2866 "Quote string buffer corrupted after %d cycles", cycle + 1);
2867
2868 /* Prepare for next cycle */
2869 current.integer_value = next.integer_value;
2870 strncpy(current.string_value, next.string_value, sizeof(current.string_value));
2871 strncpy(current.string_buf, next.string_buf, sizeof(current.string_buf));
2872 current.integer_value++; /* Change integer to simulate config updates */
2873 }
2874 }
2875
2876 /**
2877 * @brief Test edge case: string containing only a quote
2878 */
ZTEST(lib_json_test,test_json_single_quote_string)2879 ZTEST(lib_json_test, test_json_single_quote_string)
2880 {
2881 struct escape_test_data test_data = {
2882 .string_value = "\"",
2883 .integer_value = 1,
2884 };
2885 strncpy(test_data.string_buf, "\"", sizeof(test_data.string_buf) - 1);
2886
2887 char buffer[256];
2888 struct escape_test_data decoded = {0};
2889 int ret;
2890
2891 /* Encode */
2892 ret = json_obj_encode_buf(escape_test_descr, ARRAY_SIZE(escape_test_descr), &test_data,
2893 buffer, sizeof(buffer));
2894 zassert_equal(ret, 0, "Encoding single quote failed");
2895
2896 /* Should contain escaped quote */
2897 zassert_not_null(strstr(buffer, "\\\""), "Single quote not escaped");
2898
2899 /* Decode */
2900 ret = json_obj_parse(buffer, strlen(buffer), escape_test_descr,
2901 ARRAY_SIZE(escape_test_descr), &decoded);
2902 zassert_equal(ret, (1 << ARRAY_SIZE(escape_test_descr)) - 1,
2903 "Decoding single quote failed");
2904
2905 /* Should get back the single quote */
2906 zassert_str_equal(decoded.string_value, "\"", "Single quote not preserved");
2907 zassert_str_equal(decoded.string_buf, "\"", "Single quote in buffer not preserved");
2908 }
2909
ZTEST(lib_json_test,test_debug_string_types)2910 ZTEST(lib_json_test, test_debug_string_types)
2911 {
2912 char encoded[] = "{\"string_value\":\"test\\nvalue\",\"string_buf\":\"buffer\\ttab\"}";
2913 struct escape_test_data decoded = {0};
2914
2915 printf("=== DEBUG TEST ===\n");
2916 printf("Input JSON: %s\n", encoded);
2917
2918 int ret = json_obj_parse(encoded, strlen(encoded), escape_test_descr,
2919 ARRAY_SIZE(escape_test_descr), &decoded);
2920
2921 printf("Parse result: %d\n", ret);
2922 printf("string_value: '%s'\n", decoded.string_value);
2923 printf("string_buf: '%s'\n", decoded.string_buf);
2924 printf("=== END DEBUG ===\n");
2925
2926 zassert_str_equal(decoded.string_value, "test\nvalue", "string_value not unescaped");
2927 zassert_str_equal(decoded.string_buf, "buffer\ttab", "string_buf not unescaped");
2928 }
2929
2930 ZTEST_SUITE(lib_json_test, NULL, NULL, NULL, NULL, NULL);
2931