diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/CMakeLists.txt b/tests/subsys/mgmt/mcumgr/cb_notifications/CMakeLists.txt new file mode 100644 index 0000000000..c7094bd4dd --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(cb_notifications) + +FILE(GLOB app_sources + src/*.c +) + +target_sources(app PRIVATE ${app_sources}) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/mgmt/mcumgr/transport/include/mgmt/mcumgr/transport/) diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv32_smp.conf b/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv32_smp.conf new file mode 100644 index 0000000000..1ede042960 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv32_smp.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv64.conf b/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv64.conf new file mode 100644 index 0000000000..1ede042960 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv64.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv64_smp.conf b/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv64_smp.conf new file mode 100644 index 0000000000..1ede042960 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/boards/qemu_riscv64_smp.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf b/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf new file mode 100644 index 0000000000..465de12700 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/prj.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_ZTEST=y +CONFIG_MCUMGR=y +CONFIG_MCUMGR_TRANSPORT_DUMMY=y +CONFIG_MCUMGR_TRANSPORT_DUMMY_RX_BUF_SIZE=256 +CONFIG_MCUMGR_GRP_OS=y +CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y +CONFIG_MCUMGR_SMP_COMMAND_STATUS_HOOKS=y +CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c b/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c new file mode 100644 index 0000000000..0d747ee470 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smp_test_util.h" + +#define SMP_RESPONSE_WAIT_TIME 3 +#define ZCBOR_BUFFER_SIZE 64 +#define OUTPUT_BUFFER_SIZE 64 +#define ZCBOR_HISTORY_ARRAY_SIZE 4 + +/* Test sets */ +enum { + CB_NOTIFICATION_TEST_CALLBACK_DISABLED, + CB_NOTIFICATION_TEST_CALLBACK_ENABLED, + CB_NOTIFICATION_TEST_CALLBACK_DISABLED_VERIFY, + + CB_NOTIFICATION_TEST_SET_COUNT +}; + +static struct net_buf *nb; + +struct state { + uint8_t test_set; +}; + +static struct state test_state = { + .test_set = 0, +}; + +static bool cmd_recv_got; +static bool cmd_status_got; +static bool cmd_done_got; +static bool cmd_other_got; + +/* Responses to commands */ + +static int32_t mgmt_event_cmd_callback(uint32_t event, int32_t rc, bool *abort_more, + void *data, size_t data_size) +{ + if (event == MGMT_EVT_OP_CMD_RECV) { + cmd_recv_got = true; + } else if (event == MGMT_EVT_OP_CMD_STATUS) { + cmd_status_got = true; + } else if (event == MGMT_EVT_OP_CMD_DONE) { + cmd_done_got = true; + } else { + cmd_other_got = true; + } + + return MGMT_ERR_EOK; +} + +static struct mgmt_callback mgmt_event_callback = { + .callback = mgmt_event_cmd_callback, + .event_id = (MGMT_EVT_OP_CMD_RECV | MGMT_EVT_OP_CMD_STATUS | MGMT_EVT_OP_CMD_DONE), +}; + +static void *setup_callbacks(void) +{ + mgmt_callback_register(&mgmt_event_callback); + return NULL; +} + +static void destroy_callbacks(void *p) +{ + mgmt_callback_unregister(&mgmt_event_callback); +} + +ZTEST(callback_disabled, test_notifications_disabled) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + + ok = create_mcumgr_format_packet(zse, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful\n"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + + zassert_true(received, "Expected to receive data but timed out\n"); + + /* Retrieve response buffer */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Check events */ + zassert_false(cmd_recv_got, "Did not expect received command callback\n"); + zassert_false(cmd_status_got, "Did not expect IMG status callback\n"); + zassert_false(cmd_done_got, "Did not expect done command callback\n"); + zassert_false(cmd_other_got, "Did not expect other callback(s)\n"); +} + +ZTEST(callback_enabled, test_notifications_enabled) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + + ok = create_mcumgr_format_packet(zse, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful\n"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + + zassert_true(received, "Expected to receive data but timed out\n"); + + /* Retrieve response buffer */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Check events */ + zassert_true(cmd_recv_got, "Expected received command callback\n"); + zassert_false(cmd_status_got, "Did not expect IMG status callback\n"); + zassert_true(cmd_done_got, "Expected done command callback\n"); + zassert_false(cmd_other_got, "Did not expect other callback(s)\n"); +} + +ZTEST(callback_disabled_verify, test_notifications_disabled_verify) +{ + uint8_t buffer[ZCBOR_BUFFER_SIZE]; + uint8_t buffer_out[OUTPUT_BUFFER_SIZE]; + bool ok; + uint16_t buffer_size; + zcbor_state_t zse[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + zcbor_state_t zsd[ZCBOR_HISTORY_ARRAY_SIZE] = { 0 }; + bool received; + + memset(buffer, 0, sizeof(buffer)); + memset(buffer_out, 0, sizeof(buffer_out)); + buffer_size = 0; + memset(zse, 0, sizeof(zse)); + memset(zsd, 0, sizeof(zsd)); + + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + + ok = create_mcumgr_format_packet(zse, buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful\n"); + + /* Enable dummy SMP backend and ready for usage */ + smp_dummy_enable(); + smp_dummy_clear_state(); + + /* Send query command to dummy SMP backend */ + (void)smp_dummy_tx_pkt(buffer_out, buffer_size); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + + zassert_true(received, "Expected to receive data but timed out\n"); + + /* Retrieve response buffer */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Check events */ + zassert_false(cmd_recv_got, "Did not expect received command callback\n"); + zassert_false(cmd_status_got, "Did not expect IMG status callback\n"); + zassert_false(cmd_done_got, "Did not expect done command callback\n"); + zassert_false(cmd_other_got, "Did not expect other callback(s)\n"); +} + +static void cleanup_test(void *p) +{ + if (nb != NULL) { + net_buf_unref(nb); + nb = NULL; + } + + cmd_recv_got = false; + cmd_status_got = false; + cmd_done_got = false; + cmd_other_got = false; +} + +void test_main(void) +{ + while (test_state.test_set < CB_NOTIFICATION_TEST_SET_COUNT) { + ztest_run_all(&test_state); + ++test_state.test_set; + } + + ztest_verify_all_test_suites_ran(); +} + +static bool callback_disabled_predicate(const void *state) +{ + return ((struct state *)state)->test_set == CB_NOTIFICATION_TEST_CALLBACK_DISABLED; +} + +static bool callback_enabled_predicate(const void *state) +{ + return ((struct state *)state)->test_set == CB_NOTIFICATION_TEST_CALLBACK_ENABLED; +} + +static bool callback_disabled_verify_predicate(const void *state) +{ + return ((struct state *)state)->test_set == CB_NOTIFICATION_TEST_CALLBACK_DISABLED_VERIFY; +} + +ZTEST_SUITE(callback_disabled, callback_disabled_predicate, NULL, NULL, cleanup_test, NULL); +ZTEST_SUITE(callback_enabled, callback_enabled_predicate, setup_callbacks, NULL, cleanup_test, + destroy_callbacks); +ZTEST_SUITE(callback_disabled_verify, callback_disabled_verify_predicate, NULL, NULL, + cleanup_test, NULL); diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/src/smp_test_util.c b/tests/subsys/mgmt/mcumgr/cb_notifications/src/smp_test_util.c new file mode 100644 index 0000000000..a20f948f30 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/src/smp_test_util.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "smp_test_util.h" +#include +#include +#include +#include + +void smp_make_hdr(struct smp_hdr *rsp_hdr, size_t len) +{ + *rsp_hdr = (struct smp_hdr) { + .nh_len = sys_cpu_to_be16(len), + .nh_flags = 0, + .nh_op = 0, + .nh_group = sys_cpu_to_be16(MGMT_GROUP_ID_OS), + .nh_seq = 1, + .nh_id = OS_MGMT_ID_ECHO, + }; +} + +bool create_mcumgr_format_packet(zcbor_state_t *zse, uint8_t *buffer, uint8_t *output_buffer, + uint16_t *buffer_size) +{ + bool ok; + + ok = zcbor_map_start_encode(zse, 2) && + zcbor_tstr_put_lit(zse, "d") && + zcbor_tstr_put_term(zse, "some test data") && + zcbor_map_end_encode(zse, 2); + + *buffer_size = (zse->payload_mut - buffer); + smp_make_hdr((struct smp_hdr *)output_buffer, *buffer_size); + memcpy(&output_buffer[sizeof(struct smp_hdr)], buffer, *buffer_size); + *buffer_size += sizeof(struct smp_hdr); + + return ok; +} diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/src/smp_test_util.h b/tests/subsys/mgmt/mcumgr/cb_notifications/src/smp_test_util.h new file mode 100644 index 0000000000..2d2a33cd43 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/src/smp_test_util.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_SMP_TEST_UTIL_ +#define H_SMP_TEST_UTIL_ + +#include +#include +#include +#include + +/* SMP header function for generating MCUmgr command header with sequence number set to 1 */ +void smp_make_hdr(struct smp_hdr *rsp_hdr, size_t len); + +/* Function for creating an os_mgmt echo command */ +bool create_mcumgr_format_packet(zcbor_state_t *zse, uint8_t *buffer, uint8_t *output_buffer, + uint16_t *buffer_size); + + +#endif diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml b/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml new file mode 100644 index 0000000000..58b1162268 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/testcase.yaml @@ -0,0 +1,9 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +tests: + cb.notifications: + platform_allow: qemu_cortex_m3 native_posix native_posix_64 qemu_riscv32_smp qemu_riscv64 + tags: cb_notifications