diff options
Diffstat (limited to 'src/components/connection_handler/test/heart_beat_monitor_test.cc')
-rw-r--r-- | src/components/connection_handler/test/heart_beat_monitor_test.cc | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/components/connection_handler/test/heart_beat_monitor_test.cc b/src/components/connection_handler/test/heart_beat_monitor_test.cc new file mode 100644 index 000000000..710977c64 --- /dev/null +++ b/src/components/connection_handler/test/heart_beat_monitor_test.cc @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2013-2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string> +#include <iostream> +//#include <stdio.h> +#include "gmock/gmock.h" +#include "connection_handler/heartbeat_monitor.h" +#include "connection_handler/connection.h" +#include "connection_handler/connection_handler.h" +#include "config_profile/profile.h" + +namespace { +const int32_t MILLISECONDS_IN_SECOND = 1000; +const int32_t MICROSECONDS_IN_MILLISECONDS = 1000; +const int32_t MICROSECONDS_IN_SECOND = 1000 * 1000; +} + +namespace test { +namespace components { +namespace connection_handler_test { +using ::testing::_; + +class ConnectionHandlerMock : public connection_handler::ConnectionHandler { + public: + MOCK_METHOD1(set_connection_handler_observer, + void(connection_handler::ConnectionHandlerObserver*)); + MOCK_METHOD1(set_transport_manager, + void(transport_manager::TransportManager*)); + MOCK_METHOD0(StartTransportManager, + void()); + MOCK_METHOD1(ConnectToDevice, + void(connection_handler::DeviceHandle device_handle)); + MOCK_METHOD0(ConnectToAllDevices, + void()); + MOCK_METHOD1(CloseRevokedConnection, void(uint32_t connection_key)); + MOCK_METHOD1(CloseConnection, + void(connection_handler::ConnectionHandle connection_handle)); + MOCK_METHOD1(GetConnectionSessionsCount, uint32_t(uint32_t connection_key)); + MOCK_METHOD2(GetDeviceID, + bool(const std::string& mac_address, + connection_handler::DeviceHandle* device_handle)); + MOCK_CONST_METHOD1(GetConnectedDevicesMAC, void(std::vector<std::string> &device_macs)); + MOCK_METHOD2(CloseSession, + void(uint32_t key, + connection_handler::CloseSessionReason close_reason)); + MOCK_METHOD3(CloseSession, + void(connection_handler::ConnectionHandle connection_handle, + uint8_t session_id, + connection_handler::CloseSessionReason close_reason)); + MOCK_METHOD2(SendEndService, + void(uint32_t key, uint8_t service_type)); + + MOCK_METHOD1(StartSessionHeartBeat, + void(uint32_t key)); + MOCK_METHOD2(SendHeartBeat, + void(connection_handler::ConnectionHandle connection_handle, + uint8_t session_id)); + MOCK_METHOD2(SetHeartBeatTimeout, void(uint32_t connection_key, + uint32_t timeout)); + MOCK_METHOD2(BindProtocolVersionWithSession, + void(uint32_t connection_key, + uint8_t protocol_version)); + MOCK_METHOD4(GetDataOnSessionKey, + int32_t(uint32_t key, uint32_t* app_id, + std::list<int32_t>* sessions_list, + uint32_t* device_id)); +}; + +class HeartBeatMonitorTest : public testing::Test { +public: + HeartBeatMonitorTest(): + conn(NULL) { + profile::Profile::instance()->config_file_name("smartDeviceLink.ini"); + kTimeout = profile::Profile::instance()->heart_beat_timeout(); + } + +protected: + testing::NiceMock<ConnectionHandlerMock> connection_handler_mock; + connection_handler::Connection* conn; + uint32_t kTimeout; + static const connection_handler::ConnectionHandle kConnectionHandle = 0xABCDEF; + + virtual void SetUp() { + conn = new connection_handler::Connection(kConnectionHandle, 0, + &connection_handler_mock, + kTimeout); + } + + virtual void TearDown() { + delete conn; + } + +}; + +ACTION_P2(RemoveSession, conn, session_id){ + conn->RemoveSession(session_id); +} + +TEST_F(HeartBeatMonitorTest, TimerNotStarted) { + + // Whithout StartHeartBeat nothing to be call + EXPECT_CALL(connection_handler_mock, CloseSession(_, _)).Times(0); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)).Times(0); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, _)).Times(0); + + conn->AddNewSession(); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND); +} + +TEST_F(HeartBeatMonitorTest, TimerNotElapsed) { + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, _)).Times(0); + EXPECT_CALL(connection_handler_mock, CloseSession(_, _)).Times(0); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)).Times(0); + + const uint32_t session = conn->AddNewSession(); + conn->StartHeartBeat(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); +} + +TEST_F(HeartBeatMonitorTest, TimerElapsed) { + const uint32_t session = conn->AddNewSession(); + + EXPECT_CALL(connection_handler_mock, CloseSession(_, session,_)) + .WillOnce(RemoveSession(conn, session)); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, session)); + + conn->StartHeartBeat(session); + usleep(2 * kTimeout * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND); +} + +TEST_F(HeartBeatMonitorTest, KeptAlive) { + EXPECT_CALL(connection_handler_mock, CloseSession(_, _)).Times(0); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)).Times(0); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, _)).Times(0); + + const uint32_t session = conn->AddNewSession(); + conn->StartHeartBeat(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); + conn->KeepAlive(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); + conn->KeepAlive(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); + conn->KeepAlive(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); +} + +TEST_F(HeartBeatMonitorTest, NotKeptAlive) { + const uint32_t session = conn->AddNewSession(); + + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, session)); + EXPECT_CALL(connection_handler_mock, CloseSession(_, session,_)) + .WillOnce(RemoveSession(conn, session)); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)); + + conn->StartHeartBeat(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); + conn->KeepAlive(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); + conn->KeepAlive(session); + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS - MICROSECONDS_IN_SECOND); + conn->KeepAlive(session); + usleep(2 * kTimeout * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND); +} + +TEST_F(HeartBeatMonitorTest, TwoSessionsElapsed) { + const uint32_t kSession1 = conn->AddNewSession(); + const uint32_t kSession2 = conn->AddNewSession(); + + EXPECT_CALL(connection_handler_mock, CloseSession(_, kSession1,_)) + .WillOnce(RemoveSession(conn, kSession1)); + EXPECT_CALL(connection_handler_mock, CloseSession(_, kSession2,_)) + .WillOnce(RemoveSession(conn, kSession2)); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, kSession1)); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, kSession2)); + + conn->StartHeartBeat(kSession1); + conn->StartHeartBeat(kSession2); + usleep(2 * kTimeout * MICROSECONDS_IN_MILLISECONDS + MICROSECONDS_IN_SECOND); +} + +TEST_F(HeartBeatMonitorTest, IncreaseHeartBeatTimeout) { + const uint32_t kSession = conn->AddNewSession(); + + EXPECT_CALL(connection_handler_mock, CloseSession(_, _)).Times(0); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)).Times(0); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, _)).Times(0); + + + const uint32_t kNewTimeout = kTimeout + MICROSECONDS_IN_MILLISECONDS; + conn->StartHeartBeat(kSession); + conn->SetHeartBeatTimeout(kNewTimeout, kSession); + // new timeout greater by old timeout so mock object shouldn't be invoked + usleep(kTimeout * MICROSECONDS_IN_MILLISECONDS); +} + +TEST_F(HeartBeatMonitorTest, DecreaseHeartBeatTimeout) { + const uint32_t kSession = conn->AddNewSession(); + + EXPECT_CALL(connection_handler_mock, CloseSession(_, kSession,_)) + .WillOnce(RemoveSession(conn, kSession)); + EXPECT_CALL(connection_handler_mock, CloseConnection(_)); + EXPECT_CALL(connection_handler_mock, SendHeartBeat(_, kSession)); + + const uint32_t kNewTimeout = kTimeout - MICROSECONDS_IN_MILLISECONDS; + conn->StartHeartBeat(kSession); + conn->SetHeartBeatTimeout(kNewTimeout, kSession); + // new timeout less than old timeout so mock object should be invoked + usleep(kTimeout * 2 * MICROSECONDS_IN_MILLISECONDS); +} + +} // namespace connection_handler_test +} // namespace components +} // namespace test |