diff --git a/include/net/nrf_cloud.h b/include/net/nrf_cloud.h index ee9949c9821b..c478e861c0b7 100644 --- a/include/net/nrf_cloud.h +++ b/include/net/nrf_cloud.h @@ -946,6 +946,7 @@ int nrf_cloud_modem_fota_completed(const bool fota_success); * @param[in] id_buf_sz Size of buffer, maximum size is NRF_CLOUD_CLIENT_ID_MAX_LEN + 1. * * @retval 0 If successful. + * @retval -EINVAL The id_buf parameter is NULL and/or the id_buf_sz parameter is 0. * @retval -EMSGSIZE The provided buffer is too small. * @retval -EIO The client ID could not be initialized. * @retval -ENXIO The Kconfig option @kconfig{CONFIG_NRF_CLOUD_CLIENT_ID_SRC_RUNTIME} is enabled @@ -965,6 +966,8 @@ int nrf_cloud_client_id_get(char *id_buf, size_t id_buf_sz); * Max string length is NRF_CLOUD_CLIENT_ID_MAX_LEN. * * @retval 0 If successful. + * @retval -EINVAL The length of the client_id provided exceeds the maximum allowed. + * @retval -ENODATA The client_id cannot be empty. * @return A negative value indicates an error. */ int nrf_cloud_client_id_runtime_set(const char *const client_id); diff --git a/tests/subsys/net/lib/nrf_cloud/client_id/CMakeLists.txt b/tests/subsys/net/lib/nrf_cloud/client_id/CMakeLists.txt new file mode 100644 index 000000000000..4d4dab4fdd6d --- /dev/null +++ b/tests/subsys/net/lib/nrf_cloud/client_id/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(nrf_cloud_client_id) +set(NRF_SDK_DIR ${ZEPHYR_BASE}/../nrf) +set(NRFXLIB_MODEM_DIR ${ZEPHYR_BASE}/../nrfxlib/nrf_modem) +cmake_path(NORMAL_PATH NRF_SDK_DIR) +cmake_path(NORMAL_PATH NRFXLIB_MODEM_DIR) + +FILE(GLOB app_sources src/main.c) + +target_sources(app PRIVATE ${app_sources}) + +target_sources(app + PRIVATE + ${ZEPHYR_NRF_MODULE_DIR}/subsys/net/lib/nrf_cloud/src/nrf_cloud_client_id.c +) + +target_include_directories(app + PRIVATE + src + ${NRF_SDK_DIR}/subsys/net/lib/nrf_cloud/include + ${ZEPHYR_BASE}/subsys/testsuite/include +) + +if (CONFIG_NRF_MODEM_LIB) + +set_source_files_properties( + ${NRF_SDK_DIR}/lib/nrf_modem_lib/nrf_modem_lib.c + PROPERTIES HEADER_FILE_ONLY ON +) + +set_source_files_properties( + ${NRFXLIB_MODEM_DIR}/include/nrf_modem_at.h + PROPERTIES HEADER_FILE_ONLY ON +) + +set_source_files_properties( + ${NRF_SDK_DIR}/lib/modem_jwt/modem_jwt.c + PROPERTIES HEADER_FILE_ONLY ON +) + +set_source_files_properties( + ${NRF_SDK_DIR}/lib/hw_id/hw_id.c + PROPERTIES HEADER_FILE_ONLY ON +) + + +endif() diff --git a/tests/subsys/net/lib/nrf_cloud/client_id/boards/qemu_cortex_m3.conf b/tests/subsys/net/lib/nrf_cloud/client_id/boards/qemu_cortex_m3.conf new file mode 100644 index 000000000000..892f0ff2776b --- /dev/null +++ b/tests/subsys/net/lib/nrf_cloud/client_id/boards/qemu_cortex_m3.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Disable networking +CONFIG_NETWORKING=n + +# For the unit test to run in qemu_cortex_m3, +# we need the following KConfig values to be set. +# See https://github.com/zephyrproject-rtos/zephyr/issues/15565 +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/subsys/net/lib/nrf_cloud/client_id/prj.conf b/tests/subsys/net/lib/nrf_cloud/client_id/prj.conf new file mode 100644 index 000000000000..ac8e788961df --- /dev/null +++ b/tests/subsys/net/lib/nrf_cloud/client_id/prj.conf @@ -0,0 +1,27 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# ZTEST with new API +CONFIG_ZTEST=y + +# Networking +CONFIG_NETWORKING=y +CONFIG_NET_NATIVE=n +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_OFFLOAD=y +CONFIG_POSIX_API=y + +# Modem library +CONFIG_NRF_MODEM_LIB=y + +# AT host library +CONFIG_AT_HOST_LIBRARY=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Stacks and heaps +CONFIG_MAIN_STACK_SIZE=3072 +CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_AT_MONITOR_HEAP_SIZE=512 diff --git a/tests/subsys/net/lib/nrf_cloud/client_id/src/fakes.h b/tests/subsys/net/lib/nrf_cloud/client_id/src/fakes.h new file mode 100644 index 000000000000..cd0137754365 --- /dev/null +++ b/tests/subsys/net/lib/nrf_cloud/client_id/src/fakes.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +DEFINE_FFF_GLOBALS; + +#if !IS_ENABLED(CONFIG_NRF_MODEM_LIB) +FAKE_VALUE_FUNC(int, nrf_modem_lib_init); +FAKE_VALUE_FUNC(int, nrf_modem_lib_shutdown); +FAKE_VALUE_FUNC_VARARG(int, nrf_modem_at_cmd, void *, size_t, const char *, ...); +FAKE_VALUE_FUNC(int, modem_jwt_get_uuids, struct nrf_device_uuid *, struct nrf_modem_fw_uuid *); +FAKE_VALUE_FUNC(int, hw_id_get, char *, size_t); + +int nrf_modem_lib_shutdown__succeeds(void) +{ + return 0; +} + +int nrf_modem_lib_shutdown__fails(void) +{ + return -1; +} + +int nrf_modem_at_cmd__fails(void *buf, size_t len, const char *fmt, ...) +{ + return -1; +} + +int nrf_modem_at_cmd__succeeds(void *buf, size_t len, const char *fmt, ...) +{ + return 0; +} + +int modem_jwt_get_uuids__fails(struct nrf_device_uuid *dev, + struct nrf_modem_fw_uuid *mfw) +{ + return -1; +} + +int modem_jwt_get_uuids__succeeds(struct nrf_device_uuid *dev, + struct nrf_modem_fw_uuid *mfw) +{ + return 0; +} + +int hw_id_get__fails(char *buf, size_t buf_len) +{ + return -1; +} + +int hw_id_get__succeeds(char *buf, size_t buf_len) +{ + return 0; +} +#endif diff --git a/tests/subsys/net/lib/nrf_cloud/client_id/src/main.c b/tests/subsys/net/lib/nrf_cloud/client_id/src/main.c new file mode 100644 index 000000000000..c06c6005b30a --- /dev/null +++ b/tests/subsys/net/lib/nrf_cloud/client_id/src/main.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#if IS_ENABLED(CONFIG_NRF_MODEM) +#include +#endif +#include +#include "fakes.h" +#include "string.h" + +#define RUNTIME_ID "test" +#define UUID_LEN 36 + +/* This function runs before each test */ +static void run_before(void *fixture) +{ + ARG_UNUSED(fixture); + +#if !IS_ENABLED(CONFIG_NRF_MODEM_LIB) + RESET_FAKE(nrf_modem_lib_init); + RESET_FAKE(nrf_modem_lib_shutdown); + RESET_FAKE(nrf_modem_at_cmd); + RESET_FAKE(modem_jwt_get_uuids); + RESET_FAKE(hw_id_get); +#endif + int err = nrf_modem_lib_init(); + + printk("MODEM LIB INIT: %d\n", err); + +} + +/* This function runs after each completed test */ +static void run_after(void *fixture) +{ + ARG_UNUSED(fixture); +} + +ZTEST_SUITE(nrf_cloud_client_id_test, NULL, NULL, run_before, run_after, NULL); + +/* + * + */ +ZTEST(nrf_cloud_client_id_test, test_nrf_cloud_client_id) +{ + int ret; + char buf[NRF_CLOUD_CLIENT_ID_MAX_LEN + 2]; + size_t len; + +#if IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI) + printk("IMEI TEST\n"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_COMPILE_TIME) + printk("COMPTIME TEST\n"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_INTERNAL_UUID) + printk("UUID TEST\n"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_HW_ID) + printk("HWID TEST\n"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_RUNTIME) + printk("RUNTIME TEST\n"); +#endif + + ret = nrf_cloud_client_id_get(buf, 0); + zassert_true((ret < 0), "Zero len buffer returned a value >= 0."); + zassert_equal(ret, -EINVAL, "Zero len returned wrong error."); + + len = NRF_CLOUD_CLIENT_ID_MAX_LEN; + ret = nrf_cloud_client_id_get(NULL, len); + zassert_true((ret < 0), "NULL pointer returned a value >= 0."); + zassert_equal(ret, -EINVAL, "NULL pointer returned wrong error."); + +#if IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_RUNTIME) + len = NRF_CLOUD_CLIENT_ID_MAX_LEN; + ret = nrf_cloud_client_id_get(buf, len); + zassert_true((ret < 0), "Unset runtime ID returned a value >= 0."); + zassert_equal(ret, -ENXIO, "Wrong error returned when runtime ID not set."); + + ret = nrf_cloud_client_id_runtime_set(""); + zassert_equal(ret, -ENODATA, "Wrong error returned when empty runtime ID set."); + + memset(buf, 'A', NRF_CLOUD_CLIENT_ID_MAX_LEN + 1); + buf[NRF_CLOUD_CLIENT_ID_MAX_LEN + 1] = '\0'; + ret = nrf_cloud_client_id_runtime_set(buf); + zassert_equal(ret, -EINVAL, "Wrong error returned when too large runtime ID set."); + + ret = nrf_cloud_client_id_runtime_set(RUNTIME_ID); + zassert_equal(ret, 0, "Unexpected error when setting runtime client id"); +#endif + + len = 1; + ret = nrf_cloud_client_id_get(buf, len); + zassert_true((ret < 0), "Too-small buffer returned a value >= 0."); + zassert_equal(ret, -EMSGSIZE, "Wrong error returned with too-small buffer."); + + len = NRF_CLOUD_CLIENT_ID_MAX_LEN; + ret = nrf_cloud_client_id_get(buf, len); + printk("nrf_cloud_client_id_get: ret = %d, id: %.*s\n", ret, len, buf); + zassert_equal(ret, 0, "Unexpected error when getting client id"); + +#if IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI) + ret = strncmp(buf, CONFIG_NRF_CLOUD_CLIENT_ID_PREFIX, + strlen(CONFIG_NRF_CLOUD_CLIENT_ID_PREFIX)); + zassert_equal(ret, 0, "Unexpected prefix on IMEI client id"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_COMPILE_TIME) + ret = strncmp(buf, CONFIG_NRF_CLOUD_CLIENT_ID, + strlen(CONFIG_NRF_CLOUD_CLIENT_ID)); + zassert_equal(ret, 0, "Unexpected miscompare on compile time client id"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_INTERNAL_UUID) + zassert_equal(strlen(buf), UUID_LEN, "Unexpected length of UUID id"); +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_HW_ID) + /* TODO: check length returned depending on CONFIG_HW_ID_LIBRARY_SOURCE */ +#elif IS_ENABLED(CONFIG_NRF_CLOUD_CLIENT_ID_SRC_RUNTIME) + ret = strncmp(buf, RUNTIME_ID, len); + zassert_equal(ret, 0, "Unexpected miscompare on runtime client id"); +#endif +} diff --git a/tests/subsys/net/lib/nrf_cloud/client_id/testcase.yaml b/tests/subsys/net/lib/nrf_cloud/client_id/testcase.yaml new file mode 100644 index 000000000000..6fc5c556be0e --- /dev/null +++ b/tests/subsys/net/lib/nrf_cloud/client_id/testcase.yaml @@ -0,0 +1,42 @@ +common: + platform_allow: nrf9160dk/nrf9160/ns nrf9161dk/nrf9161/ns nrf9151dk/nrf9151/ns + integration_platforms: + - nrf9160dk/nrf9160/ns nrf9161dk/nrf9161/ns nrf9151dk/nrf9151/ns + tags: ci_build nrf_cloud_test nrf_cloud_lib ci_tests_subsys_net +tests: + net.lib.nrf_cloud.client_id.imei: + sysbuild: true + timeout: 60 + extra_args: + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI=y + tags: sysbuild ci_tests_subsys_net + net.lib.nrf_cloud.client_id.runtime: + sysbuild: true + timeout: 60 + extra_args: + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI=n + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_RUNTIME=y + tags: sysbuild ci_tests_subsys_net + net.lib.nrf_cloud.client_id.uuid: + sysbuild: true + timeout: 60 + extra_args: + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI=n + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_INTERNAL_UUID=y + - CONFIG_MODEM_JWT=y + tags: sysbuild ci_tests_subsys_net + net.lib.nrf_cloud.client_id.hwid: + sysbuild: true + timeout: 60 + extra_args: + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI=n + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_HW_ID=y + - CONFIG_HW_ID_LIBRARY=y + tags: sysbuild ci_tests_subsys_net + net.lib.nrf_cloud.client_id.comptime: + sysbuild: true + timeout: 60 + extra_args: + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_IMEI=n + - CONFIG_NRF_CLOUD_CLIENT_ID_SRC_COMPILE_TIME=y + tags: sysbuild ci_tests_subsys_net