summaryrefslogtreecommitdiff
path: root/src/components/transport_manager/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/transport_manager/test')
-rw-r--r--src/components/transport_manager/test/CMakeLists.txt10
-rw-r--r--src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h82
-rw-r--r--src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h117
-rw-r--r--src/components/transport_manager/test/tcp_client_listener_test.cc62
-rw-r--r--src/components/transport_manager/test/test_certs/ca-cert.pem23
-rw-r--r--src/components/transport_manager/test/test_certs/client-cert.pem21
-rw-r--r--src/components/transport_manager/test/test_certs/client-key.pem28
-rw-r--r--src/components/transport_manager/test/test_certs/invalid_cert.pem22
-rw-r--r--src/components/transport_manager/test/test_certs/invalid_key.pem28
-rw-r--r--src/components/transport_manager/test/test_certs/server-cert.pem21
-rw-r--r--src/components/transport_manager/test/test_certs/server-key.pem28
-rw-r--r--src/components/transport_manager/test/transport_manager_default_test.cc21
-rw-r--r--src/components/transport_manager/test/websocket_client_connection_test.cc482
-rw-r--r--src/components/transport_manager/test/websocket_connection_test.cc504
-rw-r--r--src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc193
-rw-r--r--src/components/transport_manager/test/websocket_server_listener_test.cc260
16 files changed, 1396 insertions, 506 deletions
diff --git a/src/components/transport_manager/test/CMakeLists.txt b/src/components/transport_manager/test/CMakeLists.txt
index f6e1212b36..76680b2fad 100644
--- a/src/components/transport_manager/test/CMakeLists.txt
+++ b/src/components/transport_manager/test/CMakeLists.txt
@@ -48,11 +48,18 @@ set(EXCLUDE_PATHS
if (NOT BUILD_CLOUD_APP_SUPPORT)
list(APPEND EXCLUDE_PATHS
- ${CMAKE_CURRENT_SOURCE_DIR}/websocket_connection_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/sample_websocket_server.cc
)
endif()
+if (NOT BUILD_WEBSOCKET_SERVER_SUPPORT)
+ list(APPEND EXCLUDE_PATHS
+ ${CMAKE_CURRENT_SOURCE_DIR}/websocket_client_connection_test.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/websocket_connection_test.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/websocket_server_listener_test.cc
+ )
+endif()
+
collect_sources(SOURCES "${CMAKE_CURRENT_SOURCE_DIR}" "${EXCLUDE_PATHS}")
set(PLATFORM_DEPENDENT_SOURCES)
@@ -90,3 +97,4 @@ endif()
create_test("transport_manager_test" "${SOURCES}" "${LIBRARIES}")
file(COPY smartDeviceLink_test.ini DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+file(COPY "test_certs/" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test_certs)
diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h
index 1de5eac702..7ddb84001c 100644
--- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h
+++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h
@@ -45,56 +45,66 @@ using namespace ::transport_manager::transport_adapter;
class MockTransportAdapterController : public TransportAdapterController {
public:
MOCK_METHOD1(AddDevice, DeviceSptr(DeviceSptr device));
- MOCK_METHOD1(SearchDeviceDone, void(DeviceVector device));
+ MOCK_METHOD1(SearchDeviceDone, void(const DeviceVector& device));
MOCK_METHOD1(ApplicationListUpdated,
- ApplicationListUpdated(const DeviceUID& device_handle));
+ void(const transport_manager::DeviceUID& device_handle));
MOCK_METHOD0(FindNewApplicationsRequest, void());
- MOCK_METHOD1(SearchDeviceFailed, void(const SearchDeviceError& error));
- MOCK_CONST_METHOD1(FindDevice, DeviceSptr(const DeviceUID& device_handle));
- MOCK_CONST_METHOD3(FindDevice,
- void(ConnectionSPtr connection,
- const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_CONST_METHOD2(FindPendingConnection,
- ConnectionSPtr(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ MOCK_METHOD1(SearchDeviceFailed,
+ void(const transport_manager::SearchDeviceError& error));
+ MOCK_CONST_METHOD1(
+ FindDevice,
+ DeviceSptr(const transport_manager::DeviceUID& device_handle));
+ MOCK_CONST_METHOD2(
+ FindPendingConnection,
+ ConnectionSPtr(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
+ MOCK_METHOD3(ConnectionCreated,
+ void(ConnectionSPtr connection,
+ const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
+ MOCK_METHOD2(ConnectPending,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD2(ConnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD3(ConnectFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ConnectError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
+ const transport_manager::ConnectError& error));
MOCK_METHOD2(ConnectionFinished,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD3(ConnectionAborted,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const CommunicationError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
+ const transport_manager::CommunicationError& error));
MOCK_METHOD2(DeviceDisconnected,
- void(const DeviceUID& device_handle,
- const DisconnectDeviceError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::DisconnectDeviceError& error));
MOCK_METHOD2(DisconnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD3(DataReceiveDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
::protocol_handler::RawMessagePtr message));
MOCK_METHOD3(DataReceiveFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const DataReceiveError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
+ const transport_manager::DataReceiveError& error));
MOCK_METHOD3(DataSendDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
::protocol_handler::RawMessagePtr message));
- MOCK_METHOD3(DataReceiveFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
+
+ MOCK_METHOD4(DataSendFailed,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
::protocol_handler::RawMessagePtr message,
- const DataSendError& error));
+ const transport_manager::DataSendError&));
+ MOCK_METHOD1(TransportConfigUpdated, void(const TransportConfig& new_config));
+ MOCK_CONST_METHOD0(GetWebEngineDevice, DeviceSptr());
};
} // namespace transport_manager_test
diff --git a/src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h b/src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h
new file mode 100644
index 0000000000..138502e02c
--- /dev/null
+++ b/src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h
@@ -0,0 +1,117 @@
+/*
+ * \file websocket_listener.h
+ * \brief WebSocketListener class header file.
+ *
+ * Copyright (c) 2020
+ * 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.
+ */
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SAMPLE_CLIENT_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SAMPLE_CLIENT_
+
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/beast/websocket/stream.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace transport_manager {
+namespace transport_adapter {
+
+namespace beast = boost::beast;
+namespace http = beast::http;
+namespace websocket = beast::websocket;
+namespace asio = boost::asio;
+namespace ssl = boost::asio::ssl;
+using tcp = boost::asio::ip::tcp;
+
+using WS = websocket::stream<tcp::socket>;
+using WSS = websocket::stream<ssl::stream<tcp::socket> >;
+
+struct SecurityParams {
+ std::string ca_cert_;
+ std::string client_cert_;
+ std::string client_key_;
+};
+
+template <typename Stream = WS>
+class WSSampleClient
+ : public std::enable_shared_from_this<WSSampleClient<Stream> > {
+ public:
+ WSSampleClient(const std::string& host, const std::string& port);
+ WSSampleClient(const std::string& host,
+ const std::string& port,
+ const SecurityParams& params);
+ ~WSSampleClient() {}
+
+ /**
+ * @brief Inside a Run(), functions are invoked from the boost (connection,
+ * handshake, message) which are blocking calls
+ * @return true if Run() did without errors
+ **/
+ bool Run();
+
+ void OnRead(beast::error_code ec, std::size_t bytes_transferred);
+
+ bool Connect(tcp::resolver::results_type& results);
+
+ bool Handshake(const std::string& host, const std::string& target);
+
+ void OnHandshakeTimeout();
+
+ bool IsHandshakeSuccessful() const;
+
+ void Stop();
+
+ private:
+ asio::io_context ioc_;
+ tcp::resolver resolver_;
+ ssl::context ctx_;
+ std::unique_ptr<Stream> ws_;
+ boost::asio::thread_pool io_pool_;
+ beast::flat_buffer buffer_;
+ std::string host_;
+ std::string port_;
+ std::atomic_bool handshake_successful_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SAMPLE_CLIENT_
diff --git a/src/components/transport_manager/test/tcp_client_listener_test.cc b/src/components/transport_manager/test/tcp_client_listener_test.cc
index d524b3eb6a..dbd7799b62 100644
--- a/src/components/transport_manager/test/tcp_client_listener_test.cc
+++ b/src/components/transport_manager/test/tcp_client_listener_test.cc
@@ -42,6 +42,7 @@
#include "transport_manager/tcp/tcp_client_listener.h"
#include "transport_manager/transport_adapter/mock_device.h"
#include "transport_manager/transport_adapter/mock_transport_adapter.h"
+#include "transport_manager/transport_adapter/mock_transport_adapter_controller.h"
#include "transport_manager/transport_adapter/transport_adapter_controller.h"
#include "utils/test_async_waiter.h"
@@ -62,67 +63,6 @@ const long kThreadStartWaitMsec = 10;
const uint32_t kConnectionCreatedTimeoutMsec = 200;
} // namespace
-class MockTransportAdapterController : public TransportAdapterController {
- public:
- MOCK_METHOD1(AddDevice, DeviceSptr(DeviceSptr device));
- MOCK_METHOD0(AckDevices, void());
- MOCK_METHOD1(SearchDeviceDone, void(const DeviceVector& devices));
- MOCK_METHOD1(SearchDeviceFailed, void(const SearchDeviceError& error));
- MOCK_CONST_METHOD1(FindDevice, DeviceSptr(const DeviceUID& device_handle));
- MOCK_CONST_METHOD2(FindPendingConnection,
- ConnectionSPtr(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(ConnectionCreated,
- void(ConnectionSPtr connection,
- const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD2(ConnectPending,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD2(ConnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(ConnectFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ConnectError& error));
- MOCK_METHOD2(ConnectionFinished,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(ConnectionAborted,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const CommunicationError& error));
- MOCK_METHOD2(DisconnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(DataReceiveDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ::protocol_handler::RawMessagePtr message));
- MOCK_METHOD3(DataReceiveFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const DataReceiveError& error));
- MOCK_METHOD3(DataSendDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ::protocol_handler::RawMessagePtr message));
- MOCK_METHOD4(DataSendFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ::protocol_handler::RawMessagePtr message,
- const DataSendError& error));
- MOCK_METHOD0(FindNewApplicationsRequest, void());
- MOCK_METHOD1(ApplicationListUpdated, void(const DeviceUID& device_handle));
- MOCK_METHOD2(DeviceDisconnected,
- void(const DeviceUID& device_handle,
- const DisconnectDeviceError& error));
- MOCK_METHOD1(TransportConfigUpdated,
- void(const transport_manager::transport_adapter::TransportConfig&
- new_config));
-};
-
class MockNetworkInterfaceListener : public NetworkInterfaceListener {
public:
MOCK_METHOD0(Init, bool());
diff --git a/src/components/transport_manager/test/test_certs/ca-cert.pem b/src/components/transport_manager/test/test_certs/ca-cert.pem
new file mode 100644
index 0000000000..e28684043c
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/ca-cert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDyzCCArOgAwIBAgIJAM6Tk4KJmUgsMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVBMQ8wDQYDVQQIDAZPZGVzc2ExDzANBgNVBAcMBk9kZXNzYTEPMA0GA1UE
+CgwGTHV4b2Z0MQ0wCwYDVQQLDARGVENOMQ8wDQYDVQQDDAZMdXgtQ0ExGjAYBgkq
+hkiG9w0BCQEWC2NhQGZ0Y24uY29tMB4XDTIwMDExMDE0MzA1OFoXDTIyMTAwNjE0
+MzA1OFowfDELMAkGA1UEBhMCVUExDzANBgNVBAgMBk9kZXNzYTEPMA0GA1UEBwwG
+T2Rlc3NhMQ8wDQYDVQQKDAZMdXhvZnQxDTALBgNVBAsMBEZUQ04xDzANBgNVBAMM
+Bkx1eC1DQTEaMBgGCSqGSIb3DQEJARYLY2FAZnRjbi5jb20wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDWEz7yGIAEs6w/7CdMjkZ5J0O9IghL0f9wZVFO
+ficeREJglClInPrD7BwG7MG1tydPULbrf1rXgxi1NdDY+lsJLFmkxrGVlgJUJl55
+cGpWGliTUepfPz/6CgIabRw2fEMx/eIUlcE+WjY+f4uowVyRYjmNj7IydlQ5UjcL
+wWhjg1QMcjgmDzh8Jdx8I+JHYuOP9CtEEfFZy5DjVPFDSlTYhhnNclfw+4NkOYcs
+hp+EcMBr6egfxpG2dZbdCJtGw6QqHGG7kqqtLr+9wM5VFhuvebus5waM1G18dIME
+SgZmDdgvHO3bbylR+DRmAjJVn4DaDW6uszK9MSPsk53idOUXAgMBAAGjUDBOMB0G
+A1UdDgQWBBSSRwc4sGpz6V1kb0H371ZqhDuQDzAfBgNVHSMEGDAWgBSSRwc4sGpz
+6V1kb0H371ZqhDuQDzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCb
+ZYtM2nrokFL1D34bhozrLu0MxWwDF+gQrUsRr45s63Y5Pv7BVvuS6gF2MubMXskw
+mVeCerFw2vQHJKqe7leTy69hwIydPxPQWWno7MamwBDm3VQThr+b18rEpcjbmBMm
+p50usYzU9nxEEbIaiSbxfuZNvInLNmvMhKnKO/CIazJnYin9TGdOj9vZnh0UkWF3
+780mMBisycfxG+VwPXQZz5OzWWFB1uMiYrRVdwU6Y5umc2Oce7+ykWy+fXeefMhb
+lLJXHZK584qY/krmW0Ec6ZWSbiWcLW5SjGh756n05gBGLDBwijHnfEHNaqn+KlnZ
+qqIAImNTA9F+DlMQ7BV3
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/client-cert.pem b/src/components/transport_manager/test/test_certs/client-cert.pem
new file mode 100644
index 0000000000..47e85876c8
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/client-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDeDCCAmACAQIwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVUExDzANBgNV
+BAgMBk9kZXNzYTEPMA0GA1UEBwwGT2Rlc3NhMQ8wDQYDVQQKDAZMdXhvZnQxDTAL
+BgNVBAsMBEZUQ04xDzANBgNVBAMMBkx1eC1DQTEaMBgGCSqGSIb3DQEJARYLY2FA
+ZnRjbi5jb20wHhcNMjAwMTEwMTQzODQxWhcNMjIxMDA2MTQzODQxWjCBhzELMAkG
+A1UEBhMCVUExDTALBgNVBAgMBEt5aXYxDTALBgNVBAcMBEt5aXYxDzANBgNVBAoM
+Bkx1eG9mdDEVMBMGA1UECwwMQXBwc0VueXdoZXJlMRIwEAYDVQQDDAlsb2NhbGhv
+c3QxHjAcBgkqhkiG9w0BCQEWD2NsaWVudEBmdGNuLmNvbTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALV4qI/gRvVip3u5JtT+n+7j7gUsUVW5DtwHruIy
+drzNvQbG1Ukd3EXvU69HTG4BtoDRubqlSe/sjvO5Ypmg/UvpzV36IbjrA46s98uR
+T6fKpJU/Zl2zwAHH++iWpFo3mqIDmu7i0KVBieKaGpz+Ft0zh7wHAztS7b6Mjns4
+QynpjDO+iaLIaHqBjc1hLn8dIBXNolOtLu8F8CL7RLRpWP2I2Fk2k0+Q5YKajbil
+gptA53Uu55wCBVLTOfUYzTarGwS00+7txLY06g2x20FHD8UQxfCK7kSAeZwSNkbt
+SUhXc9OWUvT1uggb2/wBHJN3fwj7y6pvzUJy7p09212hw7UCAwEAATANBgkqhkiG
+9w0BAQsFAAOCAQEAjfASZwfJMTPKk45XVbvuNqdlbiI20SNV7pQQ/FqTBKbFmh4g
+ndNCvECmBEUH5YdZegiGaONQlsQujmtIkguu3HnA0+2pO2SncmK6D1DLzJv1IFDC
+25tTStA6806hWcTK31sxEbi5/aPdy7FMmsRfyhRr/yew0TqlWCVOfJRwgDSc3NKH
+/AXgDBrqHzSBegnWe9v3xL8NxehFp41dJG2fyUab03cHzmNtR9v7/NrBglSdK9VS
+AU4BCmjmvYlbvmvhZai23y+uLqzlWZ9OtK3qhEWkg6QHor11iBvxBQFeYKp1ZjMl
+sQuTxyBLmXOZ/u3hkqLcKvasx9W4DmmPjG2T8Q==
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/client-key.pem b/src/components/transport_manager/test/test_certs/client-key.pem
new file mode 100644
index 0000000000..b286854bd5
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/client-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1eKiP4Eb1Yqd7
+uSbU/p/u4+4FLFFVuQ7cB67iMna8zb0GxtVJHdxF71OvR0xuAbaA0bm6pUnv7I7z
+uWKZoP1L6c1d+iG46wOOrPfLkU+nyqSVP2Zds8ABx/volqRaN5qiA5ru4tClQYni
+mhqc/hbdM4e8BwM7Uu2+jI57OEMp6YwzvomiyGh6gY3NYS5/HSAVzaJTrS7vBfAi
++0S0aVj9iNhZNpNPkOWCmo24pYKbQOd1LuecAgVS0zn1GM02qxsEtNPu7cS2NOoN
+sdtBRw/FEMXwiu5EgHmcEjZG7UlIV3PTllL09boIG9v8ARyTd38I+8uqb81Ccu6d
+PdtdocO1AgMBAAECggEALiPCf+pfQE7YFJ4L4IXo9h1fzFLrTydhPtJ5RavdAr4w
+vINbgV6lPebO2TcAmMu4smIgnfMerHDyG8fb6QHExUNp4uYRIuomGmWiD1Ef9qKQ
+XB4lkdd9Dzbgts9udD3FBEJ0Zx6mPA5A16uk7puwBofukAEccj3wks08ANpaQVJh
+LoYQdVY9Q2QHUucED9uO2hOv66bDM5aunk0x4Q/b0gIOAnJyqk0xXnmnU76FbkgI
+bU3YQ73ZEJKTFLF8B2JaE9REASmHyLQChYqGA9SPdObVhgxJ8gz5AWp5yHgMmYjf
+Dp66tCsyGnmfgTlG4Wi13HInxLpRWDWT2JWIy9cUlQKBgQDshRq/rTj4tuVW09hX
+bWlAEV2IDn7JOWEZqPagnxew0atqow44VORW+OoUZ5760aOVjvmXeyGXpWCJk5ch
+qsFRL9rLRzIy9oC6C/chkJQAprcaOBOSXvj3HnFHVChjbIBENf4dvtsYZHOW42h2
+br0kszv1bbBzVIyTTY0OvGsBUwKBgQDEauIuC6RiDN+qFAf4/lHkUx7wG6DPhvDm
+EhpkiVEHYVjH5vm132/cc12y9CvsFS4MJPK4KQR9P+HFhEu/uH3uLa1vvKY+69iU
+dZ1bfe4UrEm/bwBepDSbqlQk58WC6NyJ6fwMq0BYJVvx593znEbU2wLVUTm8H7l2
+yzyxQwXd1wKBgBkYvo/cJ5FshsVB0VDlkSd1MEGBmD5t0jnQzeqZNwBSHyg/iQC9
+MUVxQBVOMXZXzE3QT/ec3yGiMK4odP7jiYO92i97rH3v3hTftCdhmfK/veoQTTNY
+1H4UQtzYtzhliO6z8/TgDYt3DTTTiIAYnAVK52/RZcm3DPuMXQ1VPN11AoGBAIN5
+eASSTmpDa8OQvPVyZqaK7P6Tv8Sp8r5OB9ScBd0G0EKe3S9cbKgHoQSUZIIWe0gt
+wzp6WkLsa9emgn3GpKS1do6AnFcpz0MwpzACz0aPPJ4jUwAGsiAwlzpM2eySqmy2
+brycNOnLuAvoxKy4QsFgCDl5sUe3hJF74RhWYKrpAoGAUrJMF5IaAAsv367nD8CX
+CfDsDlez54H/sZD7iKj8LhyuspAQBU3vQ3xKfaKRi4px8bgnty3stOMZxEC7I6BC
+jHH1hQK8l9nqRhOjPvoViUM6aOpabCkVsOZjWKD+OCz3X9+MmlGkMuNd22GRdwlb
+Emb3yEoFr5vDbez0IQNxnLs=
+-----END PRIVATE KEY-----
diff --git a/src/components/transport_manager/test/test_certs/invalid_cert.pem b/src/components/transport_manager/test/test_certs/invalid_cert.pem
new file mode 100644
index 0000000000..70d124c2b7
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/invalid_cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnwCCQDIe7AwFpWRlDANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMC
+UlUxEzARBgNVBAgMClNvbWUtU3RhdGUxGTAXBgNVBAcMEFNhaW50LVBldGVyc2J1
+cmcxDzANBgNVBAoMBkx1eG9mdDEXMBUGA1UEAwwORG1pdHJ5IENobWVyZXYxIjAg
+BgkqhkiG9w0BCQEWE2RjaG1lcmV2QGx1eG9mdC5jb20wHhcNMTQwMjI1MDkxODUz
+WhcNMTYxMTIyMDkxODUzWjCBizELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUt
+U3RhdGUxGTAXBgNVBAcMEFNhaW50LVBldGVyc2J1cmcxDzANBgNVBAoMBkx1eG9m
+dDEXMBUGA1UEAwwORG1pdHJ5IENobWVyZXYxIjAgBgkqhkiG9w0BCQEWE2RjaG1l
+cmV2QGx1eG9mdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCn
+Mu9wNmXKaKOnefSv5iT8G2ESLjq+eYlxys/XAnDfkmnlgGYAcPno+XMhRj/lNV/c
+3A0L/R4631GFJA8vaM8m9Bn47FrPP4AXIHEQh9acA4qXiLfhhA8+9PPt4xVkjQYj
+bmexBLqDvRgT3MJwwFecUn/UABBlVZRCspn+6DkjiodbgmBOqyi1p0ng8BFeUbEH
++fLQVILCX3pjnMiP2bBtvq/7njgZT2luVtAAcOdRwRTuZT0YbgaXrHYsOa6VYDl1
+I0uOcdD8qENBXtBnykEqH+jZtKu6Rej1DsGOYWqz3AAaGiR1GJauNBxh+4v+i/eB
+0aCIA8T8qUqyuVVg48S/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBACliraOJYijK
+yS+Sl6S6pFRqdF/evPdYF6zDJlM3P+/9qHoEy751vbBTzRkVbC/azyiZLwQMuyED
+6oCpkI7MqnrRip1ZelGx9K7ChaHOpX/QRN+3eqiDhzvMTGd2nPJf9np4xi8SJpGP
+UUROYI5fToIY5MaOKuOIR2a6c8xIuLWMG1XKJxXrRetLJZDgBqQPkuqaZIjYCY+q
+HQRjNUFNX4Mc453tKd90gFLGI3fxs1fJDIRSGfKJsj0qc+amSz4Sgiz4QUBcUQKd
+hJxUpStYhliZGZchEopLsShtIGfKKFaaPCIOTpVAwSr1oIDm9lpkdxeuQfedKT5f
+ZZmkez2pAF8=
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/invalid_key.pem b/src/components/transport_manager/test/test_certs/invalid_key.pem
new file mode 100644
index 0000000000..d2aacc1638
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/invalid_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEApzLvcDZlymijp3n0r+Yk/BthEi46vnmJccrP1wJw35Jp5YBm
+AHD56PlzIUY/5TVf3NwNC/0eOt9RhSQPL2jPJvQZ+Oxazz+AFyBxEIfWnAOKl4i3
+4YQPPvTz7eMVZI0GI25nsQS6g70YE9zCcMBXnFJ/1AAQZVWUQrKZ/ug5I4qHW4Jg
+TqsotadJ4PARXlGxB/ny0FSCwl96Y5zIj9mwbb6v+544GU9pblbQAHDnUcEU7mU9
+GG4Gl6x2LDmulWA5dSNLjnHQ/KhDQV7QZ8pBKh/o2bSrukXo9Q7BjmFqs9wAGhok
+dRiWrjQcYfuL/ov3gdGgiAPE/KlKsrlVYOPEvwIDAQABAoIBAQCAjkNXzhuZ87bR
+UI34qUYKqaqLZgw45A3v9naz5OaQoGzXz0+eSz98CECjdvYt8EoS8Qb/DtGthoOR
+kVYzp6yPUOSfZmu0Kij8ny8P/MHgF0D6nl50ASwPxhu/7vhF5cCwgXUswGwAWuYm
+b3j5ZIp4YV5zzNDOeWyTk+uf+UHltqFD7Ae4M9z58r17/OWhva5mtusTuuEYjzC6
+AE/fsOC0gLNSM4+SfclfCkHpH+GikzNMSQ2H0hlXllPmR73BoC6N6aoY5hQWBLV7
+LxtYbJqx7TAqRyypBQekjJe36roRetXtzy3i6V/y69045td5kk70cVjmFhl79475
+82rnRLHBAoGBANgq4axr5OotTUmPkGd0afoaWSRPJfiTTdNeMkqTzM6zIcVLSKhB
+78ERwdDD9FOu+Bgivg4DlpmH7ArWn8QNDtdkhmPfKYfTqX6qH7AK4cybvYICMlct
+EdW4TvKm/ZB3mrVOP9JVPjdyFMp+Je6N+qp1w+ui9mxX8pWnrC/+DfTvAoGBAMYC
+GFjnw/O9hjF2Mb00qUarmM+reJZMXv/pVik+cm0eAiYvgGvKbAYkIXwdb7rLBw9k
+baJmxP0PrAoXy5TpPdfROqPwrRCyReKymKkEZeTpONgD0s8MbX167ovZu1OQVKQo
+IyJeUzWa0kpglnbL2lLVu49x8jWHDJdYhmkDNE0xAoGAR4ux07qGMoe5693rYoJi
+TRgJZv4XSDWg7ZNgu9Q9VjBtvfoT2zSvoMw6xNkGdegUTxC4rLS9VKVrF48/o8ja
+n6my3T1QZpdEoxq1kDOZ1nm5eF03wii1nXH6F0/z3qvndZingPsbs4g7n2WvMkyl
+qWN+6++s9eEJ9kRftia1AdsCgYAUnU05nE97RcT9y0dcYmopMF5FaJ2yUBsn23wb
+6SNylsg0f4eIMVfTv9k4mbvzH4YJpTQAz2A81G/d0SJhy3Kj0GWhgcIS1eyOsHdS
+SWHuVhWT77n30lxnzu+c4bst9P3K5V7bCiTxlL/F/I5NqeV98ECJq5xC1F+MNiww
+LKQ6UQKBgC2zL59Vf8QnRkRN0gOUfs3ejrLcxFRzTXvcKqcHtbaqzCs3qSNC6UvV
+wjBazEwQCo1wnM81X8uT5fLhnjXebWtnYexQo5P38PiaqTQDgrbAdhP5P8NwRCXM
+G3SNEz0XeL27jmWjf0VJdwD0LuHXYhcwAWq4alhJ024rjgVHwOze
+-----END RSA PRIVATE KEY-----
+
diff --git a/src/components/transport_manager/test/test_certs/server-cert.pem b/src/components/transport_manager/test/test_certs/server-cert.pem
new file mode 100644
index 0000000000..d2b1cf0ec8
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/server-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdDCCAlwCAQEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVUExDzANBgNV
+BAgMBk9kZXNzYTEPMA0GA1UEBwwGT2Rlc3NhMQ8wDQYDVQQKDAZMdXhvZnQxDTAL
+BgNVBAsMBEZUQ04xDzANBgNVBAMMBkx1eC1DQTEaMBgGCSqGSIb3DQEJARYLY2FA
+ZnRjbi5jb20wHhcNMjAwMTEwMTQzMzM2WhcNMjIxMDA2MTQzMzM2WjCBgzELMAkG
+A1UEBhMCVUExDzANBgNVBAgMBk9kZXNzYTEPMA0GA1UEBwwGT2Rlc3NhMQ8wDQYD
+VQQKDAZMdXhvZnQxDTALBgNVBAsMBEZUQ04xEjAQBgNVBAMMCWxvY2FsaG9zdDEe
+MBwGCSqGSIb3DQEJARYPc2VydmVyQGZ0Y24uY29tMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEApnW3zyWadWiD1eMPszMM0Hyzm3Zd6mr21LMtQMwqw10p
+PxMpZLo0rgCkJevVRxO/y4J+TcE9LtralzzsWK+DD/i2Gf8CfAOapcDETJ8b68jM
+rUMwmN3tdiEBqimHBKEKIgDOiJt2Y08Jw2AWR41LuyjtD+IWSWo1kqJF3rxpsfz0
+SfTQWkvHVXg1c0qbfsp2i82Nvt5HzvDdk0jzX+GNHSmkUECcE0GIhK8GHxAFYugk
+siRU/tgY/wzP9iUkj7UbPWb5k+d8Z3sqUFpVAa4dXhIzx5L0l5peXvhunYqr7Vk+
+cfBAHIQZKJa7coBBahA7gjBylz+BbIOadGYYoYZVBQIDAQABMA0GCSqGSIb3DQEB
+CwUAA4IBAQDNUMIv6X9scvVN8II/PbvvQzWAxi0qzDejnEF579PA9MCNt6JY20lj
+JTscUN5lWNuLGJtkUuscBMBYe21ePtGeS855Q6csoUe6m0fnY+ybKVYIKk+SL5Hx
+1vurBIsHOyX6097e8VIzWyxcWW1074oTYLpYfEWr0vECrGodoXGtPdEeyB0+QdbI
+H0Pcngqu5yLoWxoWwuAj94YG7eX3sJv6PXOW71i4yMmT8ToYNXFwqTK/xq/pl6H2
+KH150zDNOaE2Z5+u21Elau+3qWPWQ6C9KpxhmJ/iDftRe+hgMISSygYK0nwk0zk4
+rmNODAeuTvsrh9bNsYQfjERsh0VYaG24
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/server-key.pem b/src/components/transport_manager/test/test_certs/server-key.pem
new file mode 100644
index 0000000000..6ff13eaf28
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/server-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmdbfPJZp1aIPV
+4w+zMwzQfLObdl3qavbUsy1AzCrDXSk/EylkujSuAKQl69VHE7/Lgn5NwT0u2tqX
+POxYr4MP+LYZ/wJ8A5qlwMRMnxvryMytQzCY3e12IQGqKYcEoQoiAM6Im3ZjTwnD
+YBZHjUu7KO0P4hZJajWSokXevGmx/PRJ9NBaS8dVeDVzSpt+ynaLzY2+3kfO8N2T
+SPNf4Y0dKaRQQJwTQYiErwYfEAVi6CSyJFT+2Bj/DM/2JSSPtRs9ZvmT53xneypQ
+WlUBrh1eEjPHkvSXml5e+G6diqvtWT5x8EAchBkolrtygEFqEDuCMHKXP4Fsg5p0
+ZhihhlUFAgMBAAECggEBAJ35UfuxACk0iwlNd/TlGeAyuHFtoCt8X8v0T5oTKPJH
+U4GcucfyP1RzH1Utvza5M2f768n2/g2dfZ3SH6r6xjM+IfQB42W2NengS2s8BM97
+vWMhRNmOpHFbWa0XxB9MhcVHZrqWb4BH3kggxIQbQCfa60ALnIMH3NfQUObVgKl8
+khPU3fWx5zH2fbLNiLbImr5U5ViNoOKw592cmAEocIgIE33SDf2LHuuByikb38/r
+98bAp6IdNhRb7qY/Jllq3fu06fLubGQusVT01vu3sp//G2gCzFwp0O/qX2M1JBPS
+JYKKGXrNxeaQNzzD6cEcSkADpZvIG/CmmnR9u/FjIXECgYEA2palcAJKXPWsnwLb
+QtDd7MQ6sG3qvkCaiiDsn5BAGkxn1rZ3NRGMxBx4Fb9oiIl6SBpQ/YdMkd7tMkLX
+MEmbPyOcHPnsxcCqeFGsiTejpx1OyPSUAtxtpxGc/D63wCPhHGO3xNdQ2FiYb5K3
+jG8cslE39gH+/9XSN8kS2gZZ4d8CgYEAwvMUbXSBYx01I+jjqsjSI9afk3w9VwKM
+vuW9MgUBYLP5ryadNqt2cuHydT5KJiZ7YUQSLNztZ++g5WR7yamWpLzoGFmrSyWb
+304xA9jdLRJHMsBM0V32abdfTV5+EW+24309UmcaUtsQoUTxXOSqwDaHF4Mq1zLg
+jwb2phYlzZsCgYEAtz5q2gdRh7R8TaD7ZnvqTz4BZT3/+BX4d6s6MlmfI2zB8AFu
+1ZIsy4qCMNkRLMTzOda15pOx4OddOTFHbDeIadnUWYY6s1zci5kMZsu56bJsBZLj
+MbLQSao+TEfXir+JS19dAyrtnzBGOeJo9NWA3QuxOg5aUuZRIGrz3spMN0kCgYB3
+ZLnpAwZO9k9aS8JLESypqEMY52kFxdj+/OKvJKOgXvkWzPZRyhcD6t878McmsEC1
+5COheDipg/etJaouan+JKuyWJSykHEdnLpMUQRfMB7q1GVKykvJb8mMaljltYlbG
+4ifRNLXJcsKvkfKkKqNsjriTrNBq9YzT67bZJw1F6wKBgGlEd9O+qWY4dSPKN60N
+khG1Splz+eBbbsqcISeFGZepEc4HaEIcYgIHTh8nw5ycYxh8A1UBdaBZmU9UHdfl
+j9M2u0htKZ27ntVVNZJCLeSgufaPUDIfvnK4o5q630NGhKJmVcYD3WeggIrPfca3
+fP8WaHq9fx5k4YZokD2VHOJb
+-----END PRIVATE KEY-----
diff --git a/src/components/transport_manager/test/transport_manager_default_test.cc b/src/components/transport_manager/test/transport_manager_default_test.cc
index bedc1634cc..67b4a0a8ba 100644
--- a/src/components/transport_manager/test/transport_manager_default_test.cc
+++ b/src/components/transport_manager/test/transport_manager_default_test.cc
@@ -65,6 +65,12 @@ const std::string kTransportManager = "TransportManager";
const std::string kTcpAdapter = "TcpAdapter";
const std::string kBluetoothAdapter = "BluetoothAdapter";
const std::string kDevices = "devices";
+const uint16_t kPort = 12345u;
+const std::string kAddress = "127.0.0.1";
+const std::string kServerCertPath = "server_certificate.crt";
+const std::string kServerCACertPath = "ca-certificate.crt";
+const std::string kWSServerKeyPathKey = "WSServerKeyPath";
+const std::string kWSServerCACertPath = "WSServerCACertificatePath";
std::vector<uint8_t> kBTUUID = {0x93,
0x6D,
0xA0,
@@ -180,7 +186,7 @@ void TestTransportManagerDefault::ExpectationsSettings_TM(
// Arrange TM Settings expectations
Json::Value tcp_device;
tcp_device[kDeviceName] = unique_tcp_dev_name_;
- tcp_device[kDeviceAddress] = "127.0.0.1";
+ tcp_device[kDeviceAddress] = kAddress;
tcp_device[kDeviceApplications][0][kApplicationPort] = "1";
Json::Value bluetooth_device;
@@ -192,16 +198,29 @@ void TestTransportManagerDefault::ExpectationsSettings_TM(
custom_dictionary_[kTransportManager][kTcpAdapter][kDevices][0] = tcp_device;
custom_dictionary_[kTransportManager][kBluetoothAdapter][kDevices][0] =
bluetooth_device;
+ ON_CALL(transport_manager_settings_, websocket_server_port())
+ .WillByDefault(Return(kPort));
+ ON_CALL(transport_manager_settings_, websocket_server_address())
+ .WillByDefault(ReturnRef(kAddress));
+ ON_CALL(transport_manager_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kServerCertPath));
+ ON_CALL(transport_manager_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kWSServerKeyPathKey));
+ ON_CALL(transport_manager_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(kWSServerCACertPath));
ON_CALL(*mock_last_state_, dictionary())
.WillByDefault(Return(custom_dictionary_));
ON_CALL(*mock_last_state_, get_dictionary())
.WillByDefault(ReturnRef(custom_dictionary_));
+
EXPECT_CALL(transport_manager_settings_, use_last_state())
.WillRepeatedly(Return(use_last_state));
EXPECT_CALL(transport_manager_settings_, transport_manager_tcp_adapter_port())
.WillRepeatedly(Return(tcp_adapter_port_));
+
EXPECT_CALL(transport_manager_settings_, bluetooth_uuid())
.WillRepeatedly(Return(kBTUUID.data()));
+
EXPECT_CALL(transport_manager_settings_, aoa_filter_manufacturer())
.WillRepeatedly(ReturnRef(dummy_parameter_));
EXPECT_CALL(transport_manager_settings_, aoa_filter_model_name())
diff --git a/src/components/transport_manager/test/websocket_client_connection_test.cc b/src/components/transport_manager/test/websocket_client_connection_test.cc
new file mode 100644
index 0000000000..b9aa6f7c7e
--- /dev/null
+++ b/src/components/transport_manager/test/websocket_client_connection_test.cc
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2020, 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 "transport_manager/cloud/websocket_client_connection.h"
+#include "gtest/gtest.h"
+#include "resumption/last_state_impl.h"
+#include "resumption/last_state_wrapper_impl.h"
+#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
+#include "transport_manager/cloud/sample_websocket_server.h"
+#include "transport_manager/transport_adapter/connection.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+#include "transport_manager/mock_transport_manager_settings.h"
+
+namespace test {
+namespace components {
+namespace transport_manager_test {
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using namespace ::transport_manager;
+using namespace ::transport_manager::transport_adapter;
+namespace websocket = sample::websocket;
+
+class WebsocketConnectionTest : public ::testing::Test {
+ public:
+ struct WebsocketClient {
+ std::shared_ptr<CloudWebsocketTransportAdapter> adapter;
+ std::shared_ptr<WebsocketClientConnection> connection;
+ };
+
+ void InitWebsocketClient(
+ const transport_manager::transport_adapter::CloudAppProperties&
+ properties,
+ WebsocketClient& client_out) {
+ uniq_id = dev_id = properties.endpoint;
+
+ client_out =
+ WebsocketClient{std::make_shared<CloudWebsocketTransportAdapter>(
+ last_state_wrapper_, transport_manager_settings),
+ nullptr};
+ client_out.adapter->SetAppCloudTransportConfig(uniq_id, properties);
+
+ TransportAdapterImpl* ta_cloud =
+ dynamic_cast<TransportAdapterImpl*>(client_out.adapter.get());
+ ta_cloud->CreateDevice(uniq_id);
+
+ auto connection = client_out.adapter->FindPendingConnection(dev_id, 0);
+
+ ASSERT_NE(connection, nullptr);
+
+ client_out.connection =
+ std::dynamic_pointer_cast<WebsocketClientConnection>(connection);
+
+ ASSERT_NE(client_out.connection.use_count(), 0);
+ }
+
+ void StartWSServer(std::string path) {
+ ws_session = std::make_shared<websocket::WSSession>(kHost, kPort);
+ ws_session->AddRoute(path);
+ ws_session->Run();
+ }
+
+ void StartWSSServer(std::string path) {
+ wss_session = std::make_shared<websocket::WSSSession>(
+ kHost, kPort, kCertificate, kPrivateKey);
+ wss_session->AddRoute(path);
+ wss_session->Run();
+ }
+
+ protected:
+ WebsocketConnectionTest()
+ : last_state_(std::make_shared<resumption::LastStateImpl>(
+ "app_storage_folder", "app_info_storage"))
+ , last_state_wrapper_(
+ std::make_shared<resumption::LastStateWrapperImpl>(last_state_)) {}
+
+ ~WebsocketConnectionTest() {}
+
+ void SetUp() OVERRIDE {
+ ON_CALL(transport_manager_settings, use_last_state())
+ .WillByDefault(Return(true));
+ }
+
+ NiceMock<MockTransportManagerSettings> transport_manager_settings;
+ std::shared_ptr<resumption::LastStateImpl> last_state_;
+ std::shared_ptr<resumption::LastStateWrapperImpl> last_state_wrapper_;
+ std::string dev_id;
+ std::string uniq_id;
+ std::shared_ptr<websocket::WSSession> ws_session;
+ std::shared_ptr<websocket::WSSSession> wss_session;
+ WebsocketClient ws_client;
+ std::string kHost = "127.0.0.1";
+ uint16_t kPort = 8080;
+ std::string kPath = "/folder/file.html/";
+ std::string kQuery = "?eventId=2345&eventName='Test'&expectedResult=true";
+ std::string kFragment = "#section_1";
+
+ // Sample certificate for localhost
+ std::string kCertificate =
+ "-----BEGIN "
+ "CERTIFICATE-----\nMIIDqTCCApECCQC/"
+ "5LlQ+"
+ "GLgqTANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAwx\nMjcuMC4wLjEgQ0EwIBcNMTkwNTA"
+ "2MTkzMjM2WhgPMjExOTA0MTIxOTMyMzZaMBQx\nEjAQBgNVBAMMCTEyNy4wLjAuMTCCAiIwD"
+ "QYJKoZIhvcNAQEBBQADggIPADCCAgoC\nggIBALbeIoAHFaFeNqbMnhtAO5QTgRd0X9qxpB0"
+ "d4M0dEeog2l/+inNA/eu+CCvm\nJj2I8+6MWH2TUrl/"
+ "2xfhHjzsMrtISCdpNcjaNzCnvi8ZcspFi3evknvs3+uo2/"
+ "wn\nyNZ04jp0oQ0k1cZ6WBpLTYV7WgmueemiWEiAfw+YE+wtRg+"
+ "0H7rksrbpeNPnxQHX\nBDDkWqwvfkD15Sd0XFQkW27K72/"
+ "et2uKuAcJHCIUbsA4iZyJw4Uu4eusy7W5kddX\nThE7Y1WqTXyA4j/"
+ "ZCYigXmsHbWrikPLVXbORhiMF4/60u8RDs0jI8xtgRQhLR9Vp\n3xys7/"
+ "5tHZX00s6x6OVy8aMSZIIVS0eWoVN8bGd9B4+fDMOcNT0YODeQA10w/"
+ "85P\nEiZDQ8AxneQkh8H3qjD2+"
+ "G9oHZaTk0zHTyaKRg3xGP3N9C96onaJX4Rm6nNvApO8\nU7lQ+xHkLwjKCQke39W+"
+ "r3FHwwQvUDeoJBXf6iVkIMFoUPAHNZqKf9Db6KKIEp8i\nDgIhbBxiB4MSn36Zly4SOMojyM"
+ "ZFri+"
+ "HzMbuHFlm8e8QRWGmM4UM2rHIpl4OJolg\nejesDqO8YZR5mZXV0FJRiPgLo2Q4OTtb3tEHJ"
+ "ZLmlT+"
+ "f42bge4ZCZmGPrkNfr68Y\nDEnJ6z4ksOVkMefOp2SNYLYYGPYyiKwa9qVkH9Obkect1omNA"
+ "gMBAAEwDQYJKoZI\nhvcNAQELBQADggEBABFJQtOTftrzbLBA5Vm6aPkbUyxhcaOpz+d+"
+ "Ljd6pIs4H+"
+ "Eb\nXkoHhmay4stZkDc2HVSKESZloI3Ylup8z3aRJjfOexJqHlYzk2vraYryWm8odgID\n5V"
+ "B0Zle8ofpHTJw1LCOXHkzKt1G6vdQpuq/"
+ "4OKpmggaIqqEC1bfOYZt5t6vIx3OF\nxjPz91NTR9gZ4lKrho1+sfS+"
+ "jbSjKkqVAhE4yTpKLPHRshQnBFEhvATXNvdZGftF\n+tXxqKsBZ9aX0/"
+ "YmPFIXFcjdjSSiuq1F1DjiqIZo88qfa9jlTg6VJdayyQ/"
+ "cu41C\nBucY8YTF0Ui8ccIS55h2UTzPy5/4PbrwI4P+Zgo=\n-----END "
+ "CERTIFICATE-----\n";
+ // Sample private key
+ std::string kPrivateKey =
+ "-----BEGIN RSA PRIVATE "
+ "KEY-----\nMIIJKAIBAAKCAgEAtt4igAcVoV42psyeG0A7lBOBF3Rf2rGkHR3gzR0R6iDaX/"
+ "6K\nc0D9674IK+YmPYjz7oxYfZNSuX/"
+ "bF+EePOwyu0hIJ2k1yNo3MKe+LxlyykWLd6+S\ne+zf66jb/"
+ "CfI1nTiOnShDSTVxnpYGktNhXtaCa556aJYSIB/"
+ "D5gT7C1GD7QfuuSy\ntul40+fFAdcEMORarC9+"
+ "QPXlJ3RcVCRbbsrvb963a4q4BwkcIhRuwDiJnInDhS7h\n66zLtbmR11dOETtjVapNfIDiP9"
+ "kJiKBeawdtauKQ8tVds5GGIwXj/rS7xEOzSMjz\nG2BFCEtH1WnfHKzv/"
+ "m0dlfTSzrHo5XLxoxJkghVLR5ahU3xsZ30Hj58Mw5w1PRg4\nN5ADXTD/"
+ "zk8SJkNDwDGd5CSHwfeqMPb4b2gdlpOTTMdPJopGDfEY/"
+ "c30L3qidolf\nhGbqc28Ck7xTuVD7EeQvCMoJCR7f1b6vcUfDBC9QN6gkFd/"
+ "qJWQgwWhQ8Ac1mop/"
+ "\n0NvooogSnyIOAiFsHGIHgxKffpmXLhI4yiPIxkWuL4fMxu4cWWbx7xBFYaYzhQza\nscim"
+ "Xg4miWB6N6wOo7xhlHmZldXQUlGI+AujZDg5O1ve0QclkuaVP5/"
+ "jZuB7hkJm\nYY+uQ1+"
+ "vrxgMScnrPiSw5WQx586nZI1gthgY9jKIrBr2pWQf05uR5y3WiY0CAwEA\nAQKCAgBGSDGyS"
+ "wbBMliG2vWZO6KqUqS2wv9kKgoNNsKDkryj42SKqGXFziDJTgwN\n8zKXS9+Uu1P3T3vn13/"
+ "5OYhJme4VlL5Gh2UogNXdWVr69yjrHLdxlIUUJAIbrJZ/"
+ "\n3zqNUfbwyIptZs7SrYrW8EInHzWHqwsoBEEx/"
+ "FDZSXW+u9fFiVD4n5UgP7M0nktV\nXbI6qElBDC/V/"
+ "6vG8i3aGO8bMdu8fzi3mGUKLzIk1v2J2zDofPosYcxqq8rPWTb4\nMJHMhaqz7fRB+"
+ "bb7GwtS+2/Oathe0B0td1u//Bo1s7ng1s2jrPFm8/"
+ "SbfPCLM4O0\nPjCF8OF8Q6uvSp0K283LAdZk+liuDztc/"
+ "Ed8mcnCZQhBp86mJQi0Jj3Mje7prOAY\nXojMroYj7r2igCJvcwGb1y6zZWSj3jXuHze3bLy"
+ "fv7pCD+hkiZR7mZhQpOhQRZaU\ntdFGc+"
+ "DuykxKPqVjAPy7iVQXYnMjpo36SGIWoZLuepQto3GvU6czyOwhK0/"
+ "Mwbwd\nZpYpLH3L9IetY8GcPefmUR5wQUlUTrpxgGElIzkkWW8zmUWBXwrGbAtN1HJWpJdN"
+ "\neVshKod2fo03IQMPywSdENCJVeSrgRMuwPyFaOM+"
+ "CVrBJwD66K9YWn4cVRUIZsTq\nAXhQ8DzF+WCOZshhMUbCJX+KpcOFI8nxOrPp+"
+ "J1s1YpLLvdmcQKCAQEA7bwvOiCD\nHvaqpYg1jJak6l/"
+ "iY3QIOOpFyjfYrQXS0BNRmmxK8Lzevi/"
+ "NPTqu146QKDaIGvzu\n+"
+ "bXnuV1LmZqnOm5J6Kdx0Mk4Fb88akRtS9gOdzU7WWMYIGkeF1oih0ZrhHuIey6e\nCeLSmJh"
+ "UDaTIWcCirALRHcLWUS6BTGGuE+up5QG7djIW/"
+ "LD17lhGE6fXPlbYXb7l\nPbYwL1Yr0urIp9Un+zrExw+77TTGK7T37T1ZJv46qnro0/"
+ "HK8XxZ+"
+ "JNc18F763O4\nPmwu8KWrx4qnyPYAuB1rbVntK6UxYks9jvk93XecCUP6HHp0I0tV/"
+ "kBNd2+"
+ "18zux\n033xFEVKrUksmwKCAQEAxOrPGyBVFp29V4gQsMQdmafkDAgCLREgjQTOamFsYL5+"
+ "\nZWq+6VhT/"
+ "B650sIoRdX0N8timnSLBfjeqaBG5VVhhyKZhP5hulfRjALhdbGBOYvf\n0gLSffImwWdYQfx"
+ "jtCSO+"
+ "XCLVdAJGOOWeBVVKzH18ZvCFQwUr3Yrp7KmKWKAqgf7\n6rYovWh8T5LLYS0NzXCEwf9nJ0N"
+ "JMOy7I9B7EtF8Cs6tK3aaHVqDz7zufwosS7gI\n3aI51Qh4a5D1p95+"
+ "YU09beWjWGYnPiCKk4D47zaeOe7OQINaWugExlelHtJh9unO\nnhOFXhziav2Kxq1CICAuXl"
+ "Vx3A+gn/cU3niNHz2A9wKCAQEAws+aw78ws4bef5cG\nipZHveek1GqY8krHtdXdsKs8/"
+ "VVXYXusTWn3/VGelbYo4GrqpolJLxRloCr4IGXb\nNZwNvUvzNLtCAR1i4C89irdX+Paro/"
+ "PzFmSluKlrByfNc5y5Lm8sgATLbL56ZKEu\n/58wrpu0sc/"
+ "9HK40gYHiYn0I8ToElqy8uTaCr78zSIT9p826DFOOKgPsRo2tHp02\nfDf5Bc8eXDjkV1sFX"
+ "HQKkHZTVA0ZqWJbIKhncoaJDyofcBsR0ZuzuFWzfTOZo4mf\nInz00TEFldpF1e4C8+"
+ "kCdtHBOA/2Ki2Bp/YUVpHh6aoqZZa75Euehhs8tVpW242M\njEOSUQKCAQAM64sjMH/kt/"
+ "zQXXEa6AM5LbbcwznBUzpbhlE00aeWwWjxpotYLB92\nj12J4otZ6avYbVPO5o6omaeiYY3F"
+ "RlDb2P1RqI8o9tIc6aN5YWglKnRJBz5gXR8F\n2Y4E5lZ0X2GyJBxASSIPq/"
+ "8Xae7ooqKMc7fMQbqpuIssuaAFXx0qCtQQllsd8lkV\nr4AApEAflp5fTC6seNG4kA/"
+ "HTcqFdZE59E2QaHu8KVA0tSTA2R4G6dBLGnXI8IFW\nLXCwzvxjzfmV2FdbWXiBrwjonLG4o"
+ "FDJZE3MFdI73LVTfjSrTQp4dObFoGpDvols\nk64jUwLfsLzaG6kY0z2qwT9xSV+"
+ "ZCSQJAoIBADsSBeyELc5KnmOhT0Xue2o0bkAS\n8KcGWdAoQlaLCIs3vtdlC7DXDXO1l8FkT"
+ "Qrd+GwP3eWDq6ymtO4vkJ3m4cZ1PEsv\n6Qet7qtkVhUfa+"
+ "FYKtDzSMRuSaFPW3Ro1PesFa1H3y+sw5HL36vhRaSK+T4Wy5k2\nf7EwNZIf/"
+ "ZZeA+"
+ "sEtqj33obOBIiuU9htAjN81Kz4a0Xlh6jc4q6iwYKL8nZ76JYV\n8hXWIz6OXxLXE158+"
+ "QtJSZaRCvdr6L5UtWfMPKSMqgfhXfTYViPDleQCkJ132mIS\nH28UoET0Y5wI8M6pMkWpSqW"
+ "WcKPFGwyLInvHdxgnTAsutowkldA7qFwoRz4=\n-----END RSA PRIVATE KEY-----\n";
+ // Sample CA certificate(used to sign the server certificate)
+ std::string kCACertificate =
+ "-----BEGIN "
+ "CERTIFICATE-----"
+ "\nMIIDBjCCAe6gAwIBAgIJAPyCrKRDl3SWMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV\nBAMM"
+ "DDEyNy4wLjAuMSBDQTAgFw0xOTA1MDYxOTMyMzZaGA8yMTE5MDQxMjE5MzIz\nNlowFzEVMB"
+ "MGA1UEAwwMMTI3LjAuMC4xIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA"
+ "xrNHoY5+"
+ "JCgnyvEdG2dvvOaZ3sg6uhuF5Ssb5snyo9ixrxO5\nZkDGWwUqFO9PiYuO5ovNeq9LZtPG6s"
+ "K8zsCS062ChZX/7tZHndf4MKCUDzv/"
+ "LPHe\nnROoPi9n2FAiOPctY5hpgpIJDPI5Ofx0el2KPeFGeUO/"
+ "W3yqnfol1ZqzZ2h3uErR\noHkgT2Ja4K+5gnPkr/"
+ "RluJIu3AmWYw4eKi8i3+"
+ "PoThGmCFvoGfcWvRoctgnOHYHE\n4bDRirXL9nGkZ5FMzOVDeoIAEAShOqJwL08VcY+Pg/"
+ "qFQjzRrTmiKgm6QsHNnm0q\nzg70XaD88VJimiGYZOuJHNZpX8o0W+1Ls/"
+ "NbawIDAQABo1MwUTAdBgNVHQ4EFgQU\nkW3hgFWYMpVUkq9AlzGlI3awTGEwHwYDVR0jBBgw"
+ "FoAUkW3hgFWYMpVUkq9AlzGl\nI3awTGEwDwYDVR0TAQH/BAUwAwEB/"
+ "zANBgkqhkiG9w0BAQsFAAOCAQEAZeMkILiG\neEcELWb8cktP3LzvS47O8hys9+"
+ "6TFmftuO7kjDBd9YH2v8iQ7qCcUvMJ7bqL5RP1\nQssKfNOHZtw/"
+ "MMcKE6E3nl4yQSKc8ymivvYSVu5SYtQCedcgfRLb5zvVxXw8JmCp\nGNS3/"
+ "OlIYZAamh76GxkKSaV3tv0XZB6n3rUVQZShncFbMpyJRW0XWxReGWrhXv4s\nNxMeC1r07EE"
+ "WIDecv8KKf1F8uT4UF48HnC0VBpXiOyDGvn35NiKp+"
+ "Q5k7QV6jdCS\ngPRcnZhs6jiU0jnV8C9A1A+"
+ "3pXSSPrAed7tvECOgHCfS10CLsLWsLuSjc93BE5Vt\nav7kmxSwrdvQ2A==\n-----END "
+ "CERTIFICATE-----\n";
+ std::string kIncorrectCertificate =
+ "-----BEGIN "
+ "CERTIFICATE-----\nMIIC/"
+ "jCCAeagAwIBAgIJAIZjLucUID1mMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV\nBAMMCTEyNy4"
+ "wLjAuMTAeFw0xOTA1MDYxNDA1MzdaFw0yOjA1MDZxNDA1MzdaMBQx\nEjAQBgNVBAMMCTEyN"
+ "y4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBALfE5Qhc2mHTIux30l7"
+ "eHFjFLdzYeXE8vcaXKodalCG8EkRxojDOfUv+y2DV\nJzHAMiGxMFAEcSz71k+"
+ "jFZwhNG8PLY0b36ChnUsrGkOSJWq3OKUFrg8KxO9At9dL\nJsa+"
+ "R0N0D1bMoPYdpCi3m0b0q2ITHe56qKuTLTrIPia+"
+ "qXGEVD7EoEhU9tnwlcwE\npsUURMXCn2+FhHyqN9wjFkldmu4k8U3OJOK4385L+"
+ "4RJoIV8dsYawAMAf+"
+ "WuxyWq\niPQTPxr8q33ZZm6z0XrgsgxHYCCsryx8L9Ub9Zwu0mie7eL63rYdr86gULvnF1bY"
+ "\ncOunKFc71rBYFalbD6YYsre733kCAwEAAaNTMFEwHQYDVR0OBBYEFKW9ByUNG84Z\nYiSc"
+ "hUrB7KV9FinZMB8GA1UdIwQYMBaAFKW9ByUNG84ZYiSchUrB7KV9FinZMA8G\nA1UdEwEB/"
+ "wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYROS1EL2qnrwmAsR6c\nqo8yrk8qzLKt4os"
+ "41nv7QMUQFIO+QLPE8SbH4fK1YOMMUJ4ppARQBDaIIR3UEhp1\nZHT/"
+ "wGjK9qxcuQ1EXLyHOY0rxS5q57dYGxOyQo4v6IoLVMZ1ij+RJGPYI/"
+ "2fDXs0\nbDldeJyC1voHmG6lqTN5nLG7Y3j9j6rtSqJyRz5muaecQNiFPQOM2OTp0rC4VeAF"
+ "\ndejmTmLhUFVuHMzLF+"
+ "bpzsN76GnnQquJy2jexzFoWgbEfFVLKuyhTHQAalRb4ccq\nXCIx1hecNDYRY3Sc2Gzv5qxk"
+ "kWF8zqltT/0d5tx0JwN3k5nP4SlaEldFvD6BELxy\nVkU=\n-----END "
+ "CERTIFICATE-----\n";
+};
+
+TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort),
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
+ kQuery + kFragment,
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSServer(kPath);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
+ kQuery + kFragment,
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + kPath,
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer((kPath + kQuery + kFragment));
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+
+#ifdef ENABLE_SECURITY
+TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer(kPath);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kIncorrectCertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+#endif // ENABLE_SECURITY
+} // namespace transport_manager_test
+} // namespace components
+} // namespace test
diff --git a/src/components/transport_manager/test/websocket_connection_test.cc b/src/components/transport_manager/test/websocket_connection_test.cc
index a7ddb820a0..306bdc4784 100644
--- a/src/components/transport_manager/test/websocket_connection_test.cc
+++ b/src/components/transport_manager/test/websocket_connection_test.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Ford Motor Company
+ * Copyright (c) 2020, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,15 +31,26 @@
*/
#include "gtest/gtest.h"
+
+#include <memory>
+#include <string>
+
#include "resumption/last_state_impl.h"
-#include "resumption/last_state_wrapper_impl.h"
-#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
-#include "transport_manager/cloud/sample_websocket_server.h"
-#include "transport_manager/cloud/websocket_client_connection.h"
-#include "transport_manager/transport_adapter/connection.h"
-#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+#include "transport_manager/websocket_server/websocket_connection.h"
+#include "transport_manager/websocket_server/websocket_session.h"
#include "transport_manager/mock_transport_manager_settings.h"
+#include "transport_manager/transport_adapter/mock_transport_adapter_controller.h"
+
+namespace {
+const std::string kHost = "127.0.0.1";
+const uint16_t kPort = 8080;
+const std::string kPath = "/folder/file.html/";
+const std::uint32_t kConnectionKey = 1u;
+const std::uint32_t kProtocolVersion = 5u;
+const std::string kDeviceUid_ = "deviceUID";
+const transport_manager::ApplicationHandle kAppHandle = 12345u;
+} // namespace
namespace test {
namespace components {
@@ -48,433 +59,112 @@ namespace transport_manager_test {
using ::testing::_;
using ::testing::NiceMock;
using ::testing::Return;
+
+using protocol_handler::RawMessagePtr;
+using protocol_handler::ServiceType;
+
using namespace ::transport_manager;
using namespace ::transport_manager::transport_adapter;
-namespace websocket = sample::websocket;
-class WebsocketConnectionTest : public ::testing::Test {
+class WebsocketNotSecureSessionConnectionTest : public testing::Test {
public:
- struct WebsocketClient {
- std::shared_ptr<CloudWebsocketTransportAdapter> adapter;
- std::shared_ptr<WebsocketClientConnection> connection;
- };
+ WebsocketNotSecureSessionConnectionTest()
+ : websocket_connection_(
+ std::make_shared<WebSocketConnection<WebSocketSession<> > >(
+ kDeviceUid_,
+ kAppHandle,
+ boost::asio::ip::tcp::socket(i_co_),
+ &mock_transport_adapter_ctrl_))
- void InitWebsocketClient(
- const transport_manager::transport_adapter::CloudAppProperties&
- properties,
- WebsocketClient& client_out) {
- uniq_id = dev_id = properties.endpoint;
+ , last_state_("test_app_folder", "test_app_info_storage") {}
- client_out =
- WebsocketClient{std::make_shared<CloudWebsocketTransportAdapter>(
- last_state_, transport_manager_settings),
- nullptr};
- client_out.adapter->SetAppCloudTransportConfig(uniq_id, properties);
-
- TransportAdapterImpl* ta_cloud =
- dynamic_cast<TransportAdapterImpl*>(client_out.adapter.get());
- ta_cloud->CreateDevice(uniq_id);
+ void SetUp() OVERRIDE {
+ ON_CALL(mock_transport_manager_settings_, use_last_state())
+ .WillByDefault(Return(true));
+ }
- auto connection = client_out.adapter->FindPendingConnection(dev_id, 0);
+ RawMessagePtr CreateDefaultRawMessage() {
+ const uint32_t data_sending_size = 3u;
+ unsigned char data_sending[data_sending_size] = {0x20, 0x07, 0x01};
+ RawMessagePtr raw_message_ptr(
+ new ::protocol_handler::RawMessage(kConnectionKey,
+ kProtocolVersion,
+ data_sending,
+ data_sending_size,
+ false,
+ ServiceType::kAudio));
+ return raw_message_ptr;
+ }
- ASSERT_NE(connection, nullptr);
+ protected:
+ boost::asio::io_context i_co_;
+ std::shared_ptr<WebSocketConnection<WebSocketSession<> > >
+ websocket_connection_;
+ NiceMock<MockTransportAdapterController> mock_transport_adapter_ctrl_;
+ NiceMock<MockTransportManagerSettings> mock_transport_manager_settings_;
+ resumption::LastStateImpl last_state_;
+};
- client_out.connection =
- std::dynamic_pointer_cast<WebsocketClientConnection>(connection);
+TEST_F(WebsocketNotSecureSessionConnectionTest, Disconnect_SUCCESS) {
+ websocket_connection_->Run();
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DisconnectDone(kDeviceUid_, kAppHandle))
+ .Times(1);
- ASSERT_NE(client_out.connection.use_count(), 0);
- }
+ auto error = websocket_connection_->Disconnect();
- void StartWSServer(std::string path) {
- ws_session = std::make_shared<websocket::WSSession>(kHost, kPort);
- ws_session->AddRoute(path);
- ws_session->Run();
- }
+ ASSERT_EQ(TransportAdapter::Error::OK, error);
+}
- void StartWSSServer(std::string path) {
- wss_session = std::make_shared<websocket::WSSSession>(
- kHost, kPort, kCertificate, kPrivateKey);
- wss_session->AddRoute(path);
- wss_session->Run();
- }
+TEST_F(WebsocketNotSecureSessionConnectionTest, SecondDisconnect_UNSUCCESS) {
+ websocket_connection_->Run();
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DisconnectDone(kDeviceUid_, kAppHandle))
+ .Times(1);
- protected:
- WebsocketConnectionTest()
- : last_state_(std::make_shared<resumption::LastStateWrapperImpl>(
- std::make_shared<resumption::LastStateImpl>("app_storage_folder",
- "app_info_storage"))) {}
+ auto result_error = websocket_connection_->Disconnect();
- ~WebsocketConnectionTest() {}
+ ASSERT_EQ(TransportAdapter::Error::OK, result_error);
- void SetUp() OVERRIDE {
- ON_CALL(transport_manager_settings, use_last_state())
- .WillByDefault(Return(true));
- }
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DisconnectDone(kDeviceUid_, kAppHandle))
+ .Times(0);
- NiceMock<MockTransportManagerSettings> transport_manager_settings;
- resumption::LastStateWrapperPtr last_state_;
- std::string dev_id;
- std::string uniq_id;
- std::shared_ptr<websocket::WSSession> ws_session;
- std::shared_ptr<websocket::WSSSession> wss_session;
- WebsocketClient ws_client;
- std::string kHost = "127.0.0.1";
- uint16_t kPort = 8080;
- std::string kPath = "/folder/file.html/";
- std::string kQuery = "?eventId=2345&eventName='Test'&expectedResult=true";
- std::string kFragment = "#section_1";
-
- // Sample certificate for localhost
- std::string kCertificate =
- "-----BEGIN "
- "CERTIFICATE-----\nMIIDqTCCApECCQC/"
- "5LlQ+"
- "GLgqTANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAwx\nMjcuMC4wLjEgQ0EwIBcNMTkwNTA"
- "2MTkzMjM2WhgPMjExOTA0MTIxOTMyMzZaMBQx\nEjAQBgNVBAMMCTEyNy4wLjAuMTCCAiIwD"
- "QYJKoZIhvcNAQEBBQADggIPADCCAgoC\nggIBALbeIoAHFaFeNqbMnhtAO5QTgRd0X9qxpB0"
- "d4M0dEeog2l/+inNA/eu+CCvm\nJj2I8+6MWH2TUrl/"
- "2xfhHjzsMrtISCdpNcjaNzCnvi8ZcspFi3evknvs3+uo2/"
- "wn\nyNZ04jp0oQ0k1cZ6WBpLTYV7WgmueemiWEiAfw+YE+wtRg+"
- "0H7rksrbpeNPnxQHX\nBDDkWqwvfkD15Sd0XFQkW27K72/"
- "et2uKuAcJHCIUbsA4iZyJw4Uu4eusy7W5kddX\nThE7Y1WqTXyA4j/"
- "ZCYigXmsHbWrikPLVXbORhiMF4/60u8RDs0jI8xtgRQhLR9Vp\n3xys7/"
- "5tHZX00s6x6OVy8aMSZIIVS0eWoVN8bGd9B4+fDMOcNT0YODeQA10w/"
- "85P\nEiZDQ8AxneQkh8H3qjD2+"
- "G9oHZaTk0zHTyaKRg3xGP3N9C96onaJX4Rm6nNvApO8\nU7lQ+xHkLwjKCQke39W+"
- "r3FHwwQvUDeoJBXf6iVkIMFoUPAHNZqKf9Db6KKIEp8i\nDgIhbBxiB4MSn36Zly4SOMojyM"
- "ZFri+"
- "HzMbuHFlm8e8QRWGmM4UM2rHIpl4OJolg\nejesDqO8YZR5mZXV0FJRiPgLo2Q4OTtb3tEHJ"
- "ZLmlT+"
- "f42bge4ZCZmGPrkNfr68Y\nDEnJ6z4ksOVkMefOp2SNYLYYGPYyiKwa9qVkH9Obkect1omNA"
- "gMBAAEwDQYJKoZI\nhvcNAQELBQADggEBABFJQtOTftrzbLBA5Vm6aPkbUyxhcaOpz+d+"
- "Ljd6pIs4H+"
- "Eb\nXkoHhmay4stZkDc2HVSKESZloI3Ylup8z3aRJjfOexJqHlYzk2vraYryWm8odgID\n5V"
- "B0Zle8ofpHTJw1LCOXHkzKt1G6vdQpuq/"
- "4OKpmggaIqqEC1bfOYZt5t6vIx3OF\nxjPz91NTR9gZ4lKrho1+sfS+"
- "jbSjKkqVAhE4yTpKLPHRshQnBFEhvATXNvdZGftF\n+tXxqKsBZ9aX0/"
- "YmPFIXFcjdjSSiuq1F1DjiqIZo88qfa9jlTg6VJdayyQ/"
- "cu41C\nBucY8YTF0Ui8ccIS55h2UTzPy5/4PbrwI4P+Zgo=\n-----END "
- "CERTIFICATE-----\n";
- // Sample private key
- std::string kPrivateKey =
- "-----BEGIN RSA PRIVATE "
- "KEY-----\nMIIJKAIBAAKCAgEAtt4igAcVoV42psyeG0A7lBOBF3Rf2rGkHR3gzR0R6iDaX/"
- "6K\nc0D9674IK+YmPYjz7oxYfZNSuX/"
- "bF+EePOwyu0hIJ2k1yNo3MKe+LxlyykWLd6+S\ne+zf66jb/"
- "CfI1nTiOnShDSTVxnpYGktNhXtaCa556aJYSIB/"
- "D5gT7C1GD7QfuuSy\ntul40+fFAdcEMORarC9+"
- "QPXlJ3RcVCRbbsrvb963a4q4BwkcIhRuwDiJnInDhS7h\n66zLtbmR11dOETtjVapNfIDiP9"
- "kJiKBeawdtauKQ8tVds5GGIwXj/rS7xEOzSMjz\nG2BFCEtH1WnfHKzv/"
- "m0dlfTSzrHo5XLxoxJkghVLR5ahU3xsZ30Hj58Mw5w1PRg4\nN5ADXTD/"
- "zk8SJkNDwDGd5CSHwfeqMPb4b2gdlpOTTMdPJopGDfEY/"
- "c30L3qidolf\nhGbqc28Ck7xTuVD7EeQvCMoJCR7f1b6vcUfDBC9QN6gkFd/"
- "qJWQgwWhQ8Ac1mop/"
- "\n0NvooogSnyIOAiFsHGIHgxKffpmXLhI4yiPIxkWuL4fMxu4cWWbx7xBFYaYzhQza\nscim"
- "Xg4miWB6N6wOo7xhlHmZldXQUlGI+AujZDg5O1ve0QclkuaVP5/"
- "jZuB7hkJm\nYY+uQ1+"
- "vrxgMScnrPiSw5WQx586nZI1gthgY9jKIrBr2pWQf05uR5y3WiY0CAwEA\nAQKCAgBGSDGyS"
- "wbBMliG2vWZO6KqUqS2wv9kKgoNNsKDkryj42SKqGXFziDJTgwN\n8zKXS9+Uu1P3T3vn13/"
- "5OYhJme4VlL5Gh2UogNXdWVr69yjrHLdxlIUUJAIbrJZ/"
- "\n3zqNUfbwyIptZs7SrYrW8EInHzWHqwsoBEEx/"
- "FDZSXW+u9fFiVD4n5UgP7M0nktV\nXbI6qElBDC/V/"
- "6vG8i3aGO8bMdu8fzi3mGUKLzIk1v2J2zDofPosYcxqq8rPWTb4\nMJHMhaqz7fRB+"
- "bb7GwtS+2/Oathe0B0td1u//Bo1s7ng1s2jrPFm8/"
- "SbfPCLM4O0\nPjCF8OF8Q6uvSp0K283LAdZk+liuDztc/"
- "Ed8mcnCZQhBp86mJQi0Jj3Mje7prOAY\nXojMroYj7r2igCJvcwGb1y6zZWSj3jXuHze3bLy"
- "fv7pCD+hkiZR7mZhQpOhQRZaU\ntdFGc+"
- "DuykxKPqVjAPy7iVQXYnMjpo36SGIWoZLuepQto3GvU6czyOwhK0/"
- "Mwbwd\nZpYpLH3L9IetY8GcPefmUR5wQUlUTrpxgGElIzkkWW8zmUWBXwrGbAtN1HJWpJdN"
- "\neVshKod2fo03IQMPywSdENCJVeSrgRMuwPyFaOM+"
- "CVrBJwD66K9YWn4cVRUIZsTq\nAXhQ8DzF+WCOZshhMUbCJX+KpcOFI8nxOrPp+"
- "J1s1YpLLvdmcQKCAQEA7bwvOiCD\nHvaqpYg1jJak6l/"
- "iY3QIOOpFyjfYrQXS0BNRmmxK8Lzevi/"
- "NPTqu146QKDaIGvzu\n+"
- "bXnuV1LmZqnOm5J6Kdx0Mk4Fb88akRtS9gOdzU7WWMYIGkeF1oih0ZrhHuIey6e\nCeLSmJh"
- "UDaTIWcCirALRHcLWUS6BTGGuE+up5QG7djIW/"
- "LD17lhGE6fXPlbYXb7l\nPbYwL1Yr0urIp9Un+zrExw+77TTGK7T37T1ZJv46qnro0/"
- "HK8XxZ+"
- "JNc18F763O4\nPmwu8KWrx4qnyPYAuB1rbVntK6UxYks9jvk93XecCUP6HHp0I0tV/"
- "kBNd2+"
- "18zux\n033xFEVKrUksmwKCAQEAxOrPGyBVFp29V4gQsMQdmafkDAgCLREgjQTOamFsYL5+"
- "\nZWq+6VhT/"
- "B650sIoRdX0N8timnSLBfjeqaBG5VVhhyKZhP5hulfRjALhdbGBOYvf\n0gLSffImwWdYQfx"
- "jtCSO+"
- "XCLVdAJGOOWeBVVKzH18ZvCFQwUr3Yrp7KmKWKAqgf7\n6rYovWh8T5LLYS0NzXCEwf9nJ0N"
- "JMOy7I9B7EtF8Cs6tK3aaHVqDz7zufwosS7gI\n3aI51Qh4a5D1p95+"
- "YU09beWjWGYnPiCKk4D47zaeOe7OQINaWugExlelHtJh9unO\nnhOFXhziav2Kxq1CICAuXl"
- "Vx3A+gn/cU3niNHz2A9wKCAQEAws+aw78ws4bef5cG\nipZHveek1GqY8krHtdXdsKs8/"
- "VVXYXusTWn3/VGelbYo4GrqpolJLxRloCr4IGXb\nNZwNvUvzNLtCAR1i4C89irdX+Paro/"
- "PzFmSluKlrByfNc5y5Lm8sgATLbL56ZKEu\n/58wrpu0sc/"
- "9HK40gYHiYn0I8ToElqy8uTaCr78zSIT9p826DFOOKgPsRo2tHp02\nfDf5Bc8eXDjkV1sFX"
- "HQKkHZTVA0ZqWJbIKhncoaJDyofcBsR0ZuzuFWzfTOZo4mf\nInz00TEFldpF1e4C8+"
- "kCdtHBOA/2Ki2Bp/YUVpHh6aoqZZa75Euehhs8tVpW242M\njEOSUQKCAQAM64sjMH/kt/"
- "zQXXEa6AM5LbbcwznBUzpbhlE00aeWwWjxpotYLB92\nj12J4otZ6avYbVPO5o6omaeiYY3F"
- "RlDb2P1RqI8o9tIc6aN5YWglKnRJBz5gXR8F\n2Y4E5lZ0X2GyJBxASSIPq/"
- "8Xae7ooqKMc7fMQbqpuIssuaAFXx0qCtQQllsd8lkV\nr4AApEAflp5fTC6seNG4kA/"
- "HTcqFdZE59E2QaHu8KVA0tSTA2R4G6dBLGnXI8IFW\nLXCwzvxjzfmV2FdbWXiBrwjonLG4o"
- "FDJZE3MFdI73LVTfjSrTQp4dObFoGpDvols\nk64jUwLfsLzaG6kY0z2qwT9xSV+"
- "ZCSQJAoIBADsSBeyELc5KnmOhT0Xue2o0bkAS\n8KcGWdAoQlaLCIs3vtdlC7DXDXO1l8FkT"
- "Qrd+GwP3eWDq6ymtO4vkJ3m4cZ1PEsv\n6Qet7qtkVhUfa+"
- "FYKtDzSMRuSaFPW3Ro1PesFa1H3y+sw5HL36vhRaSK+T4Wy5k2\nf7EwNZIf/"
- "ZZeA+"
- "sEtqj33obOBIiuU9htAjN81Kz4a0Xlh6jc4q6iwYKL8nZ76JYV\n8hXWIz6OXxLXE158+"
- "QtJSZaRCvdr6L5UtWfMPKSMqgfhXfTYViPDleQCkJ132mIS\nH28UoET0Y5wI8M6pMkWpSqW"
- "WcKPFGwyLInvHdxgnTAsutowkldA7qFwoRz4=\n-----END RSA PRIVATE KEY-----\n";
- // Sample CA certificate(used to sign the server certificate)
- std::string kCACertificate =
- "-----BEGIN "
- "CERTIFICATE-----"
- "\nMIIDBjCCAe6gAwIBAgIJAPyCrKRDl3SWMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV\nBAMM"
- "DDEyNy4wLjAuMSBDQTAgFw0xOTA1MDYxOTMyMzZaGA8yMTE5MDQxMjE5MzIz\nNlowFzEVMB"
- "MGA1UEAwwMMTI3LjAuMC4xIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA"
- "xrNHoY5+"
- "JCgnyvEdG2dvvOaZ3sg6uhuF5Ssb5snyo9ixrxO5\nZkDGWwUqFO9PiYuO5ovNeq9LZtPG6s"
- "K8zsCS062ChZX/7tZHndf4MKCUDzv/"
- "LPHe\nnROoPi9n2FAiOPctY5hpgpIJDPI5Ofx0el2KPeFGeUO/"
- "W3yqnfol1ZqzZ2h3uErR\noHkgT2Ja4K+5gnPkr/"
- "RluJIu3AmWYw4eKi8i3+"
- "PoThGmCFvoGfcWvRoctgnOHYHE\n4bDRirXL9nGkZ5FMzOVDeoIAEAShOqJwL08VcY+Pg/"
- "qFQjzRrTmiKgm6QsHNnm0q\nzg70XaD88VJimiGYZOuJHNZpX8o0W+1Ls/"
- "NbawIDAQABo1MwUTAdBgNVHQ4EFgQU\nkW3hgFWYMpVUkq9AlzGlI3awTGEwHwYDVR0jBBgw"
- "FoAUkW3hgFWYMpVUkq9AlzGl\nI3awTGEwDwYDVR0TAQH/BAUwAwEB/"
- "zANBgkqhkiG9w0BAQsFAAOCAQEAZeMkILiG\neEcELWb8cktP3LzvS47O8hys9+"
- "6TFmftuO7kjDBd9YH2v8iQ7qCcUvMJ7bqL5RP1\nQssKfNOHZtw/"
- "MMcKE6E3nl4yQSKc8ymivvYSVu5SYtQCedcgfRLb5zvVxXw8JmCp\nGNS3/"
- "OlIYZAamh76GxkKSaV3tv0XZB6n3rUVQZShncFbMpyJRW0XWxReGWrhXv4s\nNxMeC1r07EE"
- "WIDecv8KKf1F8uT4UF48HnC0VBpXiOyDGvn35NiKp+"
- "Q5k7QV6jdCS\ngPRcnZhs6jiU0jnV8C9A1A+"
- "3pXSSPrAed7tvECOgHCfS10CLsLWsLuSjc93BE5Vt\nav7kmxSwrdvQ2A==\n-----END "
- "CERTIFICATE-----\n";
- std::string kIncorrectCertificate =
- "-----BEGIN "
- "CERTIFICATE-----\nMIIC/"
- "jCCAeagAwIBAgIJAIZjLucUID1mMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV\nBAMMCTEyNy4"
- "wLjAuMTAeFw0xOTA1MDYxNDA1MzdaFw0yOjA1MDZxNDA1MzdaMBQx\nEjAQBgNVBAMMCTEyN"
- "y4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBALfE5Qhc2mHTIux30l7"
- "eHFjFLdzYeXE8vcaXKodalCG8EkRxojDOfUv+y2DV\nJzHAMiGxMFAEcSz71k+"
- "jFZwhNG8PLY0b36ChnUsrGkOSJWq3OKUFrg8KxO9At9dL\nJsa+"
- "R0N0D1bMoPYdpCi3m0b0q2ITHe56qKuTLTrIPia+"
- "qXGEVD7EoEhU9tnwlcwE\npsUURMXCn2+FhHyqN9wjFkldmu4k8U3OJOK4385L+"
- "4RJoIV8dsYawAMAf+"
- "WuxyWq\niPQTPxr8q33ZZm6z0XrgsgxHYCCsryx8L9Ub9Zwu0mie7eL63rYdr86gULvnF1bY"
- "\ncOunKFc71rBYFalbD6YYsre733kCAwEAAaNTMFEwHQYDVR0OBBYEFKW9ByUNG84Z\nYiSc"
- "hUrB7KV9FinZMB8GA1UdIwQYMBaAFKW9ByUNG84ZYiSchUrB7KV9FinZMA8G\nA1UdEwEB/"
- "wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYROS1EL2qnrwmAsR6c\nqo8yrk8qzLKt4os"
- "41nv7QMUQFIO+QLPE8SbH4fK1YOMMUJ4ppARQBDaIIR3UEhp1\nZHT/"
- "wGjK9qxcuQ1EXLyHOY0rxS5q57dYGxOyQo4v6IoLVMZ1ij+RJGPYI/"
- "2fDXs0\nbDldeJyC1voHmG6lqTN5nLG7Y3j9j6rtSqJyRz5muaecQNiFPQOM2OTp0rC4VeAF"
- "\ndejmTmLhUFVuHMzLF+"
- "bpzsN76GnnQquJy2jexzFoWgbEfFVLKuyhTHQAalRb4ccq\nXCIx1hecNDYRY3Sc2Gzv5qxk"
- "kWF8zqltT/0d5tx0JwN3k5nP4SlaEldFvD6BELxy\nVkU=\n-----END "
- "CERTIFICATE-----\n";
-};
+ result_error = websocket_connection_->Disconnect();
-TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort),
- .certificate = "no cert",
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> ws_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = ws_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = ws_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- ws_session->Stop();
+ ASSERT_EQ(TransportAdapter::Error::BAD_STATE, result_error);
}
-TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
- kQuery + kFragment,
- .certificate = "no cert",
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSServer(kPath);
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> ws_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = ws_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = ws_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- ws_session->Stop();
-}
+TEST_F(WebsocketNotSecureSessionConnectionTest, SUCCESS_SendData) {
+ auto message = CreateDefaultRawMessage();
-TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
- kQuery + kFragment,
- .certificate = "no cert",
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> ws_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = ws_connection->Start();
- EXPECT_EQ(TransportAdapter::FAIL, ret_code);
-
- // Stop client
- ret_code = ws_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- ws_session->Stop();
-}
+ auto error = websocket_connection_->SendData(message);
-TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
- .certificate = kCACertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
+ ASSERT_EQ(TransportAdapter::Error::OK, error);
}
-TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + kPath,
- .certificate = kCACertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer((kPath + kQuery + kFragment));
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
-}
+TEST_F(WebsocketNotSecureSessionConnectionTest, UNSUCCESS_SendData_BAD_STATE) {
+ websocket_connection_->Run();
+ auto message = CreateDefaultRawMessage();
+
+ auto disconnect_error = websocket_connection_->Disconnect();
+
+ auto send_data_error = websocket_connection_->SendData(message);
-#ifdef ENABLE_SECURITY
-TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
- .certificate = kCACertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer(kPath);
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::FAIL, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
+ ASSERT_EQ(TransportAdapter::Error::OK, disconnect_error);
+ ASSERT_EQ(TransportAdapter::Error::BAD_STATE, send_data_error);
}
-TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
- .certificate = kIncorrectCertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::FAIL, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
+TEST_F(WebsocketNotSecureSessionConnectionTest, DataReceive_SUCCESS) {
+ auto message = CreateDefaultRawMessage();
+
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DataReceiveDone(kDeviceUid_, kAppHandle, _))
+ .Times(1);
+
+ websocket_connection_->DataReceive(message);
}
-#endif // ENABLE_SECURITY
+
} // namespace transport_manager_test
} // namespace components
} // namespace test
diff --git a/src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc b/src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc
new file mode 100644
index 0000000000..88525ad29d
--- /dev/null
+++ b/src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc
@@ -0,0 +1,193 @@
+/*
+ * \file websocket_listener.h
+ * \brief WebSocketListener class header file.
+ *
+ * Copyright (c) 2020
+ * 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 "transport_manager/websocket_server/websocket_sample_client.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+template <>
+WSSampleClient<websocket::stream<ssl::stream<tcp::socket> > >::WSSampleClient(
+ const std::string& host,
+ const std::string& port,
+ const SecurityParams& params)
+ : resolver_(ioc_)
+ , ctx_(ssl::context::sslv23_client)
+ , ws_(nullptr)
+ , io_pool_(1)
+ , host_(host)
+ , port_(port)
+ , handshake_successful_(false) {
+ ctx_.set_verify_mode(ssl::context::verify_peer);
+ ctx_.load_verify_file(params.ca_cert_);
+ ctx_.use_certificate_chain_file(params.client_cert_);
+ ctx_.use_private_key_file(params.client_key_, boost::asio::ssl::context::pem);
+ ws_.reset(new WSS(ioc_, ctx_));
+}
+
+template <>
+WSSampleClient<WS>::WSSampleClient(const std::string& host,
+ const std::string& port)
+ : resolver_(ioc_)
+ , ctx_(ssl::context::sslv23_client)
+ , ws_(new WS(ioc_))
+ , host_(host)
+ , port_(port) {}
+
+template <typename Stream>
+bool WSSampleClient<Stream>::Run() {
+ boost::system::error_code ec;
+ ctx_.set_verify_mode(ssl::verify_none);
+
+ auto results = resolver_.resolve(host_, port_, ec);
+ if (ec) {
+ std::cout << "ErrorMessage: " + ec.message() << std::endl;
+ return false;
+ }
+
+ if (!Connect(results)) {
+ return false;
+ }
+
+ if (!Handshake(host_, "/")) {
+ return false;
+ }
+
+ ws_->async_read(buffer_,
+ std::bind(&WSSampleClient::OnRead,
+ this->shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2));
+ boost::asio::post(io_pool_, [&]() { ioc_.run(); });
+ return true;
+}
+
+template <typename Stream>
+void WSSampleClient<Stream>::OnRead(beast::error_code ec,
+ std::size_t bytes_transferred) {
+ boost::ignore_unused(bytes_transferred);
+}
+
+template <>
+bool WSSampleClient<WS>::Connect(tcp::resolver::results_type& results) {
+ boost::system::error_code ec;
+ boost::asio::connect(ws_->next_layer(), results.begin(), results.end(), ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+ return true;
+}
+
+template <>
+bool WSSampleClient<WSS>::Connect(tcp::resolver::results_type& results) {
+ boost::system::error_code ec;
+ boost::asio::connect(ws_->lowest_layer(), results.begin(), results.end(), ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+ return true;
+}
+
+template <>
+bool WSSampleClient<WS>::Handshake(const std::string& host,
+ const std::string& target) {
+ boost::system::error_code ec;
+ ws_->handshake(host, target, ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+ return true;
+}
+
+template <>
+void WSSampleClient<WS>::Stop() {
+ ioc_.stop();
+ ws_->lowest_layer().close();
+
+ io_pool_.stop();
+ io_pool_.join();
+}
+
+template <>
+bool WSSampleClient<WSS>::Handshake(const std::string& host,
+ const std::string& target) {
+ boost::system::error_code ec;
+
+ ws_->next_layer().handshake(ssl::stream_base::client, ec);
+ if (ec) {
+ std::cout << "ErrorMessage: " + ec.message() << std::endl;
+ return false;
+ }
+
+ ws_->handshake(host, target, ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+
+ handshake_successful_ = true;
+ return true;
+}
+
+template <>
+void WSSampleClient<WSS>::Stop() {
+ ioc_.stop();
+ ws_->next_layer().next_layer().shutdown(
+ boost::asio::ip::tcp::socket::shutdown_both);
+ ws_->lowest_layer().close();
+
+ io_pool_.stop();
+ io_pool_.join();
+}
+
+template <>
+void WSSampleClient<WSS>::OnHandshakeTimeout() {
+ if (!handshake_successful_) {
+ Stop();
+ }
+}
+
+template <>
+bool WSSampleClient<WSS>::IsHandshakeSuccessful() const {
+ return handshake_successful_;
+}
+
+template class WSSampleClient<WS>;
+template class WSSampleClient<WSS>;
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/test/websocket_server_listener_test.cc b/src/components/transport_manager/test/websocket_server_listener_test.cc
new file mode 100644
index 0000000000..7991c6f1cb
--- /dev/null
+++ b/src/components/transport_manager/test/websocket_server_listener_test.cc
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2020, 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "transport_manager/mock_transport_manager_settings.h"
+#include "transport_manager/transport_adapter/mock_transport_adapter_controller.h"
+#include "transport_manager/websocket_server/websocket_device.h"
+#include "transport_manager/websocket_server/websocket_listener.h"
+#include "utils/timer.h"
+#include "utils/timer_task_impl.h"
+
+#include <thread>
+#include "transport_manager/websocket_server/websocket_sample_client.h"
+
+namespace test {
+namespace components {
+namespace transport_manager_test {
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::ReturnArg;
+using ::testing::ReturnPointee;
+using ::testing::ReturnRef;
+using namespace ::transport_manager;
+using namespace ::transport_manager::transport_adapter;
+
+namespace {
+const std::string kDefaultAddress = "127.0.0.1";
+const std::string kDefaultCertPath = "";
+const std::string kDefaultKeyPath = "";
+const std::string kDefaultCACertPath = "";
+const uint32_t kDefaultPort = 2021;
+const std::string kDefaultPortStr = "2021";
+const uint32_t kWrongPort = 1000;
+const std::string kCACertPath = "./test_certs/ca-cert.pem";
+const std::string kClientCertPath = "./test_certs/client-cert.pem";
+const std::string kClientKeyPath = "./test_certs/client-key.pem";
+const std::string kServerCert = "./test_certs/server-cert.pem";
+const std::string kServerKey = "./test_certs/server-key.pem";
+const std::string kCACert = "./test_certs/ca-cert.pem";
+const std::string kDefaultDeviceName = "Web Engine";
+const int kNumThreads = 2;
+} // namespace
+
+class WebSocketListenerTest : public ::testing::Test {
+ protected:
+ MockTransportAdapterController mock_ta_controller_;
+ MockTransportManagerSettings mock_tm_settings_;
+
+ public:
+ WebSocketListenerTest() {}
+ ~WebSocketListenerTest() {}
+
+ void SetUp() OVERRIDE {
+ ON_CALL(mock_tm_settings_, websocket_server_address())
+ .WillByDefault(ReturnRef(kDefaultAddress));
+ ON_CALL(mock_tm_settings_, websocket_server_port())
+ .WillByDefault(Return(kDefaultPort));
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kServerCert));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kServerKey));
+ ON_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(kCACert));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(true));
+ }
+
+ std::shared_ptr<WebSocketDevice> CreateDevice(const bool secure_connection) {
+ return std::make_shared<WebSocketDevice>(kDefaultDeviceName,
+ kDefaultDeviceName);
+ }
+};
+
+TEST_F(WebSocketListenerTest, StartListening_ClientConnect_SUCCESS) {
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCertPath));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ ON_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCACertPath));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(false));
+
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(false)));
+
+ ws_listener->StartListening();
+ EXPECT_TRUE(ws_client->Run());
+ ws_client->Stop();
+}
+
+TEST_F(WebSocketListenerTest, StartListening_ClientConnectSecure_SUCCESS) {
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const SecurityParams params{kCACertPath, kClientCertPath, kClientKeyPath};
+ const auto wss_client = std::make_shared<WSSampleClient<WSS> >(
+ kDefaultAddress, kDefaultPortStr, params);
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(true)));
+
+ ws_listener->StartListening();
+ EXPECT_TRUE(wss_client->Run());
+ wss_client->Stop();
+}
+
+TEST_F(WebSocketListenerTest,
+ StartListening_ClientConnectSecureInvalidCert_FAIL) {
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const SecurityParams params{kCACertPath,
+ "./test_certs/invalid_cert.pem",
+ "./test_certs/invalid_key.pem"};
+ const auto wss_client = std::make_shared<WSSampleClient<WSS> >(
+ kDefaultAddress, kDefaultPortStr, params);
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(true)));
+ EXPECT_CALL(mock_ta_controller_, ConnectionAborted(_, _, _));
+
+ ws_listener->StartListening();
+ timer::Timer handshake_timer(
+ "HandshakeTimer",
+ new ::timer::TimerTaskImpl<WSSampleClient<WSS> >(
+ wss_client.get(), &WSSampleClient<WSS>::OnHandshakeTimeout));
+ handshake_timer.Start(3000, timer::kSingleShot);
+ wss_client->Run();
+ EXPECT_EQ(wss_client->IsHandshakeSuccessful(), false);
+}
+
+TEST_F(WebSocketListenerTest, StartListening_CertificateNotFound_Fail) {
+ const std::string server_cert = "./test_certs/server-cert.pem";
+ const std::string server_key = "./test_certs/server-key.pem";
+ const std::string ca_cert = "./not_valid_path/ca-cert.pem";
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(server_cert));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(server_key));
+ ON_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(ca_cert));
+
+ const auto ws_listener_ = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client_ =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_EQ(TransportAdapter::Error::FAIL, ws_listener_->StartListening());
+}
+
+TEST_F(WebSocketListenerTest, StartListening_WrongConfig_FAIL) {
+ const std::string server_cert = "./test_certs/server-cert.pem";
+
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(server_cert));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ EXPECT_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillOnce(ReturnRef(kDefaultCACertPath));
+
+ const auto ws_listener_ = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client_ =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_EQ(TransportAdapter::Error::FAIL, ws_listener_->StartListening());
+}
+
+TEST_F(WebSocketListenerTest, StartListening_BindToTheServerAddress_FAIL) {
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCertPath));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(false));
+ EXPECT_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillOnce(ReturnRef(kDefaultCACertPath));
+ EXPECT_CALL(mock_tm_settings_, websocket_server_port())
+ .WillOnce(Return(kWrongPort));
+
+ const auto ws_listener_ = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client_ =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_EQ(TransportAdapter::Error::FAIL, ws_listener_->StartListening());
+}
+
+TEST_F(WebSocketListenerTest, StartListening_AcceptorIsOpen_SUCCESS) {
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCertPath));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(false));
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(false)));
+
+ EXPECT_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillOnce(ReturnRef(kDefaultCACertPath));
+
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ ws_listener->StartListening();
+ ws_client->Run();
+ EXPECT_EQ(TransportAdapter::Error::OK, ws_listener->StartListening());
+ ws_client->Stop();
+}
+
+} // namespace transport_manager_test
+} // namespace components
+} // namespace test