diff options
Diffstat (limited to 'src/components/transport_manager/test/tcp_transport_adapter_test.cc')
-rw-r--r-- | src/components/transport_manager/test/tcp_transport_adapter_test.cc | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/src/components/transport_manager/test/tcp_transport_adapter_test.cc b/src/components/transport_manager/test/tcp_transport_adapter_test.cc new file mode 100644 index 0000000000..13bf838ec0 --- /dev/null +++ b/src/components/transport_manager/test/tcp_transport_adapter_test.cc @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2015, 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 <sys/time.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + +#include "transport_manager/tcp/tcp_transport_adapter.h" +#include "transport_manager/transport_adapter/transport_adapter_listener.h" +#include "include/mock_transport_adapter_listener.h" +#include "protocol/raw_message.h" +#include "utils/logger.h" + +namespace transport_manager { +namespace transport_adapter { + +using namespace ::protocol_handler; + +TEST(TcpAdapterBasicTest, GetDeviceType_Return_sdltcp) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_EQ("sdl-tcp", transport_adapter->GetDeviceType()); + + delete transport_adapter; +} + +TEST(TcpAdapterBasicTest, isServerOriginatedConnectSupported_Return_True) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_TRUE(transport_adapter->IsServerOriginatedConnectSupported()); + + delete transport_adapter; +} + +TEST(TcpAdapterBasicTest, isClientOriginatedConnectSupported_Return_True) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_TRUE(transport_adapter->IsClientOriginatedConnectSupported()); + + delete transport_adapter; +} + +TEST(TcpAdapterBasicTest, isSearchDevicesSupported_Return_True) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_TRUE(transport_adapter->IsSearchDevicesSupported()); + + delete transport_adapter; +} + +TEST(TcpAdapterBasicTest, NotInitialised_Return_BAD_STATE) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_EQ(TransportAdapter::BAD_STATE, transport_adapter->SearchDevices()); + + delete transport_adapter; +} + +//TODO(KKolodiy)APPLINK-11045 +TEST(TcpAdapterBasicTest, DISABLED_NotInitialised_Return_OK_InConnect) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_EQ(TransportAdapter::OK, + transport_adapter->Connect(DeviceUID("xxx"), 2)); + delete transport_adapter; +} + +TEST(TcpAdapterBasicTest, NotInitialised_Return_BAD_STATE_inDisconnect) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_EQ(TransportAdapter::BAD_STATE, + transport_adapter->Disconnect(DeviceUID("xxx"), 2)); + delete transport_adapter; +} + +TEST(TcpAdapterBasicTest, NotInitialised_Return_BAD_STATE_in_DisconnectDevice) { + + //arrange + TransportAdapter* transport_adapter = new TcpTransportAdapter(12345); + + //assert + EXPECT_EQ(TransportAdapter::BAD_STATE, + transport_adapter->DisconnectDevice(DeviceUID("xxx"))); + delete transport_adapter; +} + +class ClientTcpSocket { + public: + bool Connect(uint16_t server_port) { + + socket_ = socket(AF_INET, SOCK_STREAM, 0); + std::cout << "socket is " << socket_ << "\n\n"; + if (socket_ < 0) + return false; + + struct sockaddr_in addr; + memset((char*) &addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(server_port); + + if (::connect(socket_, (struct sockaddr*) &addr, sizeof(addr)) < 0) + return false; + else + return true; + } + + bool Send(const std::string& str) { + size_t size = str.size(); + ssize_t written = write(socket_, str.c_str(), size); + if (written != -1) { + size_t count = static_cast<size_t>(written); + return count == size; + } else { + return false; + } + } + + std::string receive(size_t size) { + char* buf = new char[size]; + ssize_t read = recv(socket_, buf, size, MSG_WAITALL); + if (read != -1) { + return std::string(buf, buf + read); + } else { + return std::string(); + } + } + + void Disconnect() { + close(socket_); + } + + private: + uint16_t port_; + int socket_; +}; + +using ::testing::_; +using ::testing::Invoke; + +void Disconnect(const TransportAdapter* transport_adapter, + const DeviceUID device_handle, + const ApplicationHandle app_handle) { + EXPECT_EQ( + TransportAdapter::OK, + const_cast<TransportAdapter*>(transport_adapter)->Disconnect( + device_handle, app_handle)); + + std::cout << "adapter is disconnected" << "\n"; +} + +class TcpAdapterTest : public ::testing::Test { + public: + TcpAdapterTest() + : port_(ChoosePort()), + transport_adapter_(new TcpTransportAdapter(port_)), + suspended_(false), + finished_(false) { + pthread_mutex_init(&suspend_mutex_, 0); + pthread_cond_init(&suspend_cond_, 0); + } + + uint16_t ChoosePort() { + return getpid() % 1000 + 3000; + } + + virtual void SetUp() { + const TransportAdapter::Error error = transport_adapter_->Init(); + ASSERT_EQ(TransportAdapter::OK, error); + transport_adapter_->AddListener(&mock_dal_); + time_t end_time = time(NULL) + 5; + while (!transport_adapter_->IsInitialised() && time(NULL) < end_time) + sleep(0); + ASSERT_TRUE(transport_adapter_->IsInitialised()); + } + + virtual void TearDown() { + transport_adapter_->StopClientListening(); + } + + virtual ~TcpAdapterTest() { + pthread_mutex_lock(&suspend_mutex_); + if (!finished_) + suspended_ = true; + struct timeval now; + gettimeofday(&now, NULL); + timespec abs_time; + abs_time.tv_sec = now.tv_sec + 1; + abs_time.tv_nsec = now.tv_usec * 1000; + while (suspended_) { + if (ETIMEDOUT + == pthread_cond_timedwait(&suspend_cond_, &suspend_mutex_, + &abs_time)) { + break; + } + } + pthread_mutex_unlock(&suspend_mutex_); + delete transport_adapter_; + + pthread_mutex_destroy(&suspend_mutex_); + pthread_cond_destroy(&suspend_cond_); + } + + void wakeUp() { + pthread_mutex_lock(&suspend_mutex_); + finished_ = true; + suspended_ = false; + pthread_cond_signal(&suspend_cond_); + pthread_mutex_unlock(&suspend_mutex_); + } + + uint16_t port() const { + return port_; + } + + const uint16_t port_; + TransportAdapter* transport_adapter_; + ::test::components::transport_manager::MockTransportAdapterListener mock_dal_; + ClientTcpSocket client_; + + pthread_cond_t suspend_cond_; + pthread_mutex_t suspend_mutex_; + bool suspended_; + bool finished_; + +}; + +class TcpAdapterTestWithListenerAutoStart : public TcpAdapterTest { + virtual void SetUp() { + TcpAdapterTest::SetUp(); + transport_adapter_->StartClientListening(); + } + +}; + +MATCHER_P(ContainsMessage, str, ""){ return strlen(str) == arg->data_size() && 0 == memcmp(str, arg->data(), arg->data_size());} + +// TODO{ALeshin} APPLINK-11090 - transport_adapter_->IsInitialised() doesn't return true as expected +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_Connect_Return_True) { + { + ::testing::InSequence seq; + EXPECT_CALL(mock_dal_, OnDeviceListUpdated(_)); + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)).WillOnce( + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + EXPECT_TRUE(client_.Connect(port())); +} + +// TODO{ALeshin} APPLINK-11090 - transport_adapter_->IsInitialised() doesn't return true as expected +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_SecondConnect_Return_True) { + { + ::testing::InSequence seq; + EXPECT_CALL(mock_dal_, OnDeviceListUpdated(_)); + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)).WillOnce( + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + EXPECT_TRUE(client_.Connect(port())); +} + +// TODO{ALeshin} APPLINK-11090 - transport_adapter_->IsInitialised() doesn't return true as expected +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_Receive_Return_True) { + { + ::testing::InSequence seq; + + EXPECT_CALL(mock_dal_, OnDeviceListUpdated(_)); + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)); + + EXPECT_CALL( + mock_dal_, + OnDataReceiveDone(transport_adapter_, _, _, ContainsMessage("abcd"))). + WillOnce(InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + EXPECT_TRUE(client_.Connect(port())); + EXPECT_TRUE(client_.Send("abcd")); +} + +struct SendHelper { + explicit SendHelper(TransportAdapter::Error expected_error) + : expected_error_(expected_error), + message_( + new RawMessage( + 1, + 1, + const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>("efgh")), + 4)) { + } + void sendMessage(const TransportAdapter* transport_adapter, + const DeviceUID device_handle, + const ApplicationHandle app_handle) { + EXPECT_EQ( + expected_error_, + const_cast<TransportAdapter*>(transport_adapter)->SendData( + device_handle, app_handle, message_)); + } + TransportAdapter::Error expected_error_; + RawMessagePtr message_; +}; + +// TODO{ALeshin} APPLINK-11090 - transport_adapter_->IsInitialised() doesn't return true as expected +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_Send_Message) { + SendHelper helper(TransportAdapter::OK); + { + ::testing::InSequence seq; + + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)).WillOnce( + Invoke(&helper, &SendHelper::sendMessage)); + EXPECT_CALL(mock_dal_, + OnDataSendDone(transport_adapter_, _, _, helper.message_)).WillOnce( + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + + EXPECT_TRUE(client_.Connect(port())); + EXPECT_EQ("efgh", client_.receive(4)); +} + +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_DisconnectFromClient) { + { + ::testing::InSequence seq; + + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)); + EXPECT_CALL(mock_dal_, OnUnexpectedDisconnect(transport_adapter_, _, _, _)); + EXPECT_CALL(mock_dal_, OnDisconnectDone(transport_adapter_, _, _)).WillOnce( + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + EXPECT_TRUE(client_.Connect(port())); + client_.Disconnect(); +} + +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_DisconnectFromServer) { + { + ::testing::InSequence seq; + + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)).WillOnce( + Invoke(Disconnect)); + EXPECT_CALL(mock_dal_, OnDisconnectDone(transport_adapter_, _, _)).WillOnce( + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + EXPECT_TRUE(client_.Connect(port())); + +} + +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_SendToDisconnected) { + SendHelper* helper = new SendHelper(TransportAdapter::BAD_PARAM); + { + ::testing::InSequence seq; + + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)).WillOnce( + Invoke(Disconnect)); + EXPECT_CALL(mock_dal_, OnDisconnectDone(transport_adapter_, _, _)).WillOnce( + ::testing::DoAll(Invoke(helper, &SendHelper::sendMessage), + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp))); + } + EXPECT_TRUE(client_.Connect(port())); +} + +TEST_F(TcpAdapterTestWithListenerAutoStart, DISABLED_SendFailed) { +// static unsigned char zzz[2000000]; //message will send without fail because socket buffer can contain it + //this test works correctly starting with number 2539009 + static unsigned char zzz[2600000]; + SendHelper* helper = new SendHelper(TransportAdapter::OK); + helper->message_ = new RawMessage(1, 1, zzz, sizeof(zzz)); + { + ::testing::InSequence seq; + EXPECT_CALL(mock_dal_, OnConnectDone(transport_adapter_, _, _)).WillOnce( + Invoke(helper, &SendHelper::sendMessage)); + EXPECT_CALL( + mock_dal_, + OnDataSendFailed(transport_adapter_, _, _, helper->message_, _)); + EXPECT_CALL(mock_dal_, OnDisconnectDone(transport_adapter_, _, _)).WillOnce( + InvokeWithoutArgs(this, &TcpAdapterTest::wakeUp)); + } + EXPECT_TRUE(client_.Connect(port())); + client_.receive(2); + client_.Disconnect(); +} + +// TODO{ALeshin} APPLINK-11090 - transport_adapter_->IsInitialised() doesn't return true as expected +TEST_F(TcpAdapterTest, DISABLED_StartStop) { + + //assert + EXPECT_EQ(TransportAdapter::BAD_STATE, + transport_adapter_->StopClientListening()); + EXPECT_TRUE(client_.Connect(port())); + EXPECT_EQ(TransportAdapter::OK, transport_adapter_->StartClientListening()); + EXPECT_TRUE(client_.Connect(port())); + + //act + client_.Disconnect(); + + //assert + EXPECT_EQ(TransportAdapter::BAD_STATE, + transport_adapter_->StartClientListening()); + EXPECT_TRUE(client_.Connect(port())); + + //act + client_.Disconnect(); + + //assert + EXPECT_EQ(TransportAdapter::OK, transport_adapter_->StopClientListening()); + EXPECT_TRUE(client_.Connect(port())); + + //act + wakeUp(); +} + +} // namespace +} // namespace + |