From d9da52a385e7fad9a0dfe448554483e88638a400 Mon Sep 17 00:00:00 2001 From: suvi-123 Date: Tue, 7 Nov 2023 17:18:22 +0530 Subject: [PATCH] Unit test cases for multipart.c --- CMakeLists.txt | 14 ++ src/webcfg_multipart.h | 7 + tests/CMakeLists.txt | 33 ++++- tests/test_cmoka_multipart.c | 223 ++++++++++++++++++++++++++++ tests/test_multipart_unittest.c | 247 ++++++++++++++++++++++++++++++++ 5 files changed, 523 insertions(+), 1 deletion(-) create mode 100644 tests/test_cmoka_multipart.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bdb2ecc..79849d2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,7 +210,21 @@ add_library(liblibparodus STATIC SHARED IMPORTED) add_dependencies(liblibparodus libparodus) endif (FEATURE_SUPPORT_AKER) +if (BUILD_TESTING) +# cmocka external dependency +#------------------------------------------------------------------------------- +ExternalProject_Add(cmocka + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/_prefix/cmocka + GIT_REPOSITORY https://github.com/elventear/cmocka.git + GIT_TAG "b71a3060699bc1a5b00e958be353772f42545ac2" + CMAKE_ARGS += -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} +) +add_library(libcmocka STATIC SHARED IMPORTED) +add_dependencies(libcmocka cmocka) + +endif (BUILD_TESTING) endif () + link_directories ( ${LIBRARY_DIR} ${COMMON_LIBRARY_DIR} ${LIBRARY_DIR64} ) diff --git a/src/webcfg_multipart.h b/src/webcfg_multipart.h index 061ec496..e96331ac 100644 --- a/src/webcfg_multipart.h +++ b/src/webcfg_multipart.h @@ -75,6 +75,13 @@ int get_global_eventFlag(void); void set_global_eventFlag(); void set_global_ETAG(char *etag); char *get_global_ETAG(void); +void line_parser(char *ptr, int no_of_bytes, char **name_space, uint32_t *etag, char **data, size_t *data_size); +void subdoc_parser(char *ptr, int no_of_bytes); +void stripspaces(char *str, char **final_str); +void get_webCfg_interface(char **interface); +size_t headr_callback(char *buffer, size_t size, size_t nitems, void* data); +size_t writer_callback_fn(void *buffer, size_t size, size_t nmemb, void *datain); +WEBCFG_STATUS processMsgpackSubdoc(char *transaction_id); #ifdef WAN_FAILOVER_SUPPORTED void set_global_interface(char * value); char * get_global_interface(void); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c494000e..20b98808 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -343,6 +343,35 @@ endif (WEBCONFIG_BIN_SUPPORT) target_link_libraries (test_generic_pc gcov -Wl,--no-as-needed ) +#------------------------------------------------------------------------------- +# test_cmoka_multipart.c +#------------------------------------------------------------------------------- +add_test(NAME test_cmoka_multipart COMMAND ${MEMORY_CHECK} ./test_cmoka_multipart) + +set(SOURCES test_cmoka_multipart.c ../src/webcfg_param.c ../src/webcfg_multipart.c ../src/webcfg_helpers.c ../src/webcfg.c ../src/webcfg_auth.c ../src/webcfg_notify.c ../src/webcfg_db.c ../src/webcfg_pack.c ../src/webcfg_blob.c ../src/webcfg_event.c ../src/webcfg_generic_pc.c ../src/webcfg_metadata.c) + +if (WEBCONFIG_BIN_SUPPORT) +set(SOURCES ${SOURCES} ../src/webcfg_rbus.c) +endif (WEBCONFIG_BIN_SUPPORT) + +if (FEATURE_SUPPORT_AKER) +set(SOURCES ${SOURCES} ../src/webcfg_client.c ../src/webcfg_aker.c) +endif (FEATURE_SUPPORT_AKER) + +add_executable(test_cmoka_multipart ${SOURCES}) + +target_link_libraries (test_cmoka_multipart -lcmocka -lcunit -lmsgpackc -lpthread -lm -luuid -ltrower-base64 -lwdmp-c -lcimplog -lcjson -lwrp-c -lcurl ) + +if (WEBCONFIG_BIN_SUPPORT) +target_link_libraries (test_cmoka_multipart -lrbus) +endif (WEBCONFIG_BIN_SUPPORT) + +if (FEATURE_SUPPORT_AKER) +target_link_libraries (test_cmoka_multipart -llibparodus -lnanomsg) +endif (FEATURE_SUPPORT_AKER) + +target_link_libraries (test_cmoka_multipart gcov -Wl,--no-as-needed ) + # Code coverage add_custom_target(coverage @@ -376,7 +405,8 @@ COMMAND lcov -q --capture --directory ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/test_notify.dir/__/src --output-file test_notify.info COMMAND lcov -q --capture --directory ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/test_generic.dir/__/src --output-file test_generic_pc.info - +COMMAND lcov -q --capture --directory +${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/test_cmoka_multipart.dir/__/src --output-file test_cmoka_multipart.info COMMAND lcov -a test_events_supp.info @@ -394,6 +424,7 @@ COMMAND lcov -a test_timer.info -a test_notify.info -a test_generic_pc.info +-a test_cmoka_multipart.info --output-file coverage.info COMMAND genhtml coverage.info diff --git a/tests/test_cmoka_multipart.c b/tests/test_cmoka_multipart.c new file mode 100644 index 00000000..626e5f9b --- /dev/null +++ b/tests/test_cmoka_multipart.c @@ -0,0 +1,223 @@ +/** + * Copyright 2019 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../src/webcfg_log.h" +#include "../src/webcfg_param.h" +#include "../src/webcfg.h" +#include "../src/webcfg_multipart.h" +#include "../src/webcfg_helpers.h" +#include "../src/webcfg_db.h" +#include "../src/webcfg_notify.h" +#include "../src/webcfg_metadata.h" +#include "../src/webcfg_generic.h" +#include "../src/webcfg_event.h" +#include "../src/webcfg_auth.h" +#include "../src/webcfg_blob.h" +#include "../src/webcfg_timer.h" + +#define UNUSED(x) (void )(x) +int numLoops; + +typedef void CURL; + +#undef curl_easy_setopt +#undef curl_easy_getinfo + +long long getRetryExpiryTimeout() +{ + return 0; +} + +int get_retry_timer() +{ + return 0; +} + +int updateRetryTimeDiff(long long expiry_time) +{ + UNUSED(expiry_time); + return 0; +} + +int checkRetryTimer( long long timestamp) +{ + return timestamp; +} + +char* printTime(long long time) +{ + UNUSED(time); + return NULL; +} + +int checkMaintenanceTimer() +{ + return 0; +} + +void initMaintenanceTimer() +{ + return; +} + +int getMaintenanceSyncSeconds(int maintenance_count) +{ + UNUSED(maintenance_count); + return 0; +} + +long get_global_retry_timestamp() +{ + return 0; +} + +int retrySyncSeconds() +{ + return 0; +} + +void set_retry_timer(int value) +{ + UNUSED(value); + return; +} + +void set_global_retry_timestamp(long value) +{ + UNUSED(value); + return; +} + +void set_global_maintenance_time(long value) +{ + UNUSED(value); + return; +} + +int Get_Webconfig_URL(char *pString) +{ + // Set a non-empty value for configURL + strcpy(pString, "http://example.com/config.xml"); + return 0; // or whatever the expected return value is +} + +CURL *curl_easy_init () +{ + function_called(); + return (CURL *) mock(); +} + +CURLcode curl_easy_perform(CURL *curl) +{ + UNUSED(curl); + int rtn; + + function_called(); + rtn = (int) mock(); + return rtn; +} + +CURLcode curl_easy_setopt(CURL *easy, CURLoption option, ...) +{ + UNUSED (easy); + UNUSED (option); + return CURLE_OK; +} + +CURLcode curl_easy_getinfo(CURL *easy, CURLINFO info, ... ) +{ + UNUSED (easy); + UNUSED (info); + int rtn; + + function_called(); + rtn = (int) mock(); + return rtn; +} + +void curl_easy_cleanup(CURL *easy) +{ + (void) easy; +} + +void test_webcfg_http_request_curl_init_fail() +{ + // Set up your test data and mock behaviors + char *config = NULL; // Initialize with your data + int r_count = 1; // Set the number of retries as needed + int status = 0; // Set the status as needed + long code = 0; // Response code + char *transaction_id = NULL; // Transaction ID + char contentType[64] = {0}; // Content type + size_t dataSize = 0; // Data size + char docname[64] = {0}; // Document name + + will_return (curl_easy_init, NULL); + expect_function_calls (curl_easy_init, 1); + + WEBCFG_STATUS result = webcfg_http_request(&config, r_count, status, &code, &transaction_id, contentType, &dataSize, docname); + + printf("The result is %d", result); +} + +void test_webcfg_http_request_curl_init_success() +{ + // Set up your test data and mock behaviors + char *config = NULL; // Initialize with your data + int r_count = 1; // Set the number of retries as needed + int status = 0; // Set the status as needed + long code = 0; // Response code + char *transaction_id = NULL; // Transaction ID + char contentType[64] = {0}; // Content type + size_t dataSize = 0; // Data size + char docname[64] = {0}; // Document name + + will_return (curl_easy_init, 1); + expect_function_calls (curl_easy_init, 1); + + will_return (curl_easy_perform, 0); + expect_function_calls (curl_easy_perform, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + will_return (curl_easy_getinfo, 0); + expect_function_calls (curl_easy_getinfo, 1); + + WEBCFG_STATUS result = webcfg_http_request(&config, r_count, status, &code, &transaction_id, contentType, &dataSize, docname); + + printf("The result is %d", result); + + assert_int_equal (result, 0); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_webcfg_http_request_curl_init_fail), + cmocka_unit_test(test_webcfg_http_request_curl_init_success) + + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/test_multipart_unittest.c b/tests/test_multipart_unittest.c index 06925b17..5c9a3076 100644 --- a/tests/test_multipart_unittest.c +++ b/tests/test_multipart_unittest.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "../src/webcfg_log.h" #include "../src/webcfg_param.h" @@ -52,6 +53,14 @@ int numLoops; #define MAX_HEADER_LEN 4096 #define UNUSED(x) (void )(x) + +struct mock_token_data { + size_t size; + char* data; +}; + +struct mock_token_data mock_data; + char device_mac[32] = {'\0'}; char* get_deviceMAC() @@ -632,6 +641,232 @@ void test_get_multipartdoc_count(){ CU_ASSERT_FATAL( NULL == get_global_mp() ); } +void test_parseMultipartDocument_ValidBoundary() { + WEBCFG_STATUS result; + const char config_data[] = "HTTP 200 OK\nContent-Type: multipart/mixed; boundary=+CeB5yCWds7LeVP4oibmKefQ091Vpt2x4g99cJfDCmXpFxt5d\nEtag: 345431215\n\n--+CeB5yCWds7LeVP4oibmKefQ091Vpt2x4g99cJfDCmXpFxt5d\nContent-type: application/msgpack\nEtag: 2132354\nNamespace: moca\nparameter: somedata\n--+CeB5yCWds7LeVP4oibmKefQ091Vpt2x4g99cJfDCmXpFxt5d--"; + size_t data_size = strlen(config_data); + char ct[] = "Content-Type: multipart/mixed; boundary=+CeB5yCWds7LeVP4oibmKefQ091Vpt2x4g99cJfDCmXpFxt5d"; + char *trans_uuid = strdup("1234"); + char *config_data_copy = (char *)malloc(data_size + 1); + + if (config_data_copy != NULL) { + strcpy(config_data_copy, config_data); + result = parseMultipartDocument(config_data_copy, ct, data_size, trans_uuid); + CU_ASSERT_EQUAL(result, WEBCFG_FAILURE); + } else { + CU_FAIL("Memory allocation for config_data_copy (valid boundary) failed"); + } +} + +void test_loadInitURLFromFile() +{ + //URL value NULL + char *data=""; + char *web_url; + writeToDBFile(DEVICE_PROPS_FILE,data,strlen(data)); + loadInitURLFromFile(&web_url); + printf("The value of url is %s",web_url); + //CU_ASSERT_PTR_NULL(web_url); + + //URL value not NULL + data = "WEBCONFIG_INIT_URL=tcp://112.1.1.1:4444 "; + writeToDBFile(DEVICE_PROPS_FILE,data,strlen(data)); + loadInitURLFromFile(&web_url); + CU_ASSERT_STRING_EQUAL("tcp://112.1.1.1:4444", web_url); +} + +void test_failedDocsRetry() +{ + multipartdocs_t *multipartdocs = (multipartdocs_t *)malloc(sizeof(multipartdocs_t)); + multipartdocs->name_space = strdup("moca"); + multipartdocs->data = (char* )malloc(64); + multipartdocs->isSupplementarySync = 0; + multipartdocs->next = NULL; + set_global_mp(multipartdocs); + //checkRetryTimer returns true + webconfig_tmp_data_t *tmpData = (webconfig_tmp_data_t *)malloc(sizeof(webconfig_tmp_data_t)); + tmpData->name = strdup("moca"); + tmpData->version = 1234; + tmpData->status = strdup("success"); + tmpData->trans_id = 4104; + tmpData->retry_count = 0; + tmpData->error_code = 192; + tmpData->error_details = strdup("none"); + tmpData->retry_timestamp = 1; + tmpData->next = NULL; + set_global_tmp_node(tmpData); + + //subdoc set fails + failedDocsRetry(); + CU_ASSERT_STRING_EQUAL("moca",tmpData->name); + + //retry skip + failedDocsRetry(); + printf("The value is %s",tmpData->error_details); + CU_ASSERT_PTR_NOT_NULL(tmpData->error_details); + +} + +void test_getRootDocVersionFromDBCache() +{ + uint32_t expected_version; + char *expected_string; + int expected_subdoclist; + + uint32_t rt_version; + char *rt_string = NULL; + int subdoclist = 0; + char *rootstr = strdup("factory-reset"); + uint32_t version = 1234; + updateDBlist("root", version, rootstr); + getRootDocVersionFromDBCache(&rt_version, &rt_string, &subdoclist); + + expected_version = version; + expected_string = rootstr; + expected_subdoclist = 1; + + CU_ASSERT(rt_version == expected_version); + CU_ASSERT_STRING_EQUAL(rt_string, expected_string); + CU_ASSERT_EQUAL(subdoclist, expected_subdoclist); +} + +void test_lineparser() +{ + char *name_space = NULL; + uint32_t etag = 0; + char *data = NULL; + size_t data_size = 0; + char input[100] = "Content-type: application/msgpack"; + + //content type as msgpack + line_parser(input, sizeof(input), &name_space, &etag, &data, &data_size); + + //content type not msgpack + strcpy(input, "Content-type: application/"); + line_parser(input, sizeof(input), &name_space, &etag, &data, &data_size); + + //proper name + strcpy(input, "Namespace: blob"); + line_parser(input, sizeof(input), &name_space, &etag, &data, &data_size); + CU_ASSERT_STRING_EQUAL(name_space, "blob"); + + //proper etag + strcpy(input, "Etag: 2132354"); + line_parser(input, sizeof(input), &name_space, &etag, &data, &data_size); + CU_ASSERT_EQUAL(etag, 2132354); + + //parameter + strcpy(input, "ªparameters: somedata"); + line_parser(input, sizeof(input), &name_space, &etag, &data, &data_size); + + CU_ASSERT_PTR_NOT_NULL(data); + CU_ASSERT_EQUAL(data_size, sizeof(input)); +} + +void test_subdoc_parser() +{ + set_global_mp(NULL); + //Proper values + char *input_data = "Content-type: application/msgpack\nNamespace: blob\nEtag: 12345\nparameters: somedata\nThis is the end of it\n"; + int no_of_bytes = strlen(input_data); + subdoc_parser(input_data, no_of_bytes); + + CU_ASSERT_PTR_NOT_NULL(get_global_mp()); + + //NULL etag and namespace + input_data = "Content-type: application/msgpack\nNamespace: NULL\nEtag: 0\nparameters: somedata\nThis is the end of it\n"; + no_of_bytes = strlen(input_data); + subdoc_parser(input_data, no_of_bytes); + CU_ASSERT_PTR_NOT_NULL(get_global_mp()); +} + +void test_stripspaces() +{ + char input1[] = "This is a test"; // No spaces, newlines, or carriage returns + char input2[] = "This\nis a\rtest"; // Contains newlines and carriage returns + char input3[] = " Remove spaces "; // Contains extra spaces + + char *result1 = NULL; + char *result2 = NULL; + char *result3 = NULL; + + // Test with input1 + stripspaces(input1, &result1); + CU_ASSERT_STRING_EQUAL(result1, "Thisisatest"); + + // Test with input2 + stripspaces(input2, &result2); + CU_ASSERT_STRING_EQUAL(result2, "Thisisatest"); + + // Test with input3 + stripspaces(input3, &result3); + CU_ASSERT_STRING_EQUAL(result3, "Removespaces"); +} + +void test_get_webCfg_interface() +{ + char *data = "WEBCONFIG_INTERFACE=erouter0 "; + char *interface = NULL; + writeToDBFile(DEVICE_PROPS_FILE,data,strlen(data)); + + get_webCfg_interface(&interface); + CU_ASSERT_PTR_NOT_NULL(interface); + CU_ASSERT_STRING_EQUAL(interface, "erouter0"); +} + +void test_headr_callback() +{ + char buffer[100] = "Etag: 2132354"; + size_t size = strlen(buffer); + size_t nitems = 15; + void* data = NULL; + set_global_contentLen(NULL); + + size_t result = headr_callback(buffer, size, nitems, data); + CU_ASSERT_EQUAL(result, nitems); + CU_ASSERT_PTR_NULL(get_global_contentLen()); + + char *content = get_global_contentLen(); + printf("The value is %s\n",content); + + strcpy(buffer,"Content-Length: 1052"); + size = strlen(buffer); + result = headr_callback(buffer, size, nitems, data); + CU_ASSERT_EQUAL(result, nitems); + CU_ASSERT_PTR_NOT_NULL(get_global_contentLen()); + CU_ASSERT_STRING_EQUAL(get_global_contentLen(), "1052"); +} + +void test_writer_callback_fn() +{ + mock_data.size = 0; + mock_data.data = NULL; + char buffer[] = "Hello, World!"; + size_t size = sizeof(char); + size_t nmemb = strlen(buffer); + + size_t result = writer_callback_fn(buffer, size, nmemb, &mock_data); + CU_ASSERT_EQUAL(result, nmemb); + CU_ASSERT_EQUAL(mock_data.size, nmemb); +} + +void test_refreshConfigVersionList() +{ + char versionsList[512]; + char docsList[512]; + int http_status = 200; + refreshConfigVersionList(versionsList, http_status, docsList); + CU_ASSERT_PTR_NOT_NULL(get_global_db_node); +} + +void test_processMsgpackSubdoc() +{ + char *transaction_id = strdup("1234"); + WEBCFG_STATUS result; + result = processMsgpackSubdoc(transaction_id); + CU_ASSERT_EQUAL(result, WEBCFG_FAILURE); +} + void add_suites( CU_pSuite *suite ) { *suite = CU_add_suite( "tests", NULL, NULL ); @@ -677,6 +912,18 @@ void add_suites( CU_pSuite *suite ) CU_add_test( *suite, "test addToMpList", test_addToMpList); CU_add_test( *suite, "test delete_mp_doc", test_delete_mp_doc); CU_add_test( *suite, "test get_multipartdoc_count", test_get_multipartdoc_count); + CU_add_test( *suite, "test parseMultipartDocument_ValidBoundary", test_parseMultipartDocument_ValidBoundary); + CU_add_test( *suite, "test loadInitURLFromFile", test_loadInitURLFromFile); + CU_add_test( *suite, "test failedDocsRetry", test_failedDocsRetry); + CU_add_test( *suite, "test getRootDocVersionFromDBCache", test_getRootDocVersionFromDBCache); + CU_add_test( *suite, "test lineparser", test_lineparser); + CU_add_test( *suite, "test subdoc_parser", test_subdoc_parser); + CU_add_test( *suite, "test stripspaces", test_stripspaces); + CU_add_test( *suite, "test get_webCfg_interface", test_get_webCfg_interface); + CU_add_test( *suite, "test headr_callback", test_headr_callback); + CU_add_test( *suite, "test writer_callback_fn", test_writer_callback_fn); + CU_add_test( *suite, "test refreshConfigVersionList", test_refreshConfigVersionList); + CU_add_test( *suite, "test processMsgpackSubdoc", test_processMsgpackSubdoc); } /*----------------------------------------------------------------------------*/