From 2571d6c3e305e81a2b00eb5a079a89b239cf77ae Mon Sep 17 00:00:00 2001 From: Andreas Chmielewski Date: Tue, 3 Jan 2023 16:03:24 +0100 Subject: [PATCH] tests: lwm2m_rd_client: Added fff tests Added unittests for lwm2m_rd_client.c using FFF framework. Signed-off-by: Andreas Chmielewski --- .../lib/lwm2m/lwm2m_rd_client/CMakeLists.txt | 30 ++ .../net/lib/lwm2m/lwm2m_rd_client/prj.conf | 3 + .../net/lib/lwm2m/lwm2m_rd_client/src/main.c | 361 ++++++++++++++++++ .../net/lib/lwm2m/lwm2m_rd_client/src/stubs.c | 204 ++++++++++ .../net/lib/lwm2m/lwm2m_rd_client/src/stubs.h | 116 ++++++ .../lib/lwm2m/lwm2m_rd_client/testcase.yaml | 9 + 6 files changed, 723 insertions(+) create mode 100644 tests/subsys/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt create mode 100644 tests/subsys/net/lib/lwm2m/lwm2m_rd_client/prj.conf create mode 100644 tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/main.c create mode 100644 tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c create mode 100644 tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.h create mode 100644 tests/subsys/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml diff --git a/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt new file mode 100644 index 00000000000..5c7d1060d3f --- /dev/null +++ b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lwm2m_rd_client) + +set(APP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) + +# Add test sources +target_sources(app PRIVATE ${APP_SRC_DIR}/main.c) +target_sources(app PRIVATE ${APP_SRC_DIR}/stubs.c) +target_sources(app PRIVATE ${ZEPHYR_BASE}/subsys/net/lib/lwm2m/lwm2m_rd_client.c) + +# Add includes directories +target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/include/) +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/lib/lwm2m/) + +add_compile_definitions(CONFIG_LWM2M_ENGINE_MAX_PENDING=2) +add_compile_definitions(CONFIG_LWM2M_ENGINE_MAX_REPLIES=2) +add_compile_definitions(CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE=512) +add_compile_definitions(CONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE=512) +add_compile_definitions(CONFIG_LWM2M_RD_CLIENT_ENDPOINT_NAME_MAX_LENGTH=32) +add_compile_definitions(CONFIG_LWM2M_RD_CLIENT_MAX_RETRIES=2) +add_compile_definitions(CONFIG_LWM2M_COAP_BLOCK_SIZE=256) +add_compile_definitions(CONFIG_LWM2M_COAP_MAX_MSG_SIZE=512) +add_compile_definitions(CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME=60) +add_compile_definitions(CONFIG_LWM2M_SECURITY_INSTANCE_COUNT=1) +add_compile_definitions(CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY=30) +add_compile_definitions(CONFIG_LWM2M_QUEUE_MODE_UPTIME=30) +add_compile_definitions(CONFIG_LWM2M_LOG_LEVEL=4) diff --git a/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/prj.conf b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/prj.conf new file mode 100644 index 00000000000..fce1a57928f --- /dev/null +++ b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/prj.conf @@ -0,0 +1,3 @@ +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y +CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/main.c b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/main.c new file mode 100644 index 00000000000..d5fe2edc20a --- /dev/null +++ b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/main.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2022 grandcentrix GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "stubs.h" + +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(lwm2m_rd_client_test); + +DEFINE_FFF_GLOBALS; + +/* Maximum number of iterations within the state machine of RD Client + * service that is waited for until a possible event occurs + */ +static const uint8_t RD_CLIENT_MAX_LOOKUP_ITERATIONS = 10; + +FAKE_VOID_FUNC(show_lwm2m_event, enum lwm2m_rd_client_event); +FAKE_VOID_FUNC(show_lwm2m_observe, enum lwm2m_observe_event); + +bool check_lwm2m_rd_client_event(uint8_t expected_val, uint8_t arg_index) +{ + int max_service_iterations = RD_CLIENT_MAX_LOOKUP_ITERATIONS; + + while (max_service_iterations > 0) { + if (show_lwm2m_event_fake.call_count > arg_index) { + return show_lwm2m_event_fake.arg0_history[arg_index] == expected_val; + } + + wait_for_service(1); + max_service_iterations--; + } + + return false; +} + +bool check_lwm2m_observe_event(uint8_t expected_val, uint8_t arg_index) +{ + int max_service_iterations = RD_CLIENT_MAX_LOOKUP_ITERATIONS; + + while (max_service_iterations > 0) { + if (show_lwm2m_observe_fake.call_count > arg_index) { + return show_lwm2m_observe_fake.arg0_history[arg_index] == expected_val; + } + + wait_for_service(1); + max_service_iterations--; + } + + return false; +} + +static void lwm2m_event_cb(struct lwm2m_ctx *client, enum lwm2m_rd_client_event client_event) +{ + ARG_UNUSED(client); + + switch (client_event) { + case LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED"); + break; + case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE"); + break; + case LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT"); + break; + case LWM2M_RD_CLIENT_EVENT_DISCONNECT: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_DISCONNECT"); + break; + case LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE"); + break; + case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE"); + break; + case LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR: + LOG_INF("**** LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR"); + break; + default: + break; + } + + show_lwm2m_event(client_event); +} + +static void lwm2m_observe_cb(enum lwm2m_observe_event event, struct lwm2m_obj_path *path, + void *user_data) +{ + switch (event) { + case LWM2M_OBSERVE_EVENT_OBSERVER_ADDED: + LOG_INF("**** LWM2M_OBSERVE_EVENT_OBSERVER_ADDED"); + break; + case LWM2M_OBSERVE_EVENT_NOTIFY_TIMEOUT: + LOG_INF("**** LWM2M_OBSERVE_EVENT_NOTIFY_TIMEOUT"); + break; + case LWM2M_OBSERVE_EVENT_OBSERVER_REMOVED: + LOG_INF("**** LWM2M_OBSERVE_EVENT_OBSERVER_REMOVED"); + break; + case LWM2M_OBSERVE_EVENT_NOTIFY_ACK: + LOG_INF("**** LWM2M_OBSERVE_EVENT_NOTIFY_ACK"); + break; + default: + break; + } + + show_lwm2m_observe(event); +} + +#define FFF_FAKES_LIST(FAKE) + +static void my_suite_before(void *data) +{ + /* Register resets */ + DO_FOREACH_FAKE(RESET_FAKE); + + /* reset common FFF internal structures */ + FFF_RESET_HISTORY(); + + RESET_FAKE(show_lwm2m_event); + RESET_FAKE(show_lwm2m_observe); + + test_lwm2m_engine_stop_service(); +} + +void message_reply_cb_default(struct lwm2m_message *msg) +{ + struct coap_packet response; + struct coap_reply reply; + struct sockaddr from; + + memset(&response, 0, sizeof(struct coap_packet)); + memset(&reply, 0, sizeof(struct coap_reply)); + memset(&from, 0, sizeof(struct sockaddr)); + + msg->reply_cb(&response, &reply, &from); +} + +void message_reply_timeout_cb_default(struct lwm2m_message *msg) +{ + msg->message_timeout_cb(msg); +} + +ZTEST_SUITE(lwm2m_rd_client, NULL, NULL, my_suite_before, NULL, NULL); + +ZTEST(lwm2m_rd_client, test_start_registration_ok) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_created; + coap_find_options_fake.custom_fake = coap_find_options_do_registration_reply_cb_ok; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, 0), + NULL); + + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_deleted; + zassert_true(lwm2m_rd_client_stop(&ctx, lwm2m_event_cb, true) == 0, NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DISCONNECT, 1), NULL); +} + +ZTEST(lwm2m_rd_client, test_start_registration_timeout) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_timeout_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_DISCONNECT, 0), NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT, 1), NULL); +} + +ZTEST(lwm2m_rd_client, test_start_registration_fail) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE, 0), + NULL); +} + +ZTEST(lwm2m_rd_client, test_start_registration_update) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_created; + coap_find_options_fake.custom_fake = coap_find_options_do_registration_reply_cb_ok; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, 0), + NULL); + + lwm2m_rd_client_update(); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE, 1), + NULL); +} + +ZTEST(lwm2m_rd_client, test_start_registration_update_fail) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_created; + coap_find_options_fake.custom_fake = coap_find_options_do_registration_reply_cb_ok; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, 0), + NULL); + + RESET_FAKE(coap_header_get_code); + + lwm2m_rd_client_update(); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE, 1), + NULL); +} + +ZTEST(lwm2m_rd_client, test_error_on_registration_update) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_created; + coap_find_options_fake.custom_fake = coap_find_options_do_registration_reply_cb_ok; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, 0), + NULL); + + coap_packet_append_option_fake.custom_fake = coap_packet_append_option_fake_err; + lwm2m_rd_client_update(); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, 1), + NULL); +} + +ZTEST(lwm2m_rd_client, test_network_error_on_registration) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_created; + coap_find_options_fake.custom_fake = coap_find_options_do_registration_reply_cb_ok; + coap_packet_append_option_fake.custom_fake = coap_packet_append_option_fake_err; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR, 0), NULL); +} + +ZTEST(lwm2m_rd_client, test_suspend_resume_registration) +{ + struct lwm2m_ctx ctx; + + (void)memset(&ctx, 0x0, sizeof(ctx)); + + test_prepare_pending_message_cb(&message_reply_cb_default); + + lwm2m_engine_add_service_fake.custom_fake = lwm2m_engine_add_service_fake_default; + lwm2m_rd_client_init(); + test_lwm2m_engine_start_service(); + wait_for_service(1); + + lwm2m_get_bool_fake.custom_fake = lwm2m_get_bool_fake_default; + lwm2m_sprint_ip_addr_fake.custom_fake = lwm2m_sprint_ip_addr_fake_default; + lwm2m_init_message_fake.custom_fake = lwm2m_init_message_fake_default; + coap_header_get_code_fake.custom_fake = coap_header_get_code_fake_created; + coap_find_options_fake.custom_fake = coap_find_options_do_registration_reply_cb_ok; + zassert_true(lwm2m_rd_client_start(&ctx, "Test", 0, lwm2m_event_cb, lwm2m_observe_cb) == 0, + NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, 0), + NULL); + + zassert_true(lwm2m_rd_client_pause() == 0, NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED, 1), NULL); + + zassert_true(lwm2m_rd_client_resume() == 0, NULL); + zassert_true(check_lwm2m_rd_client_event(LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE, 2), + NULL); +} diff --git a/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c new file mode 100644 index 00000000000..fe2125419e9 --- /dev/null +++ b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2022 grandcentrix GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +LOG_MODULE_DECLARE(lwm2m_rd_client_test); + +/* zephyr/net/coap.h */ +DEFINE_FAKE_VALUE_FUNC(uint8_t, coap_header_get_code, const struct coap_packet *); +uint8_t coap_header_get_code_fake_created(const struct coap_packet *cpkt) +{ + return COAP_RESPONSE_CODE_CREATED; +} +uint8_t coap_header_get_code_fake_deleted(const struct coap_packet *cpkt) +{ + return COAP_RESPONSE_CODE_DELETED; +} + +DEFINE_FAKE_VALUE_FUNC(int, coap_append_option_int, struct coap_packet *, uint16_t, unsigned int); +DEFINE_FAKE_VALUE_FUNC(int, coap_packet_append_option, struct coap_packet *, uint16_t, + const uint8_t *, uint16_t); +int coap_packet_append_option_fake_err(struct coap_packet *cpkt, uint16_t code, + const uint8_t *value, uint16_t len) +{ + return -1; +} + +DEFINE_FAKE_VALUE_FUNC(int, coap_packet_append_payload_marker, struct coap_packet *); +DEFINE_FAKE_VALUE_FUNC(int, coap_find_options, const struct coap_packet *, uint16_t, + struct coap_option *, uint16_t); +int coap_find_options_do_registration_reply_cb_ok(const struct coap_packet *cpkt, uint16_t code, + struct coap_option *options, uint16_t veclen) +{ + char options0[] = "rd"; + char options1[] = "jATO2yn9u7"; + + options[1].len = sizeof(options0); + memcpy(&options[1].value, &options0, sizeof(options0)); + options[1].len = sizeof(options1); + memcpy(&options[1].value, &options1, sizeof(options1)); + return 3; +} + +DEFINE_FAKE_VALUE_FUNC(uint16_t, coap_next_id); + +/* zephyr/net/lwm2m.h */ +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_start, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_stop, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_open_socket, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_u32, const struct lwm2m_obj_path *, uint32_t *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_u16, const struct lwm2m_obj_path *, uint16_t *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_bool, const struct lwm2m_obj_path *, bool *); +int lwm2m_get_bool_fake_default(const struct lwm2m_obj_path *path, bool *value) +{ + *value = false; + return 0; +} + +/* subsys/net/lib/lwm2m/lwm2m_engine.h */ +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_socket_start, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_socket_close, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_close_socket, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_security_inst_id_to_index, uint16_t); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_connection_resume, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_push_queued_buffers, struct lwm2m_ctx *); +DEFINE_FAKE_VOID_FUNC(lwm2m_engine_context_init, struct lwm2m_ctx *); +DEFINE_FAKE_VOID_FUNC(lwm2m_engine_context_close, struct lwm2m_ctx *); +DEFINE_FAKE_VALUE_FUNC(char *, lwm2m_sprint_ip_addr, const struct sockaddr *); +char *lwm2m_sprint_ip_addr_fake_default(const struct sockaddr *addr) +{ + return "192.168.1.1:4444"; +} + +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_server_short_id_to_inst, uint16_t); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_security_index_to_inst_id, int); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_add_service, k_work_handler_t, uint32_t); + +k_work_handler_t lwm2m_engine_add_service_service; +uint32_t lwm2m_engine_add_service_period_ms = 20; +int lwm2m_engine_add_service_fake_default(k_work_handler_t service, uint32_t period_ms) +{ + lwm2m_engine_add_service_service = service; + lwm2m_engine_add_service_period_ms = period_ms; + return 0; +} + +uint16_t counter = RD_CLIENT_MAX_SERVICE_ITERATIONS; +struct lwm2m_message *pending_message; +void *(*pending_message_cb)(); + +static void service_work_fn(struct k_work *work) +{ + while (lwm2m_engine_add_service_service != NULL) { + if (pending_message != NULL && pending_message_cb != NULL) { + pending_message_cb(pending_message); + pending_message = NULL; + } + + lwm2m_engine_add_service_service(work); + k_sleep(K_MSEC(lwm2m_engine_add_service_period_ms)); + counter--; + + /* avoid endless loop if rd client is stuck somewhere */ + if (counter == 0) { + break; + } + } +} + +void wait_for_service(uint16_t cycles) +{ + uint16_t end = counter - cycles; + + while (counter > end) { + k_sleep(K_MSEC(1)); + } +} + +K_WORK_DEFINE(service_work, service_work_fn); + +void test_lwm2m_engine_start_service(void) +{ + counter = RD_CLIENT_MAX_SERVICE_ITERATIONS; + k_work_submit(&service_work); +} + +void test_lwm2m_engine_stop_service(void) +{ + pending_message_cb = NULL; + k_work_cancel(&service_work); +} + +/* subsys/net/lib/lwm2m/lwm2m_message_handling.h */ +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_init_message, struct lwm2m_message *); +int lwm2m_init_message_fake_default(struct lwm2m_message *msg) +{ + pending_message = msg; + return 0; +} + +void test_prepare_pending_message_cb(void *cb) +{ + pending_message_cb = cb; +} + +DEFINE_FAKE_VOID_FUNC(lwm2m_reset_message, struct lwm2m_message *, bool); +DEFINE_FAKE_VALUE_FUNC(int, lwm2m_send_message_async, struct lwm2m_message *); + +/* subsys/net/lib/lwm2m/lwm2m_registry.h */ +DEFINE_FAKE_VOID_FUNC(lwm2m_engine_get_binding, char *); +DEFINE_FAKE_VOID_FUNC(lwm2m_engine_get_queue_mode, char *); + +/* subsys/net/lib/lwm2m/lwm2m_rw_link_format.h */ +FAKE_VALUE_FUNC(int, put_begin, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_end, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_begin_oi, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_end_oi, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_begin_r, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_end_r, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_begin_ri, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_end_ri, struct lwm2m_output_context *, struct lwm2m_obj_path *); +FAKE_VALUE_FUNC(int, put_s8, struct lwm2m_output_context *, struct lwm2m_obj_path *, int8_t); +FAKE_VALUE_FUNC(int, put_s16, struct lwm2m_output_context *, struct lwm2m_obj_path *, int16_t); +FAKE_VALUE_FUNC(int, put_s32, struct lwm2m_output_context *, struct lwm2m_obj_path *, int32_t); +FAKE_VALUE_FUNC(int, put_s64, struct lwm2m_output_context *, struct lwm2m_obj_path *, int64_t); +FAKE_VALUE_FUNC(int, put_time, struct lwm2m_output_context *, struct lwm2m_obj_path *, time_t); +FAKE_VALUE_FUNC(int, put_string, struct lwm2m_output_context *, struct lwm2m_obj_path *, char *, + size_t); +FAKE_VALUE_FUNC(int, put_float, struct lwm2m_output_context *, struct lwm2m_obj_path *, double *); +FAKE_VALUE_FUNC(int, put_bool, struct lwm2m_output_context *, struct lwm2m_obj_path *, bool); +FAKE_VALUE_FUNC(int, put_opaque, struct lwm2m_output_context *, struct lwm2m_obj_path *, char *, + size_t); +FAKE_VALUE_FUNC(int, put_objlnk, struct lwm2m_output_context *, struct lwm2m_obj_path *, + struct lwm2m_objlnk *); +FAKE_VALUE_FUNC(int, put_corelink, struct lwm2m_output_context *, const struct lwm2m_obj_path *); + +const struct lwm2m_writer link_format_writer = { + .put_begin = put_begin, + .put_end = put_end, + .put_begin_oi = put_begin_oi, + .put_end_oi = put_end_oi, + .put_begin_r = put_begin_r, + .put_end_r = put_end_r, + .put_begin_ri = put_begin_oi, + .put_end_ri = put_end_oi, + .put_s8 = put_s8, + .put_s16 = put_s16, + .put_s32 = put_s32, + .put_s64 = put_s64, + .put_time = put_time, + .put_string = put_string, + .put_float = put_float, + .put_bool = put_bool, + .put_opaque = put_opaque, + .put_objlnk = put_objlnk, + .put_corelink = put_corelink, +}; + +DEFINE_FAKE_VALUE_FUNC(int, do_register_op_link_format, struct lwm2m_message *); diff --git a/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.h b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.h new file mode 100644 index 00000000000..9a87ebfad62 --- /dev/null +++ b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/src/stubs.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2022 grandcentrix GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef STUBS_H +#define STUBS_H + +#include +#include + +#include +#include +#include + +#include + +/* Number of iterations the state machine within the RDClient service + * is triggered + */ +static const uint8_t RD_CLIENT_MAX_SERVICE_ITERATIONS = 50; + +/* zephyr/net/coap.h */ +DECLARE_FAKE_VALUE_FUNC(uint8_t, coap_header_get_code, const struct coap_packet *); +uint8_t coap_header_get_code_fake_created(const struct coap_packet *cpkt); +uint8_t coap_header_get_code_fake_deleted(const struct coap_packet *cpkt); +DECLARE_FAKE_VALUE_FUNC(int, coap_append_option_int, struct coap_packet *, uint16_t, unsigned int); +DECLARE_FAKE_VALUE_FUNC(int, coap_packet_append_option, struct coap_packet *, uint16_t, + const uint8_t *, uint16_t); +int coap_packet_append_option_fake_err(struct coap_packet *cpkt, uint16_t code, + const uint8_t *value, uint16_t len); +DECLARE_FAKE_VALUE_FUNC(int, coap_packet_append_payload_marker, struct coap_packet *); +DECLARE_FAKE_VALUE_FUNC(int, coap_find_options, const struct coap_packet *, uint16_t, + struct coap_option *, uint16_t); +int coap_find_options_do_registration_reply_cb_ok(const struct coap_packet *cpkt, uint16_t code, + struct coap_option *options, uint16_t veclen); +DECLARE_FAKE_VALUE_FUNC(uint16_t, coap_next_id); + +/* zephyr/net/lwm2m.h */ +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_engine_start, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_engine_stop, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_open_socket, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_get_u32, const struct lwm2m_obj_path *, uint32_t *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_get_u16, const struct lwm2m_obj_path *, uint16_t *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_get_bool, const struct lwm2m_obj_path *, bool *); +int lwm2m_get_bool_fake_default(const struct lwm2m_obj_path *path, bool *value); + +/* subsys/net/lib/lwm2m/lwm2m_engine.h */ +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_socket_start, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_socket_close, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_close_socket, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_security_inst_id_to_index, uint16_t); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_engine_connection_resume, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_push_queued_buffers, struct lwm2m_ctx *); +DECLARE_FAKE_VOID_FUNC(lwm2m_engine_context_init, struct lwm2m_ctx *); +DECLARE_FAKE_VOID_FUNC(lwm2m_engine_context_close, struct lwm2m_ctx *); +DECLARE_FAKE_VALUE_FUNC(char *, lwm2m_sprint_ip_addr, const struct sockaddr *); +char *lwm2m_sprint_ip_addr_fake_default(const struct sockaddr *addr); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_server_short_id_to_inst, uint16_t); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_security_index_to_inst_id, int); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_engine_add_service, k_work_handler_t, uint32_t); +int lwm2m_engine_add_service_fake_default(k_work_handler_t service, uint32_t period_ms); +void wait_for_service(uint16_t cycles); +void test_lwm2m_engine_start_service(void); +void test_lwm2m_engine_stop_service(void); + +/* subsys/net/lib/lwm2m/lwm2m_message_handling.h */ +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_init_message, struct lwm2m_message *); +int lwm2m_init_message_fake_default(struct lwm2m_message *msg); +void test_prepare_pending_message_cb(void *cb); + +DECLARE_FAKE_VOID_FUNC(lwm2m_reset_message, struct lwm2m_message *, bool); +DECLARE_FAKE_VALUE_FUNC(int, lwm2m_send_message_async, struct lwm2m_message *); + +/* subsys/net/lib/lwm2m/lwm2m_registry.h */ +DECLARE_FAKE_VOID_FUNC(lwm2m_engine_get_binding, char *); +DECLARE_FAKE_VOID_FUNC(lwm2m_engine_get_queue_mode, char *); + +/* subsys/net/lib/lwm2m/lwm2m_rw_link_format.h */ +DECLARE_FAKE_VALUE_FUNC(int, do_register_op_link_format, struct lwm2m_message *); + +#define DO_FOREACH_FAKE(FUNC) \ + do { \ + FUNC(coap_header_get_code) \ + FUNC(coap_append_option_int) \ + FUNC(coap_packet_append_option) \ + FUNC(coap_packet_append_payload_marker) \ + FUNC(coap_find_options) \ + FUNC(coap_next_id) \ + FUNC(lwm2m_engine_start) \ + FUNC(lwm2m_engine_stop) \ + FUNC(lwm2m_get_u32) \ + FUNC(lwm2m_get_u16) \ + FUNC(lwm2m_get_bool) \ + FUNC(lwm2m_socket_start) \ + FUNC(lwm2m_socket_close) \ + FUNC(lwm2m_close_socket) \ + FUNC(lwm2m_security_inst_id_to_index) \ + FUNC(lwm2m_engine_connection_resume) \ + FUNC(lwm2m_push_queued_buffers) \ + FUNC(lwm2m_engine_context_init) \ + FUNC(lwm2m_engine_context_close) \ + FUNC(lwm2m_sprint_ip_addr) \ + FUNC(lwm2m_server_short_id_to_inst) \ + FUNC(lwm2m_security_index_to_inst_id) \ + FUNC(lwm2m_engine_add_service) \ + FUNC(lwm2m_init_message) \ + FUNC(lwm2m_reset_message) \ + FUNC(lwm2m_send_message_async) \ + FUNC(lwm2m_engine_get_binding) \ + FUNC(lwm2m_engine_get_queue_mode) \ + FUNC(do_register_op_link_format) \ + } while (0) + +#endif /* STUBS_H */ diff --git a/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml new file mode 100644 index 00000000000..a5af87c50c6 --- /dev/null +++ b/tests/subsys/net/lib/lwm2m/lwm2m_rd_client/testcase.yaml @@ -0,0 +1,9 @@ +common: + depends_on: netif +tests: + subsys.net.lib.lwm2m_rd_client: + tags: net lwm2m + platform_allow: native_posix qemu_x86 qemu_x86_64 + integration_platforms: + - native_posix + - qemu_x86