diff options
author | Serhii Niukalov (GitHub) <36993782+SNiukalov@users.noreply.github.com> | 2020-01-24 23:21:12 +0200 |
---|---|---|
committer | Jacob Keeler <jacob.keeler@livioradio.com> | 2020-01-24 16:21:12 -0500 |
commit | b901c9d720384534ab8d47735030164bd4b07d4e (patch) | |
tree | e312127ed957ac0eaee06cc9d0d8d28635e0087e | |
parent | cf49a3ba79eea3307c3b10511eeb9c1e487a3402 (diff) | |
download | sdl_core-b901c9d720384534ab8d47735030164bd4b07d4e.tar.gz |
Rework Uts and add synchronization to avoid race condition in transport adapter (#3134)
* Allow code compatibility with flag TELEMETRY_MONITOR On/Off
Added missed virtual keyword for SetTelemetryMonitor method.
Updated related interface and dependent mock classes
* Add missed mock classes and update existing ones
* Update TCP transport Adapter unit test logic
Replaced mock object with real TCP transport adapter
to be used with mock object to allow unit testing.
* Rework TransportManagerDefault class to allow its unit testing
1) Replaced local variables(raw pointers) by class members
2) Reworked Transport Manager unit tests
* Add missed logic when Connection failed to ThreadedSocketConnection::threadMain()
Added missed "else" case to ThreadedSocketConnection::threadMain()
when connection establishing is failed
* Add the Terminate method to the connection interface.
To avoid race condition and deadlock during destroying object of TcpServerOriginatedSocketConnection the Terminate method was added to the ThreadedSocketConnection.
Race condition can happen between the call FindEstablishedConnection from TcpTransportAdapter::Store and Terminate from TransportAdapterImpl.
In case when TcpServerOriginatedSocketConnection destroyed after FindEstablishedConnection called we will get deadlock , because in destructor of TcpServerOriginatedSocketConnection we call StopAndJoinThread(), but now we are in the same thread.
Co-authored-by: Andriy Byzhynar (GitHub) <AByzhynar@luxoft.com>
23 files changed, 566 insertions, 183 deletions
diff --git a/src/appMain/life_cycle_impl.cc b/src/appMain/life_cycle_impl.cc index 146380f953..a7786e302b 100644 --- a/src/appMain/life_cycle_impl.cc +++ b/src/appMain/life_cycle_impl.cc @@ -85,7 +85,8 @@ bool LifeCycleImpl::StartComponents() { profile_.app_info_storage()); DCHECK(!transport_manager_); - transport_manager_ = new transport_manager::TransportManagerDefault(profile_); + transport_manager_ = new transport_manager::TransportManagerDefault( + profile_, transport_manager::TransportAdapterFactory()); DCHECK(!connection_handler_); connection_handler_ = new connection_handler::ConnectionHandlerImpl( diff --git a/src/components/include/test/application_manager/mock_rpc_handler.h b/src/components/include/test/application_manager/mock_rpc_handler.h index fb577622ce..cc7fe988a0 100644 --- a/src/components/include/test/application_manager/mock_rpc_handler.h +++ b/src/components/include/test/application_manager/mock_rpc_handler.h @@ -30,8 +30,10 @@ class MockRPCHandler : public application_manager::rpc_handler::RPCHandler { MOCK_METHOD1(OnErrorSending, void(std::shared_ptr<application_manager::Message> message)); +#ifdef TELEMETRY_MONITOR MOCK_METHOD1(SetTelemetryObserver, void(application_manager::AMTelemetryObserver* observer)); +#endif // TELEMETRY_MONITOR }; } // namespace application_manager_test diff --git a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h index 0c0e2dd5ec..a07365f8c0 100644 --- a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h +++ b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h @@ -111,6 +111,9 @@ class MockTransportAdapter #ifdef TELEMETRY_MONITOR MOCK_METHOD0(GetTelemetryObserver, ::transport_manager::TMTelemetryObserver*()); + MOCK_METHOD1(SetTelemetryObserver, + void(::transport_manager::TMTelemetryObserver* observer)); + #endif // TELEMETRY_MONITOR }; diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter.h b/src/components/include/transport_manager/transport_adapter/transport_adapter.h index b92e010ece..8b46be253b 100644 --- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h +++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h @@ -357,6 +357,14 @@ class TransportAdapter { * @param return pointer to Time metric observer */ virtual TMTelemetryObserver* GetTelemetryObserver() = 0; + + /** + * @brief Setup observer for time metric. + * + * @param observer - pointer to observer + */ + virtual void SetTelemetryObserver(TMTelemetryObserver* observer) = 0; + #endif // TELEMETRY_MONITOR }; } // namespace transport_adapter diff --git a/src/components/telemetry_monitor/CMakeLists.txt b/src/components/telemetry_monitor/CMakeLists.txt index a9c0e14224..3e8b2a9741 100644 --- a/src/components/telemetry_monitor/CMakeLists.txt +++ b/src/components/telemetry_monitor/CMakeLists.txt @@ -47,6 +47,7 @@ include_directories ( ${COMPONENTS_DIR}/media_manager/include/ ${COMPONENTS_DIR}/smart_objects/include/ ${COMPONENTS_DIR}/config_profile/include/ + ${COMPONENTS_DIR}/resumption/include ${JSONCPP_INCLUDE_DIRECTORY} ${CMAKE_BINARY_DIR}/src/components/ ${LOG4CXX_INCLUDE_DIRECTORY} diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/connection.h b/src/components/transport_manager/include/transport_manager/transport_adapter/connection.h index 2374d8a126..4d9910b9f3 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/connection.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/connection.h @@ -64,6 +64,13 @@ class Connection { * @brief Disconnect the current connection. */ virtual TransportAdapter::Error Disconnect() = 0; + + /** + * @brief Terminate method may implement the logic of correct thread + * termination, if necessary for specific connection. Unlike the disconnect + * method, which manipulates physical descriptors + */ + virtual void Terminate() {} }; typedef std::shared_ptr<Connection> ConnectionSPtr; diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/threaded_socket_connection.h b/src/components/transport_manager/include/transport_manager/transport_adapter/threaded_socket_connection.h index 11123ceb1c..7c4e07fa59 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/threaded_socket_connection.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/threaded_socket_connection.h @@ -74,6 +74,8 @@ class ThreadedSocketConnection : public Connection { */ TransportAdapter::Error Disconnect(); + void Terminate() OVERRIDE; + /** * @brief Start thread creation. * diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h index 0750b58aae..5f54cf8376 100644 --- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h +++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h @@ -500,7 +500,7 @@ class TransportAdapterImpl : public TransportAdapter, * * @param observer - pointer to observer */ - void SetTelemetryObserver(TMTelemetryObserver* observer); + void SetTelemetryObserver(TMTelemetryObserver* observer) OVERRIDE; /** * @brief Return Time metric observer diff --git a/src/components/transport_manager/include/transport_manager/transport_manager_default.h b/src/components/transport_manager/include/transport_manager/transport_manager_default.h index 7fb0904fdf..63061b14b7 100644 --- a/src/components/transport_manager/include/transport_manager/transport_manager_default.h +++ b/src/components/transport_manager/include/transport_manager/transport_manager_default.h @@ -44,12 +44,36 @@ class LastState; namespace transport_manager { +struct TransportAdapterFactory { + TransportAdapterFactory(); + template <typename... Args> + using CreatorTA = + std::function<transport_adapter::TransportAdapter*(Args&&... args)>; +#ifdef BLUETOOTH_SUPPORT + CreatorTA<resumption::LastState&, const TransportManagerSettings&> + ta_bluetooth_creator_; +#endif + CreatorTA<const uint16_t, + resumption::LastState&, + const TransportManagerSettings&> + ta_tcp_creator_; +#if defined(USB_SUPPORT) + CreatorTA<resumption::LastState&, const TransportManagerSettings&> + ta_usb_creator_; +#endif +#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) + CreatorTA<resumption::LastState&, const TransportManagerSettings&> + ta_cloud_creator_; +#endif +}; + /** * @brief Default realization of transport_manager_impl class. */ class TransportManagerDefault : public TransportManagerImpl { public: - explicit TransportManagerDefault(const TransportManagerSettings& settings); + explicit TransportManagerDefault(const TransportManagerSettings& settings, + const TransportAdapterFactory& ta_factory_); /** * @brief Initialize transport manager. @@ -63,6 +87,8 @@ class TransportManagerDefault : public TransportManagerImpl { */ virtual ~TransportManagerDefault(); + private: + TransportAdapterFactory ta_factory_; DISALLOW_COPY_AND_ASSIGN(TransportManagerDefault); }; } // namespace transport_manager diff --git a/src/components/transport_manager/src/transport_adapter/threaded_socket_connection.cc b/src/components/transport_manager/src/transport_adapter/threaded_socket_connection.cc index 96c4c2c370..7d96c685f1 100644 --- a/src/components/transport_manager/src/transport_adapter/threaded_socket_connection.cc +++ b/src/components/transport_manager/src/transport_adapter/threaded_socket_connection.cc @@ -62,7 +62,7 @@ ThreadedSocketConnection::ThreadedSocketConnection( , unexpected_disconnect_(false) , device_uid_(device_id) , app_handle_(app_handle) - , thread_(NULL) { + , thread_(nullptr) { const std::string thread_name = std::string("Socket ") + device_handle(); thread_ = threads::CreateThread(thread_name.c_str(), new SocketConnectionDelegate(this)); @@ -70,7 +70,7 @@ ThreadedSocketConnection::ThreadedSocketConnection( ThreadedSocketConnection::~ThreadedSocketConnection() { LOG4CXX_AUTO_TRACE(logger_); - DCHECK(NULL == thread_); + DCHECK(nullptr == thread_); if (-1 != read_fd_) { close(read_fd_); @@ -82,10 +82,12 @@ ThreadedSocketConnection::~ThreadedSocketConnection() { void ThreadedSocketConnection::StopAndJoinThread() { Disconnect(); - thread_->join(); - delete thread_->delegate(); - threads::DeleteThread(thread_); - thread_ = NULL; + if (thread_) { + thread_->join(); + delete thread_->delegate(); + threads::DeleteThread(thread_); + thread_ = nullptr; + } } void ThreadedSocketConnection::Abort() { @@ -167,16 +169,23 @@ TransportAdapter::Error ThreadedSocketConnection::Disconnect() { return Notify(); } +void ThreadedSocketConnection::Terminate() { + LOG4CXX_AUTO_TRACE(logger_); + StopAndJoinThread(); +} + void ThreadedSocketConnection::threadMain() { LOG4CXX_AUTO_TRACE(logger_); - ConnectError* connect_error = NULL; + ConnectError* connect_error = nullptr; if (!Establish(&connect_error)) { LOG4CXX_ERROR(logger_, "Connection Establish failed"); delete connect_error; Abort(); + } else { + LOG4CXX_DEBUG(logger_, "Connection established"); + controller_->ConnectDone(device_handle(), application_handle()); } - LOG4CXX_DEBUG(logger_, "Connection established"); - controller_->ConnectDone(device_handle(), application_handle()); + while (!terminate_flag_) { Transmit(); } diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc index c35520ff7b..78a9840401 100644 --- a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc +++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc @@ -138,6 +138,12 @@ void TransportAdapterImpl::Terminate() { connections_lock_.AcquireForWriting(); std::swap(connections, connections_); connections_lock_.Release(); + for (const auto& connection : connections) { + auto& info = connection.second; + if (info.connection) { + info.connection->Terminate(); + } + } connections.clear(); LOG4CXX_DEBUG(logger_, "Connections deleted"); diff --git a/src/components/transport_manager/src/transport_manager_default.cc b/src/components/transport_manager/src/transport_manager_default.cc index 71fc41ada9..0d58e24b5c 100644 --- a/src/components/transport_manager/src/transport_manager_default.cc +++ b/src/components/transport_manager/src/transport_manager_default.cc @@ -55,9 +55,39 @@ namespace transport_manager { CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager") +TransportAdapterFactory::TransportAdapterFactory() { +#ifdef BLUETOOTH_SUPPORT + ta_bluetooth_creator_ = [](resumption::LastState& last_state, + const TransportManagerSettings& settings) { + return new transport_adapter::BluetoothTransportAdapter(last_state, + settings); + }; +#endif + ta_tcp_creator_ = [](const uint16_t port, + resumption::LastState& last_state, + const TransportManagerSettings& settings) { + return new transport_adapter::TcpTransportAdapter( + port, last_state, settings); + }; +#if defined(USB_SUPPORT) + ta_usb_creator_ = [](resumption::LastState& last_state, + const TransportManagerSettings& settings) { + return new transport_adapter::UsbAoaAdapter(last_state, settings); + }; +#endif +#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) + ta_cloud_creator_ = [](resumption::LastState& last_state, + const TransportManagerSettings& settings) { + return new transport_adapter::CloudWebsocketTransportAdapter(last_state, + settings); + }; +#endif +} + TransportManagerDefault::TransportManagerDefault( - const TransportManagerSettings& settings) - : TransportManagerImpl(settings) {} + const TransportManagerSettings& settings, + const TransportAdapterFactory& ta_factory) + : TransportManagerImpl(settings), ta_factory_(ta_factory) {} int TransportManagerDefault::Init(resumption::LastState& last_state) { LOG4CXX_TRACE(logger_, "enter"); @@ -68,54 +98,45 @@ int TransportManagerDefault::Init(resumption::LastState& last_state) { return E_TM_IS_NOT_INITIALIZED; } -#ifdef BLUETOOTH_SUPPORT - transport_adapter::TransportAdapterImpl* ta_bluetooth = - new transport_adapter::BluetoothTransportAdapter(last_state, - get_settings()); + const auto& settings = get_settings(); + +#if defined(BLUETOOTH_SUPPORT) + auto ta_bluetooth = ta_factory_.ta_bluetooth_creator_(last_state, settings); #ifdef TELEMETRY_MONITOR if (metric_observer_) { ta_bluetooth->SetTelemetryObserver(metric_observer_); } #endif // TELEMETRY_MONITOR AddTransportAdapter(ta_bluetooth); - ta_bluetooth = NULL; -#endif +#endif // BLUETOOTH_SUPPORT - const uint16_t port = get_settings().transport_manager_tcp_adapter_port(); - transport_adapter::TransportAdapterImpl* ta_tcp = - new transport_adapter::TcpTransportAdapter( - port, last_state, get_settings()); + auto ta_tcp = ta_factory_.ta_tcp_creator_( + settings.transport_manager_tcp_adapter_port(), last_state, settings); #ifdef TELEMETRY_MONITOR if (metric_observer_) { ta_tcp->SetTelemetryObserver(metric_observer_); } #endif // TELEMETRY_MONITOR AddTransportAdapter(ta_tcp); - ta_tcp = NULL; #if defined(USB_SUPPORT) - transport_adapter::TransportAdapterImpl* ta_usb = - new transport_adapter::UsbAoaAdapter(last_state, get_settings()); + auto ta_usb = ta_factory_.ta_usb_creator_(last_state, settings); #ifdef TELEMETRY_MONITOR if (metric_observer_) { ta_usb->SetTelemetryObserver(metric_observer_); } #endif // TELEMETRY_MONITOR AddTransportAdapter(ta_usb); - ta_usb = NULL; #endif // USB_SUPPORT #if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) - transport_adapter::TransportAdapterImpl* ta_cloud = - new transport_adapter::CloudWebsocketTransportAdapter(last_state, - get_settings()); + auto ta_cloud = ta_factory_.ta_cloud_creator_(last_state, settings); #ifdef TELEMETRY_MONITOR if (metric_observer_) { ta_cloud->SetTelemetryObserver(metric_observer_); } #endif // TELEMETRY_MONITOR AddTransportAdapter(ta_cloud); - ta_cloud = NULL; #endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT #if defined BUILD_TESTS @@ -123,14 +144,14 @@ int TransportManagerDefault::Init(resumption::LastState& last_state) { transport_adapter::IAP2BluetoothEmulationTransportAdapter* iap2_bt_emu_adapter = new transport_adapter::IAP2BluetoothEmulationTransportAdapter( - iap2_bt_emu_port, last_state, get_settings()); + iap2_bt_emu_port, last_state, settings); AddTransportAdapter(iap2_bt_emu_adapter); const uint16_t iap2_usb_emu_port = 34567; transport_adapter::IAP2USBEmulationTransportAdapter* iap2_usb_emu_adapter = new transport_adapter::IAP2USBEmulationTransportAdapter( - iap2_usb_emu_port, last_state, get_settings()); + iap2_usb_emu_port, last_state, settings); AddTransportAdapter(iap2_usb_emu_adapter); #endif // BUILD_TEST diff --git a/src/components/transport_manager/test/include/transport_manager/bt/mock_bluetooth_transport_adapter.h b/src/components/transport_manager/test/include/transport_manager/bt/mock_bluetooth_transport_adapter.h new file mode 100644 index 0000000000..ffd8cd9647 --- /dev/null +++ b/src/components/transport_manager/test/include/transport_manager/bt/mock_bluetooth_transport_adapter.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, 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. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_BT_MOCK_BLUETOOTH_TRANSPORT_ADAPTER_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_BT_MOCK_BLUETOOTH_TRANSPORT_ADAPTER_H_ + +#include "transport_manager/transport_adapter/mock_transport_adapter.h" + +namespace test { +namespace components { +namespace transport_manager_test { + +using namespace ::transport_manager::transport_adapter; + +class MockBluetoothTransportAdapter : public MockTransportAdapter { + public: + MOCK_CONST_METHOD0(GetDeviceType, DeviceType()); + MOCK_CONST_METHOD0(Store, void()); + MOCK_METHOD0(Restore, bool()); +}; + +} // namespace transport_manager_test +} // namespace components +} // namespace test + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_BT_MOCK_BLUETOOTH_TRANSPORT_ADAPTER_H_ diff --git a/src/components/transport_manager/test/include/transport_manager/cloud/mock_cloud_websocket_transport_adapter.h b/src/components/transport_manager/test/include/transport_manager/cloud/mock_cloud_websocket_transport_adapter.h new file mode 100644 index 0000000000..2d240ab3ff --- /dev/null +++ b/src/components/transport_manager/test/include/transport_manager/cloud/mock_cloud_websocket_transport_adapter.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019, 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. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_MOCK_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_MOCK_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ + +#include "transport_manager/cloud/cloud_websocket_transport_adapter.h" + +namespace test { +namespace components { +namespace transport_manager_test { + +using namespace ::transport_manager::transport_adapter; + +class MockCloudWebsocketTransportAdapter + : public CloudWebsocketTransportAdapter { + public: + MockCloudWebsocketTransportAdapter( + resumption::LastState& last_state, + const transport_manager::TransportManagerSettings& settings) + : CloudWebsocketTransportAdapter(last_state, settings) {} + MOCK_CONST_METHOD0(GetDeviceType, DeviceType()); + MOCK_CONST_METHOD0(Store, void()); + MOCK_METHOD0(Restore, bool()); + MOCK_CONST_METHOD0(IsInitialised, bool()); + MOCK_METHOD1(AddListener, void(TransportAdapterListener* listener)); + MOCK_METHOD0(Init, TransportAdapter::Error()); + MOCK_METHOD0(Terminate, void()); +}; + +} // namespace transport_manager_test +} // namespace components +} // namespace test + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_MOCK_CLOUD_WEBSOCKET_TRANSPORT_ADAPTER_H_ diff --git a/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h b/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h index a8b801c1fe..e29f182059 100644 --- a/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h +++ b/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h @@ -39,6 +39,7 @@ #include <boost/asio/placeholders.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> @@ -61,9 +62,9 @@ namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> // Accepts incoming connections and launches the WSServer -class WSSession { +class WSSession : public std::enable_shared_from_this<WSSession> { private: - class WSServer { + class WSServer : public std::enable_shared_from_this<WSServer> { public: explicit WSServer(tcp::socket&& socket); void AddURLRoute(const std::string& route); @@ -95,6 +96,7 @@ class WSSession { private: void on_accept(boost::system::error_code ec); boost::asio::io_context ioc_; + boost::asio::thread_pool io_pool_; const std::string& address_; uint16_t port_; tcp::acceptor acceptor_; @@ -106,9 +108,9 @@ class WSSession { }; // Accepts incoming connections and launches the sessions -class WSSSession { +class WSSSession : public std::enable_shared_from_this<WSSSession> { private: - class WSSServer { + class WSSServer : public std::enable_shared_from_this<WSSServer> { public: // Take ownership of the socket WSSServer(tcp::socket&& socket, ssl::context& ctx); @@ -148,6 +150,7 @@ class WSSSession { private: boost::asio::io_context ioc_; + boost::asio::thread_pool io_pool_; tcp::acceptor acceptor_; tcp::socket socket_; ssl::context ctx_; diff --git a/src/components/transport_manager/test/include/transport_manager/tcp/mock_tcp_transport_adapter.h b/src/components/transport_manager/test/include/transport_manager/tcp/mock_tcp_transport_adapter.h index daa9397b7d..fb84bce085 100644 --- a/src/components/transport_manager/test/include/transport_manager/tcp/mock_tcp_transport_adapter.h +++ b/src/components/transport_manager/test/include/transport_manager/tcp/mock_tcp_transport_adapter.h @@ -33,10 +33,7 @@ #ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_TCP_MOCK_TCP_TRANSPORT_ADAPTER_H_ #define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_TCP_MOCK_TCP_TRANSPORT_ADAPTER_H_ -#include "gmock/gmock.h" -#include "transport_manager/common.h" #include "transport_manager/tcp/tcp_transport_adapter.h" -#include "transport_manager/transport_manager_settings.h" namespace test { namespace components { @@ -63,6 +60,11 @@ class MockTCPTransportAdapter : public TcpTransportAdapter { TransportAdapter::Error( const transport_manager::DeviceUID& device_handle, const transport_manager::ApplicationHandle& app_handle)); + + MOCK_CONST_METHOD0(IsInitialised, bool()); + MOCK_METHOD1(AddListener, void(TransportAdapterListener* listener)); + MOCK_METHOD0(Init, TransportAdapter::Error()); + MOCK_METHOD0(Terminate, void()); void CallStore() { Store(); } diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_connection.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_connection.h index d1f48c1ed9..7bb272c82e 100644 --- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_connection.h +++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_connection.h @@ -48,6 +48,7 @@ class MockConnection : public Connection { SendData, TransportAdapter::Error(::protocol_handler::RawMessagePtr message)); MOCK_METHOD0(Disconnect, TransportAdapter::Error()); + MOCK_METHOD0(Terminate, void()); }; } // namespace transport_manager_test diff --git a/src/components/transport_manager/test/include/transport_manager/usb/mock_usb_aoa_adapter.h b/src/components/transport_manager/test/include/transport_manager/usb/mock_usb_aoa_adapter.h new file mode 100644 index 0000000000..230f5ed170 --- /dev/null +++ b/src/components/transport_manager/test/include/transport_manager/usb/mock_usb_aoa_adapter.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, 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. + */ + +#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_USB_MOCK_USB_AOA_ADAPTER_H_ +#define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_USB_MOCK_USB_AOA_ADAPTER_H_ + +#include "transport_manager/usb/usb_aoa_adapter.h" + +namespace test { +namespace components { +namespace transport_manager_test { + +using namespace ::transport_manager::transport_adapter; + +class MockUsbAoaAdapter : public UsbAoaAdapter { + public: + MockUsbAoaAdapter(resumption::LastState& last_state, + const transport_manager::TransportManagerSettings& settings) + : UsbAoaAdapter(last_state, settings) {} + MOCK_CONST_METHOD0(GetDeviceType, DeviceType()); + MOCK_CONST_METHOD0(IsInitialised, bool()); + MOCK_METHOD1(AddListener, void(TransportAdapterListener* listener)); + MOCK_METHOD0(Init, TransportAdapter::Error()); + MOCK_METHOD0(Terminate, void()); + + MOCK_CONST_METHOD1(ToBeAutoConnected, bool(DeviceSptr device)); +}; + +} // namespace transport_manager_test +} // namespace components +} // namespace test + +#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_USB_MOCK_USB_AOA_ADAPTER_H_ diff --git a/src/components/transport_manager/test/sample_websocket_server.cc b/src/components/transport_manager/test/sample_websocket_server.cc index 917184a361..9b0e5b59d5 100644 --- a/src/components/transport_manager/test/sample_websocket_server.cc +++ b/src/components/transport_manager/test/sample_websocket_server.cc @@ -51,11 +51,12 @@ void WSSession::WSServer::AddURLRoute(const std::string& target) { void WSSession::WSServer::Run() { req_ = {}; - http::async_read( - ws_.next_layer(), - buffer_, - req_, - std::bind(&WSServer::OnWebsocketHandshake, this, std::placeholders::_1)); + http::async_read(ws_.next_layer(), + buffer_, + req_, + std::bind(&WSServer::OnWebsocketHandshake, + shared_from_this(), + std::placeholders::_1)); } void WSSession::WSServer::OnWebsocketHandshake( @@ -75,9 +76,10 @@ void WSSession::WSServer::OnWebsocketHandshake( // Accept the websocket handshake ws_.async_accept( req_, - boost::asio::bind_executor( - strand_, - std::bind(&WSServer::OnAccept, this, std::placeholders::_1))); + boost::asio::bind_executor(strand_, + std::bind(&WSServer::OnAccept, + shared_from_this(), + std::placeholders::_1))); } } @@ -112,7 +114,8 @@ std::string WSSession::WSServer::ParseRouteFromTarget( } WSSession::WSSession(const std::string& address, uint16_t port) - : address_(address) + : io_pool_(1) + , address_(address) , port_(port) , acceptor_(ioc_) , socket_(ioc_) @@ -152,8 +155,10 @@ WSSession::WSSession(const std::string& address, uint16_t port) void WSSession::Run() { if (acceptor_.is_open()) { acceptor_.async_accept( - socket_, std::bind(&WSSession::on_accept, this, std::placeholders::_1)); - ioc_.run(); + socket_, + std::bind( + &WSSession::on_accept, shared_from_this(), std::placeholders::_1)); + boost::asio::post(io_pool_, [&]() { ioc_.run(); }); } } @@ -161,6 +166,7 @@ void WSSession::Stop() { try { ioc_.stop(); acceptor_.close(); + io_pool_.join(); } catch (...) { std::cerr << "Failed to close connection" << std::endl; } @@ -199,9 +205,10 @@ void WSSSession::WSSServer::AddURLRoute(const std::string& target) { } void WSSSession::WSSServer::Run() { // Perform the SSL handshake - wss_.next_layer().async_handshake( - ssl::stream_base::server, - std::bind(&WSSServer::OnSSLHandshake, this, std::placeholders::_1)); + wss_.next_layer().async_handshake(ssl::stream_base::server, + std::bind(&WSSServer::OnSSLHandshake, + shared_from_this(), + std::placeholders::_1)); } void WSSSession::WSSServer::OnSSLHandshake(beast::error_code ec) { @@ -210,11 +217,12 @@ void WSSSession::WSSServer::OnSSLHandshake(beast::error_code ec) { } req_ = {}; - http::async_read( - wss_.next_layer(), - buffer_, - req_, - std::bind(&WSSServer::OnWebsocketHandshake, this, std::placeholders::_1)); + http::async_read(wss_.next_layer(), + buffer_, + req_, + std::bind(&WSSServer::OnWebsocketHandshake, + shared_from_this(), + std::placeholders::_1)); } void WSSSession::WSSServer::OnWebsocketHandshake( @@ -233,7 +241,9 @@ void WSSSession::WSSServer::OnWebsocketHandshake( } // Accept the websocket handshake wss_.async_accept( - req_, std::bind(&WSSServer::OnAccept, this, std::placeholders::_1)); + req_, + std::bind( + &WSSServer::OnAccept, shared_from_this(), std::placeholders::_1)); } } @@ -271,7 +281,8 @@ WSSSession::WSSSession(const std::string& address, uint16_t port, const std::string& certificate, const std::string& private_key) - : acceptor_(ioc_) + : io_pool_(1) + , acceptor_(ioc_) , socket_(ioc_) , ctx_(ssl::context::sslv23_server) , wss_(nullptr) { @@ -336,6 +347,7 @@ void WSSSession::Stop() { try { ioc_.stop(); acceptor_.close(); + io_pool_.join(); } catch (...) { std::cerr << "Failed to close connection" << std::endl; } @@ -353,8 +365,9 @@ void WSSSession::do_accept() { if (acceptor_.is_open()) { acceptor_.async_accept( socket_, - std::bind(&WSSSession::on_accept, this, std::placeholders::_1)); - ioc_.run(); + std::bind( + &WSSSession::on_accept, shared_from_this(), std::placeholders::_1)); + boost::asio::post(io_pool_, [&]() { ioc_.run(); }); } } diff --git a/src/components/transport_manager/test/tcp_transport_adapter_test.cc b/src/components/transport_manager/test/tcp_transport_adapter_test.cc index f5f6cc38c8..0fbdc6d65f 100644 --- a/src/components/transport_manager/test/tcp_transport_adapter_test.cc +++ b/src/components/transport_manager/test/tcp_transport_adapter_test.cc @@ -350,7 +350,7 @@ TEST_F(TcpAdapterTest, StoreDataWithSeveralDevices_RestoreData) { TEST_F(TcpAdapterTest, NotifyTransportConfigUpdated) { MockTransportAdapterListener mock_adapter_listener; - MockTCPTransportAdapter transport_adapter( + TcpTransportAdapter transport_adapter( port, last_state_, transport_manager_settings); transport_adapter.AddListener(&mock_adapter_listener); @@ -359,13 +359,15 @@ TEST_F(TcpAdapterTest, NotifyTransportConfigUpdated) { config[tc_tcp_ip_address] = std::string("192.168.1.1"); config[tc_tcp_port] = std::string("12345"); - EXPECT_CALL(mock_adapter_listener, OnTransportConfigUpdated(_)).Times(1); + EXPECT_CALL(mock_adapter_listener, + OnTransportConfigUpdated(&transport_adapter)) + .Times(1); transport_adapter.TransportConfigUpdated(config); } TEST_F(TcpAdapterTest, GetTransportConfiguration) { - MockTCPTransportAdapter transport_adapter( + TcpTransportAdapter transport_adapter( port, last_state_, transport_manager_settings); TransportConfig config; diff --git a/src/components/transport_manager/test/transport_adapter_test.cc b/src/components/transport_manager/test/transport_adapter_test.cc index 712cc5f750..025c86f3ac 100644 --- a/src/components/transport_manager/test/transport_adapter_test.cc +++ b/src/components/transport_manager/test/transport_adapter_test.cc @@ -611,6 +611,7 @@ TEST_F(TransportAdapterTest, Disconnect_ConnectDoneSuccess) { EXPECT_EQ(TransportAdapter::OK, new_res); EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*mock_connection, Terminate()); } #if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) @@ -651,6 +652,9 @@ TEST_F(TransportAdapterTest, FindPending) { ConnectionSPtr mock_connection_fake = transport_adapter.FindPendingConnection(uniq_id, 1); ASSERT_TRUE(mock_connection_fake.use_count() == 0); + + EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*connection, Terminate()); } TEST_F(TransportAdapterTest, @@ -743,6 +747,8 @@ TEST_F(TransportAdapterTest, EXPECT_EQ(ConnectionStatus::PENDING, mockdev2->connection_status()); EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*mock_connection, Terminate()); + EXPECT_CALL(*connection2, Terminate()); } TEST_F(TransportAdapterTest, WebsocketEndpointParsing_SUCCESS) { @@ -864,6 +870,7 @@ TEST_F(TransportAdapterTest, DisconnectDevice_DeviceAddedConnectionCreated) { EXPECT_EQ(ConnectionStatus::CLOSING, mockdev->connection_status()); EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*mock_connection, Terminate()); } TEST_F(TransportAdapterTest, DeviceDisconnected) { @@ -978,6 +985,7 @@ TEST_F(TransportAdapterTest, SendData) { EXPECT_CALL(*dev_mock, Terminate()); EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*mock_connection, Terminate()); } TEST_F(TransportAdapterTest, SendData_ConnectionNotEstablished) { @@ -1018,6 +1026,7 @@ TEST_F(TransportAdapterTest, SendData_ConnectionNotEstablished) { EXPECT_CALL(*dev_mock, Terminate()); EXPECT_CALL(*clientMock, Terminate()); EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*mock_connection, Terminate()); } TEST_F(TransportAdapterTest, StartClientListening_ClientNotInitialized) { @@ -1171,7 +1180,7 @@ TEST_F(TransportAdapterTest, FindEstablishedConnection) { TransportAdapter::Error res = transport_adapter.Connect(dev_id, app_handle); EXPECT_EQ(TransportAdapter::OK, res); - ConnectionSPtr mock_connection = std::make_shared<MockConnection>(); + auto mock_connection = std::make_shared<MockConnection>(); transport_adapter.ConnectionCreated(mock_connection, dev_id, app_handle); EXPECT_CALL(transport_adapter, Store()); @@ -1182,6 +1191,7 @@ TEST_F(TransportAdapterTest, FindEstablishedConnection) { EXPECT_EQ(mock_connection, conn); EXPECT_CALL(*serverMock, Terminate()); + EXPECT_CALL(*mock_connection, Terminate()); } TEST_F(TransportAdapterTest, RunAppOnDevice_NoDeviseWithAskedId_UNSUCCESS) { 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 40938d0370..8a7f95c74b 100644 --- a/src/components/transport_manager/test/transport_manager_default_test.cc +++ b/src/components/transport_manager/test/transport_manager_default_test.cc @@ -33,14 +33,21 @@ #include "transport_manager/transport_manager_default.h" #include "gtest/gtest.h" #include "resumption/mock_last_state.h" +#include "transport_manager/bt/mock_bluetooth_transport_adapter.h" +#include "transport_manager/cloud/mock_cloud_websocket_transport_adapter.h" #include "transport_manager/mock_transport_manager_settings.h" +#include "transport_manager/tcp/mock_tcp_transport_adapter.h" +#include "transport_manager/transport_adapter/mock_device.h" +#include "transport_manager/transport_adapter/mock_transport_adapter_listener.h" #include "transport_manager/transport_manager.h" +#include "transport_manager/usb/mock_usb_aoa_adapter.h" namespace test { namespace components { namespace transport_manager_test { using resumption_test::MockLastState; +using ::testing::_; using ::testing::NiceMock; using ::testing::Return; using ::testing::ReturnRef; @@ -75,117 +82,211 @@ std::vector<uint8_t> kBTUUID = {0x93, 0xA8}; } // namespace -TEST(TestTransportManagerDefault, Init_LastStateNotUsed) { - MockTransportManagerSettings transport_manager_settings; - transport_manager::TransportManagerDefault transport_manager( - transport_manager_settings); - - NiceMock<MockLastState> mock_last_state; - Json::Value custom_dictionary = Json::Value(); - - ON_CALL(mock_last_state, get_dictionary()) - .WillByDefault(ReturnRef(custom_dictionary)); - - EXPECT_CALL(transport_manager_settings, use_last_state()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(transport_manager_settings, transport_manager_tcp_adapter_port()) - .WillRepeatedly(Return(12345u)); - std::string network_interface = ""; - EXPECT_CALL(transport_manager_settings, - transport_manager_tcp_adapter_network_interface()) - .WillRepeatedly(ReturnRef(network_interface)); - EXPECT_CALL(transport_manager_settings, bluetooth_uuid()) - .WillRepeatedly(Return(kBTUUID.data())); +class TestTransportManagerDefault : public ::testing::Test { + public: + TestTransportManagerDefault() + : transport_manager_settings_() + , unique_tcp_dev_name_("unique_tcp_device_name") + , dev_id_("device_id") + , tcp_adapter_port_(1u) + , network_interface_("test_iface") {} - std::string dummy_parameter; - EXPECT_CALL(transport_manager_settings, aoa_filter_manufacturer()) - .WillRepeatedly(ReturnRef(dummy_parameter)); - EXPECT_CALL(transport_manager_settings, aoa_filter_model_name()) - .WillRepeatedly(ReturnRef(dummy_parameter)); - EXPECT_CALL(transport_manager_settings, aoa_filter_description()) - .WillRepeatedly(ReturnRef(dummy_parameter)); - EXPECT_CALL(transport_manager_settings, aoa_filter_version()) - .WillRepeatedly(ReturnRef(dummy_parameter)); - EXPECT_CALL(transport_manager_settings, aoa_filter_uri()) - .WillRepeatedly(ReturnRef(dummy_parameter)); - EXPECT_CALL(transport_manager_settings, aoa_filter_serial_number()) - .WillRepeatedly(ReturnRef(dummy_parameter)); - transport_manager.Init(mock_last_state); - transport_manager.Stop(); -} + void SetUp() OVERRIDE { + EXPECT_CALL(transport_manager_settings_, + transport_manager_tcp_adapter_network_interface()) + .WillRepeatedly(ReturnRef(network_interface_)); + + // Replace creation of real transport adapters by mock objects + // to be able to check related function calls + mock_bt_ta_ = new MockBluetoothTransportAdapter(); + mock_tcp_ta_ = new MockTCPTransportAdapter( + tcp_adapter_port_, mock_last_state_, transport_manager_settings_); + mock_usb_aoa_ta_ = + new MockUsbAoaAdapter(mock_last_state_, transport_manager_settings_); + mock_cloud_websocket_ta_ = new MockCloudWebsocketTransportAdapter( + mock_last_state_, transport_manager_settings_); + + TransportAdapterFactory ta_factory; +#ifdef BLUETOOTH_SUPPORT + ta_factory.ta_bluetooth_creator_ = + [&](resumption::LastState& last_state, + const TransportManagerSettings& settings) { + UNUSED(last_state); + UNUSED(settings); + return mock_bt_ta_; + }; +#endif + ta_factory.ta_tcp_creator_ = [&](const uint16_t port, + resumption::LastState& last_state, + const TransportManagerSettings& settings) { + UNUSED(port); + UNUSED(last_state); + UNUSED(settings); + return mock_tcp_ta_; + }; +#if defined(USB_SUPPORT) + ta_factory.ta_usb_creator_ = [&](resumption::LastState& last_state, + const TransportManagerSettings& settings) { + UNUSED(last_state); + UNUSED(settings); + return mock_usb_aoa_ta_; + }; +#endif +#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) + ta_factory.ta_cloud_creator_ = + [&](resumption::LastState& last_state, + const TransportManagerSettings& settings) { + UNUSED(last_state); + UNUSED(settings); + return mock_cloud_websocket_ta_; + }; +#endif + transport_manager_ = std::unique_ptr<TransportManagerDefault>( + new TransportManagerDefault(transport_manager_settings_, ta_factory)); + } -TEST(TestTransportManagerDefault, Init_LastStateUsed) { - MockTransportManagerSettings transport_manager_settings; - transport_manager::TransportManagerDefault transport_manager( - transport_manager_settings); + void ExpectationsSettings_TM(const bool use_last_state); + void ExpectationsBluetooth_TA(); + void ExpectationsTCP_TA(); + void ExpectationsUSB_TA(); + void ExpectationsCloudWebsocket_TA(); - NiceMock<MockLastState> mock_last_state; - Json::Value custom_dictionary; + protected: + MockTransportManagerSettings transport_manager_settings_; + std::unique_ptr<TransportManagerDefault> transport_manager_; + NiceMock<MockLastState> mock_last_state_; + Json::Value custom_dictionary_; + const std::string unique_tcp_dev_name_; + const std::string dev_id_; + const uint16_t tcp_adapter_port_; + std::string network_interface_; + std::string dummy_parameter_; + // Arrange necessary transport adapters mock objects + MockBluetoothTransportAdapter* mock_bt_ta_; + MockTCPTransportAdapter* mock_tcp_ta_; + MockUsbAoaAdapter* mock_usb_aoa_ta_; + MockCloudWebsocketTransportAdapter* mock_cloud_websocket_ta_; +}; + +void TestTransportManagerDefault::ExpectationsSettings_TM( + const bool use_last_state) { + // Arrange TM Settings expectations Json::Value tcp_device; - tcp_device[kDeviceName] = "unique_tcp_device_name"; + tcp_device[kDeviceName] = unique_tcp_dev_name_; tcp_device[kDeviceAddress] = "127.0.0.1"; - tcp_device[kDeviceApplications][0][kApplicationPort] = kApplicationPortValue; + tcp_device[kDeviceApplications][0][kApplicationPort] = "1"; Json::Value bluetooth_device; - bluetooth_device[kDeviceName] = "unique_bluetooth_device_name"; + + std::string unique_bt_dev_name("unique_bluetooth_device_name"); + bluetooth_device[kDeviceName] = unique_bt_dev_name; bluetooth_device[kDeviceAddress] = "AB:CD:EF:GH:IJ:KL"; bluetooth_device[kDeviceApplications][0][kApplicationRfcomm] = kApplicationRfcommValue; - custom_dictionary[kTransportManager][kTcpAdapter][kDevices][0] = tcp_device; - custom_dictionary[kTransportManager][kBluetoothAdapter][kDevices][0] = + custom_dictionary_[kTransportManager][kTcpAdapter][kDevices][0] = tcp_device; + custom_dictionary_[kTransportManager][kBluetoothAdapter][kDevices][0] = bluetooth_device; + ON_CALL(mock_last_state_, get_dictionary()) + .WillByDefault(ReturnRef(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, use_last_state()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(transport_manager_settings, transport_manager_tcp_adapter_port()) - .WillRepeatedly(Return(12345u)); - std::string network_interface = ""; - EXPECT_CALL(transport_manager_settings, - transport_manager_tcp_adapter_network_interface()) - .WillRepeatedly(ReturnRef(network_interface)); - EXPECT_CALL(transport_manager_settings, bluetooth_uuid()) + EXPECT_CALL(transport_manager_settings_, bluetooth_uuid()) .WillRepeatedly(Return(kBTUUID.data())); - transport_manager.Init(mock_last_state); - transport_manager.Stop(); + + EXPECT_CALL(transport_manager_settings_, aoa_filter_manufacturer()) + .WillRepeatedly(ReturnRef(dummy_parameter_)); + EXPECT_CALL(transport_manager_settings_, aoa_filter_model_name()) + .WillRepeatedly(ReturnRef(dummy_parameter_)); + EXPECT_CALL(transport_manager_settings_, aoa_filter_description()) + .WillRepeatedly(ReturnRef(dummy_parameter_)); + EXPECT_CALL(transport_manager_settings_, aoa_filter_version()) + .WillRepeatedly(ReturnRef(dummy_parameter_)); + EXPECT_CALL(transport_manager_settings_, aoa_filter_uri()) + .WillRepeatedly(ReturnRef(dummy_parameter_)); + EXPECT_CALL(transport_manager_settings_, aoa_filter_serial_number()) + .WillRepeatedly(ReturnRef(dummy_parameter_)); } -TEST(TestTransportManagerDefault, Init_LastStateUsed_InvalidPort) { - MockTransportManagerSettings transport_manager_settings; - transport_manager::TransportManagerDefault transport_manager( - transport_manager_settings); +void TestTransportManagerDefault::ExpectationsBluetooth_TA() { + // Expectations for Mock of bluetooth transport adapter +#ifdef BLUETOOTH_SUPPORT + EXPECT_CALL(*mock_bt_ta_, AddListener(_)); + EXPECT_CALL(*mock_bt_ta_, IsInitialised()).WillRepeatedly(Return(true)); + EXPECT_CALL(*mock_bt_ta_, Init()) + .WillRepeatedly(Return(TransportAdapter::OK)); + EXPECT_CALL(*mock_bt_ta_, Terminate()); +#endif +} - NiceMock<MockLastState> mock_last_state; - Json::Value custom_dictionary; - Json::Value tcp_device; - tcp_device[kDeviceName] = "unique_tcp_device_name"; - tcp_device[kDeviceAddress] = "127.0.0.1"; - tcp_device[kDeviceApplications][0][kApplicationPort] = "1"; - Json::Value bluetooth_device; - bluetooth_device[kDeviceName] = "unique_bluetooth_device_name"; - bluetooth_device[kDeviceAddress] = "AB:CD:EF:GH:IJ:KL"; - bluetooth_device[kDeviceApplications][0][kApplicationRfcomm] = - kApplicationRfcommValue; - custom_dictionary[kTransportManager][kTcpAdapter][kDevices][0] = tcp_device; - custom_dictionary[kTransportManager][kBluetoothAdapter][kDevices][0] = - bluetooth_device; +void TestTransportManagerDefault::ExpectationsTCP_TA() { + // Expectations for Mock of TCP transport adapter + EXPECT_CALL(*mock_tcp_ta_, AddListener(_)); + EXPECT_CALL(*mock_tcp_ta_, IsInitialised()).WillRepeatedly(Return(true)); + EXPECT_CALL(*mock_tcp_ta_, Init()) + .WillRepeatedly(Return(TransportAdapter::OK)); + + std::shared_ptr<MockDevice> mockdev = + std::make_shared<MockDevice>(dev_id_, unique_tcp_dev_name_); + EXPECT_CALL(*mock_tcp_ta_, FindDevice(unique_tcp_dev_name_)) + .WillRepeatedly(Return(mockdev)); + const int app_handle = 1; + EXPECT_CALL(*mock_tcp_ta_, Connect(unique_tcp_dev_name_, app_handle)) + .Times(0); + EXPECT_CALL(*mock_tcp_ta_, Terminate()); +} - ON_CALL(mock_last_state, get_dictionary()) - .WillByDefault(ReturnRef(custom_dictionary)); +void TestTransportManagerDefault::ExpectationsUSB_TA() { + // Expectations for Mock of USB transport adapter +#if defined(USB_SUPPORT) + EXPECT_CALL(*mock_usb_aoa_ta_, AddListener(_)); + EXPECT_CALL(*mock_usb_aoa_ta_, IsInitialised()).WillRepeatedly(Return(true)); + EXPECT_CALL(*mock_usb_aoa_ta_, Init()) + .WillRepeatedly(Return(TransportAdapter::OK)); + EXPECT_CALL(*mock_usb_aoa_ta_, Terminate()); +#endif +} - EXPECT_CALL(transport_manager_settings, use_last_state()) +void TestTransportManagerDefault::ExpectationsCloudWebsocket_TA() { + // Expectations for Mock of Cloud Websocket transport adapter +#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT) + EXPECT_CALL(*mock_cloud_websocket_ta_, AddListener(_)); + EXPECT_CALL(*mock_cloud_websocket_ta_, IsInitialised()) .WillRepeatedly(Return(true)); - EXPECT_CALL(transport_manager_settings, transport_manager_tcp_adapter_port()) - .WillRepeatedly(Return(1u)); - std::string network_interface = ""; - EXPECT_CALL(transport_manager_settings, - transport_manager_tcp_adapter_network_interface()) - .WillRepeatedly(ReturnRef(network_interface)); - EXPECT_CALL(transport_manager_settings, bluetooth_uuid()) - .WillRepeatedly(Return(kBTUUID.data())); - transport_manager.Init(mock_last_state); - transport_manager.Stop(); + EXPECT_CALL(*mock_cloud_websocket_ta_, Init()) + .WillRepeatedly(Return(TransportAdapter::OK)); + EXPECT_CALL(*mock_cloud_websocket_ta_, Terminate()); +#endif +} + +TEST_F(TestTransportManagerDefault, Init_LastStateNotUsed) { + const bool use_last_state = false; + ExpectationsSettings_TM(use_last_state); + + ExpectationsBluetooth_TA(); + ExpectationsTCP_TA(); + ExpectationsUSB_TA(); + ExpectationsCloudWebsocket_TA(); + + // Act + transport_manager_->Init(mock_last_state_); + transport_manager_->Stop(); +} + +TEST_F(TestTransportManagerDefault, Init_LastStateUsed) { + const bool use_last_state = true; + ExpectationsSettings_TM(use_last_state); + + ExpectationsBluetooth_TA(); + ExpectationsTCP_TA(); + ExpectationsUSB_TA(); + ExpectationsCloudWebsocket_TA(); + + // Act + transport_manager_->Init(mock_last_state_); + transport_manager_->Stop(); } } // namespace transport_manager_test diff --git a/src/components/transport_manager/test/websocket_connection_test.cc b/src/components/transport_manager/test/websocket_connection_test.cc index d096d351f5..6f6baa82fd 100644 --- a/src/components/transport_manager/test/websocket_connection_test.cc +++ b/src/components/transport_manager/test/websocket_connection_test.cc @@ -276,8 +276,7 @@ TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSServer, this, "/"); - usleep(5000); + StartWSServer("/"); // Start client InitWebsocketClient(properties, ws_client); @@ -294,7 +293,6 @@ TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) { // Stop server thread ws_session->Stop(); - t1.join(); } TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) { @@ -308,8 +306,7 @@ TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSServer, this, kPath); - usleep(5000); + StartWSServer(kPath); // Start client InitWebsocketClient(properties, ws_client); @@ -326,7 +323,6 @@ TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) { // Stop server thread ws_session->Stop(); - t1.join(); } TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) { @@ -340,8 +336,7 @@ TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSServer, this, "/"); - usleep(5000); + StartWSServer("/"); // Start client InitWebsocketClient(properties, ws_client); @@ -358,7 +353,6 @@ TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) { // Stop server thread ws_session->Stop(); - t1.join(); } TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) { @@ -371,8 +365,7 @@ TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSSServer, this, "/"); - usleep(5000); + StartWSSServer("/"); // Start client InitWebsocketClient(properties, ws_client); @@ -389,7 +382,6 @@ TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) { // Stop server thread wss_session->Stop(); - t1.join(); } TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) { @@ -402,10 +394,7 @@ TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSSServer, - this, - (kPath + kQuery + kFragment)); - usleep(5000); + StartWSSServer((kPath + kQuery + kFragment)); // Start client InitWebsocketClient(properties, ws_client); @@ -422,7 +411,6 @@ TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) { // Stop server thread wss_session->Stop(); - t1.join(); } #ifdef ENABLE_SECURITY @@ -436,8 +424,7 @@ TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSSServer, this, kPath); - usleep(5000); + StartWSSServer(kPath); // Start client InitWebsocketClient(properties, ws_client); @@ -454,7 +441,6 @@ TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) { // Stop server thread wss_session->Stop(); - t1.join(); } TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) { @@ -467,8 +453,7 @@ TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) { .hybrid_app_preference = "CLOUD"}; // Start server - std::thread t1(&WebsocketConnectionTest::StartWSSServer, this, "/"); - usleep(5000); + StartWSSServer("/"); // Start client InitWebsocketClient(properties, ws_client); @@ -485,7 +470,6 @@ TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) { // Stop server thread wss_session->Stop(); - t1.join(); } #endif // ENABLE_SECURITY } // namespace transport_manager_test |