// 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 #else #include #include #include #include #endif #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" #ifdef __cplusplus extern "C" { #endif void* my_gballoc_malloc(size_t size) { return malloc(size); } void my_gballoc_free(void* ptr) { free(ptr); } int my_mallocAndStrcpy_s(char** destination, const char* source) { size_t len = strlen(source); *destination = (char*)malloc(len + 1); strcpy(*destination, source); return 0; } #ifdef __cplusplus } #endif #define ENABLE_MOCKS #include "azure_c_shared_utility/crt_abstractions.h" #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/string_token.h" #undef ENABLE_MOCKS #include "azure_umqtt_c/mqtt_message.h" #ifdef __cplusplus extern "C" { #endif extern STRING_TOKEN_HANDLE real_StringToken_GetFirst(const char* source, size_t length, const char** delimiters, size_t n_delims); extern bool real_StringToken_GetNext(STRING_TOKEN_HANDLE token, const char** delimiters, size_t n_delims); extern const char* real_StringToken_GetValue(STRING_TOKEN_HANDLE token); extern size_t real_StringToken_GetLength(STRING_TOKEN_HANDLE token); extern const char* real_StringToken_GetDelimiter(STRING_TOKEN_HANDLE token); extern int real_StringToken_Split(const char* source, size_t length, const char** delimiters, size_t n_delims, bool include_empty, char*** tokens, size_t* token_count); extern void real_StringToken_Destroy(STRING_TOKEN_HANDLE token); #ifdef __cplusplus } #endif #define TEST_MESSAGE_TEXT "Message to send" static bool g_fail_alloc_calls; static const uint8_t TEST_PACKET_ID = (uint8_t)0x12; static const char* TEST_TOPIC_NAME = "$subTopic1/subTopic2/subTopic3/?$prop1=value1&$prop2=value2"; static const uint8_t* TEST_MESSAGE = (const uint8_t *)TEST_MESSAGE_TEXT; static const int TEST_MSG_LEN = sizeof(TEST_MESSAGE_TEXT) - 1; typedef struct TEST_COMPLETE_DATA_INSTANCE_TAG { unsigned char* dataHeader; size_t Length; } TEST_COMPLETE_DATA_INSTANCE; MU_DEFINE_ENUM_STRINGS_2(QOS_VALUE, QOS_VALUE_VALUES); TEST_DEFINE_ENUM_2_TYPE(QOS_VALUE, QOS_VALUE_VALUES); IMPLEMENT_UMOCK_C_ENUM_2_TYPE(QOS_VALUE, QOS_VALUE_VALUES); TEST_MUTEX_HANDLE test_serialize_mutex; 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) { ASSERT_FAIL("umock_c reported error :%s", MU_ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code)); } BEGIN_TEST_SUITE(mqtt_message_ut) TEST_SUITE_INITIALIZE(suite_init) { test_serialize_mutex = TEST_MUTEX_CREATE(); ASSERT_IS_NOT_NULL(test_serialize_mutex); umock_c_init(on_umock_c_error); ASSERT_ARE_EQUAL(int, 0, umocktypes_bool_register_types()); REGISTER_UMOCK_ALIAS_TYPE(STRING_TOKEN_HANDLE, void*); REGISTER_GLOBAL_MOCK_HOOK(gballoc_malloc, my_gballoc_malloc); REGISTER_GLOBAL_MOCK_HOOK(gballoc_free, my_gballoc_free); REGISTER_GLOBAL_MOCK_HOOK(mallocAndStrcpy_s, my_mallocAndStrcpy_s); REGISTER_GLOBAL_MOCK_HOOK(StringToken_GetFirst, real_StringToken_GetFirst); REGISTER_GLOBAL_MOCK_HOOK(StringToken_GetNext, real_StringToken_GetNext); REGISTER_GLOBAL_MOCK_HOOK(StringToken_GetDelimiter, real_StringToken_GetDelimiter); REGISTER_GLOBAL_MOCK_HOOK(StringToken_GetValue, real_StringToken_GetValue); REGISTER_GLOBAL_MOCK_HOOK(StringToken_GetLength, real_StringToken_GetLength); REGISTER_GLOBAL_MOCK_HOOK(StringToken_Split, real_StringToken_Split); REGISTER_GLOBAL_MOCK_HOOK(StringToken_Destroy, real_StringToken_Destroy); REGISTER_GLOBAL_MOCK_FAIL_RETURN(StringToken_GetFirst, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(StringToken_GetNext, false); REGISTER_GLOBAL_MOCK_FAIL_RETURN(StringToken_GetDelimiter, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(StringToken_GetValue, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(StringToken_GetLength, 0); REGISTER_GLOBAL_MOCK_FAIL_RETURN(StringToken_Split, 1); REGISTER_GLOBAL_MOCK_RETURN(mallocAndStrcpy_s, 0); REGISTER_GLOBAL_MOCK_FAIL_RETURN(mallocAndStrcpy_s, 1); } TEST_SUITE_CLEANUP(suite_cleanup) { TEST_MUTEX_DESTROY(test_serialize_mutex); } TEST_FUNCTION_INITIALIZE(method_init) { if (TEST_MUTEX_ACQUIRE(test_serialize_mutex)) { ASSERT_FAIL("Could not acquire test serialization mutex."); } g_fail_alloc_calls = false; umock_c_reset_all_calls(); } TEST_FUNCTION_CLEANUP(method_cleanup) { TEST_MUTEX_RELEASE(test_serialize_mutex); } /* Test_SRS_MQTTMESSAGE_07_001:[If the parameters topicName is NULL then mqttmessage_createMessage shall return NULL.] */ TEST_FUNCTION(mqttmessage_create_Topicname_NULL_fail) { // arrange // act MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, NULL, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); // assert ASSERT_IS_NULL(handle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Test_SRS_MQTTMESSAGE_07_001:[If the parameters topicName is NULL then mqttmessage_create shall return NULL.] */ TEST_FUNCTION(mqttmessage_create_appMsgLength_NULL_succeed) { // arrange EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_TOPIC_NAME)) .IgnoreArgument(1); // act MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, NULL, 0); // assert ASSERT_IS_NOT_NULL(handle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_002: [mqttmessage_create shall allocate and copy the topicName and appMsg parameters.]*/ /* Test_SRS_MQTTMESSAGE_07_004: [If mqttmessage_create succeeds the it shall return a NON-NULL MQTT_MESSAGE_HANDLE value.] */ TEST_FUNCTION(mqttmessage_create_succeed) { // arrange EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_TOPIC_NAME)) .IgnoreArgument(1); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // act MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); // assert ASSERT_IS_NOT_NULL(handle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Tests_SRS_MQTTMESSAGE_07_028: [If any memory allocation fails mqttmessage_create_in_place shall free any allocated memory and return NULL.] */ TEST_FUNCTION(mqttmessage_create_in_place_topic_name_name_fail) { // arrange // act MQTT_MESSAGE_HANDLE handle = mqttmessage_create_in_place(TEST_PACKET_ID, NULL, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); // assert ASSERT_IS_NULL(handle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_MQTTMESSAGE_07_027: [mqttmessage_create_in_place shall use the a pointer to topicName or appMsg .] */ /* Tests_SRS_MQTTMESSAGE_07_029: [ Upon success, mqttmessage_create_in_place shall return a NON-NULL MQTT_MESSAGE_HANDLE value.] */ /* Tests_SRS_MQTTMESSAGE_07_026: [If the parameters topicName is NULL then mqttmessage_create_in_place shall return NULL.].] */ TEST_FUNCTION(mqttmessage_create_in_place_succeed) { // arrange EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // act MQTT_MESSAGE_HANDLE handle = mqttmessage_create_in_place(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); // assert ASSERT_IS_NOT_NULL(handle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_006: [mqttmessage_destroyMessage shall free all resources associated with the MQTT_MESSAGE_HANDLE value] */ TEST_FUNCTION(mqttmessage_destroy_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); // act mqttmessage_destroy(handle); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } TEST_FUNCTION(mqttmessage_destroy_inplace_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create_in_place(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); // act mqttmessage_destroy(handle); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Test_SRS_MQTTMESSAGE_07_005: [If the handle parameter is NULL then mqttmessage_destroyMessage shall do nothing] */ TEST_FUNCTION(mqttmessage_destroy_handle_NULL_fail) { // arrange // act mqttmessage_destroy(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Test_SRS_MQTTMESSAGE_07_008: [mqttmessage_clone shall create a new MQTT_MESSAGE_HANDLE with data content identical of the handle value.] */ TEST_FUNCTION(mqttmessage_clone_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_TOPIC_NAME)); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); // act MQTT_MESSAGE_HANDLE cloneHandle = mqttmessage_clone(handle); // assert ASSERT_IS_NOT_NULL(cloneHandle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); mqttmessage_destroy(cloneHandle); } /* Test_SRS_MQTTMESSAGE_07_007: [If handle parameter is NULL then mqttmessage_clone shall return NULL.] */ TEST_FUNCTION(mqttmessage_clone_handle_fails) { // arrange // act MQTT_MESSAGE_HANDLE cloneHandle = mqttmessage_clone(NULL); // assert ASSERT_IS_NULL(cloneHandle); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Test_SRS_MQTTMESSAGE_07_010: [If handle is NULL then mqttmessage_getPacketId shall return 0.] */ TEST_FUNCTION(mqttmessage_getPacketId_handle_fails) { // arrange // act uint16_t packetId = mqttmessage_getPacketId(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, packetId); } /* Test_SRS_MQTTMESSAGE_07_011: [mqttmessage_getPacketId shall return the packetId value contained in MQTT_MESSAGE_HANDLE handle.] */ TEST_FUNCTION(mqttmessage_getPacketId_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); // act uint16_t packetId = mqttmessage_getPacketId(handle); // assert ASSERT_ARE_EQUAL(int, TEST_PACKET_ID, packetId); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_012: [If handle is NULL then mqttmessage_getTopicName shall return a NULL string.] */ TEST_FUNCTION(mqttmessage_getTopicName_handle_fails) { // arrange // act const char* topicName = mqttmessage_getTopicName(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NULL(topicName); } /* Test_SRS_MQTTMESSAGE_07_013: [mqttmessage_getTopicName shall return the topicName contained in MQTT_MESSAGE_HANDLE handle.] */ TEST_FUNCTION(mqttmessage_getTopicName_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); // act const char* topicName = mqttmessage_getTopicName(handle); // assert ASSERT_ARE_EQUAL(char_ptr, TEST_TOPIC_NAME, topicName); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_014: [If handle is NULL then mqttmessage_getQosType shall return the default DELIVER_AT_MOST_ONCE value.] */ TEST_FUNCTION(mqttmessage_getQosType_handle_fails) { // arrange // act QOS_VALUE value = mqttmessage_getQosType(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(QOS_VALUE, DELIVER_AT_MOST_ONCE, value); } /* Test_SRS_MQTTMESSAGE_07_015: [mqttmessage_getQosType shall return the QOS Type value contained in MQTT_MESSAGE_HANDLE handle.] */ TEST_FUNCTION(mqttmessage_getQosType_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_LEAST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); // act QOS_VALUE value = mqttmessage_getQosType(handle); // assert ASSERT_ARE_EQUAL(QOS_VALUE, DELIVER_AT_LEAST_ONCE, value); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_016: [If handle is NULL then mqttmessage_getIsDuplicateMsg shall return false.] */ TEST_FUNCTION(mqttmessage_getIsDuplicateMsg_handle_fails) { // arrange // act bool value = mqttmessage_getIsDuplicateMsg(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_FALSE(value); } /* Tests_SRS_MQTTMESSAGE_07_022: [If handle is NULL then mqttmessage_setIsDuplicateMsg shall return a non-zero value.] */ TEST_FUNCTION(mqttmessage_setIsDuplicateMsg_handle_fails) { // arrange // act int value = mqttmessage_setIsDuplicateMsg(NULL, false); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, value); } /* Test_SRS_MQTTMESSAGE_07_017: [mqttmessage_getIsDuplicateMsg shall return the isDuplicateMsg value contained in MQTT_MESSAGE_HANDLE handle.] */ /* Test_SRS_MQTTMESSAGE_07_023: [mqttmessage_setIsDuplicateMsg shall store the duplicateMsg value in the MQTT_MESSAGE_HANDLE handle.] */ TEST_FUNCTION(mqttmessage_set_and_get_IsDuplicateMsg_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_LEAST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); // act int value = mqttmessage_setIsDuplicateMsg(handle, true); bool dupMsg = mqttmessage_getIsDuplicateMsg(handle); // assert ASSERT_ARE_EQUAL(int, 0, value); ASSERT_IS_TRUE(dupMsg); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_018: [If handle is NULL then mqttmessage_getIsRetained shall return false.] */ TEST_FUNCTION(mqttmessage_getIsRetained_handle_fails) { // arrange // act bool value = mqttmessage_getIsRetained(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_FALSE(value); } /* Tests_SRS_MQTTMESSAGE_07_024: [If handle is NULL then mqttmessage_setIsRetained shall return a non-zero value.] */ TEST_FUNCTION(mqttmessage_setIsRetained_handle_fails) { // arrange // act int value = mqttmessage_setIsRetained(NULL, false); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, value); } /* Test_SRS_MQTTMESSAGE_07_019: [mqttmessage_getIsRetained shall return the isRetained value contained in MQTT_MESSAGE_HANDLE handle.] */ /* Test_SRS_MQTTMESSAGE_07_025: [mqttmessage_setIsRetained shall store the retainMsg value in the MQTT_MESSAGE_HANDLE handle.] */ TEST_FUNCTION(mqttmessage_set_and_get_IsRetained_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_LEAST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); // act int value = mqttmessage_setIsRetained(handle, true); bool retainMsg = mqttmessage_getIsRetained(handle); // assert ASSERT_ARE_EQUAL(int, 0, value); ASSERT_IS_TRUE(retainMsg); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } /* Test_SRS_MQTTMESSAGE_07_020: [If handle is NULL or if msgLen is 0 then mqttmessage_applicationMsg shall return NULL.] */ TEST_FUNCTION(mqttmessage_getApplicationMsg_handle_fails) { // arrange // act const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(NULL); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NULL(payload); } /* Test_SRS_MQTTMESSAGE_07_021: [mqttmessage_getApplicationMsg shall return the applicationMsg value contained in MQTT_MESSAGE_HANDLE handle and the length of the appMsg in the msgLen parameter.] */ TEST_FUNCTION(mqttmessage_getApplicationMsg_succeed) { // arrange MQTT_MESSAGE_HANDLE handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_LEAST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); // act const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(handle); // assert ASSERT_IS_NOT_NULL(payload); ASSERT_ARE_EQUAL(int, 0, memcmp(payload->message, TEST_MESSAGE, TEST_MSG_LEN) ); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); mqttmessage_destroy(handle); } // Tests_SRS_MQTTMESSAGE_09_001: [ If `handle`, `levels` or `count` are NULL the function shall return a non-zero value. ] TEST_FUNCTION(mqttmessage_getTopicLevels_NULL_handle) { // arrange char** levels; size_t count; int result; umock_c_reset_all_calls(); // act result = mqttmessage_getTopicLevels(NULL, &levels, &count); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } // Tests_SRS_MQTTMESSAGE_09_001: [ If `handle`, `levels` or `count` are NULL the function shall return a non-zero value. ] TEST_FUNCTION(mqttmessage_getTopicLevels_NULL_levels) { // arrange MQTT_MESSAGE_HANDLE handle = (MQTT_MESSAGE_HANDLE)0x4444; size_t count; int result; umock_c_reset_all_calls(); // act result = mqttmessage_getTopicLevels(handle, NULL, &count); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_NOT_EQUAL(int, 0, result); // cleanup } // Tests_SRS_MQTTMESSAGE_09_001: [ If `handle`, `levels` or `count` are NULL the function shall return a non-zero value. ] TEST_FUNCTION(mqttmessage_getTopicLevels_NULL_count) { // arrange MQTT_MESSAGE_HANDLE handle = (MQTT_MESSAGE_HANDLE)0x4444; char** levels; int result; umock_c_reset_all_calls(); // act result = mqttmessage_getTopicLevels(handle, &levels, 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 } // Tests_SRS_MQTTMESSAGE_09_002: [ The topic name, excluding the property bag, shall be split into individual tokens using "/" as separator ] // Tests_SRS_MQTTMESSAGE_09_004: [ The split tokens shall be stored in `levels` and its count in `count` ] // Tests_SRS_MQTTMESSAGE_09_005: [ If no failures occur the function shall return zero. ] TEST_FUNCTION(mqttmessage_getTopicLevels_succeed) { // arrange MQTT_MESSAGE_HANDLE handle; char** levels; size_t count; int result; umock_c_reset_all_calls(); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_TOPIC_NAME)) .IgnoreArgument(1); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); STRICT_EXPECTED_CALL(StringToken_Split(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, 1, false, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); // act result = mqttmessage_getTopicLevels(handle, &levels, &count); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(size_t, 4, count); ASSERT_ARE_EQUAL(char_ptr, "$subTopic1", levels[0]); ASSERT_ARE_EQUAL(char_ptr, "subTopic2", levels[1]); ASSERT_ARE_EQUAL(char_ptr, "subTopic3", levels[2]); ASSERT_ARE_EQUAL(char_ptr, "?$prop1=value1&$prop2=value2", levels[3]); // cleanup mqttmessage_destroy(handle); while (count > 0) { free(levels[--count]); } free(levels); } // Tests_SRS_MQTTMESSAGE_09_003: [ If splitting fails the function shall return a non-zero value. ] TEST_FUNCTION(mqttmessage_getTopicLevels_negative_tests) { // arrange MQTT_MESSAGE_HANDLE handle; char** levels; size_t count; size_t i; ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init()); umock_c_reset_all_calls(); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, TEST_TOPIC_NAME)) .IgnoreArgument(1); EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); handle = mqttmessage_create(TEST_PACKET_ID, TEST_TOPIC_NAME, DELIVER_AT_MOST_ONCE, TEST_MESSAGE, TEST_MSG_LEN); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(StringToken_Split(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, 1, false, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); umock_c_negative_tests_snapshot(); for (i = 0; i < umock_c_negative_tests_call_count(); i++) { // arrange int result; umock_c_negative_tests_reset(); umock_c_negative_tests_fail_call(i); // act result = mqttmessage_getTopicLevels(handle, &levels, &count); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result, "On failed call %zu", i); } // cleanup mqttmessage_destroy(handle); umock_c_negative_tests_deinit(); } END_TEST_SUITE(mqtt_message_ut)