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