diff options
Diffstat (limited to 'src/components/transport_manager/test')
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 |