1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/net_buf.h>
9 #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
10 #include <zephyr/mgmt/mcumgr/transport/smp_dummy.h>
11 #include <zephyr/mgmt/mcumgr/mgmt/callbacks.h>
12 #include <zephyr/mgmt/mcumgr/grp/enum_mgmt/enum_mgmt.h>
13 #include <zcbor_common.h>
14 #include <zcbor_decode.h>
15 #include <zcbor_encode.h>
16 #include <mgmt/mcumgr/util/zcbor_bulk.h>
17 #include <string.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <smp_internal.h>
20 #include "smp_test_util.h"
21
22 #define LOG_LEVEL LOG_LEVEL_DBG
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(smp_sample);
25
26 #define SHELL_MGMT_HANDLERS 1
27 #define OS_MGMT_HANDLERS 6
28 #define ENUM_MGMT_HANDLERS 4
29
30 #define OS_MGMT_NAME "os mgmt"
31 #define ENUM_MGMT_NAME "enum mgmt"
32 #define SHELL_MGMT_NAME "shell mgmt"
33
34 #if defined(CONFIG_MCUMGR_GRP_SHELL) && defined(CONFIG_MCUMGR_GRP_OS)
35 #define TEST_GROUPS 3
36 #elif defined(CONFIG_MCUMGR_GRP_SHELL) || defined(CONFIG_MCUMGR_GRP_OS)
37 #define TEST_GROUPS 2
38 #else
39 #define TEST_GROUPS 1
40 #endif
41
42 #if defined(CONFIG_MCUMGR_GRP_SHELL) && defined(CONFIG_MCUMGR_GRP_OS)
43 #define FOUND_INDEX_SHELL 2
44 #else
45 #define FOUND_INDEX_SHELL 1
46 #endif
47 #define FOUND_INDEX_OS 1
48 #define FOUND_INDEX_ENUM 0
49
50 #define SMP_RESPONSE_WAIT_TIME 3
51 #define ZCBOR_BUFFER_SIZE 128
52 #define OUTPUT_BUFFER_SIZE 512
53 #define ZCBOR_HISTORY_ARRAY_SIZE 7
54
55 static struct net_buf *nb;
56 static bool enum_valid_got;
57 static bool enum_field_added;
58 static bool event_invalid_got;
59 static bool block_access;
60 static bool add_field;
61
62 struct list_entries {
63 uint8_t entries;
64 uint16_t groups[16];
65 };
66
67 struct details_entries {
68 char expected_name[32];
69 uint8_t expected_handlers;
70 bool expected_test;
71
72 bool matched_name;
73 bool matched_handlers;
74 bool matched_test;
75 };
76
77 #if defined(CONFIG_MCUMGR_GRP_SHELL)
78 #define SINGLE_MATCHED_SHELL 0x1
79 #else
80 #define SINGLE_MATCHED_SHELL 0x0
81 #endif
82 #if defined(CONFIG_MCUMGR_GRP_OS)
83 #define SINGLE_MATCHED_OS 0x2
84 #else
85 #define SINGLE_MATCHED_OS 0x0
86 #endif
87 #define SINGLE_MATCHED_ENUM 0x4
88
89 #define SINGLE_MATCHED_ALL (SINGLE_MATCHED_SHELL | SINGLE_MATCHED_OS | SINGLE_MATCHED_ENUM)
90
cleanup_test(void * p)91 static void cleanup_test(void *p)
92 {
93 if (nb != NULL) {
94 net_buf_unref(nb);
95 nb = NULL;
96 }
97
98 enum_valid_got = false;
99 enum_field_added = false;
100 event_invalid_got = false;
101 block_access = false;
102 add_field = false;
103 }
104
ZTEST(enum_mgmt,test_count)105 ZTEST(enum_mgmt, test_count)
106 {
107 uint8_t buffer[ZCBOR_BUFFER_SIZE];
108 uint8_t buffer_out[OUTPUT_BUFFER_SIZE];
109 bool ok;
110 uint16_t buffer_size;
111 zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
112 zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
113 bool received;
114 struct smp_hdr *header;
115 uint32_t count_response = 0;
116 size_t decoded = 0;
117
118 struct zcbor_map_decode_key_val output_decode[] = {
119 ZCBOR_MAP_DECODE_KEY_DECODER("count", zcbor_uint32_decode, &count_response),
120 };
121
122 memset(buffer, 0, sizeof(buffer));
123 memset(buffer_out, 0, sizeof(buffer_out));
124 buffer_size = 0;
125 memset(zse, 0, sizeof(zse));
126 memset(zsd, 0, sizeof(zsd));
127
128 zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0);
129
130 ok = create_enum_mgmt_count_packet(zse, buffer, buffer_out, &buffer_size);
131 zassert_true(ok, "Expected packet creation to be successful");
132
133 /* Enable dummy SMP backend and ready for usage */
134 smp_dummy_enable();
135 smp_dummy_clear_state();
136
137 /* Send query command to dummy SMP backend */
138 (void)smp_dummy_tx_pkt(buffer_out, buffer_size);
139 smp_dummy_add_data();
140
141 /* Wait for a short duration to see if response has been received */
142 received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME);
143 zassert_true(received, "Expected to receive data but timed out");
144
145 /* Retrieve response buffer */
146 nb = smp_dummy_get_outgoing();
147 smp_dummy_disable();
148
149 /* Check response is as expected */
150 header = net_buf_pull_mem(nb, sizeof(struct smp_hdr));
151
152 zassert_equal(header->nh_flags, 0, "SMP header flags mismatch");
153 zassert_equal(header->nh_op, MGMT_OP_READ_RSP, "SMP header operation mismatch");
154 zassert_equal(header->nh_group, sys_cpu_to_be16(MGMT_GROUP_ID_ENUM),
155 "SMP header group mismatch");
156 zassert_equal(header->nh_seq, 1, "SMP header sequence number mismatch");
157 zassert_equal(header->nh_id, ENUM_MGMT_ID_COUNT, "SMP header command ID mismatch");
158 zassert_equal(header->nh_version, 1, "SMP header version mismatch");
159
160 /* Get the response value to compare */
161 zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1, NULL, 0);
162 ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0;
163 zassert_true(ok, "Expected decode to be successful");
164 zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element");
165
166 /* Ensure the right amount of data was read and that the value matches */
167 zassert_equal(count_response, TEST_GROUPS, "Expected data mismatch");
168
169 /* Clean up test */
170 cleanup_test(NULL);
171 }
172
parse_list_entries(zcbor_state_t * state,void * user_data)173 static bool parse_list_entries(zcbor_state_t *state, void *user_data)
174 {
175 uint32_t temp = 0;
176 uint16_t i = 0;
177 struct list_entries *entry_data = (struct list_entries *)user_data;
178
179 if (!zcbor_list_start_decode(state)) {
180 return false;
181 }
182
183 while (!zcbor_array_at_end(state)) {
184 if (!zcbor_uint32_decode(state, &temp)) {
185 return false;
186 }
187
188 if (i > ARRAY_SIZE(entry_data->groups)) {
189 return false;
190 }
191
192 entry_data->groups[i] = (uint16_t)temp;
193
194 ++i;
195 }
196
197 (void)zcbor_list_end_decode(state);
198
199 entry_data->entries = i;
200
201 return true;
202 }
203
ZTEST(enum_mgmt,test_list)204 ZTEST(enum_mgmt, test_list)
205 {
206 uint8_t buffer[ZCBOR_BUFFER_SIZE];
207 uint8_t buffer_out[OUTPUT_BUFFER_SIZE];
208 bool ok;
209 uint16_t buffer_size;
210 zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
211 zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
212 bool received;
213 struct smp_hdr *header;
214 size_t decoded = 0;
215 struct list_entries list_response = { 0 };
216 uint8_t i;
217 bool found_groups[TEST_GROUPS] = { 0 };
218
219 struct zcbor_map_decode_key_val output_decode[] = {
220 ZCBOR_MAP_DECODE_KEY_DECODER("groups", parse_list_entries, &list_response),
221 };
222
223 memset(buffer, 0, sizeof(buffer));
224 memset(buffer_out, 0, sizeof(buffer_out));
225 buffer_size = 0;
226 memset(zse, 0, sizeof(zse));
227 memset(zsd, 0, sizeof(zsd));
228
229 zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0);
230
231 ok = create_enum_mgmt_list_packet(zse, buffer, buffer_out, &buffer_size);
232 zassert_true(ok, "Expected packet creation to be successful");
233
234 /* Enable dummy SMP backend and ready for usage */
235 smp_dummy_enable();
236 smp_dummy_clear_state();
237
238 /* Send query command to dummy SMP backend */
239 (void)smp_dummy_tx_pkt(buffer_out, buffer_size);
240 smp_dummy_add_data();
241
242 /* Wait for a short duration to see if response has been received */
243 received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME);
244 zassert_true(received, "Expected to receive data but timed out");
245
246 /* Retrieve response buffer */
247 nb = smp_dummy_get_outgoing();
248 smp_dummy_disable();
249
250 /* Check response is as expected */
251 header = net_buf_pull_mem(nb, sizeof(struct smp_hdr));
252
253 zassert_equal(header->nh_flags, 0, "SMP header flags mismatch");
254 zassert_equal(header->nh_op, MGMT_OP_READ_RSP, "SMP header operation mismatch");
255 zassert_equal(header->nh_group, sys_cpu_to_be16(MGMT_GROUP_ID_ENUM),
256 "SMP header group mismatch");
257 zassert_equal(header->nh_seq, 1, "SMP header sequence number mismatch");
258 zassert_equal(header->nh_id, ENUM_MGMT_ID_LIST, "SMP header command ID mismatch");
259 zassert_equal(header->nh_version, 1, "SMP header version mismatch");
260
261 /* Get the response value to compare */
262 zcbor_new_decode_state(zsd, 4, nb->data, nb->len, 1, NULL, 0);
263 ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0;
264 zassert_true(ok, "Expected decode to be successful");
265 zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element");
266
267 /* Ensure the right amount of data was read and that the values match */
268 zassert_equal(list_response.entries, TEST_GROUPS, "Expected data mismatch");
269
270 i = 0;
271
272 while (i < list_response.entries) {
273 uint8_t index = 0xff;
274
275 if (list_response.groups[i] == MGMT_GROUP_ID_ENUM) {
276 index = FOUND_INDEX_ENUM;
277 }
278 #if defined(CONFIG_MCUMGR_GRP_OS)
279 if (list_response.groups[i] == MGMT_GROUP_ID_OS) {
280 index = FOUND_INDEX_OS;
281 }
282 #endif
283 #if defined(CONFIG_MCUMGR_GRP_SHELL)
284 if (list_response.groups[i] == MGMT_GROUP_ID_SHELL) {
285 index = FOUND_INDEX_SHELL;
286 }
287 #endif
288
289 if (index != 0xff) {
290 found_groups[index] = true;
291 }
292
293 ++i;
294 }
295
296 i = 0;
297
298 while (i < TEST_GROUPS) {
299 zassert_true(found_groups[i], "Expected group to be found in list");
300 ++i;
301 }
302
303 /* Clean up test */
304 cleanup_test(NULL);
305 }
306
ZTEST(enum_mgmt,test_single)307 ZTEST(enum_mgmt, test_single)
308 {
309 uint8_t buffer[ZCBOR_BUFFER_SIZE];
310 uint8_t buffer_out[OUTPUT_BUFFER_SIZE];
311 bool ok;
312 uint16_t buffer_size;
313 zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
314 zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
315 bool received;
316 struct smp_hdr *header;
317 size_t decoded = 0;
318 uint8_t i;
319 uint8_t matched_entries = 0;
320 uint32_t received_group = 0;
321 bool received_end = false;
322
323 i = 0;
324 while (received_end == false) {
325 struct zcbor_map_decode_key_val output_decode[] = {
326 ZCBOR_MAP_DECODE_KEY_DECODER("group", zcbor_uint32_decode, &received_group),
327 ZCBOR_MAP_DECODE_KEY_DECODER("end", zcbor_bool_decode, &received_end),
328 };
329
330 memset(buffer, 0, sizeof(buffer));
331 memset(buffer_out, 0, sizeof(buffer_out));
332 buffer_size = 0;
333 memset(zse, 0, sizeof(zse));
334 memset(zsd, 0, sizeof(zsd));
335
336 zcbor_new_encode_state(zse, 3, buffer, ARRAY_SIZE(buffer), 0);
337 ok = create_enum_mgmt_single_packet(zse, buffer, buffer_out, &buffer_size, i);
338 zassert_true(ok, "Expected packet creation to be successful");
339
340 /* Enable dummy SMP backend and ready for usage */
341 smp_dummy_enable();
342 smp_dummy_clear_state();
343
344 /* Send query command to dummy SMP backend */
345 (void)smp_dummy_tx_pkt(buffer_out, buffer_size);
346 smp_dummy_add_data();
347
348 /* Wait for a short duration to see if response has been received */
349 received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME);
350 zassert_true(received, "Expected to receive data but timed out");
351
352 /* Retrieve response buffer */
353 nb = smp_dummy_get_outgoing();
354 smp_dummy_disable();
355
356 /* Check response is as expected */
357 header = net_buf_pull_mem(nb, sizeof(struct smp_hdr));
358
359 zassert_equal(header->nh_flags, 0, "SMP header flags mismatch");
360 zassert_equal(header->nh_op, MGMT_OP_READ_RSP, "SMP header operation mismatch");
361 zassert_equal(header->nh_group, sys_cpu_to_be16(MGMT_GROUP_ID_ENUM),
362 "SMP header group mismatch");
363 zassert_equal(header->nh_seq, 1, "SMP header sequence number mismatch");
364 zassert_equal(header->nh_id, ENUM_MGMT_ID_SINGLE,
365 "SMP header command ID mismatch");
366 zassert_equal(header->nh_version, 1, "SMP header version mismatch");
367
368 /* Get the response value to compare */
369 zcbor_new_decode_state(zsd, 7, nb->data, nb->len, 1, NULL, 0);
370 ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode),
371 &decoded) == 0;
372 zassert_true(ok, "Expected decode to be successful");
373 zassert_not_equal(decoded, 0,
374 "Expected to receive at least 1 decoded zcbor element");
375
376 if (received_group == MGMT_GROUP_ID_SHELL) {
377 matched_entries |= SINGLE_MATCHED_SHELL;
378 } else if (received_group == MGMT_GROUP_ID_OS) {
379 matched_entries |= SINGLE_MATCHED_OS;
380 } else if (received_group == MGMT_GROUP_ID_ENUM) {
381 matched_entries |= SINGLE_MATCHED_ENUM;
382 } else {
383 zassert_true(0, "Received unknown group");
384 }
385
386 if (matched_entries == SINGLE_MATCHED_ALL) {
387 zassert_true(received_end, "Expected to have received end");
388 zassert_equal(decoded, 2, "Expected to receive 2 decoded zcbor elements");
389 } else {
390 zassert_false(received_end, "Did not expect to receive end");
391 zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor elements");
392 }
393
394 zassert_true((i <= TEST_GROUPS), "Loop ran too many times");
395
396 /* Clean up test */
397 cleanup_test(NULL);
398
399 ++i;
400 }
401
402 zassert_equal(matched_entries, SINGLE_MATCHED_ALL, "Received entries mismatch");
403 }
404
parse_details_entries(zcbor_state_t * state,void * user_data)405 static bool parse_details_entries(zcbor_state_t *state, void *user_data)
406 {
407 uint32_t group = 0;
408 struct zcbor_string name = { 0 };
409 uint32_t handlers = 0;
410 uint32_t test = 0;
411 uint16_t i = 0;
412 struct details_entries *entry_data = (struct details_entries *)user_data;
413
414 struct zcbor_map_decode_key_val output_decode[] = {
415 ZCBOR_MAP_DECODE_KEY_DECODER("group", zcbor_uint32_decode, &group),
416 ZCBOR_MAP_DECODE_KEY_DECODER("name", zcbor_tstr_decode, &name),
417 ZCBOR_MAP_DECODE_KEY_DECODER("handlers", zcbor_uint32_decode, &handlers),
418 ZCBOR_MAP_DECODE_KEY_DECODER("test", zcbor_uint32_decode, &test),
419 };
420
421 if (!zcbor_list_start_decode(state)) {
422 return false;
423 }
424
425 while (!zcbor_array_at_end(state)) {
426 uint8_t index = 0;
427 bool ok;
428 size_t decoded = 0;
429
430 /* Reset */
431 group = 0;
432 name.value = NULL;
433 name.len = 0;
434 handlers = 0;
435 test = 0;
436
437 i = 0;
438
439 while (i < ARRAY_SIZE(output_decode)) {
440 output_decode[i].found = false;
441 ++i;
442 }
443
444 ok = zcbor_map_decode_bulk(state, output_decode, ARRAY_SIZE(output_decode),
445 &decoded) == 0;
446 zassert_true(ok, "Expected decode to be successful");
447
448 if (group == MGMT_GROUP_ID_ENUM) {
449 index = FOUND_INDEX_ENUM;
450
451 if (strcmp(name.value, ENUM_MGMT_NAME) == 0) {
452 entry_data[index].matched_name = true;
453 }
454 }
455 #if defined(CONFIG_MCUMGR_GRP_OS)
456 else if (group == MGMT_GROUP_ID_OS) {
457 index = FOUND_INDEX_OS;
458
459 if (strcmp(name.value, OS_MGMT_NAME) == 0) {
460 entry_data[index].matched_name = true;
461 }
462 }
463 #endif
464 #if defined(CONFIG_MCUMGR_GRP_SHELL)
465 else if (group == MGMT_GROUP_ID_SHELL) {
466 index = FOUND_INDEX_SHELL;
467 }
468 #endif
469 else {
470 return false;
471 }
472
473 if (entry_data[index].expected_test) {
474 zassert_equal(decoded, 4, "Expected to receive 4 decoded zcbor element");
475 } else {
476 zassert_equal(decoded, 3, "Expected to receive 3 decoded zcbor element");
477 }
478
479 if (memcmp(name.value, entry_data[index].expected_name, name.len) == 0) {
480 entry_data[index].matched_name = true;
481 }
482
483 if (handlers == entry_data[index].expected_handlers) {
484 entry_data[index].matched_handlers = true;
485 }
486
487 if (output_decode[3].found == entry_data[index].expected_test) {
488 /* Check value is correct */
489 if (entry_data[index].expected_test == false ||
490 (entry_data[index].expected_test == true && test == (group * 3 + 1))) {
491 entry_data[index].matched_test = true;
492 }
493 }
494 }
495
496 (void)zcbor_list_end_decode(state);
497
498 return true;
499 }
500
ZTEST(enum_mgmt,test_details)501 ZTEST(enum_mgmt, test_details)
502 {
503 uint8_t buffer[ZCBOR_BUFFER_SIZE];
504 uint8_t buffer_out[OUTPUT_BUFFER_SIZE];
505 bool ok;
506 uint16_t buffer_size;
507 zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
508 zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
509 bool received;
510 struct smp_hdr *header;
511 size_t decoded = 0;
512 struct details_entries details_response[TEST_GROUPS] = { 0 };
513 uint8_t i;
514
515 #if defined(CONFIG_MCUMGR_GRP_SHELL)
516 strcpy(details_response[FOUND_INDEX_SHELL].expected_name, SHELL_MGMT_NAME);
517 details_response[FOUND_INDEX_SHELL].expected_handlers = SHELL_MGMT_HANDLERS;
518 details_response[FOUND_INDEX_SHELL].expected_test = false;
519 #endif
520
521 #if defined(CONFIG_MCUMGR_GRP_OS)
522 strcpy(details_response[FOUND_INDEX_OS].expected_name, OS_MGMT_NAME);
523 details_response[FOUND_INDEX_OS].expected_handlers = OS_MGMT_HANDLERS;
524 details_response[FOUND_INDEX_OS].expected_test = false;
525 #endif
526
527 strcpy(details_response[FOUND_INDEX_ENUM].expected_name, ENUM_MGMT_NAME);
528 details_response[FOUND_INDEX_ENUM].expected_handlers = ENUM_MGMT_HANDLERS;
529 details_response[FOUND_INDEX_ENUM].expected_test = false;
530
531 struct zcbor_map_decode_key_val output_decode[] = {
532 ZCBOR_MAP_DECODE_KEY_DECODER("groups", parse_details_entries, &details_response),
533 };
534
535 memset(buffer, 0, sizeof(buffer));
536 memset(buffer_out, 0, sizeof(buffer_out));
537 buffer_size = 0;
538 memset(zse, 0, sizeof(zse));
539 memset(zsd, 0, sizeof(zsd));
540
541 zcbor_new_encode_state(zse, 3, buffer, ARRAY_SIZE(buffer), 0);
542
543 ok = create_enum_mgmt_details_packet(zse, buffer, buffer_out, &buffer_size, NULL, 0);
544 zassert_true(ok, "Expected packet creation to be successful");
545
546 /* Enable dummy SMP backend and ready for usage */
547 smp_dummy_enable();
548 smp_dummy_clear_state();
549
550 /* Send query command to dummy SMP backend */
551 (void)smp_dummy_tx_pkt(buffer_out, buffer_size);
552 smp_dummy_add_data();
553
554 /* Wait for a short duration to see if response has been received */
555 received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME);
556 zassert_true(received, "Expected to receive data but timed out");
557
558 /* Retrieve response buffer */
559 nb = smp_dummy_get_outgoing();
560 smp_dummy_disable();
561
562 /* Check response is as expected */
563 header = net_buf_pull_mem(nb, sizeof(struct smp_hdr));
564
565 zassert_equal(header->nh_flags, 0, "SMP header flags mismatch");
566 zassert_equal(header->nh_op, MGMT_OP_READ_RSP, "SMP header operation mismatch");
567 zassert_equal(header->nh_group, sys_cpu_to_be16(MGMT_GROUP_ID_ENUM),
568 "SMP header group mismatch");
569 zassert_equal(header->nh_seq, 1, "SMP header sequence number mismatch");
570 zassert_equal(header->nh_id, ENUM_MGMT_ID_DETAILS, "SMP header command ID mismatch");
571 zassert_equal(header->nh_version, 1, "SMP header version mismatch");
572
573 /* Get the response value to compare */
574 zcbor_new_decode_state(zsd, 7, nb->data, nb->len, 1, NULL, 0);
575 ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0;
576 zassert_true(ok, "Expected decode to be successful");
577 zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element");
578
579 i = 0;
580
581 while (i < TEST_GROUPS) {
582 zassert_true(details_response[i].matched_name,
583 "Expected group name to be found in details");
584 zassert_true(details_response[i].matched_handlers,
585 "Expected group handler to be found in details");
586 zassert_true(details_response[i].matched_test,
587 "Did not expect group test to be found in details");
588 ++i;
589 }
590
591 zassert_true(enum_valid_got, "Expected callback to have ran");
592 zassert_false(enum_field_added, "Did not expect field to be added");
593 zassert_false(event_invalid_got, "Did not expect invalid callback to have ran");
594
595 /* Clean up test */
596 cleanup_test(NULL);
597 }
598
ZTEST(enum_mgmt,test_details_blocked)599 ZTEST(enum_mgmt, test_details_blocked)
600 {
601 uint8_t buffer[ZCBOR_BUFFER_SIZE];
602 uint8_t buffer_out[OUTPUT_BUFFER_SIZE];
603 bool ok;
604 uint16_t buffer_size;
605 zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
606 zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
607 bool received;
608 struct smp_hdr *header;
609 size_t decoded = 0;
610 uint32_t rc = 0;
611
612 struct zcbor_map_decode_key_val output_decode[] = {
613 ZCBOR_MAP_DECODE_KEY_DECODER("rc", zcbor_uint32_decode, &rc),
614 };
615
616 memset(buffer, 0, sizeof(buffer));
617 memset(buffer_out, 0, sizeof(buffer_out));
618 buffer_size = 0;
619 memset(zse, 0, sizeof(zse));
620 memset(zsd, 0, sizeof(zsd));
621
622 zcbor_new_encode_state(zse, 3, buffer, ARRAY_SIZE(buffer), 0);
623
624 ok = create_enum_mgmt_details_packet(zse, buffer, buffer_out, &buffer_size, NULL, 0);
625 zassert_true(ok, "Expected packet creation to be successful");
626
627 /* Enable dummy SMP backend and ready for usage */
628 smp_dummy_enable();
629 smp_dummy_clear_state();
630
631 /* Force notification callback to return an error */
632 block_access = true;
633
634 /* Send query command to dummy SMP backend */
635 (void)smp_dummy_tx_pkt(buffer_out, buffer_size);
636 smp_dummy_add_data();
637
638 /* Wait for a short duration to see if response has been received */
639 received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME);
640 zassert_true(received, "Expected to receive data but timed out");
641
642 /* Retrieve response buffer */
643 nb = smp_dummy_get_outgoing();
644 smp_dummy_disable();
645
646 /* Check response is as expected */
647 header = net_buf_pull_mem(nb, sizeof(struct smp_hdr));
648
649 zassert_equal(header->nh_flags, 0, "SMP header flags mismatch");
650 zassert_equal(header->nh_op, MGMT_OP_READ_RSP, "SMP header operation mismatch");
651 zassert_equal(header->nh_group, sys_cpu_to_be16(MGMT_GROUP_ID_ENUM),
652 "SMP header group mismatch");
653 zassert_equal(header->nh_seq, 1, "SMP header sequence number mismatch");
654 zassert_equal(header->nh_id, ENUM_MGMT_ID_DETAILS, "SMP header command ID mismatch");
655 zassert_equal(header->nh_version, 1, "SMP header version mismatch");
656
657 /* Get the response value to compare */
658 zcbor_new_decode_state(zsd, 5, nb->data, nb->len, 1, NULL, 0);
659 ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0;
660 zassert_true(ok, "Expected decode to be successful");
661 zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element");
662
663 zassert_true(enum_valid_got, "Expected callback to have ran");
664 zassert_false(enum_field_added, "Did not expect field to be added");
665 zassert_false(event_invalid_got, "Did not expect invalid callback to have ran");
666
667 /* Clean up test */
668 cleanup_test(NULL);
669 }
670
ZTEST(enum_mgmt,test_details_extra)671 ZTEST(enum_mgmt, test_details_extra)
672 {
673 uint8_t buffer[ZCBOR_BUFFER_SIZE];
674 uint8_t buffer_out[OUTPUT_BUFFER_SIZE];
675 bool ok;
676 uint16_t buffer_size;
677 zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
678 zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 };
679 bool received;
680 struct smp_hdr *header;
681 size_t decoded = 0;
682 struct details_entries details_response[TEST_GROUPS] = { 0 };
683 uint8_t i;
684
685 #if defined(CONFIG_MCUMGR_GRP_SHELL)
686 strcpy(details_response[FOUND_INDEX_SHELL].expected_name, SHELL_MGMT_NAME);
687 details_response[FOUND_INDEX_SHELL].expected_handlers = SHELL_MGMT_HANDLERS;
688 details_response[FOUND_INDEX_SHELL].expected_test = true;
689 #endif
690
691 #if defined(CONFIG_MCUMGR_GRP_OS)
692 strcpy(details_response[FOUND_INDEX_OS].expected_name, OS_MGMT_NAME);
693 details_response[FOUND_INDEX_OS].expected_handlers = OS_MGMT_HANDLERS;
694 details_response[FOUND_INDEX_OS].expected_test = true;
695 #endif
696
697 strcpy(details_response[FOUND_INDEX_ENUM].expected_name, ENUM_MGMT_NAME);
698 details_response[FOUND_INDEX_ENUM].expected_handlers = ENUM_MGMT_HANDLERS;
699 details_response[FOUND_INDEX_ENUM].expected_test = true;
700
701 struct zcbor_map_decode_key_val output_decode[] = {
702 ZCBOR_MAP_DECODE_KEY_DECODER("groups", parse_details_entries, &details_response),
703 };
704
705 memset(buffer, 0, sizeof(buffer));
706 memset(buffer_out, 0, sizeof(buffer_out));
707 buffer_size = 0;
708 memset(zse, 0, sizeof(zse));
709 memset(zsd, 0, sizeof(zsd));
710
711 zcbor_new_encode_state(zse, 3, buffer, ARRAY_SIZE(buffer), 0);
712
713 ok = create_enum_mgmt_details_packet(zse, buffer, buffer_out, &buffer_size, NULL, 0);
714 zassert_true(ok, "Expected packet creation to be successful");
715
716 add_field = true;
717
718 /* Enable dummy SMP backend and ready for usage */
719 smp_dummy_enable();
720 smp_dummy_clear_state();
721
722 /* Send query command to dummy SMP backend */
723 (void)smp_dummy_tx_pkt(buffer_out, buffer_size);
724 smp_dummy_add_data();
725
726 /* Wait for a short duration to see if response has been received */
727 received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME);
728 zassert_true(received, "Expected to receive data but timed out");
729
730 /* Retrieve response buffer */
731 nb = smp_dummy_get_outgoing();
732 smp_dummy_disable();
733
734 /* Check response is as expected */
735 header = net_buf_pull_mem(nb, sizeof(struct smp_hdr));
736
737 zassert_equal(header->nh_flags, 0, "SMP header flags mismatch");
738 zassert_equal(header->nh_op, MGMT_OP_READ_RSP, "SMP header operation mismatch");
739 zassert_equal(header->nh_group, sys_cpu_to_be16(MGMT_GROUP_ID_ENUM),
740 "SMP header group mismatch");
741 zassert_equal(header->nh_seq, 1, "SMP header sequence number mismatch");
742 zassert_equal(header->nh_id, ENUM_MGMT_ID_DETAILS, "SMP header command ID mismatch");
743 zassert_equal(header->nh_version, 1, "SMP header version mismatch");
744
745 /* Get the response value to compare */
746 zcbor_new_decode_state(zsd, 5, nb->data, nb->len, 1, NULL, 0);
747 ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0;
748 zassert_true(ok, "Expected decode to be successful");
749 zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element");
750
751 i = 0;
752
753 while (i < TEST_GROUPS) {
754 zassert_true(details_response[i].matched_name,
755 "Expected group name to be found in details");
756 zassert_true(details_response[i].matched_handlers,
757 "Expected group handler to be found in details");
758 zassert_true(details_response[i].matched_test,
759 "Expected group test to be found in details");
760 ++i;
761 }
762
763 zassert_true(enum_valid_got, "Expected callback to have ran");
764 zassert_true(enum_field_added, "Expected field to be added");
765 zassert_false(event_invalid_got, "Did not expect invalid callback to have ran");
766
767 /* Clean up test */
768 cleanup_test(NULL);
769 }
770
mgmt_event_cmd_callback(uint32_t event,enum mgmt_cb_return prev_status,int32_t * rc,uint16_t * group,bool * abort_more,void * data,size_t data_size)771 static enum mgmt_cb_return mgmt_event_cmd_callback(uint32_t event, enum mgmt_cb_return prev_status,
772 int32_t *rc, uint16_t *group, bool *abort_more,
773 void *data, size_t data_size)
774 {
775 if (event == MGMT_EVT_OP_ENUM_MGMT_DETAILS) {
776 struct enum_mgmt_detail_output *enum_data = (struct enum_mgmt_detail_output *)data;
777
778 enum_valid_got = true;
779
780 if (add_field == true) {
781 uint32_t temp = enum_data->group->mg_group_id * 3 + 1;
782 bool ok;
783
784 ok = zcbor_tstr_put_lit(enum_data->zse, "test") &&
785 zcbor_uint32_encode(enum_data->zse, &temp);
786
787 if (!ok) {
788 *rc = MGMT_ERR_EUNKNOWN;
789 return MGMT_CB_ERROR_RC;
790 }
791
792 enum_field_added = true;
793 }
794
795 if (block_access == true) {
796 *rc = MGMT_ERR_EPERUSER;
797 return MGMT_CB_ERROR_RC;
798 }
799 } else {
800 event_invalid_got = true;
801 }
802
803 return MGMT_CB_OK;
804 }
805
806 static struct mgmt_callback mgmt_event_callback = {
807 .callback = mgmt_event_cmd_callback,
808 .event_id = MGMT_EVT_OP_ENUM_MGMT_DETAILS,
809 };
810
setup_test(void)811 static void *setup_test(void)
812 {
813 mgmt_callback_register(&mgmt_event_callback);
814
815 return NULL;
816 }
817
818 ZTEST_SUITE(enum_mgmt, NULL, setup_test, NULL, cleanup_test, NULL);
819