diff --git a/tests/subsys/nfc/rpc/client/CMakeLists.txt b/tests/subsys/nfc/rpc/client/CMakeLists.txt new file mode 100644 index 000000000000..ce291f2f14e1 --- /dev/null +++ b/tests/subsys/nfc/rpc/client/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(nfc_rpc_t2t_client_test) + +FILE(GLOB app_sources src/*.c) + +target_include_directories(app PRIVATE + # Needed to access OpenThread RPC command IDs. + ${ZEPHYR_NRF_MODULE_DIR}/subsys/nfc/rpc/common + ../common +) + +target_sources(app PRIVATE + ${app_sources} + ../common/nrf_rpc_single_thread.c +) + +zephyr_include_directories(${ZEPHYR_NRFXLIB_MODULE_DIR}/nfc/include/) + +# Enforce single-threaded nRF RPC command processing. +target_link_options(app PUBLIC + -Wl,--wrap=nrf_rpc_os_init,--wrap=nrf_rpc_os_thread_pool_send +) diff --git a/tests/subsys/nfc/rpc/client/prj.conf b/tests/subsys/nfc/rpc/client/prj.conf new file mode 100644 index 000000000000..07607d637224 --- /dev/null +++ b/tests/subsys/nfc/rpc/client/prj.conf @@ -0,0 +1,18 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_ZTEST=y + +CONFIG_NFC_RPC=y +CONFIG_NFC_RPC_CLIENT=y + +CONFIG_NRF_RPC_CBKPROXY_OUT_SLOTS=0 + +CONFIG_MOCK_NRF_RPC=y +CONFIG_MOCK_NRF_RPC_TRANSPORT=y + +CONFIG_KERNEL_MEM_POOL=y +CONFIG_HEAP_MEM_POOL_SIZE=4096 diff --git a/tests/subsys/nfc/rpc/client/src/main.c b/tests/subsys/nfc/rpc/client/src/main.c new file mode 100644 index 000000000000..9bab08666e22 --- /dev/null +++ b/tests/subsys/nfc/rpc/client/src/main.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +static int slot_cnt; +static bool cb_called; + +static void nrf_rpc_err_handler(const struct nrf_rpc_err_report *report) +{ + zassert_ok(report->code); +} + +static void tc_setup(void *f) +{ + mock_nrf_rpc_tr_expect_add(RPC_INIT_REQ, RPC_INIT_RSP); + zassert_ok(nrf_rpc_init(nrf_rpc_err_handler)); + mock_nrf_rpc_tr_expect_reset(); +} + +/* Test serialization of nfc_t2t_setup() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_setup) +{ + int error; + nfc_t2t_callback_t cb = (nfc_t2t_callback_t)0xdeadbeef; + void *cb_ctx = (void *)0xcafeface; + + mock_nrf_rpc_tr_expect_add( + RPC_CMD(NFC_RPC_CMD_T2T_SETUP, slot_cnt, CBOR_UINT32(0xcafeface)), RPC_RSP(0)); + error = nfc_t2t_setup(cb, cb_ctx); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_parameter_set() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_parameter_set) +{ + int error; + uint8_t data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + mock_nrf_rpc_tr_expect_add( + RPC_CMD(NFC_RPC_CMD_T2T_PARAMETER_SET, NFC_T2T_PARAM_NFCID1, NFC_DATA), RPC_RSP(0)); + error = nfc_t2t_parameter_set(NFC_T2T_PARAM_NFCID1, data, DATA_SIZE); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_parameter_set() with NULL data */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_parameter_set_null) +{ + int error; + + error = nfc_t2t_parameter_set(NFC_T2T_PARAM_NFCID1, NULL, 10); + zassert_equal(error, -NRF_EINVAL); +} + +/* Test serialization of nfc_t2t_parameter_get() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_parameter_get) +{ + int error; + uint8_t expected_data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + uint8_t data[DATA_SIZE]; + size_t max_data_length = DATA_SIZE; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_PARAMETER_GET, NFC_T2T_PARAM_FDT_MIN, + CBOR_UINT8(DATA_SIZE)), + RPC_RSP(NFC_DATA)); + error = nfc_t2t_parameter_get(NFC_T2T_PARAM_FDT_MIN, data, &max_data_length); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); + zassert_mem_equal(data, expected_data, DATA_SIZE); +} + +/* Test serialization of nfc_t2t_parameter_get() with NULL data */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_parameter_get_null) +{ + int error; + uint8_t data[DATA_SIZE]; + size_t max_data_length = DATA_SIZE; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_PARAMETER_GET, NFC_T2T_PARAM_FDT_MIN, + CBOR_UINT8(DATA_SIZE)), + RPC_RSP(CBOR_NULL)); + error = nfc_t2t_parameter_get(NFC_T2T_PARAM_FDT_MIN, data, &max_data_length); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, -NRF_EINVAL); +} + +/* Test serialization of nfc_t2t_payload_set() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_payload_set) +{ + int error; + uint8_t data[NFC_T2T_MAX_PAYLOAD_SIZE]; + mock_nrf_rpc_pkt_t expected_pkt; + uint8_t expected_data[NFC_T2T_MAX_PAYLOAD_SIZE + 9] = { + 0x80, NFC_RPC_CMD_T2T_PAYLOAD_SET, 0xff, 0x00, 0x00, 0x59, 0x03, 0xdc}; + + for (int i = 0; i < NFC_T2T_MAX_PAYLOAD_SIZE; i++) { + data[i] = i + 1; + expected_data[8 + i] = i + 1; + } + expected_data[NFC_T2T_MAX_PAYLOAD_SIZE + 8] = 0xf6; + + expected_pkt.data = expected_data; + expected_pkt.len = sizeof(expected_data); + mock_nrf_rpc_tr_expect_add(expected_pkt, RPC_RSP(0)); + error = nfc_t2t_payload_set(data, NFC_T2T_MAX_PAYLOAD_SIZE); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_payload_set() with NULL data */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_payload_set_null) +{ + int error; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_PAYLOAD_SET, CBOR_NULL), RPC_RSP(0)); + error = nfc_t2t_payload_set(NULL, NFC_T2T_MAX_PAYLOAD_SIZE); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_payload_set() with zero length */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_payload_set_zero) +{ + int error; + uint8_t data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_PAYLOAD_SET, 0x40), RPC_RSP(0)); + error = nfc_t2t_payload_set(data, 0); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_payload_raw_set() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_payload_raw_set) +{ + int error; + uint8_t data[NFC_T2T_MAX_PAYLOAD_SIZE_RAW]; + mock_nrf_rpc_pkt_t expected_pkt; + uint8_t expected_data[NFC_T2T_MAX_PAYLOAD_SIZE_RAW + 9] = { + 0x80, NFC_RPC_CMD_T2T_PAYLOAD_RAW_SET, 0xff, 0, 0, 0x59, 0x03, 0xf0}; + + for (int i = 0; i < NFC_T2T_MAX_PAYLOAD_SIZE_RAW; i++) { + data[i] = i + 1; + expected_data[8 + i] = i + 1; + } + expected_data[NFC_T2T_MAX_PAYLOAD_SIZE_RAW + 8] = 0xf6; + + expected_pkt.data = expected_data; + expected_pkt.len = sizeof(expected_data); + mock_nrf_rpc_tr_expect_add(expected_pkt, RPC_RSP(0)); + error = nfc_t2t_payload_raw_set(data, NFC_T2T_MAX_PAYLOAD_SIZE_RAW); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_payload_raw_set() with NULL data */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_payload_raw_set_null) +{ + int error; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_PAYLOAD_RAW_SET, CBOR_NULL), RPC_RSP(0)); + error = nfc_t2t_payload_raw_set(NULL, NFC_T2T_MAX_PAYLOAD_SIZE_RAW); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_internal_set() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_internal_set) +{ + int error; + uint8_t data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_INTERNAL_SET, NFC_DATA), RPC_RSP(0)); + error = nfc_t2t_internal_set(data, DATA_SIZE); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_internal_set() with NULL data */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_internal_set_null) +{ + int error; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_INTERNAL_SET, CBOR_NULL), RPC_RSP(0)); + error = nfc_t2t_internal_set(NULL, DATA_SIZE); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_emulation_start() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_emulation_start) +{ + int error; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_EMULATION_START), RPC_RSP(0)); + error = nfc_t2t_emulation_start(); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_emulation_stop() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_emulation_stop) +{ + int error; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_EMULATION_STOP), RPC_RSP(0)); + error = nfc_t2t_emulation_stop(); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +/* Test serialization of nfc_t2t_done() */ +ZTEST(nfc_rpc_t2t_cli, test_nfc_t2t_done) +{ + int error; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_DONE), RPC_RSP(0)); + error = nfc_t2t_done(); + mock_nrf_rpc_tr_expect_done(); + zassert_equal(error, 0); +} + +static void t2t_cb(void *context, nfc_t2t_event_t event, const uint8_t *data, size_t data_length) +{ + uint8_t expected_data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + cb_called = true; + zassert_not_null(data); + zassert_not_null(context); + zassert_equal_ptr(context, (void *)0xdeadbeef); + zassert_equal(event, NFC_T2T_EVENT_DATA_READ); + zassert_equal(data_length, DATA_SIZE); + zassert_mem_equal(data, expected_data, data_length); +} + +/* Test reception of t2t callback. */ +ZTEST(nfc_rpc_t2t_cli, test_t2t_cb_handler) +{ + + int in_slot = nrf_rpc_cbkproxy_in_set(t2t_cb); + + slot_cnt++; + cb_called = false; + mock_nrf_rpc_tr_expect_add(RPC_RSP(), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_CB, NFC_T2T_EVENT_DATA_READ, NFC_DATA, + CBOR_UINT32(0xdeadbeef), in_slot)); + mock_nrf_rpc_tr_expect_done(); + + zassert_true(cb_called); +} + +ZTEST_SUITE(nfc_rpc_t2t_cli, NULL, NULL, tc_setup, NULL, NULL); diff --git a/tests/subsys/nfc/rpc/client/testcase.yaml b/tests/subsys/nfc/rpc/client/testcase.yaml new file mode 100644 index 000000000000..f848c067c186 --- /dev/null +++ b/tests/subsys/nfc/rpc/client/testcase.yaml @@ -0,0 +1,7 @@ +tests: + nfc.rpc.client: + sysbuild: true + platform_allow: native_sim + tags: nfc ci_build sysbuild + integration_platforms: + - native_sim diff --git a/tests/subsys/nfc/rpc/common/nrf_rpc_single_thread.c b/tests/subsys/nfc/rpc/common/nrf_rpc_single_thread.c new file mode 100644 index 000000000000..04d79c7033bf --- /dev/null +++ b/tests/subsys/nfc/rpc/common/nrf_rpc_single_thread.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Replacement implementation of selected nRF RPC OS functions, which enables single-threaded + * processing of a received nRF RPC command. + * + * Typically, an nRF RPC command that initiates a conversation is dispatched by the nRF RPC core + * using a dedicated thread pool. In unit tests, however, it is preferable to dispatch the command + * synchronously so that no operation timeouts are needed to detect a test case failure. + */ + +#include + +#include + +static nrf_rpc_os_work_t receive_callback; + +int __real_nrf_rpc_os_init(nrf_rpc_os_work_t callback); + +int __wrap_nrf_rpc_os_init(nrf_rpc_os_work_t callback) +{ + receive_callback = callback; + + return __real_nrf_rpc_os_init(callback); +} + +void __wrap_nrf_rpc_os_thread_pool_send(const uint8_t *data, size_t len) +{ + zassert_not_null(receive_callback); + + receive_callback(data, len); +} diff --git a/tests/subsys/nfc/rpc/common/test_rpc_env.h b/tests/subsys/nfc/rpc/common/test_rpc_env.h new file mode 100644 index 000000000000..522b8cc83037 --- /dev/null +++ b/tests/subsys/nfc/rpc/common/test_rpc_env.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#define DATA_SIZE 100 + +/* CBOR constants */ + +#define CBOR_FALSE 0xf4 +#define CBOR_TRUE 0xf5 +#define CBOR_NULL 0xf6 + +#define LSFY_IDENTITY(n, _) n + 1 +#define INT_SEQUENCE(length) LISTIFY(length, LSFY_IDENTITY, (,)) + +/* Macros for constructing nRF RPC packets for the OpenThread command group. */ + +#define RPC_PKT(bytes...) \ + (mock_nrf_rpc_pkt_t) \ + { \ + .data = (uint8_t[]){bytes}, .len = sizeof((uint8_t[]){bytes}), \ + } + +#define RPC_INIT_REQ RPC_PKT(0x04, 0x00, 0xff, 0x00, 0xff, 0x00, 'n', 'f', 'c') +#define RPC_INIT_RSP RPC_PKT(0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 'n', 'f', 'c') +#define RPC_CMD(cmd, ...) RPC_PKT(0x80, cmd, 0xff, 0x00, 0x00 __VA_OPT__(,) __VA_ARGS__, 0xf6) +#define RPC_RSP(...) RPC_PKT(0x01, 0xff, 0x00, 0x00, 0x00 __VA_OPT__(,) __VA_ARGS__, 0xf6) +#define NO_RSP RPC_PKT() + +/* Other test data */ + +#define CBOR_UINT32(value) 0x1A, BT_BYTES_LIST_LE32(BSWAP_32(value)) +#define CBOR_UINT16(value) 0x19, BT_BYTES_LIST_LE16(BSWAP_16(value)) +/* for value bigger than 0x17 */ +#define CBOR_UINT8(value) 0x18, (value) +#define NFC_DATA 0x58, 0x64, INT_SEQUENCE(DATA_SIZE) diff --git a/tests/subsys/nfc/rpc/server/CMakeLists.txt b/tests/subsys/nfc/rpc/server/CMakeLists.txt new file mode 100644 index 000000000000..3993470e2a9a --- /dev/null +++ b/tests/subsys/nfc/rpc/server/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(nfc_rpc_t2t_server_test) + +FILE(GLOB app_sources src/*.c) + +target_include_directories(app PRIVATE + # Needed to access OpenThread RPC command IDs. + ${ZEPHYR_NRF_MODULE_DIR}/subsys/nfc/rpc/common + ../common +) + +target_sources(app PRIVATE + ${app_sources} + ../common/nrf_rpc_single_thread.c +) + +zephyr_include_directories(${ZEPHYR_NRFXLIB_MODULE_DIR}/nfc/include/) + +# Enforce single-threaded nRF RPC command processing. +target_link_options(app PUBLIC + -Wl,--wrap=nrf_rpc_os_init,--wrap=nrf_rpc_os_thread_pool_send +) diff --git a/tests/subsys/nfc/rpc/server/prj.conf b/tests/subsys/nfc/rpc/server/prj.conf new file mode 100644 index 000000000000..9a7612ec9832 --- /dev/null +++ b/tests/subsys/nfc/rpc/server/prj.conf @@ -0,0 +1,18 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_ZTEST=y + +CONFIG_NFC_RPC=y +CONFIG_NFC_RPC_SERVER=y + +CONFIG_NRF_RPC_CBKPROXY_OUT_SLOTS=0 + +CONFIG_MOCK_NRF_RPC=y +CONFIG_MOCK_NRF_RPC_TRANSPORT=y + +CONFIG_KERNEL_MEM_POOL=y +CONFIG_HEAP_MEM_POOL_SIZE=4096 diff --git a/tests/subsys/nfc/rpc/server/src/main.c b/tests/subsys/nfc/rpc/server/src/main.c new file mode 100644 index 000000000000..eff988cd48dc --- /dev/null +++ b/tests/subsys/nfc/rpc/server/src/main.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +/* Fake functions */ +DEFINE_FFF_GLOBALS; +FAKE_VALUE_FUNC(int, nfc_t2t_setup, nfc_t2t_callback_t, void *); +FAKE_VALUE_FUNC(int, nfc_t2t_parameter_set, nfc_t2t_param_id_t, void *, size_t); +FAKE_VALUE_FUNC(int, nfc_t2t_parameter_get, nfc_t2t_param_id_t, void *, size_t *); +FAKE_VALUE_FUNC(int, nfc_t2t_payload_set, const uint8_t *, size_t); +FAKE_VALUE_FUNC(int, nfc_t2t_payload_raw_set, const uint8_t *, size_t); +FAKE_VALUE_FUNC(int, nfc_t2t_internal_set, const uint8_t *, size_t); +FAKE_VALUE_FUNC(int, nfc_t2t_emulation_start); +FAKE_VALUE_FUNC(int, nfc_t2t_emulation_stop); +FAKE_VALUE_FUNC(int, nfc_t2t_done); + +#define FOREACH_FAKE(f) \ + f(nfc_t2t_setup); \ + f(nfc_t2t_parameter_set); \ + f(nfc_t2t_parameter_get); \ + f(nfc_t2t_payload_set); \ + f(nfc_t2t_payload_raw_set); \ + f(nfc_t2t_internal_set); \ + f(nfc_t2t_emulation_start); \ + f(nfc_t2t_emulation_stop); \ + f(nfc_t2t_done); + +extern uint64_t nfc_t2t_cb_encoder(uint32_t callback_slot, uint32_t _rsv0, uint32_t _rsv1, + uint32_t _ret, void *context, nfc_t2t_event_t event, + const uint8_t *data, size_t data_length); + +static void nrf_rpc_err_handler(const struct nrf_rpc_err_report *report) +{ + zassert_ok(report->code); +} + +static void tc_setup(void *f) +{ + mock_nrf_rpc_tr_expect_add(RPC_INIT_REQ, RPC_INIT_RSP); + zassert_ok(nrf_rpc_init(nrf_rpc_err_handler)); + mock_nrf_rpc_tr_expect_reset(); + + FOREACH_FAKE(RESET_FAKE); + FFF_RESET_HISTORY(); +} + +/* Test reception of nfc_t2t_setup command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_setup) +{ + nfc_t2t_setup_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_SETUP, 0, CBOR_UINT32(0xcafeface))); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_setup_fake.call_count, 1); + zassert_equal_ptr(nfc_t2t_setup_fake.arg0_val, NULL); + zassert_equal_ptr(nfc_t2t_setup_fake.arg1_val, (void *)0xcafeface); +} + +static int nfc_t2t_parameter_set_custom_fake(nfc_t2t_param_id_t id, void *data, size_t data_length) +{ + uint8_t expected_data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + zassert_equal(id, NFC_T2T_PARAM_NFCID1); + zassert_mem_equal(data, expected_data, DATA_SIZE); + zassert_equal(data_length, DATA_SIZE); + + return 0; +} + +/* Test reception of nfc_t2t_parameter_set command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_parameter_set) +{ + nfc_t2t_parameter_set_fake.custom_fake = nfc_t2t_parameter_set_custom_fake; + nfc_t2t_parameter_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive( + RPC_CMD(NFC_RPC_CMD_T2T_PARAMETER_SET, NFC_T2T_PARAM_NFCID1, NFC_DATA)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_parameter_set_fake.call_count, 1); +} + +static int nfc_t2t_parameter_get_custom_fake(nfc_t2t_param_id_t id, void *data, + size_t *max_data_length) +{ + uint8_t expected_data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + zassert_equal(*max_data_length, DATA_SIZE); + memcpy(data, expected_data, *max_data_length); + + return 0; +} + +/* Test reception of nfc_t2t_parameter_get command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_parameter_get) +{ + nfc_t2t_parameter_get_fake.return_val = 0; + nfc_t2t_parameter_get_fake.custom_fake = nfc_t2t_parameter_get_custom_fake; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(NFC_DATA), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_PARAMETER_GET, NFC_T2T_PARAM_FDT_MIN, + CBOR_UINT8(DATA_SIZE))); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_parameter_get_fake.call_count, 1); + zassert_equal(nfc_t2t_parameter_get_fake.arg0_val, NFC_T2T_PARAM_FDT_MIN); + zassert_equal(*nfc_t2t_parameter_get_fake.arg2_val, DATA_SIZE); +} + +/* Test reception of nfc_t2t_parameter_get command with returned error. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_parameter_get_negative) +{ + nfc_t2t_parameter_get_fake.return_val = -NRF_EINVAL; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(CBOR_NULL), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_PARAMETER_GET, NFC_T2T_PARAM_FDT_MIN, + CBOR_UINT8(DATA_SIZE))); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_parameter_get_fake.call_count, 1); + zassert_equal(nfc_t2t_parameter_get_fake.arg0_val, NFC_T2T_PARAM_FDT_MIN); + zassert_equal(*nfc_t2t_parameter_get_fake.arg2_val, DATA_SIZE); +} + +/* Test reception of nfc_t2t_payload_set command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_payload_set) +{ + mock_nrf_rpc_pkt_t expected_pkt; + uint8_t expected_data[NFC_T2T_MAX_PAYLOAD_SIZE + 9] = { + 0x80, NFC_RPC_CMD_T2T_PAYLOAD_SET, 0xff, 0x00, 0x00, 0x59, 0x03, 0xdc}; + + for (int i = 0; i < NFC_T2T_MAX_PAYLOAD_SIZE; i++) { + expected_data[8 + i] = i + 1; + } + expected_data[NFC_T2T_MAX_PAYLOAD_SIZE + 8] = 0xf6; + + expected_pkt.data = expected_data; + expected_pkt.len = sizeof(expected_data); + + nfc_t2t_payload_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(expected_pkt); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_payload_set_fake.call_count, 1); + zassert_mem_equal(nfc_t2t_payload_set_fake.arg0_val, expected_data + 8, + NFC_T2T_MAX_PAYLOAD_SIZE); + zassert_equal(nfc_t2t_payload_set_fake.arg1_val, NFC_T2T_MAX_PAYLOAD_SIZE); +} + +/* Test reception of nfc_t2t_payload_set command with NULL data. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_payload_set_null) +{ + nfc_t2t_payload_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_PAYLOAD_SET, CBOR_NULL)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_payload_set_fake.call_count, 1); + zassert_is_null(nfc_t2t_payload_set_fake.arg0_val); +} + +/* Test reception of nfc_t2t_payload_set command with zero length. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_payload_set_zero) +{ + nfc_t2t_payload_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_PAYLOAD_SET, 0x40)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_payload_set_fake.call_count, 1); + zassert_not_null(nfc_t2t_payload_set_fake.arg0_val); + zassert_equal(nfc_t2t_payload_set_fake.arg1_val, 0); +} + +/* Test reception of nfc_t2t_payload_raw_set command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_payload_raw_set) +{ + mock_nrf_rpc_pkt_t expected_pkt; + uint8_t expected_data[NFC_T2T_MAX_PAYLOAD_SIZE_RAW + 9] = { + 0x80, NFC_RPC_CMD_T2T_PAYLOAD_RAW_SET, 0xff, 0, 0, 0x59, 0x03, 0xf0}; + + for (int i = 0; i < NFC_T2T_MAX_PAYLOAD_SIZE_RAW; i++) { + expected_data[8 + i] = i + 1; + } + expected_data[NFC_T2T_MAX_PAYLOAD_SIZE_RAW + 8] = 0xf6; + + expected_pkt.data = expected_data; + expected_pkt.len = sizeof(expected_data); + + nfc_t2t_payload_raw_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(expected_pkt); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_payload_raw_set_fake.call_count, 1); + zassert_mem_equal(nfc_t2t_payload_raw_set_fake.arg0_val, expected_data + 8, + NFC_T2T_MAX_PAYLOAD_SIZE_RAW); + zassert_equal(nfc_t2t_payload_raw_set_fake.arg1_val, NFC_T2T_MAX_PAYLOAD_SIZE_RAW); +} + +/* Test reception of nfc_t2t_payload_raw_set command with NULL data. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_payload_raw_set_null) +{ + nfc_t2t_payload_raw_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_PAYLOAD_RAW_SET, CBOR_NULL)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_payload_raw_set_fake.call_count, 1); + zassert_is_null(nfc_t2t_payload_raw_set_fake.arg0_val); +} + +static int nfc_t2t_internal_set_custom_fake(const uint8_t *data, size_t data_length) +{ + uint8_t expected_data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + + zassert_mem_equal(data, expected_data, DATA_SIZE); + zassert_equal(data_length, DATA_SIZE); + + return 0; +} + +/* Test reception of nfc_t2t_internal_set command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_internal_set) +{ + nfc_t2t_internal_set_fake.return_val = 0; + nfc_t2t_internal_set_fake.custom_fake = nfc_t2t_internal_set_custom_fake; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_INTERNAL_SET, NFC_DATA)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_internal_set_fake.call_count, 1); +} + +/* Test reception of nfc_t2t_internal_set command with NULL data. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_internal_set_null) +{ + nfc_t2t_internal_set_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_INTERNAL_SET, CBOR_NULL)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_internal_set_fake.call_count, 1); + zassert_is_null(nfc_t2t_internal_set_fake.arg0_val); +} + +/* Test reception of nfc_t2t_emulation_start command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_emulation_start) +{ + nfc_t2t_emulation_start_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_EMULATION_START)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_emulation_start_fake.call_count, 1); +} + +/* Test reception of nfc_t2t_emulation_stop command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_emulation_stop) +{ + nfc_t2t_emulation_stop_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_EMULATION_STOP)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_emulation_stop_fake.call_count, 1); +} + +/* Test reception of nfc_t2t_done command. */ +ZTEST(nfc_rpc_t2t_srv, test_nfc_t2t_done) +{ + nfc_t2t_done_fake.return_val = 0; + + mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); + mock_nrf_rpc_tr_receive(RPC_CMD(NFC_RPC_CMD_T2T_DONE)); + mock_nrf_rpc_tr_expect_done(); + + zassert_equal(nfc_t2t_done_fake.call_count, 1); +} + +/* Test sending some data over registered nfc t2t callback. */ +ZTEST(nfc_rpc_t2t_srv, test_tx_t2t_cb) +{ + void *context = (void *)0xdeadbeef; + nfc_t2t_event_t event = NFC_T2T_EVENT_STOPPED; + uint8_t data[DATA_SIZE] = {INT_SEQUENCE(DATA_SIZE)}; + size_t data_length = DATA_SIZE; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_CB, CBOR_UINT32(0xdeadbeef), + NFC_T2T_EVENT_STOPPED, NFC_DATA, 0), + RPC_RSP()); + (void)nfc_t2t_cb_encoder(0, 0, 0, 0, context, event, data, data_length); + mock_nrf_rpc_tr_expect_done(); +} + +/* Test sending NULL data over registered nfc t2t callback. */ +ZTEST(nfc_rpc_t2t_srv, test_tx_t2t_cb_null) +{ + void *context = (void *)0xbabeface; + nfc_t2t_event_t event = NFC_T2T_EVENT_FIELD_ON; + + mock_nrf_rpc_tr_expect_add(RPC_CMD(NFC_RPC_CMD_T2T_CB, CBOR_UINT32(0xbabeface), + NFC_T2T_EVENT_FIELD_ON, CBOR_NULL, 0), + RPC_RSP()); + (void)nfc_t2t_cb_encoder(0, 0, 0, 0, context, event, NULL, DATA_SIZE); + mock_nrf_rpc_tr_expect_done(); +} + +ZTEST_SUITE(nfc_rpc_t2t_srv, NULL, NULL, tc_setup, NULL, NULL); diff --git a/tests/subsys/nfc/rpc/server/testcase.yaml b/tests/subsys/nfc/rpc/server/testcase.yaml new file mode 100644 index 000000000000..333f2e47d3bd --- /dev/null +++ b/tests/subsys/nfc/rpc/server/testcase.yaml @@ -0,0 +1,7 @@ +tests: + nfc.rpc.server: + sysbuild: true + platform_allow: native_sim + tags: nfc ci_build sysbuild + integration_platforms: + - native_sim