diff options
Diffstat (limited to 'src/components/protocol_handler/test/protocol_handler_tm_test.cc')
-rw-r--r-- | src/components/protocol_handler/test/protocol_handler_tm_test.cc | 1324 |
1 files changed, 1250 insertions, 74 deletions
diff --git a/src/components/protocol_handler/test/protocol_handler_tm_test.cc b/src/components/protocol_handler/test/protocol_handler_tm_test.cc index 77de1705da..615900c7fa 100644 --- a/src/components/protocol_handler/test/protocol_handler_tm_test.cc +++ b/src/components/protocol_handler/test/protocol_handler_tm_test.cc @@ -41,15 +41,27 @@ #include "protocol_handler/mock_protocol_handler_settings.h" #include "protocol_handler/mock_session_observer.h" #include "connection_handler/mock_connection_handler.h" +#include "connection_handler/connection_handler_impl.h" #ifdef ENABLE_SECURITY #include "security_manager/mock_security_manager.h" #include "security_manager/mock_ssl_context.h" #endif // ENABLE_SECURITY #include "transport_manager/mock_transport_manager.h" -#include "utils/make_shared.h" +#include "utils/mock_system_time_handler.h" +#include "utils/semantic_version.h" + #include "utils/test_async_waiter.h" #include <bson_object.h> +namespace transport_manager { +namespace transport_adapter { +// taken from transport_adapter_impl.cc +const char* tc_enabled = "enabled"; +const char* tc_tcp_port = "tcp_port"; +const char* tc_tcp_ip_address = "tcp_ip_address"; +} +} + namespace test { namespace components { namespace protocol_handler_test { @@ -87,6 +99,10 @@ using protocol_handler::FRAME_DATA_SERVICE_DATA_ACK; using protocol_handler::FRAME_DATA_SINGLE; using protocol_handler::FRAME_DATA_FIRST; using protocol_handler::FRAME_DATA_LAST_CONSECUTIVE; +using protocol_handler::FRAME_DATA_REGISTER_SECONDARY_TRANSPORT; +using protocol_handler::FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_ACK; +using protocol_handler::FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK; +using protocol_handler::FRAME_DATA_TRANSPORT_EVENT_UPDATE; using protocol_handler::kRpc; using protocol_handler::kControl; using protocol_handler::kAudio; @@ -95,16 +111,24 @@ using protocol_handler::kBulk; using protocol_handler::kInvalidServiceType; // For TM states using transport_manager::TransportManagerListener; +using test::components::security_manager_test::MockSystemTimeHandler; using transport_manager::E_SUCCESS; using transport_manager::DeviceInfo; +#ifdef ENABLE_SECURITY +// For security +using ContextCreationStrategy = + security_manager::SecurityManager::ContextCreationStrategy; +#endif // ENABLE_SECURITY // For CH entities using connection_handler::DeviceHandle; // Google Testing Framework Entities using ::testing::Return; +using ::testing::ReturnRef; using ::testing::ReturnRefOfCopy; using ::testing::ReturnNull; using ::testing::An; using ::testing::AnyOf; +using ::testing::AtLeast; using ::testing::ByRef; using ::testing::DoAll; using ::testing::SaveArg; @@ -183,6 +207,9 @@ class ProtocolHandlerImplTest : public ::testing::Test { . // Return false to avoid call KeepConnectionAlive WillRepeatedly(Return(false)); + + session_connection_map_lock_ptr_ = + std::make_shared<sync_primitives::Lock>(); } void TearDown() OVERRIDE { @@ -209,6 +236,7 @@ class ProtocolHandlerImplTest : public ::testing::Test { const uint32_t hash_id, const bool protection_flag) { return protocol_handler::SessionContext(connection_id, + connection_id, initial_session_id, new_session_id, service_type, @@ -216,7 +244,7 @@ class ProtocolHandlerImplTest : public ::testing::Test { protection_flag); } - void AddSession(const ::utils::SharedPtr<TestAsyncWaiter>& waiter, + void AddSession(const std::shared_ptr<TestAsyncWaiter>& waiter, uint32_t& times) { using namespace protocol_handler; ASSERT_TRUE(NULL != waiter.get()); @@ -313,10 +341,11 @@ class ProtocolHandlerImplTest : public ::testing::Test { uint8_t service_type, uint8_t sessionId, uint32_t frame_data, + uint8_t protocol_version = PROTOCOL_VERSION_3, uint32_t dataSize = 0u, const uint8_t* data = NULL) { SendTMMessage(connection_id, - PROTOCOL_VERSION_3, + protocol_version, protection, FRAME_TYPE_CONTROL, service_type, @@ -327,8 +356,20 @@ class ProtocolHandlerImplTest : public ::testing::Test { data); } + void VerifySecondaryTransportParamsInStartSessionAck( + bool config_multiple_transports_enabled, + const std::vector<std::string>& config_secondary_transports_for_usb, + const std::vector<std::string>& config_secondary_transports_for_bluetooth, + const std::vector<std::string>& config_secondary_transports_for_wifi, + const std::vector<std::string>& config_audio_service_transports, + const std::vector<std::string>& config_video_service_transports, + const std::string& connection_type_string, + const std::vector<std::string>& expected_transport_strings, + const std::vector<int32_t>& expected_audio_service_transports, + const std::vector<int32_t>& expected_video_service_transports); + testing::NiceMock<MockProtocolHandlerSettings> protocol_handler_settings_mock; - ::utils::SharedPtr<ProtocolHandlerImpl> protocol_handler_impl; + std::shared_ptr<ProtocolHandlerImpl> protocol_handler_impl; TransportManagerListener* tm_listener; // Uniq connection ::transport_manager::ConnectionUID connection_id; @@ -353,6 +394,10 @@ class ProtocolHandlerImplTest : public ::testing::Test { std::vector<int> force_unprotected_services; #endif // ENABLE_SECURITY std::vector<std::string> empty_rejected_param_; + // Used by OnTransportConfigUpdated() tests. The lifetime of these objects + // should be longer than that of a test case. + connection_handler::SessionConnectionMap session_connection_map_; + std::shared_ptr<sync_primitives::Lock> session_connection_map_lock_ptr_; }; #ifdef ENABLE_SECURITY @@ -577,8 +622,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, StartSession_Protected_SessionObserverAccept) { SetProtocolVersion2(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -618,6 +662,18 @@ TEST_F(ProtocolHandlerImplTest, const ::transport_manager::ConnectionUID connection_id2 = 0xBu; const uint8_t session_id2 = 2u; +#ifdef ENABLE_SECURITY + AddSecurityManager(); + + EXPECT_CALL(session_observer_mock, KeyFromPair(connection_id2, session_id2)) + .WillOnce(Return(connection_key)); + + EXPECT_CALL(session_observer_mock, + GetSSLContext(connection_key, start_service)) + .Times(2) + .WillRepeatedly(ReturnNull()); +#endif // ENABLE_SECURITY + EXPECT_CALL(session_observer_mock, IsHeartBeatSupported(connection_id1, _)) .WillRepeatedly(Return(false)); EXPECT_CALL(session_observer_mock, IsHeartBeatSupported(connection_id2, _)) @@ -780,8 +836,7 @@ TEST_F(ProtocolHandlerImplTest, * ProtocolHandler shall send NAck on session_observer rejection */ TEST_F(ProtocolHandlerImplTest, EndSession_SessionObserverReject) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -814,8 +869,7 @@ TEST_F(ProtocolHandlerImplTest, EndSession_SessionObserverReject) { * ProtocolHandler shall send NAck on wrong hash code */ TEST_F(ProtocolHandlerImplTest, EndSession_Success) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -848,8 +902,7 @@ TEST_F(ProtocolHandlerImplTest, EndSession_Success) { #ifdef ENABLE_SECURITY TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtocoloV1) { using namespace protocol_handler; - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -987,7 +1040,10 @@ TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtected_Fail) { SetProtocolVersion2(); // Expect start protection for unprotected session - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, + CreateSSLContext(connection_key, + security_manager::SecurityManager:: + ContextCreationStrategy::kUseExisting)) . // Return fail protection WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull())); @@ -1042,7 +1098,7 @@ TEST_F(ProtocolHandlerImplTest, SetProtocolVersion2(); // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1119,7 +1175,7 @@ TEST_F(ProtocolHandlerImplTest, .WillOnce(ReturnRefOfCopy(services)); // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce(Return(&ssl_context_mock)); @@ -1198,7 +1254,7 @@ TEST_F(ProtocolHandlerImplTest, times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1296,7 +1352,7 @@ TEST_F( times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key, _)) . // Return new SSLContext WillOnce( @@ -1392,7 +1448,10 @@ TEST_F(ProtocolHandlerImplTest, times++; // call new SSLContext creation - EXPECT_CALL(security_manager_mock, CreateSSLContext(connection_key)) + EXPECT_CALL(security_manager_mock, + CreateSSLContext(connection_key, + security_manager::SecurityManager:: + ContextCreationStrategy::kUseExisting)) . // Return new SSLContext WillOnce( @@ -1420,27 +1479,37 @@ TEST_F(ProtocolHandlerImplTest, // Expect add listener for handshake result EXPECT_CALL(security_manager_mock, AddListener(_)) - // Emulate handshake fail - .WillOnce(Invoke(OnHandshakeDoneFunctor( - connection_key, - security_manager::SSLContext::Handshake_Result_Success))); + // Emulate handshake + .WillOnce( + DoAll(NotifyTestAsyncWaiter(&waiter), + Invoke(OnHandshakeDoneFunctor( + connection_key, + security_manager::SSLContext::Handshake_Result_Success)))); + times++; // Listener check SSLContext EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, start_service)) . // Emulate protection for service is not enabled - WillOnce(ReturnNull()); + WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull())); + times++; + + EXPECT_CALL(security_manager_mock, IsSystemTimeProviderReady()) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true))); + times++; - // Expect service protection enable EXPECT_CALL(session_observer_mock, - SetProtectionFlag(connection_key, start_service)); + SetProtectionFlag(connection_key, start_service)) + .WillOnce(NotifyTestAsyncWaiter(&waiter)); + times++; - // Expect send Ack with PROTECTION_OFF (on fail handshake) + // Expect send Ack with PROTECTION_ON (on successfull handshake) EXPECT_CALL(transport_manager_mock, SendMessageToDevice( ControlMessage(FRAME_DATA_START_SERVICE_ACK, PROTECTION_ON))) .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; SendControlMessage( @@ -1450,14 +1519,1138 @@ TEST_F(ProtocolHandlerImplTest, } #endif // ENABLE_SECURITY +void ProtocolHandlerImplTest::VerifySecondaryTransportParamsInStartSessionAck( + bool config_multiple_transports_enabled, + const std::vector<std::string>& config_secondary_transports_for_usb, + const std::vector<std::string>& config_secondary_transports_for_bluetooth, + const std::vector<std::string>& config_secondary_transports_for_wifi, + const std::vector<std::string>& config_audio_service_transports, + const std::vector<std::string>& config_video_service_transports, + const std::string& connection_type_string, + const std::vector<std::string>& expected_transport_strings, + const std::vector<int32_t>& expected_audio_service_transports, + const std::vector<int32_t>& expected_video_service_transports) { + const size_t maximum_rpc_payload_size = 1500; + EXPECT_CALL(protocol_handler_settings_mock, maximum_rpc_payload_size()) + .WillRepeatedly(Return(maximum_rpc_payload_size)); + InitProtocolHandlerImpl(0u, 0u); + + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + utils::SemanticVersion full_version(5, 1, 0); + char full_version_string[] = "5.1.0"; + + // configuration setup + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(config_multiple_transports_enabled)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillOnce(ReturnRef(config_audio_service_transports)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillOnce(ReturnRef(config_video_service_transports)); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + // Prepare expected BSON parameters. When we add another param in Start + // Service ACK frame in future, it should be also added here. + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // mtu + bson_object_put_int64(&expected_obj, + protocol_handler::strings::mtu, + static_cast<int64_t>(maximum_rpc_payload_size)); + // hashId + bson_object_put_int32(&expected_obj, + protocol_handler::strings::hash_id, + static_cast<int32_t>(hash_id)); + // protocolVersion + bson_object_put_string(&expected_obj, + protocol_handler::strings::protocol_version, + full_version_string); + // secondaryTransports + BsonArray secondary_transports; + bson_array_initialize(&secondary_transports, + expected_transport_strings.size()); + for (std::vector<std::string>::const_iterator it = + expected_transport_strings.begin(); + it != expected_transport_strings.end(); + ++it) { + // note: if there is no transport allowed, we can either make the array + // empty, or completely omit the array. (The spec allows both cases.) In + // this test case we make the array empty. + bson_array_add_string(&secondary_transports, + const_cast<char*>(it->c_str())); + } + bson_object_put_array(&expected_obj, + protocol_handler::strings::secondary_transports, + &secondary_transports); + // audioServiceTransports + BsonArray audio_service_transports; + if (expected_audio_service_transports.size() > 0) { + bson_array_initialize(&audio_service_transports, + expected_audio_service_transports.size()); + for (std::vector<int32_t>::const_iterator it = + expected_audio_service_transports.begin(); + it != expected_audio_service_transports.end(); + ++it) { + bson_array_add_int32(&audio_service_transports, *it); + } + bson_object_put_array(&expected_obj, + protocol_handler::strings::audio_service_transports, + &audio_service_transports); + } + // videoServiceTransports + BsonArray video_service_transports; + if (expected_video_service_transports.size() > 0) { + bson_array_initialize(&video_service_transports, + expected_video_service_transports.size()); + for (std::vector<int32_t>::const_iterator it = + expected_video_service_transports.begin(); + it != expected_video_service_transports.end(); + ++it) { + bson_array_add_int32(&video_service_transports, *it); + } + bson_object_put_array(&expected_obj, + protocol_handler::strings::video_service_transports, + &video_service_transports); + } + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + EXPECT_CALL(transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_START_SERVICE_ACK, + PROTECTION_OFF, + connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + +#ifdef ENABLE_SECURITY + AddSecurityManager(); + + EXPECT_CALL(session_observer_mock, KeyFromPair(connection_id, session_id)) + .WillOnce(Return(connection_key)); + + EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, kRpc)) + .WillOnce(ReturnNull()); +#endif // ENABLE_SECURITY + + protocol_handler_impl->SendStartSessionAck(connection_id, + session_id, + input_protocol_version, + hash_id, + protocol_handler::SERVICE_TYPE_RPC, + false /* protection */, + full_version); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_Enabled) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is Android and is connected through Bluetooth SPP + std::string connection_type_string("SPP_BLUETOOTH"); + + // Core should specify WiFi for secondary transport, and should allow video + // and audio services only on secondary transport + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(2); + + // A TransportUpdateEvent is also issued after Start Service ACK. We don't + // check it in this test case. + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_NoSecondaryTransport) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is iOS and is connected through iAP over USB + std::string connection_type_string("IAP_USB"); + + // Core should not offer any secondary transport. It will allow both video + // and audio services on primary transport. + std::vector<std::string> expected_transport_strings; // empty + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_MultipleSecondaryTransports) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi and USB + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("WiFi"); + secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + // Core should offer both Wi-Fi and USB for secondary transport. Since the + // device is iOS, Core should specify "IAP_USB". + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + expected_transport_strings.push_back("IAP_USB"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(2); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F( + ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_ServiceAllowedOnBothTransports) { + std::vector<std::string> secondary_transports_for_usb; + secondary_transports_for_usb.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video service to run on Wi-Fi transports only, and audio + // service to run on all transports + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_BLUETOOTH"); + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("SPP_BLUETOOTH"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is Android and is connected through AOA + std::string connection_type_string("AOA_USB"); + + // Core should offer Wi-Fi for secondary transport. It should allow audio + // service to run on both primary and secondary, while video service to run + // on secondary only. Since the list specifies AOA_USB then TCP_WIFI, the + // priority is primary > secondary. + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); // primary preferred + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(2); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_SecondaryDisabled) { + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; // empty + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_BLUETOOTH"); + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("SPP_BLUETOOTH"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_BLUETOOTH"); + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("SPP_BLUETOOTH"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + // Core should not offer any secondary transport. It should still send + // the video/audio service transport lists. + std::vector<std::string> expected_transport_strings; // empty + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + false, /* disabled */ + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_ServicesMapEmpty) { + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> secondary_transports_for_wifi; + secondary_transports_for_wifi.push_back("USB"); + // config does not specify video and audio services + std::vector<std::string> audio_service_transports; // empty + std::vector<std::string> video_service_transports; // empty + + // assume the device is connected through Wi-Fi (so not sure if it's iOS or + // Android) + std::string connection_type_string("TCP_WIFI"); + + // Core should offer USB transport for secondary transport. (Since the OS type + // is unknown, it will offer both IAP_USB and AOA_USB.) Also, it should allow + // video/audio services on all transports. + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("IAP_USB"); + expected_transport_strings.push_back("AOA_USB"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + expected_video_service_transports.push_back(2); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F( + ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_SecondaryDisabled_ServicesMapEmpty) { + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; // empty + std::vector<std::string> secondary_transports_for_wifi; // empty + // config does not specify video and audio services + std::vector<std::string> audio_service_transports; // empty + std::vector<std::string> video_service_transports; // empty + + std::string connection_type_string("IAP_BLUETOOTH"); + + // Core should not offer any secondary transport. It should still send + // the video/audio service transport lists. + std::vector<std::string> expected_transport_strings; // empty + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + false, /* disabled */ + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +// Secondary transport param should not be included for apps with v5.0.0 +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_Unprotected_NoSecondaryTransportParamsForV5) { + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + utils::SemanticVersion full_version(5, 0, 0); + char full_version_string[] = "5.0.0"; + + const size_t maximum_rpc_payload_size = 1500; + EXPECT_CALL(protocol_handler_settings_mock, maximum_rpc_payload_size()) + .WillRepeatedly(Return(maximum_rpc_payload_size)); + InitProtocolHandlerImpl(0u, 0u); + + // configuration + std::vector<std::string> config_secondary_transports_for_usb; // empty + std::vector<std::string> config_secondary_transports_for_bluetooth; + config_secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> config_secondary_transports_for_wifi; + config_secondary_transports_for_wifi.push_back("USB"); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + // configuration setup + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + // BSON params should not include any of "secondaryTransports", + // "audioServiceTransports" and "videoServiceTransports" since v5.0.0 app + // does not understand them + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // mtu + bson_object_put_int64(&expected_obj, + protocol_handler::strings::mtu, + static_cast<int64_t>(maximum_rpc_payload_size)); + // hashId + bson_object_put_int32(&expected_obj, + protocol_handler::strings::hash_id, + static_cast<int32_t>(hash_id)); + // protocolVersion + bson_object_put_string(&expected_obj, + protocol_handler::strings::protocol_version, + full_version_string); + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + EXPECT_CALL(transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_START_SERVICE_ACK, + PROTECTION_OFF, + connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + + // Since the protocol version is less than 5.1.0, Core should not issue + // TransportEventUpdate frame. Enable ProtocolVersionUsed() call and verify + // that transport_manager_mock will NOT receive another SendMessageToDevice() + // call. + ON_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillByDefault(Return(true)); + +#ifdef ENABLE_SECURITY + AddSecurityManager(); + + EXPECT_CALL(session_observer_mock, KeyFromPair(connection_id, session_id)) + .WillOnce(Return(connection_key)); + + EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, kRpc)) + .WillOnce(ReturnNull()); +#endif // ENABLE_SECURITY + + protocol_handler_impl->SendStartSessionAck(connection_id, + session_id, + input_protocol_version, + hash_id, + protocol_handler::SERVICE_TYPE_RPC, + false /* protection */, + full_version); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, StartSessionAck_PrimaryTransportUSBHostMode) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi + std::vector<std::string> secondary_transports_for_usb; + secondary_transports_for_usb.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_bluetooth; // empty + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is IOS and is connected through USB Host Mode + std::string connection_type_string("IAP_USB_HOST_MODE"); + + // Core should specify WiFi for secondary transport, and should allow video + // services on both transports, and audio only on secondary transport + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + expected_video_service_transports.push_back(2); + + // A TransportUpdateEvent is also issued after Start Service ACK. We don't + // check it in this test case. + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + TransportEventUpdate_afterVersionNegotiation_TCPEnabled) { + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + utils::SemanticVersion full_version(5, 1, 0); + + const size_t maximum_rpc_payload_size = 1500; + EXPECT_CALL(protocol_handler_settings_mock, maximum_rpc_payload_size()) + .WillRepeatedly(Return(maximum_rpc_payload_size)); + InitProtocolHandlerImpl(0u, 0u); + + // TCP configuration setup + bool tcp_enabled = true; + char tcp_address[] = "192.168.1.1"; + int32_t tcp_port = 12345; + std::string tcp_port_str = "12345"; + protocol_handler_impl->set_tcp_config( + tcp_enabled, std::string(tcp_address), tcp_port_str); + + // configuration setup + std::vector<std::string> config_secondary_transports_for_usb; // empty + std::vector<std::string> config_secondary_transports_for_bluetooth; + config_secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> config_secondary_transports_for_wifi; // empty + std::vector<std::string> config_audio_service_transports; + config_audio_service_transports.push_back("IAP_USB"); + config_audio_service_transports.push_back("IAP_USB_HOST_MODE"); + config_audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_audio_service_transports.push_back("IAP_CARPLAY"); + config_audio_service_transports.push_back("AOA_USB"); + config_audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> config_video_service_transports; + config_video_service_transports.push_back("IAP_USB"); + config_video_service_transports.push_back("IAP_USB_HOST_MODE"); + config_video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_video_service_transports.push_back("IAP_CARPLAY"); + config_video_service_transports.push_back("AOA_USB"); + config_video_service_transports.push_back("TCP_WIFI"); + + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillOnce(ReturnRef(config_audio_service_transports)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillOnce(ReturnRef(config_video_service_transports)); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage( + FRAME_DATA_START_SERVICE_ACK, PROTECTION_OFF, connection_id, _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + bson_object_put_string( + &expected_obj, protocol_handler::strings::tcp_ip_address, tcp_address); + // TCP port number + bson_object_put_int32( + &expected_obj, protocol_handler::strings::tcp_port, tcp_port); + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + +#ifdef ENABLE_SECURITY + AddSecurityManager(); + + EXPECT_CALL(session_observer_mock, KeyFromPair(connection_id, session_id)) + .WillOnce(Return(connection_key)); + + EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, kRpc)) + .WillOnce(ReturnNull()); +#endif // ENABLE_SECURITY + + protocol_handler_impl->SendStartSessionAck(connection_id, + session_id, + input_protocol_version, + hash_id, + protocol_handler::SERVICE_TYPE_RPC, + false /* protection */, + full_version); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, + TransportEventUpdate_afterVersionNegotiation_TCPDisabled) { + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + utils::SemanticVersion full_version(5, 1, 0); + + const size_t maximum_rpc_payload_size = 1500; + EXPECT_CALL(protocol_handler_settings_mock, maximum_rpc_payload_size()) + .WillRepeatedly(Return(maximum_rpc_payload_size)); + InitProtocolHandlerImpl(0u, 0u); + + // TCP configuration setup + bool tcp_enabled = false; + char tcp_address[] = "192.168.2.3"; + std::string tcp_port_str = "12345"; + protocol_handler_impl->set_tcp_config( + tcp_enabled, std::string(tcp_address), tcp_port_str); + + std::vector<std::string> config_secondary_transports_for_usb; // empty + std::vector<std::string> config_secondary_transports_for_bluetooth; + config_secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> config_secondary_transports_for_wifi; // empty + std::vector<std::string> config_audio_service_transports; + config_audio_service_transports.push_back("IAP_USB"); + config_audio_service_transports.push_back("IAP_USB_HOST_MODE"); + config_audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_audio_service_transports.push_back("IAP_CARPLAY"); + config_audio_service_transports.push_back("AOA_USB"); + config_audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> config_video_service_transports; + config_video_service_transports.push_back("IAP_USB"); + config_video_service_transports.push_back("IAP_USB_HOST_MODE"); + config_video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_video_service_transports.push_back("IAP_CARPLAY"); + config_video_service_transports.push_back("AOA_USB"); + config_video_service_transports.push_back("TCP_WIFI"); + + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillOnce(ReturnRef(config_audio_service_transports)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillOnce(ReturnRef(config_video_service_transports)); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage( + FRAME_DATA_START_SERVICE_ACK, PROTECTION_OFF, connection_id, _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + char empty_ip_address[] = ""; + bson_object_put_string(&expected_obj, + protocol_handler::strings::tcp_ip_address, + empty_ip_address); + // TCP port number should be omitted + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + +#ifdef ENABLE_SECURITY + AddSecurityManager(); + + EXPECT_CALL(session_observer_mock, KeyFromPair(connection_id, session_id)) + .WillOnce(Return(connection_key)); + + EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, kRpc)) + .WillOnce(ReturnNull()); +#endif // ENABLE_SECURITY + + protocol_handler_impl->SendStartSessionAck(connection_id, + session_id, + input_protocol_version, + hash_id, + protocol_handler::SERVICE_TYPE_RPC, + false /* protection */, + full_version); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, + OnTransportConfigUpdated_TransportEventUpdate_TCPEnabled) { + using connection_handler::SessionConnectionMap; + using connection_handler::SessionTransports; + + TestAsyncWaiter waiter; + uint32_t times = 0; + + char tcp_address[] = "172.16.2.3"; + int32_t tcp_port = 23456; + std::string tcp_port_str = "23456"; + + transport_manager::transport_adapter::TransportConfig configs; + configs[transport_manager::transport_adapter::tc_enabled] = + std::string("true"); + configs[transport_manager::transport_adapter::tc_tcp_port] = tcp_port_str; + configs[transport_manager::transport_adapter::tc_tcp_ip_address] = + std::string(tcp_address); + + transport_manager::ConnectionUID device1_primary_connection_id = 100; + transport_manager::ConnectionUID device2_primary_connection_id = 101; + transport_manager::ConnectionUID device2_secondary_connection_id = 150; + + SessionTransports st1 = {device1_primary_connection_id, kDisabledSecondary}; + SessionTransports st2 = {device2_primary_connection_id, + device2_secondary_connection_id}; + session_connection_map_[0x11] = st1; + session_connection_map_[0x22] = st2; + + EXPECT_CALL(connection_handler_mock, session_connection_map()) + .WillOnce(Return(DataAccessor<SessionConnectionMap>( + session_connection_map_, session_connection_map_lock_ptr_))); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + bson_object_put_string( + &expected_obj, protocol_handler::strings::tcp_ip_address, tcp_address); + // TCP port number + bson_object_put_int32( + &expected_obj, protocol_handler::strings::tcp_port, tcp_port); + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + // since device 1 doesn't support secondary transport feature, + // TransportEvetUpdate should be delivered only to device 2 + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + device2_primary_connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + tm_listener->OnTransportConfigUpdated(configs); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, + OnTransportConfigUpdated_TransportEventUpdate_TCPDisabled) { + using connection_handler::SessionConnectionMap; + using connection_handler::SessionTransports; + + TestAsyncWaiter waiter; + uint32_t times = 0; + + char tcp_address[] = "172.16.2.3"; + std::string tcp_port_str = "23456"; + + transport_manager::transport_adapter::TransportConfig configs; + configs[transport_manager::transport_adapter::tc_enabled] = + std::string("false"); + configs[transport_manager::transport_adapter::tc_tcp_port] = tcp_port_str; + configs[transport_manager::transport_adapter::tc_tcp_ip_address] = + std::string(tcp_address); + + transport_manager::ConnectionUID device1_primary_connection_id = 100; + transport_manager::ConnectionUID device1_secondary_connection_id = 150; + transport_manager::ConnectionUID device2_primary_connection_id = 101; + transport_manager::ConnectionUID device3_primary_connection_id = 102; + transport_manager::ConnectionUID device3_secondary_connection_id = 151; + + SessionTransports st1 = {device1_primary_connection_id, + device1_secondary_connection_id}; + SessionTransports st2 = {device2_primary_connection_id, kDisabledSecondary}; + SessionTransports st3 = {device3_primary_connection_id, + device3_secondary_connection_id}; + session_connection_map_[0x11] = st1; + session_connection_map_[0x22] = st2; + session_connection_map_[0x33] = st3; + + EXPECT_CALL(connection_handler_mock, session_connection_map()) + .WillOnce(Return(DataAccessor<SessionConnectionMap>( + session_connection_map_, session_connection_map_lock_ptr_))); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + char empty_ip_address[] = ""; + bson_object_put_string(&expected_obj, + protocol_handler::strings::tcp_ip_address, + empty_ip_address); + // TCP port number should be omitted + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + // both device 1 and device 3 should receive TransportEventUpdate frames + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + device1_primary_connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + device3_primary_connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + tm_listener->OnTransportConfigUpdated(configs); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, RegisterSecondaryTransport_SUCCESS) { + AddConnection(); + + TestAsyncWaiter waiter; + uint32_t times = 0; + + transport_manager::ConnectionUID primary_connection_id = 123; + + EXPECT_CALL(session_observer_mock, + ProtocolVersionUsed(primary_connection_id, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + EXPECT_CALL(connection_handler_mock, + OnSecondaryTransportStarted(_, connection_id, session_id)) + .WillOnce(DoAll(SetArgReferee<0>(primary_connection_id), Return(true))); + + EXPECT_CALL(transport_manager_mock, + SendMessageToDevice( + ControlMessage(FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_ACK, + PROTECTION_OFF, + connection_id, + _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + SendControlMessage(PROTECTION_OFF, + kControl, + session_id, + FRAME_DATA_REGISTER_SECONDARY_TRANSPORT, + PROTOCOL_VERSION_5); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, RegisterSecondaryTransport_FAILURE) { + AddConnection(); + + TestAsyncWaiter waiter; + uint32_t times = 0; + + transport_manager::ConnectionUID primary_connection_id = 123; + + EXPECT_CALL(session_observer_mock, + ProtocolVersionUsed(primary_connection_id, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + // check the behavior when OnSecondaryTransportStarted() returns false + EXPECT_CALL(connection_handler_mock, + OnSecondaryTransportStarted(_, connection_id, session_id)) + .WillOnce(DoAll(SetArgReferee<0>(primary_connection_id), Return(false))); + + EXPECT_CALL(transport_manager_mock, + SendMessageToDevice( + ControlMessage(FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK, + PROTECTION_OFF, + connection_id, + _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + SendControlMessage(PROTECTION_OFF, + kControl, + session_id, + FRAME_DATA_REGISTER_SECONDARY_TRANSPORT, + PROTOCOL_VERSION_5); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification) { const size_t period_msec = 10000; const size_t max_messages = 1000; InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1494,8 +2687,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification_ThresholdValue) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1531,8 +2723,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification_VideoFrameSkip) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1560,8 +2751,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification_AudioFrameSkip) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1589,8 +2779,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerificationDisable) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1618,8 +2807,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedVerificationDisable) { InitProtocolHandlerImpl(0u, 0u, false, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1651,8 +2839,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_MalformedLimitVerification) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1699,8 +2886,7 @@ TEST_F(ProtocolHandlerImplTest, InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1771,8 +2957,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedLimitVerification_MalformedOnly) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1832,8 +3017,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedLimitVerification_NullTimePeriod) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1866,8 +3050,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedLimitVerification_NullCount) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1910,8 +3093,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, DISABLED_SendEndServicePrivate_EndSession_MessageSent) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1935,8 +3117,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendEndServicePrivate_ServiceTypeControl_MessageSent) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1955,7 +3136,8 @@ TEST_F(ProtocolHandlerImplTest, times++; // Act - protocol_handler_impl->SendEndService(connection_id, session_id, kControl); + protocol_handler_impl->SendEndService( + connection_id, connection_id, session_id, kControl); EXPECT_TRUE(waiter->WaitFor(times, kAsyncExpectationsTimeout)); } @@ -1974,8 +3156,7 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeat_NoConnection_NotSent) { TEST_F(ProtocolHandlerImplTest, SendHeartBeat_Successful) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1989,7 +3170,8 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeat_Successful) { transport_manager_mock, SendMessageToDevice(ExpectedMessage( FRAME_TYPE_CONTROL, FRAME_DATA_HEART_BEAT, PROTECTION_OFF, kControl))) - .WillOnce(Return(E_SUCCESS)); + .WillOnce(DoAll(NotifyTestAsyncWaiter(waiter), Return(E_SUCCESS))); + times++; // Act protocol_handler_impl->SendHeartBeat(connection_id, session_id); @@ -1999,8 +3181,7 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeat_Successful) { TEST_F(ProtocolHandlerImplTest, SendHeartBeatAck_Successful) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2029,8 +3210,7 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeatAck_Successful) { TEST_F(ProtocolHandlerImplTest, DISABLED_SendHeartBeatAck_WrongProtocolVersion_NotSent) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2059,8 +3239,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendSingleControlMessage) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2068,7 +3247,7 @@ TEST_F(ProtocolHandlerImplTest, const bool is_final = true; const uint32_t total_data_size = 1; UCharDataVector data(total_data_size); - RawMessagePtr message = utils::MakeShared<RawMessage>( + RawMessagePtr message = std::make_shared<RawMessage>( connection_key, PROTOCOL_VERSION_3, &data[0], total_data_size, kControl); // Expect getting pair from key from session observer EXPECT_CALL(session_observer_mock, @@ -2086,7 +3265,8 @@ TEST_F(ProtocolHandlerImplTest, transport_manager_mock, SendMessageToDevice(ExpectedMessage( FRAME_TYPE_SINGLE, FRAME_DATA_SINGLE, PROTECTION_OFF, kControl))) - .WillOnce(Return(E_SUCCESS)); + .WillOnce(DoAll(NotifyTestAsyncWaiter(waiter), Return(E_SUCCESS))); + times++; // Act protocol_handler_impl->SendMessageToMobileApp(message, is_final); @@ -2097,8 +3277,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendSingleNonControlMessage) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2106,7 +3285,7 @@ TEST_F(ProtocolHandlerImplTest, const bool is_final = true; const uint32_t total_data_size = 1; UCharDataVector data(total_data_size); - RawMessagePtr message = utils::MakeShared<RawMessage>( + RawMessagePtr message = std::make_shared<RawMessage>( connection_key, PROTOCOL_VERSION_3, &data[0], total_data_size, kRpc); // Expect getting pair from key from session observer EXPECT_CALL(session_observer_mock, @@ -2140,8 +3319,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendMultiframeMessage) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2150,7 +3328,7 @@ TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendMultiframeMessage) { const uint32_t total_data_size = MAXIMUM_FRAME_DATA_V2_SIZE * 2; UCharDataVector data(total_data_size); const uint8_t first_consecutive_frame = 0x01; - RawMessagePtr message = utils::MakeShared<RawMessage>( + RawMessagePtr message = std::make_shared<RawMessage>( connection_key, PROTOCOL_VERSION_3, &data[0], total_data_size, kBulk); // Expect getting pair from key from session observer EXPECT_CALL(session_observer_mock, @@ -2195,8 +3373,7 @@ TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendMultiframeMessage) { } TEST_F(ProtocolHandlerImplTest, SendServiceDataAck_PreVersion5) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2222,8 +3399,7 @@ TEST_F(ProtocolHandlerImplTest, SendServiceDataAck_PreVersion5) { } TEST_F(ProtocolHandlerImplTest, SendServiceDataAck_AfterVersion5) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); |