diff --git a/source/hotspotfd/hotspotfd.c b/source/hotspotfd/hotspotfd.c index 786e9c3..59e55bf 100644 --- a/source/hotspotfd/hotspotfd.c +++ b/source/hotspotfd/hotspotfd.c @@ -195,6 +195,8 @@ rbusHandle_t handle; STATIC pthread_t dhcp_snooper_tid; +char TunnelStatus[8] = {0}; + int gSnoopNumberOfClients = 0; //shared variable across hotspotfd and dhcp_snooperd bool gSnoopEnable = true; @@ -308,84 +310,92 @@ HotspotfdType Get_HotspotfdType(char * name) return HOTSPOTFD_ERROR; } -STATIC bool set_tunnelstatus(char* status) { - - CCSP_MESSAGE_BUS_INFO *bus_info = (CCSP_MESSAGE_BUS_INFO *)bus_handle; - parameterValStruct_t *param_val = NULL; - char component[256] = "eRT.com.cisco.spvtg.ccsp.pam"; - char dstPath[64]="/com/cisco/spvtg/ccsp/pam"; - const char tunparam[]="Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus"; - char* faultParam = NULL; - int ret = 0; - - param_val = (parameterValStruct_t*)malloc(sizeof(parameterValStruct_t)); - if (NULL == param_val) - { - CcspTraceError(("Memory allocation failed in hotspot \n")); - return FALSE; +STATIC void notify_tunnel_status(char *status) +{ + rbusEvent_t event; + rbusObject_t data; + rbusValue_t value; + rbusError_t ret; + + strncpy(TunnelStatus, status, sizeof(TunnelStatus) - 1); + TunnelStatus[sizeof(TunnelStatus) - 1] = '\0'; + CcspTraceInfo(("%s:%d : TunnelStatus set to %s\n", __FUNCTION__, __LINE__, TunnelStatus)); + + rbusValue_Init(&value); + rbusValue_SetString(value, status); + rbusObject_Init(&data, NULL); + rbusObject_SetValue(data, "TunnelStatus", value); + + event.name = "Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus"; + event.type = RBUS_EVENT_GENERAL; + event.data = data; + + ret = rbusEvent_Publish(handle, &event); + + if(ret != RBUS_ERROR_SUCCESS) { + CcspTraceError(("%s:%d : rbusEvent_Publish failed: %d\n", __FUNCTION__, __LINE__, ret)); + } + else { + CcspTraceInfo(("%s:%d : rbusEvent_Publish success\n", __FUNCTION__, __LINE__)); } - param_val->parameterName = (char*)tunparam; - param_val->parameterValue=AnscCloneString(status); - CcspTraceInfo(("Setting tunnel status to %s\n", status)); - param_val->type = ccsp_string; - - ret = CcspBaseIf_setParameterValues( - bus_handle, - component, - dstPath, - 0, - 0, - param_val, - 1, - TRUE, - &faultParam - ); - - if( ( ret != CCSP_SUCCESS ) && ( faultParam!=NULL )) { - CcspTraceError(("TunnelStatus set bus failed\n")); - bus_info->freefunc( faultParam ); - if(param_val) - { - free(param_val); - param_val = NULL; - } - return FALSE; + rbusValue_Release(value); + rbusObject_Release(data); + + if(strcmp("Down",status) == 0) + { + gVapIsUp = false; } - if(param_val) + else if(strcmp("Up",status) == 0) { - free(param_val); - param_val = NULL; + gVapIsUp = true; } - return TRUE; } -STATIC void notify_tunnel_status(char *status) +rbusError_t TunnelStatus_GetStringHandler(rbusHandle_t handle, rbusProperty_t property, rbusGetHandlerOptions_t* opts) +{ + (void)handle; + (void)opts; + + //set value + rbusValue_t val; + rbusValue_Init(&val); + rbusValue_SetString(val, TunnelStatus); + rbusProperty_SetValue(property, val); + rbusValue_Release(val); + + return RBUS_ERROR_SUCCESS; +} + +rbusError_t TunnelStatus_SetStringHandler(rbusHandle_t handle, rbusProperty_t property, rbusSetHandlerOptions_t* opts) { - int ret; - if(set_tunnelstatus(status)) + (void)handle; + (void)opts; + + int ret = RBUS_ERROR_SUCCESS; + + rbusValue_t value = rbusProperty_GetValue(property); + const char* newStatus = rbusValue_GetString(value, NULL); + + if(newStatus && (strcmp(newStatus, "Up") == 0 || strcmp(newStatus, "Down") == 0)) { - CcspTraceInfo(("TunnelStatus set to %s in TR181\n", status)); + if(strcmp(TunnelStatus, newStatus) != 0){ + + CcspTraceInfo(("%s:%d : Calling notify_tunnel_status with %s\n", __FUNCTION__, __LINE__, newStatus)); + + notify_tunnel_status((char *)newStatus); + } + else{ + CcspTraceInfo(("%s:%d : TunnelStatus is already %s, no change\n", __FUNCTION__, __LINE__, TunnelStatus)); + } } else { - CcspTraceError(("Error setting TunnelStatus in TR181 Data Model\n")); - } - ret = CcspBaseIf_SendSignal_WithData(bus_handle, - "Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus", status); - if ( ret != CCSP_SUCCESS ) - { - CcspTraceError(("%s : TunnelStatus send rbus data failed, ret value is %d\n", - __FUNCTION__ ,ret)); - } - if(strcmp("Down",status) == 0) - { - gVapIsUp = false; - } - else if(strcmp("Up",status) == 0) - { - gVapIsUp = true; + CcspTraceError(("%s:%d : Invalid TunnelStatus value: %s\n", __FUNCTION__, __LINE__, newStatus ? newStatus : "NULL")); + ret = RBUS_ERROR_INVALID_INPUT; } + + return ret; } STATIC bool set_validatessid() { @@ -2046,17 +2056,27 @@ void hotspot_start() hotspotfd_log(); #ifdef WAN_FAILOVER_SUPPORTED - + rbusDataElement_t dataElements[1] = { + {"Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus", RBUS_ELEMENT_TYPE_EVENT | RBUS_ELEMENT_TYPE_PROPERTY, {TunnelStatus_GetStringHandler, TunnelStatus_SetStringHandler, NULL, NULL, NULL, NULL}} + }; ret = rbus_open(&handle, "HotspotTunnelEvent"); if(ret != RBUS_ERROR_SUCCESS) { CcspTraceError(("HotspotTunnelEvent : rbus_open failed: %d\n", ret)); return; } + ret = rbus_regDataElements(handle, 1, dataElements); + if(ret != RBUS_ERROR_SUCCESS) + { + CcspTraceError(("Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus rbus_regDataElements failed: %d\n", ret)); + return; + } + else{ + CcspTraceInfo(("Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus is registered in rbus")); + } pthread_create(&rbus_tid, NULL, handle_rbusSubscribe, NULL); #endif - if (sysevent_set(sysevent_fd_gs, sysevent_token_gs, kHotspotfd_tunnelEP, kDefault_DummyEP, 0)) { CcspTraceError(("sysevent set %s failed for %s\n", kHotspotfd_tunnelEP, kDefault_DummyEP)); @@ -2406,4 +2426,4 @@ void hotspot_start() } goto keep_it_alive; -} +} \ No newline at end of file diff --git a/source/hotspotfd/include/hotspotfd.h b/source/hotspotfd/include/hotspotfd.h index 59fecf4..53f46e3 100644 --- a/source/hotspotfd/include/hotspotfd.h +++ b/source/hotspotfd/include/hotspotfd.h @@ -137,7 +137,8 @@ bool deleteSharedMem(int key, bool snooper); void hotspot_start(); #ifdef UNIT_TEST_DOCKER_SUPPORT -bool set_tunnelstatus(char* status); +rbusError_t TunnelStatus_GetStringHandler(rbusHandle_t handle, rbusProperty_t property, rbusGetHandlerOptions_t* opts); +rbusError_t TunnelStatus_SetStringHandler(rbusHandle_t handle, rbusProperty_t property, rbusSetHandlerOptions_t* opts); void notify_tunnel_status(char *status); bool set_validatessid(); bool get_validate_ssid(); diff --git a/source/test/HotspotFdTest/HotspotFdTest.cpp b/source/test/HotspotFdTest/HotspotFdTest.cpp index bc96166..17417a6 100755 --- a/source/test/HotspotFdTest/HotspotFdTest.cpp +++ b/source/test/HotspotFdTest/HotspotFdTest.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "test/mocks/mock_hotspotApi.h" extern "C" { @@ -69,6 +70,7 @@ SecureWrapperMock * g_securewrapperMock = nullptr; HotspotApiMock * g_hotspotApiMock = nullptr; NfQueueMock * g_nfQueueMock = nullptr; SocketMock * g_socketMock = nullptr; +rbusMock *g_rbusMock = nullptr; class HotspotFdTestFixture : public ::testing::Test { protected: @@ -85,6 +87,7 @@ class HotspotFdTestFixture : public ::testing::Test { HotspotApiMock mockedHotspotApi; NfQueueMock mockedNfQueue; SocketMock mockedSocket; + rbusMock mockedRbus; HotspotFdTestFixture() { @@ -104,6 +107,7 @@ class HotspotFdTestFixture : public ::testing::Test { g_hotspotApiMock = &mockedHotspotApi; g_nfQueueMock = &mockedNfQueue; g_socketMock = &mockedSocket; + g_rbusMock = &mockedRbus; } virtual ~HotspotFdTestFixture() { @@ -120,6 +124,7 @@ class HotspotFdTestFixture : public ::testing::Test { g_hotspotApiMock = nullptr; g_nfQueueMock = nullptr; g_socketMock = nullptr; + g_rbusMock = nullptr; } virtual void SetUp() @@ -149,6 +154,8 @@ class HotspotFdTestFixture : public ::testing::Test { } }; +extern char TunnelStatus[8]; + void createFile(const char* fname) { if ((file = fopen(fname, "r"))) { fclose(file); @@ -414,58 +421,136 @@ TEST_F(HotspotFdTestFixture, deleteSharedMem_CASE_2) { EXPECT_EQ(true, result); } -TEST_F(HotspotFdTestFixture, set_tunnelstatus) { - bool result; +TEST_F(HotspotFdTestFixture, notify_tunnel_status) { char status[] = "Up"; - char mockFaultParam[] = "TRUE"; - EXPECT_CALL(*g_anscWrapperApiMock, AnscCloneString(status)).Times(1).WillOnce(Return(status)); - EXPECT_CALL(*g_baseapiMock, CcspBaseIf_setParameterValues(_, _, _, _, _, _, _, _, _)) - .Times(1) - .WillOnce(testing::DoAll( - testing::WithArg<8>([&](char** faultParam){ - *faultParam = mockFaultParam; - }), - Return(CCSP_SUCCESS))); + EXPECT_CALL(*g_rbusMock, rbusValue_Init(_)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusValue_SetString(_, StrEq(status))).Times(1); + EXPECT_CALL(*g_rbusMock, rbusObject_Init(_, nullptr)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusObject_SetValue(_, StrEq("TunnelStatus"), _)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusEvent_Publish(_, _)).Times(1).WillOnce(Return(RBUS_ERROR_SUCCESS)); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(_)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusObject_Release(_)).Times(1); - result = set_tunnelstatus(status); - EXPECT_EQ(true, result); + notify_tunnel_status(status); + + EXPECT_STREQ("Up", TunnelStatus); + EXPECT_EQ(true, gVapIsUp); } -TEST_F(HotspotFdTestFixture, notify_tunnel_status_UP) { - char status[] = "Up"; - char mockFaultParam[] = "TRUE"; +TEST_F(HotspotFdTestFixture, notify_tunnel_status_Down) { + char status[] = "Down"; - EXPECT_CALL(*g_anscWrapperApiMock, AnscCloneString(status)).Times(1).WillOnce(Return(status)); - EXPECT_CALL(*g_baseapiMock, CcspBaseIf_setParameterValues(_, _, _, _, _, _, _, _, _)) - .Times(1) - .WillOnce(testing::DoAll( - testing::WithArg<8>([&](char** faultParam){ - *faultParam = mockFaultParam; - }), - Return(CCSP_SUCCESS))); - EXPECT_CALL(*g_baseapiMock, CcspBaseIf_SendSignal_WithData(_, StrEq("Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus"), _)) - .Times(1).WillOnce(Return(CCSP_SUCCESS)); + EXPECT_CALL(*g_rbusMock, rbusValue_Init(_)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusValue_SetString(_, StrEq(status))).Times(1); + EXPECT_CALL(*g_rbusMock, rbusObject_Init(_, nullptr)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusObject_SetValue(_, StrEq("TunnelStatus"), _)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusEvent_Publish(_, _)).Times(1).WillOnce(Return(RBUS_ERROR_SUCCESS)); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(_)).Times(1); + EXPECT_CALL(*g_rbusMock, rbusObject_Release(_)).Times(1); notify_tunnel_status(status); + + EXPECT_STREQ("Down", TunnelStatus); + EXPECT_EQ(false, gVapIsUp); } -TEST_F(HotspotFdTestFixture, notify_tunnel_status_DOWN) { - char status[] = "Down"; - char mockFaultParam[] = "False"; +TEST_F(HotspotFdTestFixture, TunnelStatus_GetStringHandler) { + rbusHandle_t handle = nullptr; + rbusProperty_t property = reinterpret_cast(0x1); // dummy non-null + rbusGetHandlerOptions_t* opts = nullptr; - EXPECT_CALL(*g_anscWrapperApiMock, AnscCloneString(status)).Times(1).WillOnce(Return(status)); - EXPECT_CALL(*g_baseapiMock, CcspBaseIf_setParameterValues(_, _, _, _, _, _, _, _, _)) - .Times(1) - .WillOnce(testing::DoAll( - testing::WithArg<8>([&](char** faultParam){ - *faultParam = mockFaultParam; - }), - Return(CCSP_SUCCESS))); - EXPECT_CALL(*g_baseapiMock, CcspBaseIf_SendSignal_WithData(_, StrEq("Device.X_COMCAST-COM_GRE.Tunnel.1.TunnelStatus"), _)) - .Times(1).WillOnce(Return(CCSP_SUCCESS)); + strncpy(TunnelStatus, "Up", sizeof(TunnelStatus) - 1); + TunnelStatus[sizeof(TunnelStatus) - 1] = '\0'; - notify_tunnel_status(status); + EXPECT_CALL(*g_rbusMock, rbusValue_Init(_)) + .Times(1); + + EXPECT_CALL(*g_rbusMock, rbusValue_SetString(_, StrEq("Up"))) + .Times(1); + + EXPECT_CALL(*g_rbusMock, rbusProperty_SetValue(property, _)) + .Times(1); + + EXPECT_CALL(*g_rbusMock, rbusValue_Release(_)) + .Times(1); + + rbusError_t result = TunnelStatus_GetStringHandler(handle, property, opts); + + EXPECT_EQ(RBUS_ERROR_SUCCESS, result); +} + +TEST_F(HotspotFdTestFixture, TunnelStatus_SetStringHandler_ValidChange) { + rbusHandle_t handle = nullptr; + rbusProperty_t property = reinterpret_cast(0x1); + rbusSetHandlerOptions_t* opts = nullptr; + + strncpy(TunnelStatus, "Down", sizeof(TunnelStatus) - 1); + TunnelStatus[sizeof(TunnelStatus) - 1] = '\0'; + + rbusValue_t val = reinterpret_cast(0x2); + + EXPECT_CALL(*g_rbusMock, rbusProperty_GetValue(property)) + .Times(1) + .WillOnce(Return(val)); + + EXPECT_CALL(*g_rbusMock, rbusValue_GetString(val, _)) + .Times(1) + .WillOnce(Return("Up")); + + rbusError_t result = TunnelStatus_SetStringHandler(handle, property, opts); + + EXPECT_EQ(RBUS_ERROR_SUCCESS, result); + EXPECT_STREQ("Up", TunnelStatus); +} + +TEST_F(HotspotFdTestFixture, TunnelStatus_SetStringHandler_InvalidValue) { + rbusHandle_t handle = nullptr; + rbusProperty_t property = reinterpret_cast(0x1); + rbusSetHandlerOptions_t* opts = nullptr; + + strncpy(TunnelStatus, "Down", sizeof(TunnelStatus) - 1); + TunnelStatus[sizeof(TunnelStatus) - 1] = '\0'; + + rbusValue_t val = reinterpret_cast(0x2); + + EXPECT_CALL(*g_rbusMock, rbusProperty_GetValue(property)) + .Times(1) + .WillOnce(Return(val)); + + EXPECT_CALL(*g_rbusMock, rbusValue_GetString(val, _)) + .Times(1) + .WillOnce(Return("InvalidStatus")); + + rbusError_t result = TunnelStatus_SetStringHandler(handle, property, opts); + + EXPECT_EQ(RBUS_ERROR_INVALID_INPUT, result); + EXPECT_STREQ("Down", TunnelStatus); + +} + +TEST_F(HotspotFdTestFixture, TunnelStatus_SetStringHandler_NoChange) { + rbusHandle_t handle = nullptr; + rbusProperty_t property = reinterpret_cast(0x1); + rbusSetHandlerOptions_t* opts = nullptr; + + strncpy(TunnelStatus, "Up", sizeof(TunnelStatus) - 1); + TunnelStatus[sizeof(TunnelStatus) - 1] = '\0'; + + rbusValue_t val = reinterpret_cast(0x2); + + EXPECT_CALL(*g_rbusMock, rbusProperty_GetValue(property)) + .Times(1) + .WillOnce(Return(val)); + + EXPECT_CALL(*g_rbusMock, rbusValue_GetString(val, _)) + .Times(1) + .WillOnce(Return("Up")); + + rbusError_t result = TunnelStatus_SetStringHandler(handle, property, opts); + + EXPECT_EQ(RBUS_ERROR_SUCCESS, result); + EXPECT_STREQ("Up", TunnelStatus); } TEST_F(HotspotFdTestFixture, set_validatessid_CASE1) { diff --git a/source/test/HotspotFdTest/Makefile.am b/source/test/HotspotFdTest/Makefile.am index 2eee3cc..7701090 100755 --- a/source/test/HotspotFdTest/Makefile.am +++ b/source/test/HotspotFdTest/Makefile.am @@ -32,7 +32,8 @@ HotspotFd_gtest_bin_CPPFLAGS = -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/gtest \ -I${top_srcdir}/source/util \ -I${top_srcdir}/source/hotspotfd/include \ -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/ccsp \ - -DUNIT_TEST_DOCKER_SUPPORT + -DUNIT_TEST_DOCKER_SUPPORT \ + -DWAN_FAILOVER_SUPPORTED HotspotFd_gtest_bin_SOURCES = ${top_builddir}/source/hotspotfd/cosa_hotspot_dml.c \ ${top_builddir}/source/hotspotfd/dhcpsnooper.c \ @@ -52,7 +53,8 @@ HotspotFd_gtest_bin_LDADD = $(HOME)/usr/local/lib/libmock_ccsp_common.la \ $(HOME)/usr/local/lib/libmock_file_io.la \ $(HOME)/usr/local/lib/libmock_secure_wrapper.la \ $(HOME)/usr/local/lib/libmock_nfqueue.la \ - $(HOME)/usr/local/lib/libmock_socket.la + $(HOME)/usr/local/lib/libmock_socket.la \ + $(HOME)/usr/local/lib/libmock_rbus.la #Code Coverage Flags AM_CFLAGS += -fprofile-arcs -ftest-coverage diff --git a/source/test/mocks/mock_hotspotApi.cpp b/source/test/mocks/mock_hotspotApi.cpp index e2686a2..72f1544 100644 --- a/source/test/mocks/mock_hotspotApi.cpp +++ b/source/test/mocks/mock_hotspotApi.cpp @@ -37,4 +37,20 @@ extern "C" void recreate_tunnel() { return; } return g_hotspotApiMock->recreate_tunnel(); +} + +extern "C" int PsmGet(const char *param, char *value, int size) { + if (!g_hotspotApiMock) + { + return -1; + } + return g_hotspotApiMock->PsmGet(param, value, size); +} + +extern "C" int hotspot_wan_failover(bool remote_wan_enabled) { + if (!g_hotspotApiMock) + { + return -1; + } + return g_hotspotApiMock->hotspot_wan_failover(remote_wan_enabled); } \ No newline at end of file diff --git a/source/test/mocks/mock_hotspotApi.h b/source/test/mocks/mock_hotspotApi.h index 930fc3b..647234b 100644 --- a/source/test/mocks/mock_hotspotApi.h +++ b/source/test/mocks/mock_hotspotApi.h @@ -25,6 +25,8 @@ class HotspotApiInterface { virtual ~HotspotApiInterface() {} virtual int ipAddress_version(char*) = 0; virtual void recreate_tunnel() = 0; + virtual int PsmGet(const char *param, char *value, int size) = 0; + virtual int hotspot_wan_failover(bool) = 0; }; class HotspotApiMock: public HotspotApiInterface { @@ -32,4 +34,6 @@ class HotspotApiMock: public HotspotApiInterface { virtual ~HotspotApiMock() {} MOCK_METHOD1(ipAddress_version, int(char*)); MOCK_METHOD0(recreate_tunnel, void()); + MOCK_METHOD3(PsmGet, int(const char *param, char *value, int size)); + MOCK_METHOD1(hotspot_wan_failover, int(bool)); }; \ No newline at end of file