1 /*
2  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zcbor_common.h>
9 #include <zcbor_decode.h>
10 #include <zcbor_encode.h>
11 #include "mgmt/mcumgr/util/zcbor_bulk.h"
12 
13 #define zcbor_true_put(zse) zcbor_bool_put(zse, true)
14 
ZTEST(zcbor_bulk,test_ZCBOR_MAP_DECODE_KEY_DECODER)15 ZTEST(zcbor_bulk, test_ZCBOR_MAP_DECODE_KEY_DECODER)
16 {
17 	struct zcbor_string world;
18 	struct zcbor_map_decode_key_val map_one[] = {
19 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
20 	};
21 	/* ZCBOR_MAP_DECODE_KEY_DECODER should not be used but is still provided */
22 	struct zcbor_map_decode_key_val map_two[] = {
23 		ZCBOR_MAP_DECODE_KEY_VAL(hello, zcbor_tstr_decode, &world),
24 	};
25 
26 	zassert_ok(strcmp(map_one[0].key.value, "hello"));
27 	zassert_equal(map_one[0].key.len, sizeof("hello") - 1);
28 	zassert_equal((void *)map_one[0].decoder, (void *)&zcbor_tstr_decode);
29 	zassert_equal((void *)map_one[0].value_ptr, (void *)&world);
30 	/* Both maps should be the same */
31 	zassert_ok(strcmp(map_one[0].key.value, map_two[0].key.value));
32 	zassert_equal(map_one[0].key.len, map_two[0].key.len);
33 	zassert_equal(map_one[0].decoder, map_two[0].decoder);
34 	zassert_equal(map_one[0].value_ptr, map_two[0].value_ptr);
35 }
36 
ZTEST(zcbor_bulk,test_correct)37 ZTEST(zcbor_bulk, test_correct)
38 {
39 	uint8_t buffer[512];
40 	struct zcbor_string world;
41 	uint32_t one = 0;
42 	bool bool_val = false;
43 	zcbor_state_t zsd[4] = { 0 };
44 	size_t decoded = 0;
45 	bool ok;
46 	struct zcbor_map_decode_key_val dm[] = {
47 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
48 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
49 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
50 	};
51 
52 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
53 
54 	/* { "hello":"world", "one":1, "bool_val":true } */
55 	ok = zcbor_map_start_encode(zsd, 10) &&
56 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
57 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
58 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
59 	     zcbor_map_end_encode(zsd, 10);
60 
61 	zassert_true(ok, "Expected to be successful in encoding test pattern");
62 
63 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
64 
65 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
66 
67 	zassert_ok(rc, "Expected 0, got %d", rc);
68 	zassert_equal(decoded, ARRAY_SIZE(dm), "Expected %d got %d",
69 		ARRAY_SIZE(dm), decoded);
70 	zassert_equal(one, 1, "Expected 1");
71 	zassert_equal(sizeof("world") - 1, world.len, "Expected length %d",
72 		sizeof("world") - 1);
73 	zassert_equal(0, memcmp(world.value, "world", world.len),
74 		"Expected \"world\", got %.*s", (int)world.len, world.value);
75 	zassert_true(bool_val, "Expected bool val == true");
76 }
77 
ZTEST(zcbor_bulk,test_correct_out_of_order)78 ZTEST(zcbor_bulk, test_correct_out_of_order)
79 {
80 	uint8_t buffer[512];
81 	struct zcbor_string world;
82 	uint32_t one = 0;
83 	bool bool_val = false;
84 	zcbor_state_t zsd[4] = { 0 };
85 	size_t decoded = 0;
86 	bool ok;
87 	struct zcbor_map_decode_key_val dm[] = {
88 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
89 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
90 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
91 	};
92 
93 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
94 
95 	/* { "hello":"world", "one":1, "bool_val":true } */
96 	ok = zcbor_map_start_encode(zsd, 10) &&
97 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
98 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
99 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
100 	     zcbor_map_end_encode(zsd, 10);
101 
102 	zassert_true(ok, "Expected to be successful in encoding test pattern");
103 
104 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
105 
106 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
107 
108 	zassert_ok(rc, "Expected 0, got %d", rc);
109 	zassert_equal(decoded, ARRAY_SIZE(dm), "Expected %d got %d",
110 		ARRAY_SIZE(dm), decoded);
111 	zassert_equal(one, 1, "Expected 1");
112 	zassert_equal(sizeof("world") - 1, world.len, "Expected length %d",
113 		sizeof("world") - 1);
114 	zassert_equal(0, memcmp(world.value, "world", world.len),
115 		"Expected \"world\", got %.*s", (int)world.len, world.value);
116 	zassert_true(bool_val, "Expected bool val == true");
117 }
118 
ZTEST(zcbor_bulk,test_not_map)119 ZTEST(zcbor_bulk, test_not_map)
120 {
121 	uint8_t buffer[512];
122 	struct zcbor_string world;
123 	uint32_t one = 0;
124 	bool bool_val = false;
125 	zcbor_state_t zsd[4] = { 0 };
126 	size_t decoded = 1111;
127 	bool ok;
128 	struct zcbor_map_decode_key_val dm[] = {
129 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
130 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
131 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
132 	};
133 
134 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
135 
136 	/* List "hello", "world" */
137 	ok = zcbor_list_start_encode(zsd, 10) &&
138 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
139 	     zcbor_list_end_encode(zsd, 10);
140 
141 	zassert_true(ok, "Expected to be successful in encoding test pattern");
142 
143 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
144 
145 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
146 
147 	zassert_equal(rc, -EBADMSG, "Expected -EBADMSG(%d), got %d", -EBADMSG, rc);
148 	zassert_equal(decoded, 1111, "Expected decoded value to be unmodified");
149 }
150 
ZTEST(zcbor_bulk,test_bad_type)151 ZTEST(zcbor_bulk, test_bad_type)
152 {
153 	uint8_t buffer[512];
154 	struct zcbor_string world = { 0 };
155 	uint32_t one = 0;
156 	bool bool_val = false;
157 	zcbor_state_t zsd[4] = { 0 };
158 	size_t decoded = 0;
159 	bool ok;
160 	struct zcbor_map_decode_key_val dm[] = {
161 		/* First entry has bad decoder given instead of tstr */
162 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_uint32_decode, &world),
163 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
164 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
165 	};
166 
167 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
168 
169 	/* { "hello":"world", "one":1, "bool_val":true } */
170 	ok = zcbor_map_start_encode(zsd, 10) &&
171 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
172 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
173 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
174 	     zcbor_map_end_encode(zsd, 10);
175 
176 	zassert_true(ok, "Expected to be successful in encoding test pattern");
177 
178 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
179 
180 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
181 
182 	zassert_equal(rc, -ENOMSG, "Expected -ENOMSG, got %d", rc);
183 	zassert_equal(decoded, 0, "Expected 0 got %d", decoded);
184 	zassert_equal(one, 0, "Expected 0");
185 	zassert_equal(0, world.len, "Expected to be unmodified");
186 	zassert_false(bool_val, "Expected bool val == false");
187 }
188 
ZTEST(zcbor_bulk,test_bad_type_2)189 ZTEST(zcbor_bulk, test_bad_type_2)
190 {
191 	uint8_t buffer[512];
192 	struct zcbor_string world = { 0 };
193 	uint32_t one = 0;
194 	bool bool_val = false;
195 	zcbor_state_t zsd[4] = { 0 };
196 	size_t decoded = 0;
197 	bool ok;
198 	struct zcbor_map_decode_key_val dm[] = {
199 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
200 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
201 		/* This is bad decoder for type bool */
202 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_tstr_decode, &bool_val)
203 	};
204 
205 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
206 
207 	/* { "hello":"world", "one":1, "bool_val":true } */
208 	ok = zcbor_map_start_encode(zsd, 10) &&
209 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
210 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
211 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
212 	     zcbor_map_end_encode(zsd, 10);
213 
214 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
215 
216 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
217 
218 	zassert_equal(rc, -ENOMSG, "Expected -ENOMSG, got %d", rc);
219 	zassert_equal(decoded, ARRAY_SIZE(dm) - 1, "Expected %d got %d",
220 		ARRAY_SIZE(dm) - 1, decoded);
221 	zassert_equal(one, 1, "Expected 1");
222 	zassert_equal(sizeof("world") - 1, world.len, "Expected length %d",
223 		sizeof("world") - 1);
224 	zassert_equal(0, memcmp(world.value, "world", world.len),
225 		"Expected \"world\", got %.*s", (int)world.len, world.value);
226 	zassert_false(bool_val, "Expected bool val unmodified");
227 }
228 
ZTEST(zcbor_bulk,test_bad_type_encoded)229 ZTEST(zcbor_bulk, test_bad_type_encoded)
230 {
231 	uint8_t buffer[512];
232 	struct zcbor_string world = { 0 };
233 	uint32_t one = 0;
234 	bool bool_val = false;
235 	zcbor_state_t zsd[4] = { 0 };
236 	size_t decoded = 0;
237 	bool ok;
238 	struct zcbor_map_decode_key_val dm[] = {
239 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
240 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
241 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
242 	};
243 
244 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
245 
246 	/* { "hello":"world", "one":1, "bool_val":true } */
247 	ok = zcbor_map_start_encode(zsd, 10) &&
248 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_uint32_put(zsd, 10)		&&
249 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
250 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
251 	     zcbor_map_end_encode(zsd, 10);
252 
253 	zassert_true(ok, "Expected to be successful in encoding test pattern");
254 
255 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
256 
257 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
258 
259 	zassert_equal(rc, -ENOMSG, "Expected -ENOMSG, got %d", rc);
260 	zassert_equal(decoded, 0, "Expected 0 got %d", decoded);
261 	zassert_equal(one, 0, "Expected 0");
262 	zassert_equal(0, world.len, "Expected to be unmodified");
263 	zassert_false(bool_val, "Expected bool val == false");
264 }
265 
ZTEST(zcbor_bulk,test_duplicate)266 ZTEST(zcbor_bulk, test_duplicate)
267 {
268 	/* Duplicate key is error and should never happen */
269 	uint8_t buffer[512];
270 	struct zcbor_string world = { 0 };
271 	uint32_t one = 0;
272 	bool bool_val = false;
273 	zcbor_state_t zsd[4] = { 0 };
274 	size_t decoded = 0;
275 	bool ok;
276 	struct zcbor_map_decode_key_val dm[] = {
277 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
278 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
279 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
280 	};
281 
282 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
283 
284 	/* { "hello":"world", "hello":"world" } */
285 	ok = zcbor_map_start_encode(zsd, 10) &&
286 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
287 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
288 	     zcbor_map_end_encode(zsd, 10);
289 
290 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
291 
292 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
293 
294 	zassert_equal(rc, -EADDRINUSE, "Expected -EADDRINUSE, got %d", rc);
295 	zassert_equal(decoded, 1, "Expected %d got %d",
296 		ARRAY_SIZE(dm) - 1, decoded);
297 	zassert_equal(one, 0, "Expected unmodified");
298 	zassert_equal(sizeof("world") - 1, world.len, "Expected length %d",
299 		sizeof("world") - 1);
300 	zassert_equal(0, memcmp(world.value, "world", world.len),
301 		"Expected \"world\", got %.*s", (int)world.len, world.value);
302 	zassert_false(bool_val, "Expected bool val unmodified");
303 }
304 
305 struct in_map_decoding {
306 	size_t decoded;
307 	int ret;
308 	uint32_t number;
309 	struct zcbor_string str;
310 	uint32_t other_number;
311 };
312 
in_map_decoder(zcbor_state_t * zsd,struct in_map_decoding * imd)313 static bool in_map_decoder(zcbor_state_t *zsd, struct in_map_decoding *imd)
314 {
315 	uint32_t dont_exist = 0x64;
316 	struct zcbor_map_decode_key_val in_map[] = {
317 		ZCBOR_MAP_DECODE_KEY_VAL(number, zcbor_uint32_decode, &imd->number),
318 		ZCBOR_MAP_DECODE_KEY_VAL(str, zcbor_tstr_decode, &imd->str),
319 		ZCBOR_MAP_DECODE_KEY_VAL(dont_exist, zcbor_uint32_decode, &dont_exist),
320 	};
321 
322 	imd->ret = zcbor_map_decode_bulk(zsd, in_map, ARRAY_SIZE(in_map), &imd->decoded);
323 
324 	zassert_equal(dont_exist, 0x64, "dont_exist should not have get modified");
325 
326 	return (imd->ret == 0);
327 }
328 
ZTEST(zcbor_bulk,test_map_in_map_correct)329 ZTEST(zcbor_bulk, test_map_in_map_correct)
330 {
331 	uint8_t buffer[512];
332 	struct zcbor_string world;
333 	uint32_t one = 0;
334 	bool bool_val = false;
335 	zcbor_state_t zsd[4] = { 0 };
336 	size_t decoded = 0;
337 	bool ok;
338 	struct in_map_decoding imdd = { .ret = -1 };
339 	struct zcbor_map_decode_key_val dm[] = {
340 		ZCBOR_MAP_DECODE_KEY_VAL(hello, zcbor_tstr_decode, &world),
341 		ZCBOR_MAP_DECODE_KEY_VAL(in_map_map, in_map_decoder, &imdd),
342 		ZCBOR_MAP_DECODE_KEY_VAL(one, zcbor_uint32_decode, &one),
343 		ZCBOR_MAP_DECODE_KEY_VAL(bool_val, zcbor_bool_decode, &bool_val)
344 	};
345 
346 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
347 
348 	/* { "hello":"world",
349 	 *   "in_map" : {
350 	 *	"number" : 30,
351 	 *	"str" : "in_str"
352 	 *	},
353 	 *   "one":1,
354 	 *   "bool_val":true }
355 	 */
356 	ok = zcbor_map_start_encode(zsd, 10)						&&
357 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
358 	     zcbor_tstr_put_lit(zsd, "in_map_map")					&&
359 		zcbor_map_start_encode(zsd, 10)						&&
360 		zcbor_tstr_put_lit(zsd, "number") && zcbor_uint32_put(zsd, 30)		&&
361 		zcbor_tstr_put_lit(zsd, "str") && zcbor_tstr_put_lit(zsd, "in_str")	&&
362 		zcbor_map_end_encode(zsd, 10)						&&
363 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
364 	     zcbor_tstr_put_lit(zsd, "bool_val") && zcbor_true_put(zsd)			&&
365 	     zcbor_map_end_encode(zsd, 10);
366 
367 	zassert_true(ok, "Expected to be successful in encoding test pattern");
368 
369 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
370 
371 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
372 
373 	zassert_ok(rc, "Expected 0, got %d", rc);
374 	zassert_equal(decoded, ARRAY_SIZE(dm), "Expected %d got %d",
375 		ARRAY_SIZE(dm), decoded);
376 	zassert_equal(one, 1, "Expected 1");
377 	zassert_equal(sizeof("world") - 1, world.len, "Expected length %d",
378 		sizeof("world") - 1);
379 	zassert_equal(0, memcmp(world.value, "world", world.len),
380 		"Expected \"world\", got %.*s", (int)world.len, world.value);
381 	zassert_true(bool_val, "Expected bool_val == true");
382 
383 	/* Map within map */
384 	zassert_equal(imdd.ret, 0, "Expected successful decoding of inner map");
385 	zassert_equal(imdd.decoded, 2, "Expected two items in inner map");
386 	zassert_equal(imdd.number, 30);
387 	zassert_equal(imdd.str.len, sizeof("in_str") - 1);
388 	zassert_equal(memcmp("in_str", imdd.str.value, imdd.str.len), 0);
389 }
390 
in_map_decoder_bad(zcbor_state_t * zsd,struct in_map_decoding * imd)391 static bool in_map_decoder_bad(zcbor_state_t *zsd, struct in_map_decoding *imd)
392 {
393 	uint32_t dont_exist = 0x64;
394 	uint32_t wrong_type = 0x34;
395 	struct zcbor_map_decode_key_val in_map[] = {
396 		ZCBOR_MAP_DECODE_KEY_VAL(number, zcbor_uint32_decode, &imd->number),
397 		ZCBOR_MAP_DECODE_KEY_VAL(str, zcbor_uint32_decode, &wrong_type),
398 		ZCBOR_MAP_DECODE_KEY_VAL(dont_exist, zcbor_uint32_decode, &dont_exist),
399 	};
400 
401 	imd->ret = zcbor_map_decode_bulk(zsd, in_map, ARRAY_SIZE(in_map), &imd->decoded);
402 
403 	zassert_equal(dont_exist, 0x64, "dont_exist should not have get modified");
404 
405 	return (imd->ret == 0);
406 }
407 
ZTEST(zcbor_bulk,test_map_in_map_bad)408 ZTEST(zcbor_bulk, test_map_in_map_bad)
409 {
410 	uint8_t buffer[512];
411 	struct zcbor_string world;
412 	uint32_t one = 0;
413 	bool bool_val = false;
414 	zcbor_state_t zsd[4] = { 0 };
415 	size_t decoded = 0;
416 	bool ok;
417 	struct in_map_decoding imdd = { .ret = -1 };
418 	struct zcbor_map_decode_key_val dm[] = {
419 		ZCBOR_MAP_DECODE_KEY_VAL(hello, zcbor_tstr_decode, &world),
420 		ZCBOR_MAP_DECODE_KEY_VAL(in_map_map, in_map_decoder_bad, &imdd),
421 		ZCBOR_MAP_DECODE_KEY_VAL(one, zcbor_uint32_decode, &one),
422 		ZCBOR_MAP_DECODE_KEY_VAL(bool_val, zcbor_bool_decode, &bool_val)
423 	};
424 
425 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
426 
427 	/* { "hello":"world",
428 	 *   "in_map" : {
429 	 *	"number" : 30,
430 	 *	"str" : "in_str" # Decoding function will expect str to be int
431 	 *	},
432 	 *   "one":1,
433 	 *   "bool_val":true }
434 	 */
435 	ok = zcbor_map_start_encode(zsd, 10)						&&
436 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
437 	     zcbor_tstr_put_lit(zsd, "in_map_map")					&&
438 		zcbor_map_start_encode(zsd, 10)						&&
439 		zcbor_tstr_put_lit(zsd, "number") && zcbor_uint32_put(zsd, 30)		&&
440 		zcbor_tstr_put_lit(zsd, "str") && zcbor_tstr_put_lit(zsd, "in_str")	&&
441 		zcbor_map_end_encode(zsd, 10)						&&
442 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
443 	     zcbor_tstr_put_lit(zsd, "bool_val") && zcbor_true_put(zsd)			&&
444 	     zcbor_map_end_encode(zsd, 10);
445 
446 	zassert_true(ok, "Expected to be successful in encoding test pattern");
447 
448 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
449 
450 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
451 
452 	/* in_map_decoder_bad should fail */
453 	zassert_equal(rc, -ENOMSG, "Expected ENOMSG(-42), got %d", rc);
454 	zassert_equal(decoded, 1, "Expected 1 got %d", decoded);
455 
456 	/* Map within map */
457 	zassert_equal(imdd.ret, -ENOMSG, "Expected failure in decoding of inner map");
458 	zassert_equal(imdd.decoded, 1, "Expected 1 item before failure");
459 	zassert_equal(imdd.number, 30);
460 }
461 
ZTEST(zcbor_bulk,test_key_found)462 ZTEST(zcbor_bulk, test_key_found)
463 {
464 	uint8_t buffer[512];
465 	struct zcbor_string world;
466 	uint32_t one = 0;
467 	bool bool_val = false;
468 	zcbor_state_t zsd[4] = { 0 };
469 	size_t decoded = 0;
470 	bool ok;
471 	struct zcbor_map_decode_key_val dm[] = {
472 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
473 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
474 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
475 	};
476 
477 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
478 
479 	/* { "hello":"world", "bool val":true }, "one" is missing and will not be
480 	 * found.
481 	 */
482 	ok = zcbor_map_start_encode(zsd, 10) &&
483 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
484 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
485 	     zcbor_map_end_encode(zsd, 10);
486 
487 	zassert_true(ok, "Expected to be successful in encoding test pattern");
488 
489 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
490 
491 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
492 
493 	zassert_ok(rc, "Expected 0, got %d", rc);
494 	zassert_equal(decoded, ARRAY_SIZE(dm) - 1, "Expected %d got %d",
495 		ARRAY_SIZE(dm), decoded);
496 
497 	zassert_true(zcbor_map_decode_bulk_key_found(dm, ARRAY_SIZE(dm), "hello"),
498 		     "Expected \"hello\"");
499 	zassert_false(zcbor_map_decode_bulk_key_found(dm, ARRAY_SIZE(dm), "one"),
500 		     "Unexpected \"one\"");
501 	zassert_true(zcbor_map_decode_bulk_key_found(dm, ARRAY_SIZE(dm), "bool val"),
502 		     "Expected \"bool val\"");
503 }
504 
ZTEST(zcbor_bulk,test_reset)505 ZTEST(zcbor_bulk, test_reset)
506 {
507 	uint8_t buffer[512];
508 	struct zcbor_string world;
509 	uint32_t one = 0;
510 	bool bool_val = false;
511 	zcbor_state_t zsd[4] = { 0 };
512 	size_t decoded = 0;
513 	bool ok;
514 	struct zcbor_map_decode_key_val dm[] = {
515 		ZCBOR_MAP_DECODE_KEY_DECODER("hello", zcbor_tstr_decode, &world),
516 		ZCBOR_MAP_DECODE_KEY_DECODER("one", zcbor_uint32_decode, &one),
517 		ZCBOR_MAP_DECODE_KEY_DECODER("bool val", zcbor_bool_decode, &bool_val)
518 	};
519 
520 	zcbor_new_encode_state(zsd, 2, buffer, ARRAY_SIZE(buffer), 0);
521 
522 	/* { "hello":"world", "one":1, "bool_val":true } */
523 	ok = zcbor_map_start_encode(zsd, 10) &&
524 	     zcbor_tstr_put_lit(zsd, "hello") && zcbor_tstr_put_lit(zsd, "world")	&&
525 	     zcbor_tstr_put_lit(zsd, "one") && zcbor_uint32_put(zsd, 1)			&&
526 	     zcbor_tstr_put_lit(zsd, "bool val") && zcbor_true_put(zsd)			&&
527 	     zcbor_map_end_encode(zsd, 10);
528 
529 	zassert_true(ok, "Expected to be successful in encoding test pattern");
530 
531 	zcbor_new_decode_state(zsd, 4, buffer, ARRAY_SIZE(buffer), 1, NULL, 0);
532 
533 	int rc = zcbor_map_decode_bulk(zsd, dm, ARRAY_SIZE(dm), &decoded);
534 
535 	zassert_ok(rc, "Expected 0, got %d", rc);
536 
537 	for (int i = 0; i < ARRAY_SIZE(dm); ++i) {
538 		zassert_true(dm[i].found, "Expected found for index %d", i);
539 	}
540 
541 	zcbor_map_decode_bulk_reset(dm, ARRAY_SIZE(dm));
542 
543 	for (int i = 0; i < ARRAY_SIZE(dm); ++i) {
544 		zassert_false(dm[i].found, "Expected state reset for index %d", i);
545 	}
546 }
547 
548 ZTEST_SUITE(zcbor_bulk, NULL, NULL, NULL, NULL, NULL);
549