diff --git a/source/bulkdata/profile.c b/source/bulkdata/profile.c index bafe50c4..5a0055c9 100644 --- a/source/bulkdata/profile.c +++ b/source/bulkdata/profile.c @@ -45,6 +45,11 @@ #define MAX_LEN 256 +#ifdef GTEST_ENABLE +#define sendReportOverHTTP __wrap_sendReportOverHTTP +#define sendCachedReportsOverHTTP __wrap_sendCachedReportsOverHTTP +#endif + static bool initialized = false; static Vector *profileList; static pthread_mutex_t plMutex; diff --git a/source/bulkdata/profilexconf.c b/source/bulkdata/profilexconf.c index cd8aece8..77acf20e 100644 --- a/source/bulkdata/profilexconf.c +++ b/source/bulkdata/profilexconf.c @@ -986,4 +986,9 @@ T2ERROR ProfileXConf_storeMarkerEvent(T2Event *eventInfo) T2Debug("%s --out\n", __FUNCTION__); return T2ERROR_SUCCESS; } - +#ifdef GTEST_ENABLE +void test_set_reportThreadExits(bool value) +{ + reportThreadExits = value; +} +#endif diff --git a/source/bulkdata/reportprofiles.c b/source/bulkdata/reportprofiles.c index f220d0e1..fc7b1205 100644 --- a/source/bulkdata/reportprofiles.c +++ b/source/bulkdata/reportprofiles.c @@ -907,6 +907,7 @@ void ReportProfiles_ProcessReportProfilesBlob(cJSON *profiles_root, bool rprofil { getMarkerCompRbusSub(false); } + // Populate profile hash map for current configuration for( profileIndex = 0; profileIndex < profiles_count; profileIndex++ ) { @@ -976,7 +977,6 @@ void ReportProfiles_ProcessReportProfilesBlob(cJSON *profiles_root, bool rprofil T2Error("Failed to remove previous report profile from the disk\n"); } } - if(isRbusEnabled()) { unregisterDEforCompEventList(); @@ -1064,7 +1064,6 @@ void ReportProfiles_ProcessReportProfilesBlob(cJSON *profiles_root, bool rprofil } } } - if (rm_flag) { removeProfileFromDisk(DirPath, MSGPACK_REPORTPROFILES_PERSISTENT_FILE); @@ -1515,3 +1514,21 @@ bool isMtlsEnabled(void) #endif #endif } + +#ifdef GTEST_ENABLE +typedef void* (*reportOnDemandFunc)(void*); +reportOnDemandFunc reportOnDemandFuncCallback(void) +{ + return reportOnDemand; +} +typedef void (*freeProfilesHashMapFunc)(void *); +freeProfilesHashMapFunc freeProfilesHashMapFuncCallback(void) +{ + return freeProfilesHashMap; +} +typedef void (*freeReportProfileHashMapFunc)(void *); +freeReportProfileHashMapFunc freeReportProfileHashMapFuncCallback(void) +{ + return freeReportProfileHashMap; +} +#endif diff --git a/source/ccspinterface/rbusInterface.c b/source/ccspinterface/rbusInterface.c index a6a4c605..c566005a 100644 --- a/source/ccspinterface/rbusInterface.c +++ b/source/ccspinterface/rbusInterface.c @@ -1954,9 +1954,11 @@ bool rbusCheckMethodExists(const char* rbusMethodName) return true ; } #ifdef GTEST_ENABLE +#ifdef DCMAGENT typedef void (*rbusReloadConfFunc)(rbusHandle_t, rbusEvent_t const *, rbusEventSubscription_t *); rbusReloadConfFunc rbusReloadConfFuncCallback(void) { return rbusReloadConf; } #endif +#endif diff --git a/source/test/bulkdata/Makefile.am b/source/test/bulkdata/Makefile.am index d0fbbad3..b4413819 100644 --- a/source/test/bulkdata/Makefile.am +++ b/source/test/bulkdata/Makefile.am @@ -18,16 +18,16 @@ # limitations under the License. ########################################################################## -AM_CXXFLAGS = -fno-permissive -std=c++11 -DPERSIST_LOG_MON_REF -fPIC -DPRIVACYMODES_CONTROL -DBULKDATA +AM_CXXFLAGS = -fno-permissive -std=c++11 -DGTEST_ENABLE -DPERSIST_LOG_MON_REF -fPIC -DPRIVACYMODES_CONTROL -DBULKDATA #-DFEATURE_SUPPORT_WEBCONFIG -DDROP_ROOT_PRIV -AM_CFLAGS = -DPERSIST_LOG_MON_REF -fPIC +AM_CFLAGS = -DPERSIST_LOG_MON_REF -DGTEST_ENABLE -fPIC AUTOMAKE_OPTIONS = subdir-objects ACLOCAL_AMFLAGS = -I m4 -bin_PROGRAMS = profile_gtest.bin datamodel_gtest.bin t2markers_gtest.bin profilexconf_gtest.bin +bin_PROGRAMS = profile_gtest.bin datamodel_gtest.bin t2markers_gtest.bin profilexconf_gtest.bin reportprofiles_gtest.bin datamodel_gtest_bin_CPPFLAGS = -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/gtest -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/glib-2.0 -I$(PKG_CONFIG_SYSROOT_DIR)/usr/lib/x86_64-linux-gnu/glib-2.0/include -I$(PKG_CONFIG_SYSROOT_DIR)/usr/local/lib -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/gtest -I${top_srcdir}/gtest/include -I${top_srcdir}/source/include -I${top_srcdir}/source -I${top_srcdir}/source/test/mocks -I${top_srcdir}/source/test/rbus -I${top_srcdir}/source/test/rdk_logger -I${top_srcdir}/include -I${top_srcdir}/source/utils -I${top_srcdir}/source/privacycontrol -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/rbus -I${top_srcdir}/source/dcautil -I${top_srcdir}/source/ccspinterface -I${top_srcdir}/source/reportgen -I${top_srcdir}/source/xconf-client -I${top_srcdir}/source/protocol/http -I${top_srcdir}/source/protocol/rbusMethod -I${top_srcdir}/source/t2parser -I${top_srcdir}/source/bulkdata -I${top_srcdir}/source/scheduler -I${top_srcdir}/source/ccspinterface -I${PKG_CONFIG_SYSROOT_DIR}$(includedir) -I${PKG_CONFIG_SYSROOT_DIR}/usr/src/googletest/googlemock/include -I${RDK_PROJECT_ROOT_PATH}/$(GLIB_CFLAGS) -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/glib-2.0 -I${PKG_CONFIG_SYSROOT_DIR}$(libdir)/glib-2.0/include @@ -51,11 +51,25 @@ profilexconf_gtest_bin_LDFLAGS = -L/usr/src/googletest/googletest/lib/.libs -l profilexconf_gtest_bin_LDFLAGS += -Wl,--wrap=sendReportOverHTTP -Wl,--wrap=sendCachedReportsOverHTTP -profilexconf_gtest_bin_SOURCES = = gtest_main.cpp profilexconfTest.cpp profilexconfMock.cpp SchedulerMock.cpp ../mocks/SystemMock.cpp ../mocks/FileioMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp ../../bulkdata/profilexconf.c ../../utils/vector.c ../../utils/t2log_wrapper.c ../../utils/t2common.c ../../utils/t2collection.c ../../utils/persistence.c ../../bulkdata/t2markers.c ../../reportgen/reportgen.c ../../dcautil/legacyutils.c +profilexconf_gtest_bin_SOURCES = gtest_main.cpp profilexconfTest.cpp profilexconfMock.cpp SchedulerMock.cpp ../mocks/SystemMock.cpp ../mocks/FileioMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp ../../bulkdata/profilexconf.c ../../utils/vector.c ../../utils/t2log_wrapper.c ../../utils/t2common.c ../../utils/t2collection.c ../../utils/persistence.c ../../bulkdata/t2markers.c ../../reportgen/reportgen.c ../../dcautil/legacyutils.c + +profile_gtest_bin_CFLAGS = -DGTEST_ENABLE profile_gtest_bin_CPPFLAGS = -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/gtest -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/glib-2.0 -I$(PKG_CONFIG_SYSROOT_DIR)/usr/lib/x86_64-linux-gnu/glib-2.0/include -I$(PKG_CONFIG_SYSROOT_DIR)/usr/local/lib -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/gtest -I${top_srcdir}/gtest/include -I${top_srcdir}/source/include -I${top_srcdir}/source -I${top_srcdir}/source/test/mocks -I${top_srcdir}/source/test/rbus -I${top_srcdir}/source/test/rdk_logger -I${top_srcdir}/include -I${top_srcdir}/source/utils -I${top_srcdir}/source/privacycontrol -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/rbus -I${top_srcdir}/source/dcautil -I${top_srcdir}/source/ccspinterface -I${top_srcdir}/source/reportgen -I${top_srcdir}/source/xconf-client -I${top_srcdir}/source/protocol/http -I${top_srcdir}/source/protocol/rbusMethod -I${top_srcdir}/source/t2parser -I${top_srcdir}/source/bulkdata -I${top_srcdir}/source/scheduler -I${top_srcdir}/source/ccspinterface -I${PKG_CONFIG_SYSROOT_DIR}$(includedir) -I${PKG_CONFIG_SYSROOT_DIR}/usr/src/googletest/googlemock/include -I${RDK_PROJECT_ROOT_PATH}/$(GLIB_CFLAGS) -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/glib-2.0 -I${PKG_CONFIG_SYSROOT_DIR}$(libdir)/glib-2.0/include -profile_gtest_bin_SOURCES = gtest_main.cpp ../mocks/SystemMock.cpp ../mocks/FileioMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp ../mocks/rdkconfigMock.cpp ../mocks/VectorMock.cpp SchedulerMock.cpp ../../bulkdata/profile.c profileTest.cpp ../../utils/persistence.c ../../utils/t2common.c ../../utils/t2collection.c ../../utils/t2MtlsUtils.c ../../utils/t2log_wrapper.c ../../dcautil/dcautil.c ../../dcautil/dca.c ../../dcautil/legacyutils.c ../../dcautil/dcaproc.c ../../xconf-client/xconfclient.c ../../protocol/rbusMethod/rbusmethodinterface.c ../../privacycontrol/rdkservices_privacyutils.c ../../reportgen/reportgen.c ../../bulkdata/t2eventreceiver.c ../../bulkdata/t2markers.c ../../t2parser/t2parser.c ../../bulkdata/datamodel.c ../../t2parser/t2parserxconf.c ../../bulkdata/reportprofiles.c ../../bulkdata/profilexconf.c ../../ccspinterface/rbusInterface.c ../../ccspinterface/busInterface.c ../../protocol/http/curlinterface.c ../../protocol/http/multicurlinterface.c +profile_gtest_bin_SOURCES = gtest_main.cpp ../mocks/SystemMock.cpp ../mocks/FileioMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp ../mocks/rdkconfigMock.cpp ../mocks/VectorMock.cpp SchedulerMock.cpp profileMock.cpp ../../bulkdata/profile.c profileTest.cpp ../../utils/persistence.c ../../utils/t2common.c ../../utils/t2collection.c ../../utils/t2MtlsUtils.c ../../utils/t2log_wrapper.c ../../dcautil/dcautil.c ../../dcautil/dca.c ../../dcautil/legacyutils.c ../../dcautil/dcaproc.c ../../xconf-client/xconfclient.c ../../protocol/rbusMethod/rbusmethodinterface.c ../../privacycontrol/rdkservices_privacyutils.c ../../reportgen/reportgen.c ../../bulkdata/t2eventreceiver.c ../../bulkdata/t2markers.c ../../t2parser/t2parser.c ../../bulkdata/datamodel.c ../../t2parser/t2parserxconf.c ../../bulkdata/reportprofiles.c ../../bulkdata/profilexconf.c ../../ccspinterface/rbusInterface.c ../../ccspinterface/busInterface.c ../../protocol/http/curlinterface.c ../../protocol/http/multicurlinterface.c profile_gtest_bin_LDFLAGS = -L/usr/src/googletest/googletest/lib/.libs -lgcov -L/src/googletest/googlemock/lib -L/usr/src/googletest/googlemock/lib/.libs -L/usr/include/glib-2.0 -lgmock -lcjson -lcurl -lmsgpackc -lgtest -lgtest_main -lglib-2.0 +profile_gtest_bin_LDFLAGS += -Wl,--wrap=sendReportOverHTTP -Wl,--wrap=sendCachedReportsOverHTTP + +reportprofiles_gtest_bin_CFLAGS = -DGTEST_ENABLE + +reportprofiles_gtest_bin_CPPFLAGS = -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/gtest -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/glib-2.0 -I$(PKG_CONFIG_SYSROOT_DIR)/usr/lib/x86_64-linux-gnu/glib-2.0/include -I$(PKG_CONFIG_SYSROOT_DIR)/usr/local/lib -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/gtest -I${top_srcdir}/gtest/include -I${top_srcdir}/source/include -I${top_srcdir}/source -I${top_srcdir}/source/test/mocks -I${top_srcdir}/source/test/rbus -I${top_srcdir}/source/test/rdk_logger -I${top_srcdir}/include -I${top_srcdir}/source/utils -I${top_srcdir}/source/privacycontrol -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/rbus -I${top_srcdir}/source/dcautil -I${top_srcdir}/source/ccspinterface -I${top_srcdir}/source/reportgen -I${top_srcdir}/source/xconf-client -I${top_srcdir}/source/protocol/http -I${top_srcdir}/source/protocol/rbusMethod -I${top_srcdir}/source/t2parser -I${top_srcdir}/source/bulkdata -I${top_srcdir}/source/scheduler -I${top_srcdir}/source/ccspinterface -I${PKG_CONFIG_SYSROOT_DIR}$(includedir) -I${PKG_CONFIG_SYSROOT_DIR}/usr/src/googletest/googlemock/include -I${RDK_PROJECT_ROOT_PATH}/$(GLIB_CFLAGS) -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/glib-2.0 -I${PKG_CONFIG_SYSROOT_DIR}$(libdir)/glib-2.0/include + +reportprofiles_gtest_bin_SOURCES = gtest_main.cpp ../mocks/SystemMock.cpp ../mocks/FileioMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp ../mocks/rdkconfigMock.cpp ../mocks/VectorMock.cpp SchedulerMock.cpp reportprofileMock.cpp ../../bulkdata/reportprofiles.c reportprofilesTest.cpp ../../utils/persistence.c ../../utils/t2common.c ../../utils/t2collection.c ../../utils/t2MtlsUtils.c ../../utils/t2log_wrapper.c ../../dcautil/dcautil.c ../../dcautil/dca.c ../../dcautil/legacyutils.c ../../dcautil/dcaproc.c ../../xconf-client/xconfclient.c ../../protocol/rbusMethod/rbusmethodinterface.c ../../privacycontrol/rdkservices_privacyutils.c ../../reportgen/reportgen.c ../../bulkdata/t2eventreceiver.c ../../bulkdata/t2markers.c ../../t2parser/t2parser.c ../../bulkdata/datamodel.c ../../t2parser/t2parserxconf.c ../../bulkdata/profile.c ../../bulkdata/profilexconf.c ../../ccspinterface/rbusInterface.c ../../ccspinterface/busInterface.c ../../protocol/http/curlinterface.c ../../protocol/http/multicurlinterface.c + +reportprofiles_gtest_bin_LDFLAGS = -L/usr/src/googletest/googletest/lib/.libs -L/usr/src/googletest/googlemock/lib/.libs -lgmock -lgtest -lpthread -lcjson -lmsgpackc -lglib-2.0 -lrt -lcurl + +reportprofiles_gtest_bin_LDFLAGS += -Wl,--wrap=isRbusEnabled -Wl,--wrap=sendReportOverHTTP -Wl,--wrap=sendCachedReportsOverHTTP + diff --git a/source/test/bulkdata/profileMock.cpp b/source/test/bulkdata/profileMock.cpp new file mode 100644 index 00000000..0a295e19 --- /dev/null +++ b/source/test/bulkdata/profileMock.cpp @@ -0,0 +1,45 @@ +/* +* Copyright 2020 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. +* +* SPDX-License-Identifier: Apache-2.0 +*/ +#include +#include +#include "vector.h" +#include "msgpack.h" +#include "test/bulkdata/profileMock.h" + + +//protocol mock functions +extern "C" T2ERROR __wrap_sendReportOverHTTP(char *httpUrl, char *payload) +{ + if(!g_profileMock) + { + return T2ERROR_FAILURE; + } + // No mock function needed, just a stub + return g_profileMock->sendReportOverHTTP(httpUrl, payload); +} + +extern "C" T2ERROR __wrap_sendCachedReportsOverHTTP(char *httpUrl, Vector *reportList) +{ + if(!g_profileMock) + { + return T2ERROR_FAILURE; + } + // No mock function needed, just a stub + return g_profileMock->sendCachedReportsOverHTTP(httpUrl, reportList); +} + diff --git a/source/test/bulkdata/profileMock.h b/source/test/bulkdata/profileMock.h new file mode 100644 index 00000000..f6f7c6ef --- /dev/null +++ b/source/test/bulkdata/profileMock.h @@ -0,0 +1,35 @@ +/* +* Copyright 2020 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. +* +* SPDX-License-Identifier: Apache-2.0 +*/ +//#ifndef SOURCE_TEST_MOCKS_SYSTEMMOCK_H_ +//#define SOURCE_TEST_MOCKS_SYSTEMMOCK_H_ + +#include +#include +#include "telemetry2_0.h" + + +class profileMock +{ +public: + + MOCK_METHOD(T2ERROR, sendReportOverHTTP, (char *httpUrl, char *payload), ()); + MOCK_METHOD(T2ERROR, sendCachedReportsOverHTTP, (char *httpUrl, Vector *reportList), ()); +}; + +extern profileMock *g_profileMock; + diff --git a/source/test/bulkdata/profileTest.cpp b/source/test/bulkdata/profileTest.cpp index 7626f48d..09108f6d 100644 --- a/source/test/bulkdata/profileTest.cpp +++ b/source/test/bulkdata/profileTest.cpp @@ -17,6 +17,7 @@ #include "test/mocks/rdkconfigMock.h" #include "test/mocks/VectorMock.h" #include "test/bulkdata/SchedulerMock.h" +#include "test/bulkdata/profileMock.h" using namespace std; @@ -34,6 +35,8 @@ extern "C" { #include "profilexconf.h" #include "t2eventreceiver.h" #include "msgpack.h" +#include +#include extern bool initialized; @@ -46,6 +49,7 @@ SystemMock * g_systemMock = NULL; rdklogMock *m_rdklogMock = NULL; rbusMock *g_rbusMock = NULL; rdkconfigMock *g_rdkconfigMock = nullptr; +profileMock *g_profileMock = nullptr; extern VectorMock *g_vectorMock; extern SchedulerMock *g_schedulerMock; @@ -59,6 +63,7 @@ class ProfileTest : public ::testing::Test { g_rdkconfigMock = new rdkconfigMock(); g_vectorMock = new VectorMock(); g_schedulerMock = new SchedulerMock(); + g_profileMock = new profileMock(); } void TearDown() override { @@ -68,6 +73,7 @@ class ProfileTest : public ::testing::Test { delete g_rdkconfigMock; delete g_vectorMock; delete g_schedulerMock; + delete g_profileMock; g_fileIOMock = nullptr; g_systemMock = nullptr; @@ -75,6 +81,7 @@ class ProfileTest : public ::testing::Test { g_rdkconfigMock = nullptr; g_vectorMock = nullptr; g_schedulerMock = nullptr; + g_profileMock = nullptr; } }; @@ -225,6 +232,28 @@ TEST_F(ProfileTest, UninitProfileList_Success) { EXPECT_EQ(uninitProfileList(), T2ERROR_SUCCESS); } +TEST_F(ProfileTest, ReportProfiles_uninit) { + EXPECT_CALL(*g_vectorMock, Vector_Create(_)) + .Times(::testing::AtMost(3)) + .WillRepeatedly(Return(T2ERROR_SUCCESS)); + EXPECT_CALL(*g_vectorMock, Vector_PushBack(_, _)) + .Times(::testing::AtMost(1)) + .WillRepeatedly(Return(T2ERROR_SUCCESS)); + EXPECT_CALL(*g_vectorMock, Vector_Size(_)) + .Times(::testing::AtMost(3)) + .WillRepeatedly(Return(0)); + EXPECT_CALL(*g_vectorMock, Vector_At(_, _)) + .Times(::testing::AtMost(2)) + .WillRepeatedly(Return(nullptr)); + EXPECT_CALL(*g_schedulerMock, uninitScheduler()) + .Times(::testing::AtMost(1)); + EXPECT_CALL(*g_schedulerMock, unregisterProfileFromScheduler(_)) + .Times(::testing::AtMost(5)) + .WillRepeatedly(Return(T2ERROR_SUCCESS)); + + EXPECT_EQ(ReportProfiles_uninit(), T2ERROR_FAILURE); +} + // Test getProfileCount TEST_F(ProfileTest, GetProfileCount_NotInitialized) { EXPECT_CALL(*g_vectorMock, Vector_Size(_)) @@ -759,6 +788,14 @@ TEST_F(ProfileTest, ReportProfiles_deleteProfileXConf) { } #endif +TEST_F(ProfileTest, ReportProfiles_deleteProfileXConf_EmptyList) { + ProfileXConf profile; + EXPECT_CALL(*g_vectorMock, Vector_Size(_)) + .Times(::testing::AtMost(1)) + .WillRepeatedly(Return(0)); // Return 1 to indicate only one profile (no duplicates) + EXPECT_EQ(ReportProfiles_deleteProfileXConf(&profile), T2ERROR_SUCCESS); +} + TEST_F(ProfileTest, ReportProfiles_deleteProfile) { EXPECT_CALL(*g_vectorMock, Vector_Size(_)) .Times(::testing::AtMost(2)) @@ -810,7 +847,16 @@ TEST_F(ProfileTest, RemovePreRPfromDisk) { EXPECT_EQ(RemovePreRPfromDisk("/tmp", &dummy), T2ERROR_SUCCESS); } -#if 0 +TEST_F(ProfileTest, RemovePreRPfromDisk_FailsIfDirNull) { + hash_map_t dummy; + // Mock opendir to return NULL to simulate failure + EXPECT_CALL(*g_fileIOMock, opendir(_)) + .Times(1) + .WillOnce(Return(nullptr)); + // readdir and closedir should NOT be called in this branch + EXPECT_EQ(RemovePreRPfromDisk("/tmp", &dummy), T2ERROR_FAILURE); +} + TEST_F(ProfileTest, deleteAllReportProfiles) { EXPECT_CALL(*g_vectorMock, Vector_Size(_)) .Times(::testing::AtMost(1)) @@ -819,56 +865,67 @@ TEST_F(ProfileTest, deleteAllReportProfiles) { .WillRepeatedly(Return(T2ERROR_SUCCESS)); EXPECT_EQ(deleteAllReportProfiles(), T2ERROR_SUCCESS); } -#endif -#if 0 -TEST_F(ProfileTest, isMtlsEnabled) { - char status[8] = "true"; - EXPECT_CALL(*g_rbusMock, rbus_get(_,_,_)) - .Times(::testing::AtMost(2)) - .WillRepeatedly(Return(RBUS_ERROR_SUCCESS)); - EXPECT_CALL(*g_rbusMock, rbusValue_GetType(_)) - .Times(::testing::AtMost(2)) - .WillRepeatedly(Return(RBUS_BOOLEAN)); - EXPECT_CALL(*g_rbusMock, rbusValue_GetBoolean(_)) - .Times(::testing::AtMost(2)) - .WillRepeatedly(Return(RBUS_ERROR_SUCCESS)); - EXPECT_CALL(*g_rbusMock, rbusValue_Release(_)) - .Times(::testing::AtMost(2)) - .WillRepeatedly(Return()); - EXPECT_CALL(*g_rbusMock, rbusValue_ToString(_,_,_)) - .Times(::testing::AtMost(1)) - .WillRepeatedly(Return(status)); - EXPECT_TRUE(isMtlsEnabled()); -} -#endif +#ifdef GTEST_ENABLE +extern "C" { +typedef void* (*reportOnDemandFunc)(void*); +reportOnDemandFunc reportOnDemandFuncCallback(void); +typedef void (*freeProfilesHashMapFunc)(void *); +freeProfilesHashMapFunc freeProfilesHashMapFuncCallback(void); +typedef void (*freeReportProfileHashMapFunc)(void *); +freeReportProfileHashMapFunc freeReportProfileHashMapFuncCallback(void); +typedef void (*__msgpack_free_blobFunc)(void*); +__msgpack_free_blobFunc __msgpack_free_blobFuncCallback(void); +} + +TEST(ReportProfilesCallbacks, FreeProfilesHashMap) { + auto cb = freeProfilesHashMapFuncCallback(); + ASSERT_NE(cb, nullptr); + + // Test with an actual element + hash_element_t* item = (hash_element_t*) std::malloc(sizeof(hash_element_t)); + item->key = (char*) std::malloc(12); + std::strcpy(item->key, "testkey"); + item->data = std::malloc(8); + cb(item); + + // Test with nullptr + cb(nullptr); +} +TEST_F(ProfileTest, reportOnDemandTest) +{ + reportOnDemandFunc func = reportOnDemandFuncCallback(); + ASSERT_NE(func,nullptr); + func((void*)"ABORT"); + func((void*)"FOO"); + func(nullptr); +} + +TEST(ReportProfilesCallbacks, FreeReportProfileHashMap) { + auto cb = freeReportProfileHashMapFuncCallback(); + ASSERT_NE(cb, nullptr); + + // Make an item with ReportProfile-like .data + hash_element_t* item = (hash_element_t*) std::malloc(sizeof(hash_element_t)); + item->key = (char*) std::malloc(12); + std::strcpy(item->key, "profkey"); + struct ReportProfile { + char* hash; + char* config; + void* hash_map_pad; // just to align with how your system might fill it, can be omitted + }; + ReportProfile* rp = (ReportProfile*) std::malloc(sizeof(ReportProfile)); + rp->hash = (char*) std::malloc(6); + std::strcpy(rp->hash, "hashV"); + rp->config = (char*) std::malloc(8); + std::strcpy(rp->config, "cfgVal"); + item->data = rp; -#if 0 -TEST_F(ProfileTest, ReportProfiles_uninit) { - EXPECT_CALL(*g_vectorMock, Vector_Create(_)) - .Times(::testing::AtMost(3)) // 1 for local test configlist, 1 for global profileList, 1 for configList in loadReportProfilesFromDisk - .WillRepeatedly(Return(T2ERROR_SUCCESS)); - EXPECT_CALL(*g_vectorMock, Vector_PushBack(_, _)) - .Times(::testing::AtMost(1)) - .WillRepeatedly(Return(T2ERROR_SUCCESS)); - EXPECT_CALL(*g_vectorMock, Vector_Size(_)) - .Times(::testing::AtMost(3)) // May be called multiple times - in deleteAllProfiles, etc. - .WillRepeatedly(Return(0)); // Return 0 to indicate no profiles (avoid unregister calls) - EXPECT_CALL(*g_vectorMock, Vector_At(_, _)) - .Times(::testing::AtMost(2)) // May be called if profiles exist - .WillRepeatedly(Return(nullptr)); - - // Scheduler mock expectations - uninitScheduler is definitely called - EXPECT_CALL(*g_schedulerMock, uninitScheduler()) - .Times(::testing::AtMost(1)); - - // unregisterProfileFromScheduler may be called for each profile during deleteAllProfiles - // Using AtMost to handle cases where profiles exist - EXPECT_CALL(*g_schedulerMock, unregisterProfileFromScheduler(_)) - .Times(::testing::AtMost(5)) // Allow up to 5 calls in case profiles exist - .WillRepeatedly(Return(T2ERROR_SUCCESS)); - - EXPECT_EQ(ReportProfiles_uninit(), T2ERROR_SUCCESS); + cb(item); + + // Safe to call with nullptr + cb(nullptr); + SUCCEED(); } #endif #endif @@ -877,6 +934,13 @@ TEST_F(ProfileTest, ReportProfiles_uninit) { //comment //=================================== profilexconf.c ================================ + +#ifdef GTEST_ENABLE +extern "C" { + void test_set_reportThreadExits(bool value); + } +#endif + TEST_F(ProfileTest, InitAndUninit) { // Covers ProfileXConf_init and ProfileXConf_uninit #if 1 @@ -921,11 +985,21 @@ TEST_F(ProfileTest, SetAndIsSet) { profile->cachedReportList = nullptr; profile->protocol = strdup("HTTP"); profile->encodingType = strdup("JSON"); - profile->t2HTTPDest = nullptr; - profile->grepSeekProfile = nullptr; + profile->jsonReportObj = nullptr; // types now match + profile->checkPreviousSeek = true; + + profile->t2HTTPDest = (T2HTTP *)malloc(sizeof(T2HTTP)); + profile->t2HTTPDest->URL = strdup("https://mock1xconf:50051/dataLakeMockXconf"); + profile->isUpdated = true; + GrepSeekProfile *gsProfile = (GrepSeekProfile *)malloc(sizeof(GrepSeekProfile)); + if (gsProfile) + { + gsProfile->logFileSeekMap = hash_map_create(); + gsProfile->execCounter = 0; + } + profile->grepSeekProfile = gsProfile; + //profile->grepSeekProfile = nullptr; profile->reportInProgress = false; - profile->isUpdated = false; - EXPECT_CALL(*g_vectorMock, Vector_Size(_)) .Times(::testing::AtMost(3)) .WillRepeatedly(Return(0)); // Return 1 to indicate one profile in the list @@ -938,26 +1012,29 @@ TEST_F(ProfileTest, SetAndIsSet) { EXPECT_CALL(*g_vectorMock, Vector_PushBack(_, _)) .Times(::testing::AtMost(3)) .WillRepeatedly(Return(T2ERROR_SUCCESS)); - + // Scheduler mock expectations - ProfileXConf_set calls registerProfileWithScheduler EXPECT_CALL(*g_schedulerMock, registerProfileWithScheduler(_, _, _, _, _, _, _, _)) .Times(::testing::AtMost(1)) .WillRepeatedly(Return(T2ERROR_SUCCESS)); - + EXPECT_EQ(ProfileXConf_set(profile), T2ERROR_SUCCESS); EXPECT_TRUE(ProfileXConf_isSet()); + // Get name char* name = ProfileXconf_getName(); ASSERT_NE(name, nullptr); EXPECT_STREQ(name, "TestProfile"); free(name); - // Clean up - ProfileXConf_uninit calls unregisterProfileFromScheduler - EXPECT_CALL(*g_schedulerMock, unregisterProfileFromScheduler(_)) - .Times(::testing::AtMost(1)) - .WillRepeatedly(Return(T2ERROR_SUCCESS)); - + test_set_reportThreadExits(true); + generateDcaReport(false,true); + EXPECT_CALL(*g_schedulerMock, SendInterruptToTimeoutThread(_)) + .Times(::testing::AtMost(1)); + + ReportProfiles_Interrupt(); + EXPECT_EQ(ProfileXConf_uninit(), T2ERROR_SUCCESS); } @@ -1097,6 +1174,7 @@ TEST_F(ProfileTest, DeleteProfile) { profile->isUpdated = false; ProfileXConf_set(profile); + EXPECT_EQ(ReportProfiles_setProfileXConf(profile),T2ERROR_FAILURE); EXPECT_EQ(ProfileXConf_delete(profile), T2ERROR_FAILURE); ProfileXConf_uninit(); } diff --git a/source/test/bulkdata/reportprofileMock.cpp b/source/test/bulkdata/reportprofileMock.cpp new file mode 100644 index 00000000..50cd748b --- /dev/null +++ b/source/test/bulkdata/reportprofileMock.cpp @@ -0,0 +1,54 @@ +/* +* Copyright 2020 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. +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +#include +#include +#include "vector.h" +#include "test/bulkdata/reportprofileMock.h" + + + +// Mock Method + +extern "C" bool __wrap_isRbusEnabled() +{ + if (!g_reportprofileMock) + { + return false; + } + return g_reportprofileMock->isRbusEnabled(); +} + +extern "C" { +T2ERROR __wrap_sendReportOverHTTP(char *httpUrl, char *payload) +{ + if (g_reportprofileMock) { + return g_reportprofileMock->sendReportOverHTTP(httpUrl, payload); + } + return T2ERROR_FAILURE; +} + +T2ERROR __wrap_sendCachedReportsOverHTTP(char *httpUrl, Vector *reportList) +{ + if (g_reportprofileMock) { + return g_reportprofileMock->sendCachedReportsOverHTTP(httpUrl, reportList); + } + return T2ERROR_FAILURE; +} +} + diff --git a/source/test/bulkdata/reportprofileMock.h b/source/test/bulkdata/reportprofileMock.h new file mode 100644 index 00000000..24e19294 --- /dev/null +++ b/source/test/bulkdata/reportprofileMock.h @@ -0,0 +1,36 @@ +/* +* Copyright 2020 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. +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +#pragma once + +#include +#include + + +#include "telemetry2_0.h" + +class reportprofileMock +{ +public: + + MOCK_METHOD(bool, isRbusEnabled, (), ()); + MOCK_METHOD(T2ERROR, sendReportOverHTTP, (char *httpUrl, char *payload), ()); + MOCK_METHOD(T2ERROR, sendCachedReportsOverHTTP, (char *httpUrl, Vector *reportList), ()); +}; + +extern reportprofileMock *g_reportprofileMock; diff --git a/source/test/bulkdata/reportprofilesTest.cpp b/source/test/bulkdata/reportprofilesTest.cpp new file mode 100644 index 00000000..cea0c380 --- /dev/null +++ b/source/test/bulkdata/reportprofilesTest.cpp @@ -0,0 +1,163 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2026 RDK Management + * + * 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 + +extern "C" { +#include "reportprofiles.h" +#include "profile.h" +#include "t2eventreceiver.h" +#include "t2collection.h" +#include "t2log_wrapper.h" +#include "msgpack.h" +#include +#include +} + +#include "test/mocks/SystemMock.h" +#include "test/mocks/FileioMock.h" +#include "test/mocks/rdklogMock.h" +#include "test/mocks/rbusMock.h" +#include "test/mocks/rdkconfigMock.h" +#include "test/mocks/VectorMock.h" +#include "test/bulkdata/SchedulerMock.h" +#include "reportprofileMock.h" + +using namespace std; +using ::testing::_; +using ::testing::Return; +using ::testing::StrEq; +using ::testing::Invoke; +// Create global mocks if you need them just like t2markersTest.cpp +FileMock *g_fileIOMock = NULL; +SystemMock * g_systemMock = NULL; +rdklogMock *m_rdklogMock = NULL; +rbusMock *g_rbusMock = NULL; +rdkconfigMock *g_rdkconfigMock = nullptr; +extern VectorMock *g_vectorMock; +extern SchedulerMock *g_schedulerMock; +reportprofileMock* g_reportprofileMock = nullptr; +// Test fixture for reportprofiles +class reportprofilesTestFixture : public ::testing::Test { +protected: + void SetUp() override { + g_reportprofileMock = new reportprofileMock(); + g_systemMock = new SystemMock(); + g_fileIOMock = new FileMock(); + m_rdklogMock = new rdklogMock(); + g_rbusMock = new rbusMock(); + g_vectorMock = new VectorMock(); + } + void TearDown() override { + delete g_reportprofileMock; + delete g_systemMock; + delete g_fileIOMock; + delete m_rdklogMock; + delete g_rbusMock; + delete g_vectorMock; + g_reportprofileMock = nullptr; + g_systemMock = nullptr; + g_fileIOMock = nullptr; + m_rdklogMock = nullptr; + g_rbusMock = nullptr; + g_vectorMock = nullptr; + } +}; + + +TEST_F(reportprofilesTestFixture, ProcessMsgPackBlob_InvalidFormat) { + struct __msgpack__ msg; + msg.msgpack_blob = nullptr; + msg.msgpack_blob_size = 0; + int ret = __ReportProfiles_ProcessReportProfilesMsgPackBlob(&msg, false); + EXPECT_EQ(ret, T2ERROR_INVALID_ARGS); +} + +TEST_F(reportprofilesTestFixture, ProcessMsgPackBlob_Test1) { + const char *data = "AQ=="; + gsize decodedDataLen = 0; + guchar *webConfigString = g_base64_decode(data, &decodedDataLen); + + struct __msgpack__ *msg = (struct __msgpack__*)malloc(sizeof(struct __msgpack__)); + msg->msgpack_blob = (char*)webConfigString; + msg->msgpack_blob_size = (int)decodedDataLen; + + EXPECT_CALL(*g_vectorMock, Vector_Size(_)) + .Times(::testing::AtMost(1)) + .WillRepeatedly(Return(0)); + EXPECT_CALL(*g_vectorMock, Vector_Destroy(_, _)).Times(::testing::AtMost(1)) + .WillRepeatedly(Return(T2ERROR_SUCCESS)); + + ReportProfiles_ProcessReportProfilesMsgPackBlob(msg->msgpack_blob, msg->msgpack_blob_size); +} + +TEST_F(reportprofilesTestFixture, ProcessReportProfilesBlob_EmptyProfile_T2_TEMP_RP) { + cJSON *root = cJSON_CreateObject(); + cJSON *profiles = cJSON_CreateArray(); + cJSON_AddItemToObject(root, "profiles", profiles); + ReportProfiles_ProcessReportProfilesBlob(root, T2_TEMP_RP); + cJSON_Delete(root); +} + +TEST_F(reportprofilesTestFixture, ProcessReportProfilesBlob_EmptyProfile_Normal) { + cJSON *root = cJSON_CreateObject(); + cJSON *profiles = cJSON_CreateArray(); + cJSON_AddItemToObject(root, "profiles", profiles); + EXPECT_CALL(*g_vectorMock, Vector_Size(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*g_vectorMock, Vector_Destroy(_, _)).WillRepeatedly(Return(T2ERROR_SUCCESS)); + ReportProfiles_ProcessReportProfilesBlob(root, T2_RP); // normal, triggers deleteAllReportProfiles + cJSON_Delete(root); +} + +TEST_F(reportprofilesTestFixture, ProcessReportProfilesBlob_AddNewProfile) { + cJSON *root = cJSON_CreateObject(); + cJSON *profiles = cJSON_CreateArray(); + cJSON_AddItemToObject(root, "profiles", profiles); + cJSON *profile = cJSON_CreateObject(); + cJSON_AddStringToObject(profile, "name", "newprofile"); + cJSON_AddStringToObject(profile, "hash", "newhash"); + cJSON *value = cJSON_CreateObject(); + cJSON_AddStringToObject(value, "param", "value"); + cJSON_AddItemToObject(profile, "value", value); + cJSON_AddItemToArray(profiles, profile); + + EXPECT_CALL(*g_reportprofileMock, isRbusEnabled()) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*g_vectorMock, Vector_Size(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*g_vectorMock, Vector_Destroy(_, _)).WillRepeatedly(Return(T2ERROR_SUCCESS)); + + DIR *dir = reinterpret_cast(1); + + EXPECT_CALL(*g_fileIOMock, opendir(_)) + .Times(::testing::AtMost(1)) + .WillRepeatedly(Return(dir)); + EXPECT_CALL(*g_fileIOMock, readdir(_)) + .Times(::testing::AtMost(1)) + .WillRepeatedly(Return((struct dirent *)NULL)); + EXPECT_CALL(*g_fileIOMock, closedir(_)) + .Times(::testing::AtMost(1)) + .WillRepeatedly(Return(0)); + ReportProfiles_ProcessReportProfilesBlob(root, T2_RP); + cJSON_Delete(root); +} +TEST_F(reportprofilesTestFixture, ProcessReportProfilesMsgPackBlob_NullBlob) { + ReportProfiles_ProcessReportProfilesMsgPackBlob(NULL,0); +} + diff --git a/test/run_ut.sh b/test/run_ut.sh index 7c5b942a..90f897f5 100755 --- a/test/run_ut.sh +++ b/test/run_ut.sh @@ -49,6 +49,7 @@ tests=" ./source/test/bulkdata/datamodel_gtest.bin ./source/test/bulkdata/profilexconf_gtest.bin ./source/test/bulkdata/t2markers_gtest.bin +./source/test/bulkdata/reportprofiles_gtest.bin ./source/test/reportgen/reportgen_gtest.bin ./source/test/scheduler/scheduler_gtest.bin ./source/test/t2parser/t2parser_gtest.bin