From f4837c4fa7f45776f3305aa57f7a713e8fcbd725 Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Tue, 20 Jun 2023 14:48:07 +0200 Subject: [PATCH] module/optee/mbox: Add unitary test Add unitary tests for optee/mbox module: 100% code coverage Signed-off-by: Vincent Guittot --- module/optee/mbx/test/CMakeLists.txt | 4 + module/optee/mbx/test/config_optee_mbx.h | 53 +++ module/optee/mbx/test/ext/kernel/mutex.h | 1 + module/optee/mbx/test/fwk_module_idx.h | 8 + .../mbx/test/mocks/Mockmod_optee_mbx_extra.c | 165 ++++++++ .../mbx/test/mocks/Mockmod_optee_mbx_extra.h | 20 + module/optee/mbx/test/mod_optee_mbx_extra.h | 1 + .../optee/mbx/test/mod_optee_mbx_unit_test.c | 362 ++++++++++++++++++ 8 files changed, 614 insertions(+) create mode 100644 module/optee/mbx/test/config_optee_mbx.h diff --git a/module/optee/mbx/test/CMakeLists.txt b/module/optee/mbx/test/CMakeLists.txt index bf5bf717f..ace14d38e 100644 --- a/module/optee/mbx/test/CMakeLists.txt +++ b/module/optee/mbx/test/CMakeLists.txt @@ -26,5 +26,9 @@ set(MODULE_UT_MOCK_SRC ${CMAKE_CURRENT_LIST_DIR}/mocks) list(APPEND MOCK_REPLACEMENTS fwk_module) list(APPEND MOCK_REPLACEMENTS fwk_id) list(APPEND MOCK_REPLACEMENTS fwk_core) +list(APPEND MOCK_REPLACEMENTS fwk_mm) include(${SCP_ROOT}/unit_test/module_common.cmake) + +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC "BUILD_HAS_MOD_OPTEE_SMT") +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC "BUILD_HAS_MOD_MSG_SMT") diff --git a/module/optee/mbx/test/config_optee_mbx.h b/module/optee/mbx/test/config_optee_mbx.h new file mode 100644 index 000000000..f9aafa259 --- /dev/null +++ b/module/optee/mbx/test/config_optee_mbx.h @@ -0,0 +1,53 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * This represents index of the channel descriptor within + * element table + */ +enum msg_channel_idx { + FAKE_SCMI_SERVICE_IDX_OSPM_0, + FAKE_SCMI_SERVICE_IDX_COUNT, +}; + +enum mbx_channel_idx { + FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0, + FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT +}; + +/* Provide a fake device info */ +static const struct fwk_element mbx_element_table[] = { + [FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0] = { + .name = "OP-TEE for OSPM #0", + .data = &((struct mod_optee_mbx_channel_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + FAKE_SCMI_SERVICE_IDX_OSPM_0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *mbx_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)mbx_element_table; +} + +struct fwk_module_config config_fake_optee_mbx = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mbx_get_element_table), +}; diff --git a/module/optee/mbx/test/ext/kernel/mutex.h b/module/optee/mbx/test/ext/kernel/mutex.h index 42f8ce03d..e001f02e4 100644 --- a/module/optee/mbx/test/ext/kernel/mutex.h +++ b/module/optee/mbx/test/ext/kernel/mutex.h @@ -16,5 +16,6 @@ struct mutex { void mutex_init(struct mutex *m); void mutex_unlock(struct mutex *m); +void mutex_lock(struct mutex *m); #endif /*KERNEL_MUTEX_H*/ diff --git a/module/optee/mbx/test/fwk_module_idx.h b/module/optee/mbx/test/fwk_module_idx.h index e788a7ba2..432ab60e7 100644 --- a/module/optee/mbx/test/fwk_module_idx.h +++ b/module/optee/mbx/test/fwk_module_idx.h @@ -12,7 +12,15 @@ enum fwk_module_idx { FWK_MODULE_IDX_OPTEE_MBX, + FWK_MODULE_IDX_MSG_SMT, + FWK_MODULE_IDX_OPTEE_SMT, + FWK_MODULE_IDX_SCMI, FWK_MODULE_IDX_COUNT, }; +static const fwk_id_t fwk_module_id_scmi = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI); + +#define FWK_MODULE_BIND_ROUND_MAX 1 + #endif /* TEST_FWK_MODULE_IDX_H */ diff --git a/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.c b/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.c index 9a252943a..75caf3deb 100644 --- a/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.c +++ b/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.c @@ -7,6 +7,7 @@ static const char* CMockString_m = "m"; static const char* CMockString_mutex_init = "mutex_init"; +static const char* CMockString_mutex_lock = "mutex_lock"; static const char* CMockString_mutex_unlock = "mutex_unlock"; typedef struct _CMOCK_mutex_init_CALL_INSTANCE @@ -22,6 +23,19 @@ typedef struct _CMOCK_mutex_init_CALL_INSTANCE } CMOCK_mutex_init_CALL_INSTANCE; +typedef struct _CMOCK_mutex_lock_CALL_INSTANCE +{ + UNITY_LINE_TYPE LineNumber; + char ExpectAnyArgsBool; + struct mutex* Expected_m; + int Expected_m_Depth; + char ReturnThruPtr_m_Used; + struct mutex* ReturnThruPtr_m_Val; + size_t ReturnThruPtr_m_Size; + char IgnoreArg_m; + +} CMOCK_mutex_lock_CALL_INSTANCE; + typedef struct _CMOCK_mutex_unlock_CALL_INSTANCE { UNITY_LINE_TYPE LineNumber; @@ -42,6 +56,11 @@ static struct Mockmod_optee_mbx_extraInstance CMOCK_mutex_init_CALLBACK mutex_init_CallbackFunctionPointer; int mutex_init_CallbackCalls; CMOCK_MEM_INDEX_TYPE mutex_init_CallInstance; + char mutex_lock_IgnoreBool; + char mutex_lock_CallbackBool; + CMOCK_mutex_lock_CALLBACK mutex_lock_CallbackFunctionPointer; + int mutex_lock_CallbackCalls; + CMOCK_MEM_INDEX_TYPE mutex_lock_CallInstance; char mutex_unlock_IgnoreBool; char mutex_unlock_CallbackBool; CMOCK_mutex_unlock_CALLBACK mutex_unlock_CallbackFunctionPointer; @@ -68,6 +87,19 @@ void Mockmod_optee_mbx_extra_Verify(void) call_instance = CMOCK_GUTS_NONE; (void)call_instance; } + call_instance = Mock.mutex_lock_CallInstance; + if (Mock.mutex_lock_IgnoreBool) + call_instance = CMOCK_GUTS_NONE; + if (CMOCK_GUTS_NONE != call_instance) + { + UNITY_SET_DETAIL(CMockString_mutex_lock); + UNITY_TEST_FAIL(cmock_line, CMockStringCalledLess); + } + if (Mock.mutex_lock_CallbackFunctionPointer != NULL) + { + call_instance = CMOCK_GUTS_NONE; + (void)call_instance; + } call_instance = Mock.mutex_unlock_CallInstance; if (Mock.mutex_unlock_IgnoreBool) call_instance = CMOCK_GUTS_NONE; @@ -227,6 +259,139 @@ void mutex_init_CMockIgnoreArg_m(UNITY_LINE_TYPE cmock_line) cmock_call_instance->IgnoreArg_m = 1; } +void mutex_lock(struct mutex* m) +{ + UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM; + CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance; + UNITY_SET_DETAIL(CMockString_mutex_lock); + cmock_call_instance = (CMOCK_mutex_lock_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.mutex_lock_CallInstance); + Mock.mutex_lock_CallInstance = CMock_Guts_MemNext(Mock.mutex_lock_CallInstance); + if (Mock.mutex_lock_IgnoreBool) + { + UNITY_CLR_DETAILS(); + return; + } + if (!Mock.mutex_lock_CallbackBool && + Mock.mutex_lock_CallbackFunctionPointer != NULL) + { + Mock.mutex_lock_CallbackFunctionPointer(m, Mock.mutex_lock_CallbackCalls++); + UNITY_CLR_DETAILS(); + return; + } + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore); + cmock_line = cmock_call_instance->LineNumber; + if (!cmock_call_instance->ExpectAnyArgsBool) + { + if (!cmock_call_instance->IgnoreArg_m) + { + UNITY_SET_DETAILS(CMockString_mutex_lock,CMockString_m); + if (cmock_call_instance->Expected_m == NULL) + { UNITY_TEST_ASSERT_NULL(m, cmock_line, CMockStringExpNULL); } + else + { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(cmock_call_instance->Expected_m), (void*)(m), sizeof(struct mutex), cmock_call_instance->Expected_m_Depth, cmock_line, CMockStringMismatch); } + } + } + if (Mock.mutex_lock_CallbackFunctionPointer != NULL) + { + Mock.mutex_lock_CallbackFunctionPointer(m, Mock.mutex_lock_CallbackCalls++); + } + if (cmock_call_instance->ReturnThruPtr_m_Used) + { + UNITY_TEST_ASSERT_NOT_NULL(m, cmock_line, CMockStringPtrIsNULL); + memcpy((void*)m, (void*)cmock_call_instance->ReturnThruPtr_m_Val, + cmock_call_instance->ReturnThruPtr_m_Size); + } + UNITY_CLR_DETAILS(); +} + +void CMockExpectParameters_mutex_lock(CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance, struct mutex* m, int m_Depth); +void CMockExpectParameters_mutex_lock(CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance, struct mutex* m, int m_Depth) +{ + cmock_call_instance->Expected_m = m; + cmock_call_instance->Expected_m_Depth = m_Depth; + cmock_call_instance->IgnoreArg_m = 0; + cmock_call_instance->ReturnThruPtr_m_Used = 0; +} + +void mutex_lock_CMockIgnore(void) +{ + Mock.mutex_lock_IgnoreBool = (char)1; +} + +void mutex_lock_CMockStopIgnore(void) +{ + Mock.mutex_lock_IgnoreBool = (char)0; +} + +void mutex_lock_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line) +{ + CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mutex_lock_CALL_INSTANCE)); + CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance = (CMOCK_mutex_lock_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory); + memset(cmock_call_instance, 0, sizeof(*cmock_call_instance)); + Mock.mutex_lock_CallInstance = CMock_Guts_MemChain(Mock.mutex_lock_CallInstance, cmock_guts_index); + Mock.mutex_lock_IgnoreBool = (char)0; + cmock_call_instance->LineNumber = cmock_line; + cmock_call_instance->ExpectAnyArgsBool = (char)0; + cmock_call_instance->ExpectAnyArgsBool = (char)1; +} + +void mutex_lock_CMockExpect(UNITY_LINE_TYPE cmock_line, struct mutex* m) +{ + CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mutex_lock_CALL_INSTANCE)); + CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance = (CMOCK_mutex_lock_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory); + memset(cmock_call_instance, 0, sizeof(*cmock_call_instance)); + Mock.mutex_lock_CallInstance = CMock_Guts_MemChain(Mock.mutex_lock_CallInstance, cmock_guts_index); + Mock.mutex_lock_IgnoreBool = (char)0; + cmock_call_instance->LineNumber = cmock_line; + cmock_call_instance->ExpectAnyArgsBool = (char)0; + CMockExpectParameters_mutex_lock(cmock_call_instance, m, 1); +} + +void mutex_lock_AddCallback(CMOCK_mutex_lock_CALLBACK Callback) +{ + Mock.mutex_lock_IgnoreBool = (char)0; + Mock.mutex_lock_CallbackBool = (char)1; + Mock.mutex_lock_CallbackFunctionPointer = Callback; +} + +void mutex_lock_Stub(CMOCK_mutex_lock_CALLBACK Callback) +{ + Mock.mutex_lock_IgnoreBool = (char)0; + Mock.mutex_lock_CallbackBool = (char)0; + Mock.mutex_lock_CallbackFunctionPointer = Callback; +} + +void mutex_lock_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, struct mutex* m, int m_Depth) +{ + CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mutex_lock_CALL_INSTANCE)); + CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance = (CMOCK_mutex_lock_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory); + memset(cmock_call_instance, 0, sizeof(*cmock_call_instance)); + Mock.mutex_lock_CallInstance = CMock_Guts_MemChain(Mock.mutex_lock_CallInstance, cmock_guts_index); + Mock.mutex_lock_IgnoreBool = (char)0; + cmock_call_instance->LineNumber = cmock_line; + cmock_call_instance->ExpectAnyArgsBool = (char)0; + CMockExpectParameters_mutex_lock(cmock_call_instance, m, m_Depth); +} + +void mutex_lock_CMockReturnMemThruPtr_m(UNITY_LINE_TYPE cmock_line, struct mutex* m, size_t cmock_size) +{ + CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance = (CMOCK_mutex_lock_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.mutex_lock_CallInstance)); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringPtrPreExp); + cmock_call_instance->ReturnThruPtr_m_Used = 1; + cmock_call_instance->ReturnThruPtr_m_Val = m; + cmock_call_instance->ReturnThruPtr_m_Size = cmock_size; +} + +void mutex_lock_CMockIgnoreArg_m(UNITY_LINE_TYPE cmock_line) +{ + CMOCK_mutex_lock_CALL_INSTANCE* cmock_call_instance = (CMOCK_mutex_lock_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.mutex_lock_CallInstance)); + UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp); + cmock_call_instance->IgnoreArg_m = 1; +} + void mutex_unlock(struct mutex* m) { UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM; diff --git a/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.h b/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.h index 31e090318..55d7b0e6b 100644 --- a/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.h +++ b/module/optee/mbx/test/mocks/Mockmod_optee_mbx_extra.h @@ -44,6 +44,26 @@ void mutex_init_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, struct mutex* m void mutex_init_CMockReturnMemThruPtr_m(UNITY_LINE_TYPE cmock_line, struct mutex* m, size_t cmock_size); #define mutex_init_IgnoreArg_m() mutex_init_CMockIgnoreArg_m(__LINE__) void mutex_init_CMockIgnoreArg_m(UNITY_LINE_TYPE cmock_line); +#define mutex_lock_Ignore() mutex_lock_CMockIgnore() +void mutex_lock_CMockIgnore(void); +#define mutex_lock_StopIgnore() mutex_lock_CMockStopIgnore() +void mutex_lock_CMockStopIgnore(void); +#define mutex_lock_ExpectAnyArgs() mutex_lock_CMockExpectAnyArgs(__LINE__) +void mutex_lock_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line); +#define mutex_lock_Expect(m) mutex_lock_CMockExpect(__LINE__, m) +void mutex_lock_CMockExpect(UNITY_LINE_TYPE cmock_line, struct mutex* m); +typedef void (* CMOCK_mutex_lock_CALLBACK)(struct mutex* m, int cmock_num_calls); +void mutex_lock_AddCallback(CMOCK_mutex_lock_CALLBACK Callback); +void mutex_lock_Stub(CMOCK_mutex_lock_CALLBACK Callback); +#define mutex_lock_StubWithCallback mutex_lock_Stub +#define mutex_lock_ExpectWithArray(m, m_Depth) mutex_lock_CMockExpectWithArray(__LINE__, m, m_Depth) +void mutex_lock_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, struct mutex* m, int m_Depth); +#define mutex_lock_ReturnThruPtr_m(m) mutex_lock_CMockReturnMemThruPtr_m(__LINE__, m, sizeof(struct mutex)) +#define mutex_lock_ReturnArrayThruPtr_m(m, cmock_len) mutex_lock_CMockReturnMemThruPtr_m(__LINE__, m, cmock_len * sizeof(*m)) +#define mutex_lock_ReturnMemThruPtr_m(m, cmock_size) mutex_lock_CMockReturnMemThruPtr_m(__LINE__, m, cmock_size) +void mutex_lock_CMockReturnMemThruPtr_m(UNITY_LINE_TYPE cmock_line, struct mutex* m, size_t cmock_size); +#define mutex_lock_IgnoreArg_m() mutex_lock_CMockIgnoreArg_m(__LINE__) +void mutex_lock_CMockIgnoreArg_m(UNITY_LINE_TYPE cmock_line); #define mutex_unlock_Ignore() mutex_unlock_CMockIgnore() void mutex_unlock_CMockIgnore(void); #define mutex_unlock_StopIgnore() mutex_unlock_CMockStopIgnore() diff --git a/module/optee/mbx/test/mod_optee_mbx_extra.h b/module/optee/mbx/test/mod_optee_mbx_extra.h index addfbc1b2..388e5e6aa 100644 --- a/module/optee/mbx/test/mod_optee_mbx_extra.h +++ b/module/optee/mbx/test/mod_optee_mbx_extra.h @@ -18,4 +18,5 @@ #include void mutex_init(struct mutex *m); +void mutex_lock(struct mutex *m); void mutex_unlock(struct mutex *m); diff --git a/module/optee/mbx/test/mod_optee_mbx_unit_test.c b/module/optee/mbx/test/mod_optee_mbx_unit_test.c index 113fedf02..323c274f7 100644 --- a/module/optee/mbx/test/mod_optee_mbx_unit_test.c +++ b/module/optee/mbx/test/mod_optee_mbx_unit_test.c @@ -13,11 +13,14 @@ #include #include +#include +#include #include #include #include UNIT_TEST_SRC +#include "config_optee_mbx.h" void setUp(void) { @@ -27,10 +30,369 @@ void tearDown(void) { } +struct mbx_device_ctx fake_optee_mbx_ctx[FAKE_SCMI_SERVICE_IDX_COUNT]; + +/*! + * \brief test module's init function. + * + * \details Test all possible cases for init. + */ +void test_optee_mbx_init(void) +{ + int status; + fwk_id_t init_id; + + init_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_MBX); + + /* Element count can't be null */ + status = mbx_init(init_id, 0, NULL); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Fail to allocate module cxt */ + fwk_mm_calloc_ExpectAndReturn( + 1, + sizeof(struct mbx_device_ctx), + NULL); + status = mbx_init(init_id, FAKE_SCMI_SERVICE_IDX_COUNT, NULL); + TEST_ASSERT_EQUAL(FWK_E_NOMEM, status); + + /* Allocate module context */ + fwk_mm_calloc_ExpectAndReturn( + FAKE_SCMI_SERVICE_IDX_COUNT, + sizeof(struct mbx_device_ctx), + fake_optee_mbx_ctx); + status = mbx_init(init_id, FAKE_SCMI_SERVICE_IDX_COUNT, NULL); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(mbx_ctx.device_ctx_table, fake_optee_mbx_ctx); +} + +/*! + * \brief test module's element_init function. + * + * \details Test all possible cases for element_init. + */ +void test_optee_mbx_device_init(void) +{ + int status; + fwk_id_t device_id; + struct mod_optee_mbx_channel_config *device_config; + + /* Set fake config data */ + device_config = + (struct mod_optee_mbx_channel_config *)mbx_element_table[FAKE_SCMI_SERVICE_IDX_OSPM_0] + .data; + + /* Successfully init element */ + device_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(device_id, 0); + mutex_init_ExpectAnyArgs(); + status = mbx_device_init(device_id, 0, device_config); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test module's bind fucntion for round 0. + * + * \details Test bind for round 0 and others except for round 1 when it needs + * additional information from bind_request of other modules. + */ +void test_optee_mbx_bind_round0(void) +{ + int status; + fwk_id_t bind_id; + unsigned int i; + + /* + * Bind module always succeed because there is nothing to do ... + * Take the opportunity to test all possible rounds in one shot because + * it's a nop. + */ + bind_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_MBX); + for (i = 0; i <= FWK_MODULE_BIND_ROUND_MAX; i++) { + fwk_id_is_type_ExpectAndReturn(bind_id, FWK_ID_TYPE_MODULE, true); + status = mbx_bind(bind_id, i); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + } + + /* + * Similarly, bind something than module at any round except round 1 always + * succeed ! + */ + bind_id = FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, + FAKE_SCMI_SERVICE_IDX_OSPM_0, 0); + fwk_id_is_type_ExpectAndReturn(bind_id, FWK_ID_TYPE_MODULE, false); + status = mbx_bind(bind_id, 0); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + + bind_id = FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, + FAKE_SCMI_SERVICE_IDX_OSPM_0, 0); + fwk_id_is_type_ExpectAndReturn(bind_id, FWK_ID_TYPE_MODULE, false); + status = mbx_bind(bind_id, FWK_MODULE_BIND_ROUND_MAX+1); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test module's bind_request function. + * + * \details Test all possible cases for bind_request function. + */ +void test_optee_mbx_bind_request(void) +{ + int status; + fwk_id_t source_id; + fwk_id_t target_id; + fwk_id_t api_id; + void *test_driver_input_api; + + source_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MSG_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 0)); + + /* Bind to something else than an element always fails */ + target_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_MBX); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, false); + status = mbx_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_ACCESS, status); + + /* Bind to an out of range api i.e. != 0 */ + target_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 1)); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_api_idx_ExpectAndReturn(api_id, 1); + status = mbx_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Bind to an out of range element */ + target_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT); + api_id = ((fwk_id_t) FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 0)); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_api_idx_ExpectAndReturn(api_id, 0); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT); + status = mbx_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Bind to unknown source module */ + target_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + source_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SCMI, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_api_idx_ExpectAndReturn(api_id, 0); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_module_idx_ExpectAndReturn(source_id, FWK_MODULE_IDX_SCMI); + status = mbx_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_E_PANIC, status); + + /* Bind to optee msg source module */ + source_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_api_idx_ExpectAndReturn(api_id, 0); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_module_idx_ExpectAndReturn(source_id, FWK_MODULE_IDX_OPTEE_SMT); + status = mbx_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(&mbx_smt_api, test_driver_input_api); + + /* Bind to shared msg source module */ + source_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MSG_SMT, FAKE_SCMI_SERVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(target_id, FWK_ID_TYPE_ELEMENT, true); + fwk_id_get_api_idx_ExpectAndReturn(api_id, 0); + fwk_id_get_element_idx_ExpectAndReturn(target_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_module_idx_ExpectAndReturn(source_id, FWK_MODULE_IDX_MSG_SMT); + status = mbx_process_bind_request(source_id, target_id, api_id, (const void **)&test_driver_input_api); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(&mbx_shm_api, test_driver_input_api); +} + +/*! + * \brief test module's bind function for element during round 1. + * + * \details Test bind of elements for round 1. + */ +void test_optee_mbx_bind_round1(void) +{ + int status; + fwk_id_t element_id; + struct mbx_device_ctx *device_ctx; + device_ctx = &mbx_ctx.device_ctx_table[FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0]; + + /* Fail to bind at round 1 */ + element_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_module_bind_ExpectAndReturn( + device_ctx->config->driver_id, + device_ctx->config->driver_api_id, + &device_ctx->shmem_api, + FWK_E_PARAM); + status = mbx_bind(element_id, 1); + TEST_ASSERT_EQUAL(FWK_E_PARAM, status); + + /* Succeed to bind at round 1 */ + element_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_is_type_ExpectAndReturn(element_id, FWK_ID_TYPE_MODULE, false); + fwk_id_get_element_idx_ExpectAndReturn(element_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_module_bind_ExpectAndReturn( + device_ctx->config->driver_id, + device_ctx->config->driver_api_id, + &device_ctx->shmem_api, + FWK_SUCCESS); + status = mbx_bind(element_id, 1); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + TEST_ASSERT_EQUAL(device_ctx->shmem_id.value, device_ctx->config->driver_id.value); +} + +/*! + * \brief test module's start function. + * + * \details Test all cases for start function. + */ +void test_optee_mbx_start(void) +{ + int status; + fwk_id_t module_id; + + /* Start always succeed */ + module_id = FWK_ID_MODULE(FWK_MODULE_IDX_OPTEE_MBX); + status = mbx_start(module_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +/*! + * \brief test optee_mbx_get_devices_count function. + * + * \details Test all cases for optee_mbx_get_devices_count function. + */ +void test_optee_mbx_get_devices_count(void) +{ + int status; + + status = optee_mbx_get_devices_count(); + TEST_ASSERT_EQUAL(FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT, status); +} + +/*! + * \brief test optee_mbx_get_device function. + * + * \details Test all cases for optee_mbx_get_device function. + */ +void test_optee_mbx_get_device(void) +{ + fwk_id_t device_id, returned_id; + unsigned int id; + + /* Fail to get out of range index */ + id = FAKE_SCMI_CHANNEL_DEVICE_IDX_COUNT; + device_id = optee_mbx_get_device(id); + returned_id = (fwk_id_t)FWK_ID_NONE_INIT; + TEST_ASSERT_EQUAL(returned_id.value, device_id.value); + + /* Succeed to get a device */ + id = FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0; + device_id = optee_mbx_get_device(id); + returned_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, id); + TEST_ASSERT_EQUAL(returned_id.value, device_id.value); +} + +static int optee_signal_message(fwk_id_t channel_id) +{ + return FWK_SUCCESS; +} + +static struct mod_optee_smt_driver_input_api optee_smt_input_api = { + .signal_message = optee_signal_message, +}; + +/*! + * \brief test optee mbx with static memory. + * + * \details Test all cases for ignaling a message to a static memory. + */ +void test_optee_mbx_use_optee_smt_device(void) +{ + int status; + fwk_id_t device_id; + struct mbx_device_ctx *device_ctx; + device_ctx = &mbx_ctx.device_ctx_table[FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0]; + device_ctx->shmem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_SMT, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + device_ctx->shmem_api.smt = &optee_smt_input_api; + + /* Signal a message to static memory device */ + device_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(device_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_module_idx_ExpectAndReturn(device_ctx->shmem_id, FWK_MODULE_IDX_OPTEE_SMT); + mutex_lock_ExpectAnyArgs(); + optee_mbx_signal_smt_message(device_id); + + /* Get back from static memory devoce */ + fwk_id_get_element_idx_ExpectAndReturn(device_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + mutex_unlock_ExpectAnyArgs(); + status = raise_smt_interrupt(device_id); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); +} + +int msg_signal_message(fwk_id_t channel_id, void *msg_in, size_t in_len, void *msg_out, size_t out_len) +{ + return FWK_SUCCESS; +} + +static struct mod_msg_smt_driver_input_api msg_smt_input_api = { + .signal_message = msg_signal_message, +}; + +/*! + * \brief test optee mbx with dynamic memory. + * + * \details Test all cases for signaling a message to a dynamic memory. + */ +void test_optee_mbx_use_msg_smt_device(void) +{ + int status; + fwk_id_t device_id; + struct mbx_device_ctx *device_ctx; + void *msg_in = (void *)0xDEADBEEF, *msg_out = (void *)0xDEADBEEF; + size_t in_len = 55, out_len = 66; + + device_ctx = &mbx_ctx.device_ctx_table[FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0]; + device_ctx->shmem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MSG_SMT, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + device_ctx->shmem_api.msg = &msg_smt_input_api; + + /* Signal a message to dynamic memory device */ + device_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_MBX, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_element_idx_ExpectAndReturn(device_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + fwk_id_get_module_idx_ExpectAndReturn(device_ctx->shmem_id, FWK_MODULE_IDX_MSG_SMT); + mutex_lock_ExpectAnyArgs(); + optee_mbx_signal_msg_message(device_id, msg_in, in_len, msg_out, &out_len); + + /* Get back from dynamic memory device */ + fwk_id_get_element_idx_ExpectAndReturn(device_id, FAKE_SCMI_CHANNEL_DEVICE_IDX_OSPM_0); + mutex_unlock_ExpectAnyArgs(); + status = raise_shm_notification(device_id, out_len); + TEST_ASSERT_EQUAL(FWK_SUCCESS, status); + +} + int optee_mbx_test_main(void) { UNITY_BEGIN(); + RUN_TEST(test_optee_mbx_init); + + RUN_TEST(test_optee_mbx_device_init); + + RUN_TEST(test_optee_mbx_bind_round0); + + RUN_TEST(test_optee_mbx_bind_request); + + RUN_TEST(test_optee_mbx_bind_round1); + + RUN_TEST(test_optee_mbx_start); + + RUN_TEST(test_optee_mbx_get_devices_count); + + RUN_TEST(test_optee_mbx_get_device); + + RUN_TEST(test_optee_mbx_use_optee_smt_device); + + RUN_TEST(test_optee_mbx_use_msg_smt_device); + return UNITY_END(); } -- GitLab