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