// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #ifdef __cplusplus #include #include #include #include #else #include #include #include #include #include #endif #if defined _MSC_VER #pragma warning(disable: 4054) /* MSC incorrectly fires this */ #endif void* real_malloc(size_t size) { return malloc(size); } void real_free(void* ptr) { free(ptr); } #include "testrunnerswitcher.h" #include "umock_c/umock_c.h" #include "umock_c/umock_c_negative_tests.h" #include "umock_c/umocktypes_charptr.h" #include "umock_c/umocktypes_stdint.h" #include "umock_c/umocktypes_bool.h" #include "umock_c/umocktypes.h" #include "umock_c/umocktypes_c.h" #include #define ENABLE_MOCKS #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/optionhandler.h" #include "azure_c_shared_utility/agenttime.h" #include "azure_c_shared_utility/singlylinkedlist.h" #undef ENABLE_MOCKS #include "internal/message_queue.h" static TEST_MUTEX_HANDLE g_testByTest; MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) { char temp_str[256]; (void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", MU_ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code)); ASSERT_FAIL(temp_str); } // Data definitions #define INDEFINITE_TIME ((time_t)-1) #define TEST_OPTIONHANDLER_HANDLE (OPTIONHANDLER_HANDLE)0x7771 #define TEST_PROCESS_MESSAGE_CONTEXT (void*)0x7772 #define TEST_PROCESS_COMPLETE_CONTEXT (void*)0x7773 #define TEST_USER_CONTEXT (void*)0x7773 #define USE_DEFAULT_CONFIG NULL #define TEST_SOME_OTHER_MESSAGE_ID 17777 #define TEST_MQ_MESSAGE_HANDLE_2 (MQ_MESSAGE_HANDLE)0x7778 #define TEST_LIST_ITEM_HANDLE (LIST_ITEM_HANDLE)0x7779 #define TEST_LIST_ITEM_VALUE (void*)0x7780 #define TEST_REASON (void*)0x7781 static MQ_MESSAGE_HANDLE TEST_BASE_MQ_MESSAGE_HANDLE[10]; static time_t TEST_current_time; typedef struct TEST_MESSAGE_EXPIRATION_PROFILE_TAG { double max_message_enqueued_time_secs; double max_message_processing_time_secs; size_t* expired_pending_messages; size_t expired_pending_messages_size; size_t* expired_enqueued_in_progress_messages; size_t expired_enqueued_in_progress_messages_size; size_t* expired_in_progress_messages; size_t expired_in_progress_messages_size; } TEST_MESSAGE_EXPIRATION_PROFILE; static TEST_MESSAGE_EXPIRATION_PROFILE TEST_test_message_expiration_profile; // Helpers static int saved_malloc_returns_count = 0; static void* saved_malloc_returns[20]; static void* TEST_malloc(size_t size) { saved_malloc_returns[saved_malloc_returns_count] = real_malloc(size); return saved_malloc_returns[saved_malloc_returns_count++]; } static void TEST_free(void* ptr) { int i, j; for (i = 0, j = 0; j < saved_malloc_returns_count; i++, j++) { if (saved_malloc_returns[i] == ptr) j++; saved_malloc_returns[i] = saved_malloc_returns[j]; } if (i != j) saved_malloc_returns_count--; real_free(ptr); } static unsigned int TEST_OptionHandler_AddOption_saved_value; static OPTIONHANDLER_RESULT TEST_OptionHandler_AddOption_result; static OPTIONHANDLER_RESULT TEST_OptionHandler_AddOption(OPTIONHANDLER_HANDLE handle, const char* name, const void* value) { (void)handle; (void)name; TEST_OptionHandler_AddOption_saved_value = *(const unsigned int*)value; return TEST_OptionHandler_AddOption_result; } #ifdef __cplusplus extern "C" { #endif SINGLYLINKEDLIST_HANDLE real_singlylinkedlist_create(void); void real_singlylinkedlist_destroy(SINGLYLINKEDLIST_HANDLE list); LIST_ITEM_HANDLE real_singlylinkedlist_add(SINGLYLINKEDLIST_HANDLE list, const void* item); int real_singlylinkedlist_remove(SINGLYLINKEDLIST_HANDLE list, LIST_ITEM_HANDLE item_handle); LIST_ITEM_HANDLE real_singlylinkedlist_get_head_item(SINGLYLINKEDLIST_HANDLE list); LIST_ITEM_HANDLE real_singlylinkedlist_get_next_item(LIST_ITEM_HANDLE item_handle); LIST_ITEM_HANDLE real_singlylinkedlist_find(SINGLYLINKEDLIST_HANDLE list, LIST_MATCH_FUNCTION match_function, const void* match_context); const void* real_singlylinkedlist_item_get_value(LIST_ITEM_HANDLE item_handle); #ifdef __cplusplus } #endif static time_t add_seconds(time_t base_time, int seconds) { time_t new_time; struct tm *bd_new_time; if ((bd_new_time = localtime(&base_time)) == NULL) { new_time = INDEFINITE_TIME; } else { bd_new_time->tm_sec += seconds; new_time = mktime(bd_new_time); } return new_time; } static MESSAGE_QUEUE_HANDLE TEST_on_process_message_callback_message_queue; static MQ_MESSAGE_HANDLE TEST_on_process_message_callback_message; static uint32_t TEST_on_process_message_callback_message_id; static PROCESS_MESSAGE_COMPLETED_CALLBACK TEST_on_process_message_callback_on_process_message_completed_callback; static void* TEST_on_process_message_callback_context; static void TEST_on_process_message_callback(MESSAGE_QUEUE_HANDLE message_queue, MQ_MESSAGE_HANDLE message, uint32_t message_id, PROCESS_MESSAGE_COMPLETED_CALLBACK on_process_message_completed_callback, void* user_context) { TEST_on_process_message_callback_message_queue = message_queue; TEST_on_process_message_callback_message = message; TEST_on_process_message_callback_message_id = message_id; TEST_on_process_message_callback_on_process_message_completed_callback = on_process_message_completed_callback; TEST_on_process_message_callback_context = user_context; } static MQ_MESSAGE_HANDLE TEST_on_message_processing_completed_callback_message; static MESSAGE_QUEUE_RESULT TEST_on_message_processing_completed_callback_result; static void* TEST_on_message_processing_completed_callback_reason; static void* TEST_on_message_processing_completed_callback_context; static size_t TEST_on_message_processing_completed_callback_SUCCESS_result_count; static size_t TEST_on_message_processing_completed_callback_CANCELLED_result_count; static size_t TEST_on_message_processing_completed_callback_ERROR_result_count; static size_t TEST_on_message_processing_completed_callback_TIMEOUT_result_count; static void TEST_on_message_processing_completed_callback(MQ_MESSAGE_HANDLE message, MESSAGE_QUEUE_RESULT result, void* reason, void* context) { TEST_on_message_processing_completed_callback_message = message; TEST_on_message_processing_completed_callback_result = result; TEST_on_message_processing_completed_callback_reason = reason; TEST_on_message_processing_completed_callback_context = context; if (result == MESSAGE_QUEUE_SUCCESS) { TEST_on_message_processing_completed_callback_SUCCESS_result_count++; } else if (result == MESSAGE_QUEUE_CANCELLED) { TEST_on_message_processing_completed_callback_CANCELLED_result_count++; } else if (result == MESSAGE_QUEUE_ERROR) { TEST_on_message_processing_completed_callback_ERROR_result_count++; } else if (result == MESSAGE_QUEUE_TIMEOUT) { TEST_on_message_processing_completed_callback_TIMEOUT_result_count++; } } static MESSAGE_QUEUE_CONFIG g_config; static MESSAGE_QUEUE_CONFIG* get_message_queue_config() { g_config.max_message_enqueued_time_secs = 0; g_config.max_message_processing_time_secs = 0; g_config.max_retry_count = 0; g_config.on_process_message_callback = TEST_on_process_message_callback; return &g_config; } static void set_message_queue_create_expected_calls() { STRICT_EXPECTED_CALL(malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_create()); STRICT_EXPECTED_CALL(singlylinkedlist_create()); } static void set_dequeue_message_and_fire_callback_expected_calls() { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_remove(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG)); } static void set_retry_sending_message_expected_calls() { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_remove(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); } static void set_on_message_processing_completed_callback_expected_calls(int number_of_messages, int message_order_in_list, bool should_retry) { int i; STRICT_EXPECTED_CALL(singlylinkedlist_find(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); for (i = 0; i < number_of_messages; i++) { // Invoked by singlylinkedlist_find. STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); if (i == message_order_in_list) break; } if (i == message_order_in_list) { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); if (should_retry) { set_retry_sending_message_expected_calls(); } else { set_dequeue_message_and_fire_callback_expected_calls(); } } } static void set_message_queue_remove_all_expected_calls(size_t number_of_messages_pending, size_t number_of_messages_in_progress) { size_t i; STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (i = 0; i < number_of_messages_pending; i++) { set_dequeue_message_and_fire_callback_expected_calls(); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (i = 0; i < number_of_messages_in_progress; i++) { set_dequeue_message_and_fire_callback_expected_calls(); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); } } static void set_message_queue_destroy_expected_calls(size_t number_of_messages_pending, size_t number_of_messages_in_progress) { set_message_queue_remove_all_expected_calls(number_of_messages_pending, number_of_messages_in_progress); STRICT_EXPECTED_CALL(singlylinkedlist_destroy(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_destroy(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG)); } static void set_message_queue_add_expected_calls(time_t current_time) { STRICT_EXPECTED_CALL(malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(current_time); STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); } static void add_messages(MESSAGE_QUEUE_HANDLE mq, size_t number_of_messages, time_t current_time) { size_t i; for (i = 0; i < number_of_messages; i++) { umock_c_reset_all_calls(); set_message_queue_add_expected_calls(current_time); int result = message_queue_add(mq, TEST_BASE_MQ_MESSAGE_HANDLE[i], TEST_on_message_processing_completed_callback, TEST_USER_CONTEXT); ASSERT_ARE_EQUAL(int, 0, result, "failed adding message to queue"); } } static MESSAGE_QUEUE_HANDLE create_message_queue(MESSAGE_QUEUE_CONFIG* config) { if (config == USE_DEFAULT_CONFIG) { config = get_message_queue_config(); } umock_c_reset_all_calls(); set_message_queue_create_expected_calls(); return message_queue_create(config); } static void set_process_timeouts_expected_calls(MESSAGE_QUEUE_HANDLE mq, time_t current_time, size_t number_of_messages_pending, size_t number_of_messages_in_progress, TEST_MESSAGE_EXPIRATION_PROFILE* expiration_profile ) { (void)mq; STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(current_time); if (expiration_profile->max_message_enqueued_time_secs > 0) { size_t i, j; // pending messages, max queued time STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (i = 0, j = 0; i < number_of_messages_pending; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)); if (j < expiration_profile->expired_pending_messages_size && i == expiration_profile->expired_pending_messages[j]) { STRICT_EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG)).SetReturn(expiration_profile->max_message_enqueued_time_secs + 1); set_dequeue_message_and_fire_callback_expected_calls(); number_of_messages_pending--; j++; } else { STRICT_EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG)).SetReturn(0); break; } } // in progress messages, max queued time STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (i = 0, j = 0; i < number_of_messages_in_progress; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)); if (j < expiration_profile->expired_enqueued_in_progress_messages_size && i == expiration_profile->expired_enqueued_in_progress_messages[j]) { STRICT_EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG)).SetReturn(expiration_profile->max_message_enqueued_time_secs + 1); set_dequeue_message_and_fire_callback_expected_calls(); //set_dequeue_message_and_fire_callback_expected_calls(number_of_messages_in_progress, expiration_profile->expired_enqueued_in_progress_messages[j] - i, false); number_of_messages_in_progress--; j++; } else { STRICT_EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG)).SetReturn(0); } } } if (expiration_profile->max_message_processing_time_secs > 0) { size_t i, j; // in progress messages, max in progress time STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (i = 0, j = 0; i < number_of_messages_in_progress; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG)); if (j < expiration_profile->expired_in_progress_messages_size && i == expiration_profile->expired_in_progress_messages[j]) { STRICT_EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG)).SetReturn(expiration_profile->max_message_processing_time_secs + 1); set_dequeue_message_and_fire_callback_expected_calls(); number_of_messages_in_progress--; j++; } else { STRICT_EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG)).SetReturn(0); break; } } } } static void set_process_pending_messages_calls(MESSAGE_QUEUE_HANDLE mq, time_t current_time, size_t number_of_messages_pending) { (void)mq; STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); size_t i; for (i = 0; i < number_of_messages_pending; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_remove(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(current_time); STRICT_EXPECTED_CALL(singlylinkedlist_add(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); } } static void set_message_queue_do_work_expected_calls(MESSAGE_QUEUE_HANDLE mq, time_t current_time, size_t number_of_messages_pending, size_t number_of_messages_in_progress, TEST_MESSAGE_EXPIRATION_PROFILE* expiration_profile) { set_process_timeouts_expected_calls(mq, current_time, number_of_messages_pending, number_of_messages_in_progress, expiration_profile); set_process_pending_messages_calls(mq, current_time, number_of_messages_pending); } static void crank_message_queue(MESSAGE_QUEUE_HANDLE mq, time_t current_time, size_t number_of_messages_pending, size_t number_of_messages_in_progress, TEST_MESSAGE_EXPIRATION_PROFILE* expiration_profile) { if (expiration_profile == NULL) { expiration_profile = &TEST_test_message_expiration_profile; } umock_c_reset_all_calls(); set_message_queue_do_work_expected_calls(mq, current_time, number_of_messages_pending, number_of_messages_in_progress, expiration_profile); message_queue_do_work(mq); } static void set_message_queue_is_empty_expected_calls(size_t number_of_messages_pending, size_t number_of_messages_in_progress) { (void)number_of_messages_in_progress; STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); if (number_of_messages_pending == 0) // this statement will only be evaluated if the first boolean check (in code) succeeds. { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); } } static void set_message_queue_retrieve_options_expected_calls() { STRICT_EXPECTED_CALL(OptionHandler_Create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(OptionHandler_AddOption(TEST_OPTIONHANDLER_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(OptionHandler_AddOption(TEST_OPTIONHANDLER_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(OptionHandler_AddOption(TEST_OPTIONHANDLER_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); } static void reset_test_data() { TEST_current_time = time(NULL); saved_malloc_returns_count = 0; memset(saved_malloc_returns, 0, sizeof(saved_malloc_returns)); TEST_OptionHandler_AddOption_saved_value = 0; TEST_OptionHandler_AddOption_result = OPTIONHANDLER_OK; TEST_on_process_message_callback_message_queue = NULL; TEST_on_process_message_callback_message = NULL; TEST_on_process_message_callback_on_process_message_completed_callback = NULL; TEST_on_process_message_callback_context = NULL; TEST_on_message_processing_completed_callback_message = NULL; TEST_on_message_processing_completed_callback_result = MESSAGE_QUEUE_SUCCESS; TEST_on_message_processing_completed_callback_reason = NULL; TEST_on_message_processing_completed_callback_context = NULL; TEST_on_message_processing_completed_callback_SUCCESS_result_count = 0; TEST_on_message_processing_completed_callback_CANCELLED_result_count = 0; TEST_on_message_processing_completed_callback_ERROR_result_count = 0; TEST_on_message_processing_completed_callback_TIMEOUT_result_count = 0; TEST_test_message_expiration_profile.expired_enqueued_in_progress_messages = NULL; TEST_test_message_expiration_profile.expired_enqueued_in_progress_messages_size = 0; TEST_test_message_expiration_profile.expired_in_progress_messages = NULL; TEST_test_message_expiration_profile.expired_in_progress_messages_size = 0; TEST_test_message_expiration_profile.expired_pending_messages = NULL; TEST_test_message_expiration_profile.expired_pending_messages_size = 0; TEST_test_message_expiration_profile.max_message_enqueued_time_secs = 0; TEST_test_message_expiration_profile.max_message_processing_time_secs = 0; } static void register_umock_alias_types() { REGISTER_UMOCK_ALIAS_TYPE(time_t, long long); REGISTER_UMOCK_ALIAS_TYPE(OPTIONHANDLER_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(OPTIONHANDLER_RESULT, int); REGISTER_UMOCK_ALIAS_TYPE(pfCloneOption, void*); REGISTER_UMOCK_ALIAS_TYPE(pfDestroyOption, void*); REGISTER_UMOCK_ALIAS_TYPE(pfSetOption, void*); REGISTER_UMOCK_ALIAS_TYPE(SINGLYLINKEDLIST_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(LIST_ITEM_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(LIST_MATCH_FUNCTION, void*); REGISTER_UMOCK_ALIAS_TYPE(MQ_MESSAGE_HANDLE, void*); } static void register_global_mock_hooks() { REGISTER_GLOBAL_MOCK_HOOK(malloc, TEST_malloc); REGISTER_GLOBAL_MOCK_HOOK(free, TEST_free); REGISTER_GLOBAL_MOCK_HOOK(OptionHandler_AddOption, TEST_OptionHandler_AddOption); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_create, real_singlylinkedlist_create); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_destroy, real_singlylinkedlist_destroy); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_add, real_singlylinkedlist_add); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_remove, real_singlylinkedlist_remove); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_get_head_item, real_singlylinkedlist_get_head_item); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_get_next_item, real_singlylinkedlist_get_next_item); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_find, real_singlylinkedlist_find); REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_item_get_value, real_singlylinkedlist_item_get_value); } static void register_global_mock_returns() { REGISTER_GLOBAL_MOCK_RETURN(OptionHandler_Create, TEST_OPTIONHANDLER_HANDLE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(OptionHandler_Create, NULL); REGISTER_GLOBAL_MOCK_RETURN(OptionHandler_AddOption, OPTIONHANDLER_OK); REGISTER_GLOBAL_MOCK_FAIL_RETURN(OptionHandler_AddOption, OPTIONHANDLER_ERROR); REGISTER_GLOBAL_MOCK_RETURN(OptionHandler_FeedOptions, OPTIONHANDLER_OK); REGISTER_GLOBAL_MOCK_FAIL_RETURN(OptionHandler_FeedOptions, OPTIONHANDLER_ERROR); REGISTER_GLOBAL_MOCK_RETURN(singlylinkedlist_add, TEST_LIST_ITEM_HANDLE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(singlylinkedlist_add, NULL); REGISTER_GLOBAL_MOCK_RETURN(singlylinkedlist_remove, 0); REGISTER_GLOBAL_MOCK_FAIL_RETURN(singlylinkedlist_remove, 1); REGISTER_GLOBAL_MOCK_RETURN(singlylinkedlist_get_head_item, TEST_LIST_ITEM_HANDLE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(singlylinkedlist_get_head_item, NULL); REGISTER_GLOBAL_MOCK_RETURN(singlylinkedlist_item_get_value, TEST_LIST_ITEM_VALUE); REGISTER_GLOBAL_MOCK_FAIL_RETURN(singlylinkedlist_item_get_value, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(get_time, INDEFINITE_TIME); } BEGIN_TEST_SUITE(message_queue_ut) TEST_SUITE_INITIALIZE(TestClassInitialize) { size_t i; g_testByTest = TEST_MUTEX_CREATE(); ASSERT_IS_NOT_NULL(g_testByTest); umock_c_init(on_umock_c_error); int result = umocktypes_charptr_register_types(); ASSERT_ARE_EQUAL(int, 0, result); result = umocktypes_stdint_register_types(); ASSERT_ARE_EQUAL(int, 0, result); result = umocktypes_bool_register_types(); ASSERT_ARE_EQUAL(int, 0, result); register_umock_alias_types(); register_global_mock_returns(); register_global_mock_hooks(); for (i = 0; i < 10; i++) { TEST_BASE_MQ_MESSAGE_HANDLE[i] = (MQ_MESSAGE_HANDLE)real_malloc(sizeof(char)); ASSERT_IS_NOT_NULL(TEST_BASE_MQ_MESSAGE_HANDLE[i], "Failed setting up TEST_BASE_MQ_MESSAGE_HANDLE"); } } TEST_SUITE_CLEANUP(TestClassCleanup) { size_t i; umock_c_deinit(); TEST_MUTEX_DESTROY(g_testByTest); for (i = 0; i < 10; i++) { real_free(TEST_BASE_MQ_MESSAGE_HANDLE[i]); } } TEST_FUNCTION_INITIALIZE(TestMethodInitialize) { if (TEST_MUTEX_ACQUIRE(g_testByTest)) { ASSERT_FAIL("our mutex is ABANDONED. Failure in test framework"); } umock_c_reset_all_calls(); umock_c_negative_tests_deinit(); reset_test_data(); } TEST_FUNCTION_CLEANUP(TestMethodCleanup) { reset_test_data(); TEST_MUTEX_RELEASE(g_testByTest); } TEST_FUNCTION(create_NULL_config) { // arrange umock_c_reset_all_calls(); // act MESSAGE_QUEUE_HANDLE mq = message_queue_create(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NULL(mq); // cleanup } TEST_FUNCTION(create_NULL_on_process_message_callback) { // arrange MESSAGE_QUEUE_CONFIG* config = get_message_queue_config(); config->on_process_message_callback = NULL; umock_c_reset_all_calls(); // act MESSAGE_QUEUE_HANDLE mq = message_queue_create(config); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NULL(mq); // cleanup } TEST_FUNCTION(create_failure_checks) { // arrange ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); umock_c_reset_all_calls(); set_message_queue_create_expected_calls(); umock_c_negative_tests_snapshot(); size_t i; for (i = 0; i < umock_c_negative_tests_call_count(); i++) { // arrange char error_msg[128]; sprintf(error_msg, "On failed call %lu", (unsigned long)i); umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); // act MESSAGE_QUEUE_CONFIG* config = get_message_queue_config(); MESSAGE_QUEUE_HANDLE mq = message_queue_create(config); // assert ASSERT_IS_NULL(mq, error_msg); } // cleanup umock_c_negative_tests_deinit(); } TEST_FUNCTION(create_success) { // arrange MESSAGE_QUEUE_CONFIG* config = get_message_queue_config(); umock_c_reset_all_calls(); set_message_queue_create_expected_calls(); // act MESSAGE_QUEUE_HANDLE mq = message_queue_create(config); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NOT_NULL(mq); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(destroy_NULL_handle) { // arrange umock_c_reset_all_calls(); // act message_queue_destroy(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup } TEST_FUNCTION(destroy_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); add_messages(mq, 1, TEST_current_time); umock_c_reset_all_calls(); set_message_queue_destroy_expected_calls(1, 1); // act message_queue_destroy(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup } TEST_FUNCTION(remove_all_NULL_handle) { // arrange umock_c_reset_all_calls(); // act message_queue_remove_all(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup } TEST_FUNCTION(remove_all_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); add_messages(mq, 1, TEST_current_time); umock_c_reset_all_calls(); set_message_queue_remove_all_expected_calls(1, 1); // act message_queue_remove_all(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 2, TEST_on_message_processing_completed_callback_CANCELLED_result_count); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(add_NULL_mq_handle) { // arrange umock_c_reset_all_calls(); // act int result = message_queue_add(NULL, TEST_BASE_MQ_MESSAGE_HANDLE[0], TEST_on_message_processing_completed_callback, TEST_USER_CONTEXT); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } TEST_FUNCTION(add_NULL_message_handle) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); // act int result = message_queue_add(mq, NULL, TEST_on_message_processing_completed_callback, TEST_USER_CONTEXT); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(add_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); set_message_queue_add_expected_calls(TEST_current_time); // act int result = message_queue_add(mq, TEST_BASE_MQ_MESSAGE_HANDLE[0], TEST_on_message_processing_completed_callback, TEST_USER_CONTEXT); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(add_failure_checks) { // arrange ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); set_message_queue_add_expected_calls(TEST_current_time); umock_c_negative_tests_snapshot(); size_t i; for (i = 0; i < umock_c_negative_tests_call_count(); i++) { // arrange char error_msg[128]; sprintf(error_msg, "On failed call %lu", (unsigned long)i); umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); // act int result = message_queue_add(mq, TEST_BASE_MQ_MESSAGE_HANDLE[0], TEST_on_message_processing_completed_callback, TEST_USER_CONTEXT); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result, error_msg); } // cleanup umock_c_negative_tests_deinit(); message_queue_destroy(mq); } TEST_FUNCTION(is_empty_NULL_handle) { // arrange umock_c_reset_all_calls(); // act bool is_empty; int result = message_queue_is_empty(NULL, &is_empty); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } TEST_FUNCTION(is_empty_NULL_is_empty) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); // act int result = message_queue_is_empty(mq, NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(is_empty_0_pending_0_in_progress_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); set_message_queue_is_empty_expected_calls(0, 0); // act bool is_empty; int result = message_queue_is_empty(mq, &is_empty); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); ASSERT_IS_TRUE(is_empty); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(is_empty_1_pending_0_in_progress_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); umock_c_reset_all_calls(); set_message_queue_is_empty_expected_calls(1, 0); // act bool is_empty; int result = message_queue_is_empty(mq, &is_empty); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); ASSERT_IS_FALSE(is_empty); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(is_empty_0_pending_1_in_progress_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); umock_c_reset_all_calls(); set_message_queue_is_empty_expected_calls(0, 1); // act bool is_empty; int result = message_queue_is_empty(mq, &is_empty); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); ASSERT_IS_FALSE(is_empty); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(is_empty_1_pending_1_in_progress_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); add_messages(mq, 1, TEST_current_time); umock_c_reset_all_calls(); set_message_queue_is_empty_expected_calls(1, 1); // act bool is_empty; int result = message_queue_is_empty(mq, &is_empty); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); ASSERT_IS_FALSE(is_empty); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(do_work_NULL_handle) { // arrange umock_c_reset_all_calls(); // act message_queue_do_work(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup } TEST_FUNCTION(do_work_NO_EXPIRATION_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); umock_c_reset_all_calls(); set_message_queue_do_work_expected_calls(mq, TEST_current_time, 1, 0, &TEST_test_message_expiration_profile); // act message_queue_do_work(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(void_ptr, (void_ptr)TEST_BASE_MQ_MESSAGE_HANDLE[0], (void_ptr)TEST_on_process_message_callback_message); ASSERT_IS_NOT_NULL(TEST_on_process_message_callback_on_process_message_completed_callback); ASSERT_IS_NOT_NULL(TEST_on_process_message_callback_context); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(do_work_NO_EXPIRATION_failure_checks) { // arrange ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); size_t i, j; for (i = 0, j = 1; i < j; i++) { if (i == 6) { continue; } // arrange TEST_on_message_processing_completed_callback_message = NULL; TEST_on_message_processing_completed_callback_result = MESSAGE_QUEUE_TIMEOUT; char error_msg[128]; sprintf(error_msg, "On failed call %lu", (unsigned long)i); if (i >= 3 && i != 4) { add_messages(mq, 1, TEST_current_time); } umock_c_reset_all_calls(); set_message_queue_do_work_expected_calls(mq, TEST_current_time, 1, 0, &TEST_test_message_expiration_profile); umock_c_negative_tests_snapshot(); j = umock_c_negative_tests_call_count(); umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); // act message_queue_do_work(mq); // assert if (i == 1 || i == 2) { ASSERT_IS_NULL(TEST_on_process_message_callback_message, error_msg); ASSERT_IS_NULL(TEST_on_message_processing_completed_callback_message, error_msg); } else if (i >= 3) { ASSERT_IS_NOT_NULL(TEST_on_message_processing_completed_callback_message, error_msg); ASSERT_ARE_EQUAL(int, (int)MESSAGE_QUEUE_ERROR, (int)TEST_on_message_processing_completed_callback_result, error_msg); } umock_c_reset_all_calls(); } // cleanup message_queue_destroy(mq); umock_c_negative_tests_deinit(); } TEST_FUNCTION(message_queue_set_max_retry_count_NULL_handle) { // arrange umock_c_reset_all_calls(); // act int result = message_queue_set_max_retry_count(NULL, 2); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } TEST_FUNCTION(message_queue_set_max_retry_count_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); // act int result = message_queue_set_max_retry_count(mq, 2); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_set_max_message_processing_time_secs_NULL_handle) { // arrange umock_c_reset_all_calls(); // act int result = message_queue_set_max_message_processing_time_secs(NULL, 60); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } TEST_FUNCTION(message_queue_set_max_message_processing_time_secs_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); // act int result = message_queue_set_max_message_processing_time_secs(mq, 60); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_set_max_message_enqueued_time_secs_NULL_handle) { // arrange umock_c_reset_all_calls(); // act int result = message_queue_set_max_message_enqueued_time_secs(NULL, 60); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } TEST_FUNCTION(message_queue_set_max_message_enqueued_time_secs_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); // act int result = message_queue_set_max_message_enqueued_time_secs(mq, 60); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_retrieve_options_NULL_handle) { // arrange umock_c_reset_all_calls(); // act OPTIONHANDLER_HANDLE result = message_queue_retrieve_options(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NULL(result); // cleanup } TEST_FUNCTION(message_queue_retrieve_options_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); set_message_queue_retrieve_options_expected_calls(); // act OPTIONHANDLER_HANDLE result = message_queue_retrieve_options(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NOT_NULL(result); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_retrieve_options_failure_checks) { // arrange ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); umock_c_reset_all_calls(); set_message_queue_retrieve_options_expected_calls(); umock_c_negative_tests_snapshot(); // act size_t i; for (i = 0; i < umock_c_negative_tests_call_count(); i++) { // arrange char error_msg[128]; sprintf(error_msg, "On failed call %lu", (unsigned long)i); umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); // act OPTIONHANDLER_HANDLE result = message_queue_retrieve_options(mq); // assert ASSERT_IS_NULL(result, error_msg); } // cleanup umock_c_negative_tests_deinit(); message_queue_destroy(mq); } TEST_FUNCTION(on_message_processing_completed_callback_INVALID_message) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(singlylinkedlist_find(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); // act TEST_on_process_message_callback_on_process_message_completed_callback(mq, 12345, MESSAGE_QUEUE_SUCCESS, TEST_REASON); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); ASSERT_ARE_EQUAL(void_ptr, NULL, TEST_on_message_processing_completed_callback_reason); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(on_message_processing_completed_callback_NULL_message_queue) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); umock_c_reset_all_calls(); // act TEST_on_process_message_callback_on_process_message_completed_callback(NULL, TEST_on_process_message_callback_message_id, MESSAGE_QUEUE_SUCCESS, TEST_REASON); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); ASSERT_ARE_EQUAL(void_ptr, NULL, TEST_on_message_processing_completed_callback_reason); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(on_message_processing_completed_callback_MESSAGE_not_present) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); umock_c_reset_all_calls(); set_on_message_processing_completed_callback_expected_calls(1, -1, false); // act TEST_on_process_message_callback_on_process_message_completed_callback(mq, TEST_SOME_OTHER_MESSAGE_ID, MESSAGE_QUEUE_SUCCESS, TEST_REASON); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); ASSERT_ARE_EQUAL(void_ptr, NULL, TEST_on_message_processing_completed_callback_reason); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(on_message_processing_completed_callback_success) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); ASSERT_ARE_EQUAL(void_ptr, (void*)TEST_BASE_MQ_MESSAGE_HANDLE[0], (void*)TEST_on_process_message_callback_message); ASSERT_IS_NOT_NULL(TEST_on_process_message_callback_on_process_message_completed_callback); ASSERT_ARE_EQUAL(void_ptr, (void*)TEST_USER_CONTEXT, (void*)TEST_on_process_message_callback_context); umock_c_reset_all_calls(); set_on_message_processing_completed_callback_expected_calls(1, 0, false); // act TEST_on_process_message_callback_on_process_message_completed_callback(mq, TEST_on_process_message_callback_message_id, MESSAGE_QUEUE_SUCCESS, TEST_REASON); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 1, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); ASSERT_ARE_EQUAL(void_ptr, TEST_REASON, TEST_on_message_processing_completed_callback_reason); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(on_message_processing_completed_callback_RETRYABLE_ERROR) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); (void)message_queue_set_max_retry_count(mq, 2); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); umock_c_reset_all_calls(); set_on_message_processing_completed_callback_expected_calls(1, 0, true); set_message_queue_do_work_expected_calls(mq, TEST_current_time, 1, 0, &TEST_test_message_expiration_profile); set_on_message_processing_completed_callback_expected_calls(1, 0, true); set_message_queue_do_work_expected_calls(mq, TEST_current_time, 1, 0, &TEST_test_message_expiration_profile); set_on_message_processing_completed_callback_expected_calls(1, 0, false); // act TEST_on_process_message_callback_on_process_message_completed_callback(mq, TEST_on_process_message_callback_message_id, MESSAGE_QUEUE_RETRYABLE_ERROR, NULL); message_queue_do_work(mq); TEST_on_process_message_callback_on_process_message_completed_callback(mq, TEST_on_process_message_callback_message_id, MESSAGE_QUEUE_RETRYABLE_ERROR, NULL); message_queue_do_work(mq); TEST_on_process_message_callback_on_process_message_completed_callback(mq, TEST_on_process_message_callback_message_id, MESSAGE_QUEUE_RETRYABLE_ERROR, NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 1, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); ASSERT_ARE_EQUAL(void_ptr, NULL, TEST_on_message_processing_completed_callback_reason); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(do_work_pending_queue_timeout) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); (void)message_queue_set_max_message_enqueued_time_secs(mq, 10); add_messages(mq, 1, TEST_current_time); time_t t1 = add_seconds(TEST_current_time, 10); TEST_MESSAGE_EXPIRATION_PROFILE exp_prof; exp_prof.max_message_enqueued_time_secs = 10; exp_prof.max_message_processing_time_secs = 0; size_t expired_pending_messages[] = { 0 }; exp_prof.expired_pending_messages = expired_pending_messages; exp_prof.expired_pending_messages_size = 1; exp_prof.expired_in_progress_messages = NULL; exp_prof.expired_in_progress_messages_size = 0; exp_prof.expired_enqueued_in_progress_messages = NULL; exp_prof.expired_enqueued_in_progress_messages_size = 0; umock_c_reset_all_calls(); set_process_timeouts_expected_calls(mq, t1, 1, 0, &exp_prof); set_process_pending_messages_calls(mq, t1, 0); // act message_queue_do_work(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 1, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(do_work_in_progress_processing_timeout) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); (void)message_queue_set_max_message_processing_time_secs(mq, 10); time_t t1 = add_seconds(TEST_current_time, 10); TEST_MESSAGE_EXPIRATION_PROFILE exp_prof; exp_prof.max_message_enqueued_time_secs = 0; exp_prof.max_message_processing_time_secs = 10; exp_prof.expired_pending_messages = NULL; exp_prof.expired_pending_messages_size = 0; size_t expired_in_progress_messages[] = { 0 }; exp_prof.expired_in_progress_messages = expired_in_progress_messages; exp_prof.expired_in_progress_messages_size = 1; exp_prof.expired_enqueued_in_progress_messages = NULL; exp_prof.expired_enqueued_in_progress_messages_size = 0; umock_c_reset_all_calls(); set_process_timeouts_expected_calls(mq, t1, 0, 1, &exp_prof); set_process_pending_messages_calls(mq, t1, 0); // act message_queue_do_work(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 1, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(do_work_in_progress_queue_timeout) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 1, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); (void)message_queue_set_max_message_enqueued_time_secs(mq, 10); time_t t1 = add_seconds(TEST_current_time, 10); TEST_MESSAGE_EXPIRATION_PROFILE exp_prof; exp_prof.max_message_enqueued_time_secs = 10; exp_prof.max_message_processing_time_secs = 0; exp_prof.expired_pending_messages = NULL; exp_prof.expired_pending_messages_size = 0; exp_prof.expired_in_progress_messages = NULL; exp_prof.expired_in_progress_messages_size = 0; size_t expired_enqueued_in_progress_messages[] = { 0 }; exp_prof.expired_enqueued_in_progress_messages = expired_enqueued_in_progress_messages; exp_prof.expired_enqueued_in_progress_messages_size = 1; umock_c_reset_all_calls(); set_process_timeouts_expected_calls(mq, t1, 0, 1, &exp_prof); set_process_pending_messages_calls(mq, t1, 0); // act message_queue_do_work(mq); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_SUCCESS_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_ERROR_result_count); ASSERT_ARE_EQUAL(int, 0, (int)TEST_on_message_processing_completed_callback_CANCELLED_result_count); ASSERT_ARE_EQUAL(int, 1, (int)TEST_on_message_processing_completed_callback_TIMEOUT_result_count); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_move_all_back_to_pending_with_in_progress_and_pending_succeed) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 2, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); add_messages(mq, 2, TEST_current_time); umock_c_reset_all_calls(); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_retry_sending_message_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (int i = 0; i < 4; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_retry_sending_message_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); // act int result = message_queue_move_all_back_to_pending(mq); // assert ASSERT_ARE_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_move_all_back_to_pending_with_only_in_progress_succeed) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 2, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_retry_sending_message_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); // act int result = message_queue_move_all_back_to_pending(mq); // assert ASSERT_ARE_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_move_all_back_to_pending_with_only_pending_succeed) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 2, TEST_current_time); umock_c_reset_all_calls(); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_retry_sending_message_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_retry_sending_message_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); // act int result = message_queue_move_all_back_to_pending(mq); // assert ASSERT_ARE_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_move_all_back_to_pending_null_message_queue_failed) { // arrange // act int result = message_queue_move_all_back_to_pending(NULL); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup } TEST_FUNCTION(message_queue_move_all_back_to_pending_move_pending_failed) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 2, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); add_messages(mq, 2, TEST_current_time); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_remove(IGNORED_PTR_ARG, IGNORED_PTR_ARG)).SetReturn(1); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_dequeue_message_and_fire_callback_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_dequeue_message_and_fire_callback_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); // act int result = message_queue_move_all_back_to_pending(mq); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup message_queue_destroy(mq); } TEST_FUNCTION(message_queue_move_all_back_to_pending_move_in_progress_failed) { // arrange MESSAGE_QUEUE_HANDLE mq = create_message_queue(USE_DEFAULT_CONFIG); add_messages(mq, 2, TEST_current_time); crank_message_queue(mq, TEST_current_time, 1, 0, NULL); add_messages(mq, 2, TEST_current_time); umock_c_reset_all_calls(); for (int i = 0; i < 2; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_retry_sending_message_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_remove(IGNORED_PTR_ARG, IGNORED_PTR_ARG)).SetReturn(1); for (int i = 0; i < 4; i++) { STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); set_dequeue_message_and_fire_callback_expected_calls(); } STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG)); // act int result = message_queue_move_all_back_to_pending(mq); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup message_queue_destroy(mq); } END_TEST_SUITE(message_queue_ut)