Skip to content

Commit 0d7b765

Browse files
committed
app: tests: at_nrfcloud: Add new unit test set
Add new unit tests for nRF Cloud related functionality. Signed-off-by: Tommi Rantanen <tommi.rantanen@nordicsemi.no>
1 parent e5c5622 commit 0d7b765

13 files changed

Lines changed: 1379 additions & 2 deletions

app/src/sm_at_nrfcloud.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#include <zephyr/logging/log.h>
1010
#include <date_time.h>
1111
#include <net/nrf_cloud.h>
12-
#include <net/nrf_cloud_agnss.h>
13-
#include <net/nrf_cloud_pgps.h>
1412
#include <net/nrf_cloud_coap.h>
1513
#include "nrf_cloud_coap_transport.h"
1614
#include <modem/at_parser.h>
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
2+
#
3+
# Copyright (c) 2026 Nordic Semiconductor ASA
4+
5+
cmake_minimum_required(VERSION 3.20.0)
6+
7+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
8+
project(at_nrfcloud)
9+
10+
# Generate sm_version.h header
11+
set(GENERATED_DIR "${PROJECT_BINARY_DIR}/generated")
12+
file(MAKE_DIRECTORY "${GENERATED_DIR}")
13+
add_custom_target(
14+
generate_version_header ALL
15+
COMMAND ${CMAKE_COMMAND}
16+
-D OUTPUT_FILE=${GENERATED_DIR}/sm_version.h
17+
-P ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/write_sm_version_header.cmake
18+
BYPRODUCTS ${GENERATED_DIR}/sm_version.h
19+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../..
20+
COMMENT "Regenerating sm_version.h"
21+
)
22+
zephyr_include_directories("${GENERATED_DIR}")
23+
zephyr_include_directories(${ZEPHYR_NRFXLIB_MODULE_DIR}/nrf_modem/include/)
24+
25+
# Compiler options to set configuration values
26+
target_compile_options(app PRIVATE
27+
-DCONFIG_NRF_MODEM_LIB_MEM_DIAG=y
28+
-D__ELASTERROR=2000
29+
-DCONFIG_SM_AT_BUF_SIZE=4096
30+
-DCONFIG_SM_URC_BUFFER_SIZE=4096
31+
-DCONFIG_SM_DATAMODE_BUF_SIZE=4096
32+
-DCONFIG_SM_DATAMODE_TERMINATOR=\"+++\"
33+
-DCONFIG_SM_LOG_LEVEL=0
34+
-DCONFIG_SM_CR_LF_TERMINATION=1
35+
-DCONFIG_SM_CUSTOMER_VERSION=\"\"
36+
-DCONFIG_SM_URC_DELAY_WITH_INCOMPLETE_ECHO_MS=1000
37+
-DCONFIG_SM_AT_ECHO_MAX_LEN=256
38+
-DCONFIG_SM_UART_RX_BUF_SIZE=256
39+
-DCONFIG_SM_UART_TX_BUF_SIZE=256
40+
-DCONFIG_SM_NRF_CLOUD_LOCATION=1
41+
-DCONFIG_NRF_CLOUD_SEC_TAG=16842753
42+
)
43+
44+
# Generate CMock mocks
45+
cmock_handle(${ZEPHYR_BASE}/../nrfxlib/nrf_modem/include/nrf_modem.h)
46+
cmock_handle(${ZEPHYR_NRF_MODULE_DIR}/include/modem/nrf_modem_lib.h)
47+
cmock_handle(${ZEPHYR_BASE}/../nrfxlib/nrf_modem/include/nrf_socket.h)
48+
cmock_handle(${ZEPHYR_BASE}/../nrfxlib/nrf_modem/include/nrf_modem_at.h
49+
FUNC_EXCLUDE "__nrf_modem_printf_like"
50+
FUNC_EXCLUDE "__nrf_modem_scanf_like"
51+
FUNC_EXCLUDE "nrf_modem_at_cmd"
52+
# at_monitor_sys_init() calls this at SYS_INIT time, before CMock is
53+
# initialised by setUp(). Exclude it from mocking and provide a manual
54+
# stub in nrf_modem_at_wrapper.c instead.
55+
)
56+
cmock_handle(${ZEPHYR_BASE}/include/zephyr/net/socket.h zephyr/net)
57+
cmock_handle(${PROJECT_SOURCE_DIR}/../../src/sm_at_socket.h)
58+
# Mock nRF Cloud CoAP API – the stub header carries all required type
59+
# definitions directly; no REST-layer include chain is needed.
60+
cmock_handle(${PROJECT_SOURCE_DIR}/include/net/nrf_cloud_coap.h)
61+
62+
# Generate test runner
63+
test_runner_generate(src/test_at_nrfcloud.c)
64+
65+
# Add sources
66+
target_sources(app PRIVATE
67+
src/test_at_nrfcloud.c
68+
src/nrf_modem_at_wrapper.c
69+
src/nrf_cloud_stubs.c # date_time_update_async + nrf_cloud_client_id_get only
70+
../stubs/uart_stubs.c
71+
../stubs/sm_at_host_stubs.c
72+
../stubs/control_pin_stubs.c
73+
../stubs/pm_stubs.c
74+
../stubs/tfm_stubs.c
75+
../stubs/at_cmd_custom_stubs.c
76+
../stubs/sm_workq.c
77+
../stubs/sm_log_stubs.c
78+
../../src/sm_util.c
79+
../../src/sm_at_nrfcloud.c
80+
../../src/sm_at_host.c
81+
../../src/sm_at_commands.c
82+
${ZEPHYR_BASE}/subsys/modem/modem_pipe.c
83+
)
84+
85+
# Include directories:
86+
# 1. Test-specific overrides (stub headers) come first so they shadow the
87+
# real nrf_cloud / date_time / wifi headers.
88+
# 2. Shared test include overrides (pm_config.h, fw_info.h, etc.) from the
89+
# at_commands test.
90+
# 3. Source directories and external include paths follow.
91+
set(includes
92+
"${PROJECT_SOURCE_DIR}/include/"
93+
"${PROJECT_SOURCE_DIR}/../at_commands/include/"
94+
"${PROJECT_SOURCE_DIR}/../../src"
95+
"${ZEPHYR_BASE}/../nrfxlib/nrf_modem/include"
96+
"${ZEPHYR_BASE}/include/"
97+
"${PROJECT_SOURCE_DIR}/../stubs"
98+
)
99+
100+
target_include_directories(app PRIVATE ${includes})
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/*
8+
* Minimal stub for date_time.h used in unit tests.
9+
* Only declares the symbols needed by sm_at_nrfcloud.c.
10+
*/
11+
12+
#ifndef DATE_TIME_TEST_STUB_H_
13+
#define DATE_TIME_TEST_STUB_H_
14+
15+
#include <stdint.h>
16+
17+
/** Event types reported by the date-time library. */
18+
enum date_time_evt_type {
19+
DATE_TIME_OBTAINED_MODEM,
20+
DATE_TIME_OBTAINED_NTP,
21+
DATE_TIME_OBTAINED_EXT,
22+
DATE_TIME_NOT_OBTAINED,
23+
};
24+
25+
struct date_time_evt {
26+
enum date_time_evt_type type;
27+
};
28+
29+
typedef void (*date_time_evt_handler_t)(const struct date_time_evt *evt);
30+
31+
/**
32+
* @brief Stub: trigger async date/time update.
33+
*
34+
* In the test environment this is a no-op stub; the semaphore
35+
* sem_date_time therefore times out (after K_SECONDS(10)) inside
36+
* nrfcloud_conn_work_fn. Tests that exercise the full connect work
37+
* should give the semaphore manually or wait for the timeout.
38+
*/
39+
int date_time_update_async(date_time_evt_handler_t evt_handler);
40+
41+
#endif /* DATE_TIME_TEST_STUB_H_ */
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/* Minimal stub for nrf_cloud.h used in unit tests. */
8+
9+
#ifndef NRF_CLOUD_TEST_STUB_H_
10+
#define NRF_CLOUD_TEST_STUB_H_
11+
12+
#include <stddef.h>
13+
14+
/** Maximum length of the nRF Cloud client ID. */
15+
#define NRF_CLOUD_CLIENT_ID_MAX_LEN 64
16+
17+
/**
18+
* @brief Get the nRF Cloud client identifier (device ID).
19+
*
20+
* @param[out] id_buf Buffer to receive the null-terminated device ID.
21+
* @param[in] id_buf_sz Size of id_buf; must be at least
22+
* NRF_CLOUD_CLIENT_ID_MAX_LEN + 1.
23+
* @return 0 on success, negative errno on error.
24+
*/
25+
int nrf_cloud_client_id_get(char *id_buf, size_t id_buf_sz);
26+
27+
#endif /* NRF_CLOUD_TEST_STUB_H_ */
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/*
8+
* Stub for nrf_cloud_coap.h.
9+
*
10+
* Compilation requirement: full type definitions are pulled in through the
11+
* normal include chain (lte_lc.h, wifi_location_common.h, nrf_cloud_location.h)
12+
* exactly as in production code.
13+
*
14+
* CMock requirement: CMock's Ruby parser runs with WORKING_DIRECTORY set to
15+
* the project source root and therefore cannot resolve the relative include
16+
* paths. The parser skips includes it cannot find and parses only the
17+
* function declarations that appear directly in this file — which is
18+
* sufficient to generate correct mock stubs.
19+
*/
20+
21+
#ifndef NRF_CLOUD_COAP_TEST_STUB_H_
22+
#define NRF_CLOUD_COAP_TEST_STUB_H_
23+
24+
#include <stddef.h>
25+
#include <stdint.h>
26+
#include <stdbool.h>
27+
#include <limits.h>
28+
29+
/*
30+
* Pull in the full type definitions that sm_at_nrfcloud.c needs when it
31+
* accesses struct members (wifi_scan_info, lte_lc_cells_info, etc.).
32+
* CMock's Ruby parser will skip these includes if it cannot find them; the
33+
* function signatures below are enough for mock generation.
34+
*/
35+
#include <modem/lte_lc.h>
36+
#include "net/wifi_location_common.h"
37+
#include "net/nrf_cloud_location.h"
38+
39+
/* ----------------------------------------------------------------------
40+
* CoAP content-format constant.
41+
* In production code this comes from <zephyr/net/coap.h> when
42+
* CONFIG_NRF_CLOUD_COAP is set. Without that Kconfig the real header
43+
* defines a stub enum without the actual values, so we define it here.
44+
* ----------------------------------------------------------------------
45+
*/
46+
#ifndef COAP_CONTENT_FORMAT_APP_JSON
47+
#define COAP_CONTENT_FORMAT_APP_JSON 50
48+
#endif
49+
50+
/* ----------------------------------------------------------------------
51+
* CoAP response callback – matches the real coap_client_response_cb_t.
52+
* ----------------------------------------------------------------------
53+
*/
54+
#ifndef COAP_CLIENT_RESPONSE_CB_T_DEFINED
55+
#define COAP_CLIENT_RESPONSE_CB_T_DEFINED
56+
typedef void (*coap_client_response_cb_t)(int16_t result_code, size_t offset,
57+
const uint8_t *payload, size_t len,
58+
bool last_block, void *user_data);
59+
#endif
60+
61+
/* ----------------------------------------------------------------------
62+
* Wi-Fi and location constants (also defined in the sub-stubs; guards
63+
* prevent redefinition when this header is included first).
64+
* ----------------------------------------------------------------------
65+
*/
66+
#ifndef NRF_CLOUD_LOCATION_WIFI_AP_CNT_MIN
67+
#define NRF_CLOUD_LOCATION_WIFI_AP_CNT_MIN 2
68+
#endif
69+
#ifndef NRF_CLOUD_LOCATION_WIFI_OMIT_RSSI
70+
#define NRF_CLOUD_LOCATION_WIFI_OMIT_RSSI (INT8_MAX)
71+
#endif
72+
73+
/* ----------------------------------------------------------------------
74+
* nRF Cloud CoAP location request – matches struct nrf_cloud_coap_location_request
75+
* in the real nrf_cloud_coap.h.
76+
* ----------------------------------------------------------------------
77+
*/
78+
#ifndef NRF_CLOUD_COAP_LOCATION_REQUEST_DEFINED
79+
#define NRF_CLOUD_COAP_LOCATION_REQUEST_DEFINED
80+
/* Forward declaration; the test always passes config = NULL. */
81+
struct nrf_cloud_location_config;
82+
83+
struct nrf_cloud_coap_location_request {
84+
struct lte_lc_cells_info *cell_info;
85+
struct wifi_scan_info *wifi_info;
86+
const struct nrf_cloud_location_config *config;
87+
};
88+
#endif /* NRF_CLOUD_COAP_LOCATION_REQUEST_DEFINED */
89+
90+
/* ----------------------------------------------------------------------
91+
* nRF Cloud CoAP API – mocked by CMock
92+
* ----------------------------------------------------------------------
93+
*/
94+
int nrf_cloud_coap_init(void);
95+
int nrf_cloud_coap_connect(const char *const app_ver);
96+
int nrf_cloud_coap_disconnect(void);
97+
int nrf_cloud_coap_location_get(struct nrf_cloud_coap_location_request const *const request,
98+
struct nrf_cloud_location_result *const result);
99+
int nrf_cloud_coap_post(const char *resource, const char *query,
100+
const uint8_t *buf, size_t len,
101+
int fmt, bool reliable,
102+
coap_client_response_cb_t cb, void *user);
103+
104+
#endif /* NRF_CLOUD_COAP_TEST_STUB_H_ */
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/* Minimal stub for nrf_cloud_location.h used in unit tests. */
8+
9+
#ifndef NRF_CLOUD_LOCATION_TEST_STUB_H_
10+
#define NRF_CLOUD_LOCATION_TEST_STUB_H_
11+
12+
#include <stdint.h>
13+
#include <limits.h>
14+
15+
/** Minimum number of access points required for a Wi-Fi location request. */
16+
#define NRF_CLOUD_LOCATION_WIFI_AP_CNT_MIN 2
17+
18+
/** Sentinel RSSI value indicating that RSSI should be omitted from the request. */
19+
#define NRF_CLOUD_LOCATION_WIFI_OMIT_RSSI (INT8_MAX)
20+
21+
/** @brief Location result type from nRF Cloud (matches real SDK enum order) */
22+
#ifndef NRF_CLOUD_LOCATION_TYPE_DEFINED
23+
#define NRF_CLOUD_LOCATION_TYPE_DEFINED
24+
enum nrf_cloud_location_type {
25+
LOCATION_TYPE_SINGLE_CELL = 0,
26+
LOCATION_TYPE_MULTI_CELL,
27+
LOCATION_TYPE_WIFI,
28+
LOCATION_TYPE__INVALID,
29+
};
30+
31+
struct nrf_cloud_location_result {
32+
enum nrf_cloud_location_type type;
33+
double lat;
34+
double lon;
35+
uint32_t unc;
36+
};
37+
#endif /* NRF_CLOUD_LOCATION_TYPE_DEFINED */
38+
39+
#endif /* NRF_CLOUD_LOCATION_TEST_STUB_H_ */
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/* Minimal stub for wifi_location_common.h used in unit tests. */
8+
9+
#ifndef WIFI_LOCATION_COMMON_TEST_STUB_H_
10+
#define WIFI_LOCATION_COMMON_TEST_STUB_H_
11+
12+
#include <stdint.h>
13+
14+
#ifndef WIFI_MAC_ADDR_LEN
15+
#define WIFI_MAC_ADDR_LEN 6
16+
#endif
17+
18+
#ifndef WIFI_MAC_ADDR_STR_LEN
19+
/* 2 chars per byte + 5 colons */
20+
#define WIFI_MAC_ADDR_STR_LEN ((WIFI_MAC_ADDR_LEN * 2) + 5)
21+
#endif
22+
23+
#ifndef WIFI_MAC_ADDR_TEMPLATE
24+
#define WIFI_MAC_ADDR_TEMPLATE "%x:%x:%x:%x:%x:%x"
25+
#endif
26+
27+
#ifndef WIFI_SECURITY_TYPE_UNKNOWN
28+
#define WIFI_SECURITY_TYPE_UNKNOWN 0
29+
#endif
30+
31+
#ifndef WIFI_MFP_UNKNOWN
32+
#define WIFI_MFP_UNKNOWN 0
33+
#endif
34+
35+
/** @brief Access point information from a Wi-Fi scan. */
36+
struct wifi_scan_result {
37+
uint8_t mac[WIFI_MAC_ADDR_LEN];
38+
uint8_t mac_length;
39+
int8_t rssi;
40+
uint8_t band;
41+
int security;
42+
int mfp;
43+
};
44+
45+
/** @brief Access points found during a Wi-Fi scan. */
46+
struct wifi_scan_info {
47+
struct wifi_scan_result *ap_info;
48+
uint16_t cnt;
49+
};
50+
51+
#endif /* WIFI_LOCATION_COMMON_TEST_STUB_H_ */
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/*
8+
* Stub for nrf_cloud_coap_transport.h.
9+
* Provides the nrf_cloud_coap_post() declaration via the nrf_cloud_coap.h stub
10+
* so that sm_at_nrfcloud.c compiles in the unit test environment.
11+
*/
12+
13+
#ifndef NRF_CLOUD_COAP_TRANSPORT_TEST_STUB_H_
14+
#define NRF_CLOUD_COAP_TRANSPORT_TEST_STUB_H_
15+
16+
#include "net/nrf_cloud_coap.h"
17+
18+
#endif /* NRF_CLOUD_COAP_TRANSPORT_TEST_STUB_H_ */

0 commit comments

Comments
 (0)