diff --git a/doc/releases/release-notes-3.3.rst b/doc/releases/release-notes-3.3.rst index 4df81c9c759b9..d3de4e2a4e503 100644 --- a/doc/releases/release-notes-3.3.rst +++ b/doc/releases/release-notes-3.3.rst @@ -400,6 +400,9 @@ Libraries / Subsystems Private headers for above areas can be accessed, when required, using paths: ``mgmt/mcumgr/mgmt//``. + * MCUmgr os_mgmt info command has been added that allows querying details on + the kernel and application, allowing application-level extensibility + see :ref:`mcumgr_os_application_info` for details. * LwM2M diff --git a/doc/services/device_mgmt/smp_groups/smp_group_0.rst b/doc/services/device_mgmt/smp_groups/smp_group_0.rst index db32642bc01bc..1ffc985ed906e 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_0.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_0.rst @@ -26,6 +26,8 @@ OS management group defines following commands: +-------------------+-----------------------------------------------+ | ``6`` | MCUMGR parameters | +-------------------+-----------------------------------------------+ + | ``7`` | OS/Application info | + +-------------------+-----------------------------------------------+ Echo command ************ @@ -542,3 +544,95 @@ where: | "rc" | :ref:`mcumgr_smp_protocol_status_codes`; | | | may not appear if 0 | +-----------------------+---------------------------------------------------+ + +.. _mcumgr_os_application_info: + +OS/Application Info +******************* + +Used to obtain information on running image, similar functionality to the linux +uname command, allowing details such as kernel name, kernel version, build +date/time, processor type and application-defined details to be returned. This +functionality can be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_OS_INFO`. + +OS/Application Info Request +=========================== + +OS/Application info request header fields: + +.. table:: + :align: center + + +--------+--------------+----------------+ + | ``OP`` | ``Group ID`` | ``Command ID`` | + +========+==============+================+ + | ``0`` | ``0`` | ``7`` | + +--------+--------------+----------------+ + +CBOR data of request: + +.. code-block:: none + + { + (str,opt)"format" : (str) + } + +where: + +.. table:: + :align: center + + +----------+-------------------------------------------------------------------+ + | "format" | Format specifier of returned response, fields are appended in | + | | their natural ascending index order, not the order of | + | | characters that are received by the command. Format | + | | specifiers: |br| | + | | * ``s`` Kernel name |br| | + | | * ``n`` Node name |br| | + | | * ``r`` Kernel release |br| | + | | * ``v`` Kernel version |br| | + | | * ``b`` Build date and time (requires | + | | :kconfig:option:`CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME`) |br| | + | | * ``m`` Machine |br| | + | | * ``p`` Processor |br| | + | | * ``i`` Hardware platform |br| | + | | * ``o`` Operating system |br| | + | | * ``a`` All fields (shorthand for all above options) |br| | + | | If this option is not provided, the ``s`` Kernel name option | + | | will be used. | + +----------+-------------------------------------------------------------------+ + +OS/Application Info Response +============================ + +OS/Application info response header fields + +.. table:: + :align: center + + +--------+--------------+----------------+ + | ``OP`` | ``Group ID`` | ``Command ID`` | + +========+==============+================+ + | ``2`` | ``0`` | ``7`` | + +--------+--------------+----------------+ + +CBOR data of response: + +.. code-block:: none + + { + (str)"output" : (str) + (opt,str)"rc" : (int) + } + +where: + +.. table:: + :align: center + + +--------------+------------------------------------------------------------+ + | "output" | Text response including requested parameters | + +--------------+------------------------------------------------------------+ + | "rc" | :ref:`mcumgr_smp_protocol_status_codes`; will not appear | + | | if 0 | + +--------------+------------------------------------------------------------+ diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h index 75d9dc7518564..cd474b247bbe2 100644 --- a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h @@ -22,6 +22,66 @@ extern "C" { #define OS_MGMT_ID_DATETIME_STR 4 #define OS_MGMT_ID_RESET 5 #define OS_MGMT_ID_MCUMGR_PARAMS 6 +#define OS_MGMT_ID_INFO 7 + +/* Bitmask values used by the os info command handler. Note that the width of this variable is + * 32-bits, allowing 32 flags, custom user-level implementations should start at + * OS_MGMT_INFO_FORMAT_USER_CUSTOM_START and reference that directly as additional format + * specifiers might be added to this list in the future. + */ +enum os_mgmt_info_formats { + OS_MGMT_INFO_FORMAT_KERNEL_NAME = BIT(0), + OS_MGMT_INFO_FORMAT_NODE_NAME = BIT(1), + OS_MGMT_INFO_FORMAT_KERNEL_RELEASE = BIT(2), + OS_MGMT_INFO_FORMAT_KERNEL_VERSION = BIT(3), + OS_MGMT_INFO_FORMAT_BUILD_DATE_TIME = BIT(4), + OS_MGMT_INFO_FORMAT_MACHINE = BIT(5), + OS_MGMT_INFO_FORMAT_PROCESSOR = BIT(6), + OS_MGMT_INFO_FORMAT_HARDWARE_PLATFORM = BIT(7), + OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM = BIT(8), + + OS_MGMT_INFO_FORMAT_USER_CUSTOM_START = BIT(9), +}; + +/* Structure provided in the MGMT_EVT_OP_OS_MGMT_INFO_CHECK notification callback */ +struct os_mgmt_info_check { + /* Input format string from the mcumgr client */ + struct zcbor_string *format; + /* Bitmask of values specifying which outputs should be present */ + uint32_t *format_bitmask; + /* Number of valid format characters parsed, must be incremented by 1 for each valid + * character + */ + uint16_t *valid_formats; + /* Needs to be set to true if the OS name is being provided by external code */ + bool *custom_os_name; +}; + +/* Structure provided in the MGMT_EVT_OP_OS_MGMT_INFO_APPEND notification callback */ +struct os_mgmt_info_append { + /* The format bitmask from the processed commands, the bits should be cleared once + * processed, note that if all_format_specified is specified, the corrisponding bits here + * will not be set + */ + uint32_t *format_bitmask; + /* Will be true if the all 'a' specifier was provided */ + bool all_format_specified; + /* The output buffer which the responses should be appended to. If prior_output is true, a + * space must be added prior to the output response + */ + uint8_t *output; + /* The current size of the output response in the output buffer, must be updated to be the + * size of the output response after appending data + */ + uint16_t *output_length; + /* The size of the output buffer, including null terminator character, if the output + * response would exceed this size, the function must abort and return false to return a + * memory error to the client + */ + uint16_t buffer_size; + /* If there has been prior output, must be set to true if a response has been output */ + bool *prior_output; +}; /** * @brief Registers the OS management command handler group. diff --git a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h index 1cd6c94a46f77..aeca99ef20cfd 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h @@ -146,6 +146,12 @@ enum os_mgmt_group_events { /** Callback when a reset command has been received. */ MGMT_EVT_OP_OS_MGMT_RESET = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 0), + /** Callback when an info command is processed, data is os_mgmt_info_check. */ + MGMT_EVT_OP_OS_MGMT_INFO_CHECK = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 1), + + /** Callback when an info command needs to output data, data is os_mgmt_info_append. */ + MGMT_EVT_OP_OS_MGMT_INFO_APPEND = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_OS, 2), + /** Used to enable all os_mgmt_group events. */ MGMT_EVT_OP_OS_MGMT_ALL = MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_OS), }; diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt b/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt index 82e7a3a6eeb7f..e0a5bce58c530 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt @@ -20,3 +20,10 @@ if (CONFIG_REBOOT) endif() target_link_libraries(mgmt_mcumgr INTERFACE mgmt_mcumgr_grp_os) + +if(DEFINED CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME) + set(MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME_DIR ${PROJECT_BINARY_DIR}/os_mgmt_auto) + file(MAKE_DIRECTORY ${MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME_DIR}) + file(WRITE ${MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME_DIR}/os_mgmt_build_date.c "/* Auto generated file, do not edit */\n#include \nuint8_t *MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME = __TIMESTAMP__;") + zephyr_library_sources(${MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME_DIR}/os_mgmt_build_date.c) +endif() diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig index 381ac6c42dedc..df47d9c175954 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig @@ -123,4 +123,39 @@ config OS_MGMT_ECHO config OS_MGMT_MCUMGR_PARAMS bool "MCUMGR Parameters retrieval command" +config MCUMGR_GRP_OS_INFO + bool "Support for info command" + help + Can be used similarly to the unix/linux uname command for retrieving system information + including kernel version, processor architecture and board name. + +if MCUMGR_GRP_OS_INFO + +config MCUMGR_GRP_OS_INFO_MAX_RESPONSE_SIZE + int "Maximum response size for info command" + default 256 + range 32 512 + help + The maximum size of the response to the info command, will use a stack buffer of this + size to store the data in. If the output response is too big then the output will not be + present in the response, which will just contain the result code (rc) of memory error. + +config MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS + bool "Custom info hooks" + depends on MCUMGR_MGMT_NOTIFICATION_HOOKS + help + Supports adding custom command/character processing to the info command by using + registered callbacks. Data can be appended to the struct provided in the callback. + +config MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME + bool "Show build date and time" + help + Will allow returning the build date and time of the firmware by using the info with + format option 'b' (will also be returned with all responses by using 'a'). + + Note: This will invalidate reproducible builds of the firmware as it will embed the + build date/time in the output firmware image. + +endif + endif diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h b/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h new file mode 100644 index 0000000000000..a44b9ab269f7c --- /dev/null +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/include/os_mgmt_processor.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022 Zephyr authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_OS_MGMT_PROCESSOR_ +#define H_OS_MGMT_PROCESSOR_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Processor name (used in uname output command) + * Will be unknown if processor type is not listed + * (List extracted from /cmake/gcc-m-cpu.cmake) + */ +#if defined(CONFIG_ARM) +#if defined(CONFIG_CPU_CORTEX_M0) +#define PROCESSOR_NAME "cortex-m0" +#elif defined(CONFIG_CPU_CORTEX_M0PLUS) +#define PROCESSOR_NAME "cortex-m0plus" +#elif defined(CONFIG_CPU_CORTEX_M1) +#define PROCESSOR_NAME "cortex-m1" +#elif defined(CONFIG_CPU_CORTEX_M3) +#define PROCESSOR_NAME "cortex-m3" +#elif defined(CONFIG_CPU_CORTEX_M4) +#define PROCESSOR_NAME "cortex-m4" +#elif defined(CONFIG_CPU_CORTEX_M7) +#define PROCESSOR_NAME "cortex-m7" +#elif defined(CONFIG_CPU_CORTEX_M23) +#define PROCESSOR_NAME "cortex-m23" +#elif defined(CONFIG_CPU_CORTEX_M33) +#if defined(CONFIG_ARMV8_M_DSP) +#define PROCESSOR_NAME "cortex-m33" +#else +#define PROCESSOR_NAME "cortex-m33+nodsp" +#endif +#elif defined(CONFIG_CPU_CORTEX_M55) +#if defined(CONFIG_ARMV8_1_M_MVEF) +#define PROCESSOR_NAME "cortex-m55" +#elif defined(CONFIG_ARMV8_1_M_MVEI) +#define PROCESSOR_NAME "cortex-m55+nomve.fp" +#elif defined(CONFIG_ARMV8_M_DSP) +#define PROCESSOR_NAME "cortex-m55+nomve" +#else +#define PROCESSOR_NAME "cortex-m55+nodsp" +#endif +#elif defined(CONFIG_CPU_CORTEX_R4) +#if defined(CONFIG_FPU) && defined(CONFIG_CPU_HAS_VFP) +#define PROCESSOR_NAME "cortex-r4f" +#else +#define PROCESSOR_NAME "cortex-r4" +#endif +#elif defined(CONFIG_CPU_CORTEX_R5) +#if defined(CONFIG_FPU) && defined(CONFIG_CPU_HAS_VFP) +#if !defined(CONFIG_VFP_FEATURE_DOUBLE_PRECISION) +#define PROCESSOR_NAME "cortex-r5+nofp.dp" +#else +#define PROCESSOR_NAME "cortex-r5" +#endif +#else +#define PROCESSOR_NAME "cortex-r5+nofp" +#endif +#elif defined(CONFIG_CPU_CORTEX_R7) +#if defined(CONFIG_FPU) && defined(CONFIG_CPU_HAS_VFP) +#if !defined(CONFIG_VFP_FEATURE_DOUBLE_PRECISION) +#define PROCESSOR_NAME "cortex-r7+nofp.dp" +#else +#define PROCESSOR_NAME "cortex-r7" +#endif +#else +#define PROCESSOR_NAME "cortex-r7+nofp" +#endif +#elif defined(CONFIG_CPU_CORTEX_R52) +#if defined(CONFIG_FPU) && defined(CONFIG_CPU_HAS_VFP) +#if !defined(CONFIG_VFP_FEATURE_DOUBLE_PRECISION) +#define PROCESSOR_NAME "cortex-r52+nofp.dp" +#else +#define PROCESSOR_NAME "cortex-r52" +#endif +#else +#define PROCESSOR_NAME "cortex-r52" +#endif +#elif defined(CONFIG_CPU_CORTEX_A9) +#define PROCESSOR_NAME "cortex-a9" +#endif +#elif defined(CONFIG_ARM64) +#if defined(CONFIG_CPU_CORTEX_A53) +#define PROCESSOR_NAME "cortex-a53" +#if defined(CONFIG_CPU_CORTEX_A55) +#define PROCESSOR_NAME "cortex-a55" +#elif defined(CONFIG_CPU_CORTEX_A72) +#define PROCESSOR_NAME "cortex-a72" +#elif defined(CONFIG_CPU_CORTEX_R82) +#define PROCESSOR_NAME "armv8.4-a+nolse" +#endif +#endif +#elif defined(CONFIG_ARC) +#if defined(CONFIG_CPU_EM4_FPUS) +#define PROCESSOR_NAME "em4_fpus" +#elif defined(CONFIG_CPU_EM4_DMIPS) +#define PROCESSOR_NAME "em4_dmips" +#elif defined(CONFIG_CPU_EM4_FPUDA) +#define PROCESSOR_NAME "em4_fpuda" +#elif defined(CONFIG_CPU_HS3X) +#define PROCESSOR_NAME "archs" +#elif defined(CONFIG_CPU_HS5X) +#define PROCESSOR_NAME "hs5x" +#elif defined(CONFIG_CPU_HS6X) +#define PROCESSOR_NAME "hs6x" +#elif defined(CONFIG_CPU_EM4) +#define PROCESSOR_NAME "arcem" +#elif defined(CONFIG_CPU_EM6) +#define PROCESSOR_NAME "arcem" +#endif +#elif defined(CONFIG_X86) +#if defined(CONFIG_X86_64) +#define PROCESSOR_NAME "x86_64" +#else +#define PROCESSOR_NAME "x86" +#endif +#elif defined(CONFIG_RISCV) +#define PROCESSOR_NAME "riscv" +#endif + +#ifndef PROCESSOR_NAME +#warning "Processor type could not be determined" +#define PROCESSOR_NAME "unknown" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_OS_MGMT_PROCESSOR_ */ diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index 46de3369fb85e..869f9e90f4dd3 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -28,6 +28,18 @@ #include #endif +#ifdef CONFIG_MCUMGR_GRP_OS_INFO +#include +#include +#include +#include +#if defined(CONFIG_NET_HOSTNAME_ENABLE) +#include +#elif defined(CONFIG_BT) +#include +#endif +#endif + #ifdef CONFIG_REBOOT static void os_mgmt_reset_work_handler(struct k_work *work); static void os_mgmt_reset_cb(struct k_timer *timer); @@ -54,6 +66,19 @@ struct thread_iterator_info { }; #endif +/* Specifies what the "all" ('a') of info parameter shows */ +#define OS_MGMT_INFO_FORMAT_ALL \ + OS_MGMT_INFO_FORMAT_KERNEL_NAME | OS_MGMT_INFO_FORMAT_NODE_NAME | \ + OS_MGMT_INFO_FORMAT_KERNEL_RELEASE | OS_MGMT_INFO_FORMAT_KERNEL_VERSION | \ + (IS_ENABLED(CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME) ? \ + OS_MGMT_INFO_FORMAT_BUILD_DATE_TIME : 0) | \ + OS_MGMT_INFO_FORMAT_MACHINE | OS_MGMT_INFO_FORMAT_PROCESSOR | \ + OS_MGMT_INFO_FORMAT_HARDWARE_PLATFORM | OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME +extern uint8_t *MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME; +#endif + /** * Command handler: os echo */ @@ -318,6 +343,302 @@ os_mgmt_mcumgr_params(struct smp_streamer *ctxt) } #endif +#ifdef CONFIG_MCUMGR_GRP_OS_INFO +/** + * Command handler: os info + */ +static int os_mgmt_info(struct smp_streamer *ctxt) +{ + struct zcbor_string format = { 0 }; + uint8_t output[CONFIG_MCUMGR_GRP_OS_INFO_MAX_RESPONSE_SIZE] = { 0 }; + zcbor_state_t *zse = ctxt->writer->zs; + zcbor_state_t *zsd = ctxt->reader->zs; + uint32_t format_bitmask = 0; + bool prior_output = false; + size_t i = 0; + size_t decoded; + bool custom_os_name = false; + int rc; + uint16_t output_length = 0; + uint16_t valid_formats = 0; + + struct zcbor_map_decode_key_val fs_info_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(format, zcbor_tstr_decode, &format), + }; + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS + struct os_mgmt_info_check check_data = { + .format = &format, + .format_bitmask = &format_bitmask, + .valid_formats = &valid_formats, + .custom_os_name = &custom_os_name, + }; + + struct os_mgmt_info_append append_data = { + .format_bitmask = &format_bitmask, + .all_format_specified = false, + .output = output, + .output_length = &output_length, + .buffer_size = sizeof(output), + .prior_output = &prior_output, + }; +#endif + + if (zcbor_map_decode_bulk(zsd, fs_info_decode, ARRAY_SIZE(fs_info_decode), &decoded)) { + return MGMT_ERR_EINVAL; + } + + /* Process all input characters in format value */ + while (i < format.len) { + switch (format.value[i]) { + case 'a': { +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS + append_data.all_format_specified = true; +#endif + + format_bitmask = OS_MGMT_INFO_FORMAT_ALL; + ++valid_formats; + break; + } + case 's': { + format_bitmask |= OS_MGMT_INFO_FORMAT_KERNEL_NAME; + ++valid_formats; + break; + } + case 'n': { + format_bitmask |= OS_MGMT_INFO_FORMAT_NODE_NAME; + ++valid_formats; + break; + } + case 'r': { + format_bitmask |= OS_MGMT_INFO_FORMAT_KERNEL_RELEASE; + ++valid_formats; + break; + } + case 'v': { + format_bitmask |= OS_MGMT_INFO_FORMAT_KERNEL_VERSION; + ++valid_formats; + break; + } +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME + case 'b': { + format_bitmask |= OS_MGMT_INFO_FORMAT_BUILD_DATE_TIME; + ++valid_formats; + break; + } +#endif + case 'm': { + format_bitmask |= OS_MGMT_INFO_FORMAT_MACHINE; + ++valid_formats; + break; + } + case 'p': { + format_bitmask |= OS_MGMT_INFO_FORMAT_PROCESSOR; + ++valid_formats; + break; + } + case 'i': { + format_bitmask |= OS_MGMT_INFO_FORMAT_HARDWARE_PLATFORM; + ++valid_formats; + break; + } + case 'o': { + format_bitmask |= OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM; + ++valid_formats; + break; + } + default: { + break; + } + } + + ++i; + } + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS + /* Run callbacks to see if any additional handlers will add options */ + (void)mgmt_callback_notify(MGMT_EVT_OP_OS_MGMT_INFO_CHECK, &check_data, + sizeof(check_data)); +#endif + + if (valid_formats != format.len) { + /* A provided format specifier is not valid */ + return MGMT_ERR_EINVAL; + } else if (format_bitmask == 0) { + /* If no value is provided, use default of kernel name */ + format_bitmask = OS_MGMT_INFO_FORMAT_KERNEL_NAME; + } + + /* Process all options in order and append to output string */ + if (format_bitmask & OS_MGMT_INFO_FORMAT_KERNEL_NAME) { + rc = snprintf(output, (sizeof(output) - output_length), "Zephyr"); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + } + + if (format_bitmask & OS_MGMT_INFO_FORMAT_NODE_NAME) { + /* Get hostname, if enabled */ +#if defined(CONFIG_NET_HOSTNAME_ENABLE) + /* From network */ + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), net_hostname_get()); +#elif defined(CONFIG_BT) + /* From Bluetooth */ + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), bt_get_name()); +#else + /* Not available */ + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + "%sunknown", (prior_output == true ? " " : "")); +#endif + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_NODE_NAME; + } + + if (format_bitmask & OS_MGMT_INFO_FORMAT_KERNEL_RELEASE) { +#ifdef BUILD_VERSION + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), STRINGIFY(BUILD_VERSION)); +#else + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + "%sunknown", (prior_output == true ? " " : "")); +#endif + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_KERNEL_RELEASE; + } + + if (format_bitmask & OS_MGMT_INFO_FORMAT_KERNEL_VERSION) { + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), KERNEL_VERSION_STRING); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_KERNEL_VERSION; + } + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME + if (format_bitmask & OS_MGMT_INFO_FORMAT_BUILD_DATE_TIME) { + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), + MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_BUILD_DATE_TIME; + } +#endif + + if (format_bitmask & OS_MGMT_INFO_FORMAT_MACHINE) { + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), CONFIG_ARCH); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_MACHINE; + } + + if (format_bitmask & OS_MGMT_INFO_FORMAT_PROCESSOR) { + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s" : "%s"), PROCESSOR_NAME); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_PROCESSOR; + } + + if (format_bitmask & OS_MGMT_INFO_FORMAT_HARDWARE_PLATFORM) { + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + (prior_output == true ? " %s%s%s" : "%s%s%s"), CONFIG_BOARD, + (sizeof(CONFIG_BOARD_REVISION) > 1 ? "@" : ""), + CONFIG_BOARD_REVISION); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_HARDWARE_PLATFORM; + } + + /* If custom_os_name is not set (by extension code) then return the default OS name of + * Zephyr + */ + if (format_bitmask & OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM && custom_os_name == false) { + rc = snprintf(&output[output_length], (sizeof(output) - output_length), + "%sZephyr", (prior_output == true ? " " : "")); + + if (rc < 0 || rc >= (sizeof(output) - output_length)) { + goto fail; + } else { + output_length += (uint16_t)rc; + } + + prior_output = true; + format_bitmask &= ~OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM; + } + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS + /* Call custom handler command for additional output/processing */ + rc = mgmt_callback_notify(MGMT_EVT_OP_OS_MGMT_INFO_APPEND, &append_data, + sizeof(append_data)); + + if (rc != MGMT_ERR_EOK) { + return rc; + } +#endif + + if (zcbor_tstr_put_lit(zse, "output") && + zcbor_tstr_encode_ptr(zse, output, output_length)) { + return MGMT_ERR_EOK; + } + +fail: + return MGMT_ERR_EMSGSIZE; +} +#endif + static const struct mgmt_handler os_mgmt_group_handlers[] = { #ifdef CONFIG_OS_MGMT_ECHO [OS_MGMT_ID_ECHO] = { @@ -339,6 +660,11 @@ static const struct mgmt_handler os_mgmt_group_handlers[] = { os_mgmt_mcumgr_params, NULL }, #endif +#ifdef CONFIG_MCUMGR_GRP_OS_INFO + [OS_MGMT_ID_INFO] = { + os_mgmt_info, NULL + }, +#endif }; #define OS_MGMT_GROUP_SZ ARRAY_SIZE(os_mgmt_group_handlers) diff --git a/subsys/mgmt/mcumgr/transport/src/smp_dummy.c b/subsys/mgmt/mcumgr/transport/src/smp_dummy.c index 4df3fcb4dc82b..a74c1c5a35189 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_dummy.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_dummy.c @@ -11,6 +11,7 @@ /* Define required for uart_mcumgr.h functionality reuse */ #define CONFIG_UART_MCUMGR_RX_BUF_SIZE CONFIG_MCUMGR_SMP_DUMMY_RX_BUF_SIZE +#define MCUMGR_DUMMY_MAX_FRAME CONFIG_MCUMGR_SMP_DUMMY_RX_BUF_SIZE #include #include @@ -581,7 +582,7 @@ int mcumgr_dummy_tx_frame(const uint8_t *data, bool first, int len, } while (1) { - if (dst_off >= MCUMGR_SERIAL_MAX_FRAME - 4) { + if (dst_off >= MCUMGR_DUMMY_MAX_FRAME - 4) { /* Can't fit any more data in this frame. */ break; } diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/CMakeLists.txt b/tests/subsys/mgmt/mcumgr/os_mgmt_info/CMakeLists.txt new file mode 100644 index 0000000000000..552c82052be7e --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/CMakeLists.txt @@ -0,0 +1,24 @@ +# +# Copyright (c) 2022 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(os_mgmt_info) + +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/) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/mgmt/mcumgr/grp/os_mgmt/include/) + +if(DEFINED CONFIG_BUILD_DATE_TIME_TEST) + set(TEST_DATE_TIME_DIR ${PROJECT_BINARY_DIR}/test) + file(MAKE_DIRECTORY ${TEST_DATE_TIME_DIR}) + file(WRITE ${TEST_DATE_TIME_DIR}/test_date.c "/* Auto generated file, do not edit */\n#include \nuint8_t *test_date_time = __TIMESTAMP__;") + target_sources(app PRIVATE ${TEST_DATE_TIME_DIR}/test_date.c) +endif() diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/Kconfig b/tests/subsys/mgmt/mcumgr/os_mgmt_info/Kconfig new file mode 100644 index 0000000000000..e63a141658419 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2022 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config CUSTOM_OS_NAME_VALUE + string "Custom OS name" + default "Fake OS Name" + +config BUILD_DATE_TIME_TEST + bool "Build date time test" + select MCUMGR_GRP_OS_INFO_BUILD_DATE_TIME + +config LIMITED_TEST + bool "Limited buffer size test" + +source "Kconfig.zephyr" diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv32_smp.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv32_smp.conf new file mode 100644 index 0000000000000..1ede042960b60 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv32_smp.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv64.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv64.conf new file mode 100644 index 0000000000000..1ede042960b60 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv64.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv64_smp.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv64_smp.conf new file mode 100644 index 0000000000000..1ede042960b60 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/boards/qemu_riscv64_smp.conf @@ -0,0 +1 @@ +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf b/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf new file mode 100644 index 0000000000000..2166e715625fe --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/prj.conf @@ -0,0 +1,15 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_ZTEST=y +CONFIG_MCUMGR=y +CONFIG_MCUMGR_SMP_DUMMY=y +CONFIG_MCUMGR_SMP_DUMMY_RX_BUF_SIZE=256 +CONFIG_MCUMGR_CMD_OS_MGMT=y +CONFIG_MCUMGR_GRP_OS_INFO=y +CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS=y +CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y +CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c new file mode 100644 index 0000000000000..98b92677a09aa --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_BUILD_DATE_TIME_TEST) + +#include +#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 256 +#define OUTPUT_BUFFER_SIZE 256 +#define ZCBOR_HISTORY_ARRAY_SIZE 4 + +static struct net_buf *nb; + +/* Responses to commands */ +extern uint8_t *test_date_time; +const uint8_t response_all_board_revision_left[] = "Zephyr unknown " STRINGIFY(BUILD_VERSION) " " + KERNEL_VERSION_STRING " "; +const uint8_t response_all_board_revision_right[] = " " CONFIG_ARCH " " PROCESSOR_NAME " " + CONFIG_BOARD "@" CONFIG_BOARD_REVISION + " Zephyr"; +const uint8_t response_all_left[] = "Zephyr unknown " STRINGIFY(BUILD_VERSION) " " + KERNEL_VERSION_STRING " "; +const uint8_t response_all_right[] = " " CONFIG_ARCH " " PROCESSOR_NAME " " CONFIG_BOARD " Zephyr"; + +const uint8_t query_build_date[] = "b"; +const uint8_t query_all[] = "a"; + +#define DATE_CHECK_LEFT_CHARS 11 +#define DATE_CHECK_RIGHT_CHARS 5 +#define TIME_CHECK_HH_START_CHAR 11 + +#define TIME_HH_OFFSET 0 +#define TIME_MM_OFFSET 3 +#define TIME_SS_OFFSET 6 + +#define SECONDS_PER_HOUR 3600 +#define SECONDS_PER_MINUTE 60 + +#define TIME_DIFFERENCE_ALLOWANCE 60 + +static int32_t time_string_to_seconds(const uint8_t *time_string) +{ + uint8_t time_hh; + uint8_t time_mm; + uint8_t time_ss; + + /* Convert times to separate fields and then to timestamps which can be compared */ + time_hh = ((time_string[TIME_HH_OFFSET] - '0') * 10) + + (time_string[TIME_HH_OFFSET + 1] - '0'); + time_mm = ((time_string[TIME_MM_OFFSET] - '0') * 10) + + (time_string[TIME_MM_OFFSET + 1] - '0'); + time_ss = ((time_string[TIME_SS_OFFSET] - '0') * 10) + + (time_string[TIME_SS_OFFSET + 1] - '0'); + + return (time_hh * SECONDS_PER_HOUR) + (time_mm * SECONDS_PER_MINUTE) + time_ss; +} + +ZTEST(os_mgmt_info_build_date, test_info_build_date_1_build_date) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t expected_time_seconds; + int32_t received_time_seconds; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_build_date, 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 test echo 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal(strlen(test_date_time), output.len, + "Expected to receive %d bytes but got %d\n", + strlen(test_date_time), output.len); + + /* Check left and right sides of date which should match */ + zassert_mem_equal(test_date_time, output.value, DATE_CHECK_LEFT_CHARS, + "Expected received data mismatch"); + zassert_mem_equal(&test_date_time[(strlen(test_date_time) - DATE_CHECK_RIGHT_CHARS)], + &output.value[(strlen(test_date_time) - DATE_CHECK_RIGHT_CHARS)], + DATE_CHECK_RIGHT_CHARS, "Expected received data mismatch"); + + /* Extract time strings into timestamps */ + expected_time_seconds = time_string_to_seconds(&test_date_time[TIME_CHECK_HH_START_CHAR]); + received_time_seconds = time_string_to_seconds(&output.value[TIME_CHECK_HH_START_CHAR]); + + zassert_within(expected_time_seconds, received_time_seconds, TIME_DIFFERENCE_ALLOWANCE, + "Expected times to be within %d seconds but got %d", + TIME_DIFFERENCE_ALLOWANCE, + abs(expected_time_seconds - received_time_seconds)); +} + +ZTEST(os_mgmt_info_build_date, test_info_build_date_2_all) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t expected_time_seconds; + int32_t received_time_seconds; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_all, 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 test echo 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + if (sizeof(CONFIG_BOARD_REVISION) > 1) { + /* Check with board revision */ + zassert_equal((strlen(test_date_time) + strlen(response_all_board_revision_left) + + strlen(response_all_board_revision_right)), output.len, + "Expected to receive %d bytes but got %d\n", + (strlen(test_date_time) + strlen(response_all_board_revision_left) + + strlen(response_all_board_revision_right)), output.len); + + zassert_mem_equal(response_all_board_revision_left, output.value, + strlen(response_all_board_revision_left), + "Expected received data mismatch"); + zassert_mem_equal(response_all_board_revision_right, + &output.value[strlen(response_all_board_revision_left) + + strlen(test_date_time)], + strlen(response_all_board_revision_right), + "Expected received data mismatch"); + } else { + /* Check without board revision */ + zassert_equal((strlen(test_date_time) + strlen(response_all_left) + + strlen(response_all_right)), output.len, + "Expected to receive %d bytes but got %d\n", + (strlen(test_date_time) + strlen(response_all_left) + + strlen(response_all_right)), output.len); + + zassert_mem_equal(response_all_left, output.value, strlen(response_all_left), + "Expected received data mismatch"); + zassert_mem_equal(response_all_right, &output.value[strlen(response_all_left) + + strlen(test_date_time)], strlen(response_all_right), + "Expected received data mismatch"); + } + + /* Extract time strings into timestamps */ + expected_time_seconds = time_string_to_seconds(&test_date_time[TIME_CHECK_HH_START_CHAR]); + received_time_seconds = time_string_to_seconds(&output.value[(strlen(response_all_left) + + TIME_CHECK_HH_START_CHAR)]); + + zassert_within(expected_time_seconds, received_time_seconds, TIME_DIFFERENCE_ALLOWANCE, + "Expected times to be within %d seconds but got %d", + TIME_DIFFERENCE_ALLOWANCE, + abs(expected_time_seconds - received_time_seconds)); +} + +static void *setup_tests(void) +{ + /* Register os_mgmt mcumgr group */ + os_mgmt_register_group(); + + return NULL; +} + +static void cleanup_test(void *p) +{ + if (nb != NULL) { + net_buf_unref(nb); + nb = NULL; + } +} + +/* Build date/time test set */ +ZTEST_SUITE(os_mgmt_info_build_date, NULL, setup_tests, NULL, cleanup_test, NULL); + +#endif diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c new file mode 100644 index 0000000000000..e06faee6c0847 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_LIMITED_TEST) + +#include +#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 + +static struct net_buf *nb; + +/* Responses to commands */ +const uint8_t response_kernel_name[] = "Zephyr"; + +const uint8_t query_kernel_name[] = "s"; +const uint8_t query_all[] = "a"; + +ZTEST(os_mgmt_info_limited, test_info_1_kernel_name) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_kernel_name, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_kernel_name) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_kernel_name) - 1), output.len); + + zassert_mem_equal(response_kernel_name, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info_limited, test_info_2_all) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + struct zcbor_map_decode_key_val error_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(rc, zcbor_int32_decode, &rc), + }; + + 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, query_all, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + /* Ensure only an error is received */ + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 0, "Expected to receive 0 decoded zcbor element\n"); + + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + ok = zcbor_map_decode_bulk(zsd, error_decode, ARRAY_SIZE(error_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + zassert_equal(output.len, 0, "Expected to receive 0 bytes but got %d\n", output.len); + zassert_equal(rc, MGMT_ERR_EMSGSIZE, "Expected to receive EMSGSIZE error but got %d\n", + rc); +} + +static void *setup_tests(void) +{ + /* Register os_mgmt mcumgr group */ + os_mgmt_register_group(); + + return NULL; +} + +static void cleanup_test(void *p) +{ + if (nb != NULL) { + net_buf_unref(nb); + nb = NULL; + } +} + +/* Limited size buffer test set */ +ZTEST_SUITE(os_mgmt_info_limited, NULL, setup_tests, NULL, cleanup_test, NULL); + +#endif diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c new file mode 100644 index 0000000000000..0a9734467a215 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c @@ -0,0 +1,1562 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if !defined(CONFIG_BUILD_DATE_TIME_TEST) && !defined(CONFIG_LIMITED_TEST) + +#include +#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 QUERY_BUFFER_SIZE 16 +#define ZCBOR_BUFFER_SIZE 256 +#define OUTPUT_BUFFER_SIZE 256 +#define ZCBOR_HISTORY_ARRAY_SIZE 4 +#define QUERY_TEST_CMD_BITMASK OS_MGMT_INFO_FORMAT_USER_CUSTOM_START + +/* Test sets */ +enum { + OS_MGMT_TEST_SET_MAIN = 0, +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS + OS_MGMT_TEST_SET_CUSTOM_OS, + OS_MGMT_TEST_SET_CUSTOM_OS_DISABLED, + OS_MGMT_TEST_SET_CUSTOM_CMD_DISABLED, + OS_MGMT_TEST_SET_CUSTOM_CMD, + OS_MGMT_TEST_SET_CUSTOM_CMD_DISABLED_VERIFY, +#endif + + OS_MGMT_TEST_SET_COUNT +}; + +/* Test os_mgmt info command requesting 's' (kernel name) */ +static const uint8_t command[] = { + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x07, + 0xbf, 0x66, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x61, 0x73, 0xff +}; + +/* Expected response from mcumgr */ +static const uint8_t expected_response[] = { + 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x07, + 0xbf, 0x66, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x66, 0x5a, 0x65, 0x70, 0x68, 0x79, 0x72, 0xff +}; + +static struct net_buf *nb; + +struct state { + uint8_t test_set; +}; + +static struct state test_state = { + .test_set = 0, +}; + +/* Responses to commands */ +const uint8_t response_kernel_name[] = "Zephyr"; + +#if defined(CONFIG_BT) +const uint8_t response_node_name[] = CONFIG_BT_DEVICE_NAME; +#elif defined(CONFIG_NET_HOSTNAME_ENABLE) +const uint8_t response_node_name[] = CONFIG_NET_HOSTNAME; +#else +const uint8_t response_node_name[] = "unknown"; +#endif + +const uint8_t response_kernel_release[] = STRINGIFY(BUILD_VERSION); +const uint8_t response_kernel_version[] = KERNEL_VERSION_STRING; +const uint8_t response_machine[] = CONFIG_ARCH; +const uint8_t response_processor[] = PROCESSOR_NAME; +const uint8_t response_board_revision[] = CONFIG_BOARD "@" CONFIG_BOARD_REVISION; +const uint8_t response_board[] = CONFIG_BOARD; +const uint8_t response_os[] = "Zephyr"; +const uint8_t response_custom_cmd[] = "Magic Output for Test"; +const uint8_t response_os_custom[] = CONFIG_CUSTOM_OS_NAME_VALUE; + +const uint8_t response_all_board_revision[] = "Zephyr " +#if defined(CONFIG_BT) + CONFIG_BT_DEVICE_NAME +#elif defined(CONFIG_NET_HOSTNAME_ENABLE) + CONFIG_NET_HOSTNAME +#else + "unknown" +#endif + " " STRINGIFY(BUILD_VERSION) " " + KERNEL_VERSION_STRING " " CONFIG_ARCH " " + PROCESSOR_NAME " " CONFIG_BOARD "@" + CONFIG_BOARD_REVISION " Zephyr"; + +const uint8_t response_all[] = "Zephyr " +#if defined(CONFIG_BT) + CONFIG_BT_DEVICE_NAME +#elif defined(CONFIG_NET_HOSTNAME_ENABLE) + CONFIG_NET_HOSTNAME +#else + "unknown" +#endif + " " STRINGIFY(BUILD_VERSION) " " KERNEL_VERSION_STRING " " + CONFIG_ARCH " " PROCESSOR_NAME " " CONFIG_BOARD " Zephyr"; + +const uint8_t query_kernel_name[] = "s"; +const uint8_t query_node_name[] = "n"; +const uint8_t query_kernel_release[] = "r"; +const uint8_t query_kernel_version[] = "v"; +const uint8_t query_machine[] = "m"; +const uint8_t query_processor[] = "p"; +const uint8_t query_platform[] = "i"; +const uint8_t query_os[] = "o"; +const uint8_t query_all[] = "a"; +const uint8_t query_test_cmd[] = "k"; + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS +static int32_t os_mgmt_info_custom_os_callback(uint32_t event, int32_t rc, bool *abort_more, + void *data, size_t data_size) +{ + if (event == MGMT_EVT_OP_OS_MGMT_INFO_CHECK) { + struct os_mgmt_info_check *check_data = (struct os_mgmt_info_check *)data; + + *check_data->custom_os_name = true; + } else if (event == MGMT_EVT_OP_OS_MGMT_INFO_APPEND) { + int rc; + struct os_mgmt_info_append *append_data = (struct os_mgmt_info_append *)data; + + if (*append_data->format_bitmask & OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM) { + rc = snprintf(&append_data->output[*append_data->output_length], + (append_data->buffer_size - *append_data->output_length), + "%s%s", (*append_data->prior_output == true ? " " : ""), + CONFIG_CUSTOM_OS_NAME_VALUE); + + if (rc < 0 || + rc >= (append_data->buffer_size - *append_data->output_length)) { + *abort_more = true; + return -1; + } + + *append_data->output_length += (uint16_t)rc; + *append_data->prior_output = true; + *append_data->format_bitmask &= ~OS_MGMT_INFO_FORMAT_OPERATING_SYSTEM; + } + } + + return MGMT_ERR_EOK; +} + +static struct mgmt_callback custom_os_check_callback = { + .callback = os_mgmt_info_custom_os_callback, + .event_id = MGMT_EVT_OP_OS_MGMT_INFO_CHECK, +}; + +static struct mgmt_callback custom_os_append_callback = { + .callback = os_mgmt_info_custom_os_callback, + .event_id = MGMT_EVT_OP_OS_MGMT_INFO_APPEND, +}; + +static int32_t os_mgmt_info_custom_cmd_callback(uint32_t event, int32_t rc, bool *abort_more, + void *data, size_t data_size) +{ + if (event == MGMT_EVT_OP_OS_MGMT_INFO_CHECK) { + struct os_mgmt_info_check *check_data = (struct os_mgmt_info_check *)data; + size_t i = 0; + + while (i < check_data->format->len) { + if (check_data->format->value[i] == query_test_cmd[0]) { + *check_data->format_bitmask |= QUERY_TEST_CMD_BITMASK; + ++(*check_data->valid_formats); + } + + ++i; + } + } else if (event == MGMT_EVT_OP_OS_MGMT_INFO_APPEND) { + int rc; + struct os_mgmt_info_append *append_data = (struct os_mgmt_info_append *)data; + + if (append_data->all_format_specified || + (*append_data->format_bitmask & QUERY_TEST_CMD_BITMASK)) { + rc = snprintf(&append_data->output[*append_data->output_length], + (append_data->buffer_size - *append_data->output_length), + "%sMagic Output for Test", + (*append_data->prior_output == true ? " " : "")); + + if (rc < 0 || + rc >= (append_data->buffer_size - *append_data->output_length)) { + *abort_more = true; + return -1; + } + + *append_data->output_length += (uint16_t)rc; + *append_data->prior_output = true; + *append_data->format_bitmask &= ~QUERY_TEST_CMD_BITMASK; + } + } + + return MGMT_ERR_EOK; +} + +static struct mgmt_callback custom_cmd_check_callback = { + .callback = os_mgmt_info_custom_cmd_callback, + .event_id = MGMT_EVT_OP_OS_MGMT_INFO_CHECK, +}; + +static struct mgmt_callback custom_cmd_append_callback = { + .callback = os_mgmt_info_custom_cmd_callback, + .event_id = MGMT_EVT_OP_OS_MGMT_INFO_APPEND, +}; +#endif + +ZTEST(os_mgmt_info, test_info_1) +{ + 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 }; + + /* 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(command, sizeof(command)); + smp_dummy_add_data(); + + /* For a short duration to see if response has been received */ + bool received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); + + zassert_true(received, "Expected to receive data but timed out\n"); + + /* Retrieve response buffer and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + zassert_equal(sizeof(expected_response), nb->len, + "Expected to receive %d bytes but got %d\n", sizeof(expected_response), + nb->len); + + zassert_mem_equal(expected_response, nb->data, nb->len, + "Expected received data mismatch"); + + net_buf_unref(nb); + + /* Generate the same command dynamically */ + zcbor_new_encode_state(zse, 2, buffer, ARRAY_SIZE(buffer), 0); + + ok = create_mcumgr_format_packet(zse, "s", buffer, buffer_out, &buffer_size); + zassert_true(ok, "Expected packet creation to be successful\n"); + + /* Ensure the dynamically-generated size and payload matches the expected payload */ + zassert_equal(sizeof(command), buffer_size, + "Expected received data mismatch"); + zassert_mem_equal(command, buffer_out, sizeof(command), + "Expected received data mismatch"); + + /* 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + zassert_equal(sizeof(expected_response), nb->len, + "Expected to receive %d bytes but got %d\n", sizeof(expected_response), + nb->len); + + zassert_mem_equal(expected_response, nb->data, nb->len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_2_kernel_name) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_kernel_name, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_kernel_name) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_kernel_name) - 1), output.len); + + zassert_mem_equal(response_kernel_name, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_3_node_name) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_node_name, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_node_name) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_node_name) - 1), output.len); + + zassert_mem_equal(response_node_name, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_4_kernel_release) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_kernel_release, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_kernel_release) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_kernel_release) - 1), output.len); + + zassert_mem_equal(response_kernel_release, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_5_kernel_version) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_kernel_version, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_kernel_version) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_kernel_version) - 1), output.len); + + zassert_mem_equal(response_kernel_version, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_6_machine) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_machine, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_machine) - 1), output.len, + "Expected to receive %d bytes but got %d\n", (sizeof(response_machine) - 1), + output.len); + + zassert_mem_equal(response_machine, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_7_processor) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_processor, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_processor) - 1), output.len, + "Expected to receive %d bytes but got %d\n", (sizeof(response_processor) - 1), + output.len); + + zassert_mem_equal(response_processor, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_8_platform) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_platform, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + if (sizeof(CONFIG_BOARD_REVISION) > 1) { + /* Check with board revision */ + zassert_equal((sizeof(response_board_revision) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_board_revision) - 1), output.len); + + zassert_mem_equal(response_board_revision, output.value, output.len, + "Expected received data mismatch"); + } else { + /* Check without board revision */ + zassert_equal((sizeof(response_board) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_board) - 1), output.len); + + zassert_mem_equal(response_board, output.value, output.len, + "Expected received data mismatch"); + } +} + +ZTEST(os_mgmt_info, test_info_9_os) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_os, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_os) - 1), output.len, + "Expected to receive %d bytes but got %d\n", (sizeof(response_os) - 1), + output.len); + + zassert_mem_equal(response_os, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_10_all) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_all, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + if (sizeof(CONFIG_BOARD_REVISION) > 1) { + /* Check with board revision */ + zassert_equal((sizeof(response_all_board_revision) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_all_board_revision) - 1), output.len); + + zassert_mem_equal(response_all_board_revision, output.value, output.len, + "Expected received data mismatch"); + } else { + /* Check without board revision */ + zassert_equal((sizeof(response_all) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_all) - 1), output.len); + + zassert_mem_equal(response_all, output.value, output.len, + "Expected received data mismatch"); + } +} + +ZTEST(os_mgmt_info, test_info_11_multi_1) +{ + uint8_t query[QUERY_BUFFER_SIZE]; + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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); + + /* Construct query for processor, kernel release and OS name */ + sprintf(query, "%s%s%s", query_processor, query_kernel_release, query_os); + ok = create_mcumgr_format_packet(zse, query, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + /* Construct expected response to be compared against */ + sprintf(buffer, "%s %s %s", response_kernel_release, response_processor, response_os); + + zassert_equal(strlen(buffer), output.len, "Expected to receive %d bytes but got %d\n", + strlen(buffer), output.len); + + zassert_mem_equal(buffer, output.value, output.len, "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_12_multi_2) +{ + uint8_t query[QUERY_BUFFER_SIZE]; + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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); + + /* Construct query for node name and kernel version (twice) */ + sprintf(query, "%s%s%s", query_kernel_version, query_node_name, query_kernel_version); + ok = create_mcumgr_format_packet(zse, query, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + /* Construct expected response to be compared against, only 2 responses will be returned + * despite 3 being sent, because 2 were duplicates + */ + sprintf(buffer, "%s %s", response_node_name, response_kernel_version); + + zassert_equal(strlen(buffer), output.len, "Expected to receive %d bytes but got %d\n", + strlen(buffer), output.len); + + zassert_mem_equal(buffer, output.value, output.len, "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info, test_info_13_invalid_1) +{ + uint8_t query[QUERY_BUFFER_SIZE]; + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + struct zcbor_map_decode_key_val error_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(rc, zcbor_int32_decode, &rc), + }; + + 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); + + /* Construct query for node name with invalid specifier */ + sprintf(query, "%sM", query_kernel_version); + ok = create_mcumgr_format_packet(zse, query, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + /* Ensure only an error is received */ + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 0, "Expected to receive 0 decoded zcbor element\n"); + + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + ok = zcbor_map_decode_bulk(zsd, error_decode, ARRAY_SIZE(error_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + zassert_equal(output.len, 0, "Expected to receive 0 bytes but got %d\n", output.len); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected to receive EINVAL error but got %d\n", rc); +} + +ZTEST(os_mgmt_info, test_info_14_invalid_2) +{ + uint8_t query[QUERY_BUFFER_SIZE]; + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + struct zcbor_map_decode_key_val error_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(rc, zcbor_int32_decode, &rc), + }; + + 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); + + /* Construct query for processor with invalid specifier */ + sprintf(query, "2%s", query_processor); + ok = create_mcumgr_format_packet(zse, query, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + /* Ensure only an error is received */ + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 0, "Expected to receive 0 decoded zcbor element\n"); + + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + ok = zcbor_map_decode_bulk(zsd, error_decode, ARRAY_SIZE(error_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + zassert_equal(output.len, 0, "Expected to receive 0 bytes but got %d\n", output.len); + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected to receive EINVAL error but got %d\n", rc); +} + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS +static void *setup_custom_os(void) +{ + mgmt_callback_register(&custom_os_check_callback); + mgmt_callback_register(&custom_os_append_callback); + return NULL; +} + +static void destroy_custom_os(void *p) +{ + mgmt_callback_unregister(&custom_os_check_callback); + mgmt_callback_unregister(&custom_os_append_callback); +} + +ZTEST(os_mgmt_info_custom_os, test_info_os_custom) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_os, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_os_custom) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_os_custom) - 1), output.len); + + zassert_mem_equal(response_os_custom, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info_custom_os_disabled, test_info_os_custom_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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_os, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_os) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_os) - 1), output.len); + + zassert_mem_equal(response_os, output.value, output.len, + "Expected received data mismatch"); +} + +static void *setup_custom_cmd(void) +{ + mgmt_callback_register(&custom_cmd_check_callback); + mgmt_callback_register(&custom_cmd_append_callback); + + return NULL; +} + +static void destroy_custom_cmd(void *p) +{ + mgmt_callback_unregister(&custom_cmd_check_callback); + mgmt_callback_unregister(&custom_cmd_append_callback); +} + +ZTEST(os_mgmt_info_custom_cmd, test_info_cmd_custom) +{ + 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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + 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, query_test_cmd, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal((sizeof(response_custom_cmd) - 1), output.len, + "Expected to receive %d bytes but got %d\n", + (sizeof(response_custom_cmd) - 1), output.len); + + zassert_mem_equal(response_custom_cmd, output.value, output.len, + "Expected received data mismatch"); +} + +ZTEST(os_mgmt_info_custom_cmd_disabled, test_info_cmd_custom_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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + struct zcbor_map_decode_key_val error_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(rc, zcbor_int32_decode, &rc), + }; + + 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, query_test_cmd, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 0, "Expected to receive 0 decoded zcbor element\n"); + + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + ok = zcbor_map_decode_bulk(zsd, error_decode, ARRAY_SIZE(error_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal(output.len, 0, "Expected to receive 0 bytes but got %d\n", output.len); + + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected to receive EINVAL error but got %d\n", rc); +} + +ZTEST(os_mgmt_info_custom_cmd_disabled_verify, test_info_cmd_custom_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; + struct zcbor_string output = { 0 }; + size_t decoded = 0; + int32_t rc; + + struct zcbor_map_decode_key_val output_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(output, zcbor_tstr_decode, &output), + }; + + struct zcbor_map_decode_key_val error_decode[] = { + ZCBOR_MAP_DECODE_KEY_VAL(rc, zcbor_int32_decode, &rc), + }; + + 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, query_test_cmd, 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 and ensure validity */ + nb = smp_dummy_get_outgoing(); + smp_dummy_disable(); + + /* Process received data by removing header */ + (void)net_buf_pull(nb, sizeof(struct smp_hdr)); + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + + ok = zcbor_map_decode_bulk(zsd, output_decode, ARRAY_SIZE(output_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 0, "Expected to receive 0 decoded zcbor element\n"); + + zcbor_new_decode_state(zsd, 3, nb->data, nb->len, 1); + ok = zcbor_map_decode_bulk(zsd, error_decode, ARRAY_SIZE(error_decode), &decoded) == 0; + + zassert_true(ok, "Expected decode to be successful\n"); + zassert_equal(decoded, 1, "Expected to receive 1 decoded zcbor element\n"); + + zassert_equal(output.len, 0, "Expected to receive 0 bytes but got %d\n", output.len); + + zassert_equal(rc, MGMT_ERR_EINVAL, "Expected to receive EINVAL error but got %d\n", rc); + +} +#endif + +static void cleanup_test(void *p) +{ + if (nb != NULL) { + net_buf_unref(nb); + nb = NULL; + } +} + +void test_main(void) +{ + /* Register os_mgmt mcumgr group */ + os_mgmt_register_group(); + + while (test_state.test_set < OS_MGMT_TEST_SET_COUNT) { + ztest_run_all(&test_state); + ++test_state.test_set; + } + + ztest_verify_all_test_suites_ran(); +} + +static bool main_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_TEST_SET_MAIN; +} + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS +static bool custom_os_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_TEST_SET_CUSTOM_OS; +} + +static bool custom_os_disabled_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_TEST_SET_CUSTOM_OS_DISABLED; +} + +static bool custom_cmd_disabled_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_TEST_SET_CUSTOM_CMD_DISABLED; +} + +static bool custom_cmd_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_TEST_SET_CUSTOM_CMD; +} + +static bool custom_cmd_disabled_verify_predicate(const void *state) +{ + return ((struct state *)state)->test_set == OS_MGMT_TEST_SET_CUSTOM_CMD_DISABLED_VERIFY; +} +#endif + +/* Main test set */ +ZTEST_SUITE(os_mgmt_info, main_predicate, NULL, NULL, cleanup_test, NULL); + +#ifdef CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS +/* Custom OS test set */ +ZTEST_SUITE(os_mgmt_info_custom_os, custom_os_predicate, setup_custom_os, NULL, cleanup_test, + destroy_custom_os); +ZTEST_SUITE(os_mgmt_info_custom_os_disabled, custom_os_disabled_predicate, NULL, NULL, + cleanup_test, NULL); + +/* Custom cmd test set */ +ZTEST_SUITE(os_mgmt_info_custom_cmd_disabled, custom_cmd_disabled_predicate, NULL, NULL, + cleanup_test, NULL); +ZTEST_SUITE(os_mgmt_info_custom_cmd, custom_cmd_predicate, setup_custom_cmd, NULL, cleanup_test, + destroy_custom_cmd); +ZTEST_SUITE(os_mgmt_info_custom_cmd_disabled_verify, custom_cmd_disabled_verify_predicate, NULL, + NULL, cleanup_test, NULL); +#endif + +#endif diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/smp_test_util.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/smp_test_util.c new file mode 100644 index 0000000000000..c1dcded0ff68b --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/smp_test_util.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "smp_test_util.h" +#include +#include +#include +#include + +/* SMP header function for generating os_mgmt info command header with sequence number set to 1 */ +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_INFO, + }; +} + +/* Function for creating an os_mgmt info command */ +bool create_mcumgr_format_packet(zcbor_state_t *zse, const uint8_t *format, 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, "format") && + zcbor_tstr_put_term(zse, format) && + 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/os_mgmt_info/src/smp_test_util.h b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/smp_test_util.h new file mode 100644 index 0000000000000..1b28b850781ba --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/smp_test_util.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 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 os_mgmt info 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 info command */ +bool create_mcumgr_format_packet(zcbor_state_t *zse, const uint8_t *format, uint8_t *buffer, + uint8_t *output_buffer, uint16_t *buffer_size); + + +#endif diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/testcase.yaml b/tests/subsys/mgmt/mcumgr/os_mgmt_info/testcase.yaml new file mode 100644 index 0000000000000..4ff0292b6da94 --- /dev/null +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/testcase.yaml @@ -0,0 +1,57 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +tests: + os.mgmt.info: + # FIXME: Exclude architectures that lack a reboot handler function + # FIXME: Exclude systems whereby the processor type is not known and emits a warning + arch_exclude: arm64 nios2 sparc arc xtensa mips posix + tags: os_mgmt_info + os.mgmt.info_no_hooks: + # FIXME: Exclude architectures that lack a reboot handler function + # FIXME: Exclude systems whereby the processor type is not known and emits a warning + arch_exclude: arm64 nios2 sparc arc xtensa mips posix + tags: os_mgmt_info + extra_configs: + - CONFIG_MCUMGR_GRP_OS_INFO_CUSTOM_HOOKS=n + - CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=n + os.mgmt.info_bt: + depends_on: ble + # FIXME: Exclude architectures that lack a reboot handler function + # FIXME: Exclude systems whereby the processor type is not known and emits a warning + arch_exclude: arm64 nios2 sparc arc xtensa mips posix + tags: os_mgmt_info + extra_configs: + - CONFIG_BT=y + - CONFIG_BT_DEVICE_NAME="a_bt_name" + os.mgmt.info_net: + depends_on: netif + # FIXME: Exclude architectures that lack a reboot handler function + # FIXME: Exclude systems whereby the processor type is not known and emits a warning + arch_exclude: arm64 nios2 sparc arc xtensa mips posix + platform_exclude: qemu_cortex_a9 qemu_x86 qemu_riscv64_smp qemu_riscv64 qemu_riscv32e + qemu_riscv32 qemu_riscv32_smp qemu_cortex_m3 mps2_an385 + tags: os_mgmt_info + extra_configs: + - CONFIG_NETWORKING=y + - CONFIG_NET_HOSTNAME_ENABLE=y + - CONFIG_NET_HOSTNAME="test_net_name" + - CONFIG_TEST_RANDOM_GENERATOR=y + os.mgmt.info_build_date: + # FIXME: Exclude architectures that lack a reboot handler function + # FIXME: Exclude systems whereby the processor type is not known and emits a warning + arch_exclude: arm64 nios2 sparc arc xtensa mips posix + tags: os_mgmt_info + extra_configs: + - CONFIG_BUILD_DATE_TIME_TEST=y + os.mgmt.info_limited_size: + # FIXME: Exclude architectures that lack a reboot handler function + # FIXME: Exclude systems whereby the processor type is not known and emits a warning + arch_exclude: arm64 nios2 sparc arc xtensa mips posix + tags: os_mgmt_info + extra_configs: + - CONFIG_LIMITED_TEST=y + - CONFIG_MCUMGR_SMP_DUMMY_RX_BUF_SIZE=64 + - CONFIG_MCUMGR_GRP_OS_INFO_MAX_RESPONSE_SIZE=32