| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/protocol/jingle_session.h" |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "base/test/test_timeouts.h" |
| #include "base/time/time.h" |
| #include "net/socket/socket.h" |
| #include "net/socket/stream_socket.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "remoting/base/constants.h" |
| #include "remoting/protocol/authenticator.h" |
| #include "remoting/protocol/channel_authenticator.h" |
| #include "remoting/protocol/chromium_port_allocator_factory.h" |
| #include "remoting/protocol/connection_tester.h" |
| #include "remoting/protocol/fake_authenticator.h" |
| #include "remoting/protocol/jingle_session_manager.h" |
| #include "remoting/protocol/network_settings.h" |
| #include "remoting/protocol/session_plugin.h" |
| #include "remoting/protocol/transport.h" |
| #include "remoting/protocol/transport_context.h" |
| #include "remoting/signaling/fake_signal_strategy.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/libjingle_xmpp/xmpp/constants.h" |
| |
| using testing::_; |
| using testing::AtLeast; |
| using testing::AtMost; |
| using testing::DeleteArg; |
| using testing::DoAll; |
| using testing::InSequence; |
| using testing::Invoke; |
| using testing::InvokeWithoutArgs; |
| using testing::Return; |
| using testing::SaveArg; |
| using testing::SetArgPointee; |
| using testing::WithArg; |
| |
| namespace remoting { |
| namespace protocol { |
| |
| namespace { |
| |
| const char kHostJid[] = "[email protected]/123"; |
| const char kClientJid[] = "[email protected]/321"; |
| |
| // kHostJid the way it would be stored in the directory. |
| const char kNormalizedHostJid[] = "[email protected]/123"; |
| |
| class MockSessionManagerListener { |
| public: |
| MOCK_METHOD2(OnIncomingSession, |
| void(Session*, |
| SessionManager::IncomingSessionResponse*)); |
| }; |
| |
| class MockSessionEventHandler : public Session::EventHandler { |
| public: |
| MOCK_METHOD1(OnSessionStateChange, void(Session::State)); |
| MOCK_METHOD2(OnSessionRouteChange, void(const std::string& channel_name, |
| const TransportRoute& route)); |
| }; |
| |
| class FakeTransport : public Transport { |
| public: |
| SendTransportInfoCallback send_transport_info_callback() { |
| return send_transport_info_callback_; |
| } |
| |
| const std::vector<std::unique_ptr<buzz::XmlElement>>& received_messages() { |
| return received_messages_; |
| } |
| |
| void set_on_message_callback(const base::Closure& on_message_callback) { |
| on_message_callback_ = on_message_callback; |
| } |
| |
| // Transport interface. |
| void Start(Authenticator* authenticator, |
| SendTransportInfoCallback send_transport_info_callback) override { |
| send_transport_info_callback_ = send_transport_info_callback; |
| } |
| |
| bool ProcessTransportInfo(buzz::XmlElement* transport_info) override { |
| received_messages_.push_back( |
| std::make_unique<buzz::XmlElement>(*transport_info)); |
| if (!on_message_callback_.is_null()) |
| on_message_callback_.Run(); |
| return true; |
| } |
| |
| private: |
| SendTransportInfoCallback send_transport_info_callback_; |
| std::vector<std::unique_ptr<buzz::XmlElement>> received_messages_; |
| base::Closure on_message_callback_; |
| }; |
| |
| class FakePlugin : public SessionPlugin { |
| public: |
| std::unique_ptr<buzz::XmlElement> GetNextMessage() override { |
| std::string tag_name = "test-tag-"; |
| tag_name += base::IntToString(outgoing_messages_.size()); |
| std::unique_ptr<buzz::XmlElement> new_message(new buzz::XmlElement( |
| buzz::QName("test-namespace", tag_name))); |
| outgoing_messages_.push_back(*new_message); |
| return new_message; |
| } |
| |
| void OnIncomingMessage(const buzz::XmlElement& attachments) override { |
| for (const buzz::XmlElement* it = attachments.FirstElement(); |
| it != nullptr; |
| it = it->NextElement()) { |
| incoming_messages_.push_back(*it); |
| } |
| } |
| |
| const std::vector<buzz::XmlElement>& outgoing_messages() const { |
| return outgoing_messages_; |
| } |
| |
| const std::vector<buzz::XmlElement>& incoming_messages() const { |
| return incoming_messages_; |
| } |
| |
| void Clear() { |
| outgoing_messages_.clear(); |
| incoming_messages_.clear(); |
| } |
| |
| private: |
| std::vector<buzz::XmlElement> outgoing_messages_; |
| std::vector<buzz::XmlElement> incoming_messages_; |
| }; |
| |
| std::unique_ptr<buzz::XmlElement> CreateTransportInfo(const std::string& id) { |
| std::unique_ptr<buzz::XmlElement> result( |
| buzz::XmlElement::ForStr("<transport xmlns='google:remoting:ice'/>")); |
| result->AddAttr(buzz::QN_ID, id); |
| return result; |
| } |
| |
| } // namespace |
| |
| class JingleSessionTest : public testing::Test { |
| public: |
| JingleSessionTest() { |
| message_loop_.reset(new base::MessageLoopForIO()); |
| network_settings_ = |
| NetworkSettings(NetworkSettings::NAT_TRAVERSAL_OUTGOING); |
| } |
| |
| // Helper method that handles OnIncomingSession(). |
| void SetHostSession(Session* session) { |
| DCHECK(session); |
| host_session_.reset(session); |
| host_session_->SetEventHandler(&host_session_event_handler_); |
| host_session_->SetTransport(&host_transport_); |
| host_session_->AddPlugin(&host_plugin_); |
| } |
| |
| void DeleteHostSession() { host_session_.reset(); } |
| |
| void DeleteClientSession() { client_session_.reset(); } |
| |
| protected: |
| void TearDown() override { |
| CloseSessions(); |
| CloseSessionManager(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void CloseSessions() { |
| host_session_.reset(); |
| client_session_.reset(); |
| } |
| |
| void CreateSessionManagers(FakeAuthenticator::Config auth_config, |
| int messages_till_start) { |
| host_signal_strategy_ = |
| std::make_unique<FakeSignalStrategy>(SignalingAddress(kHostJid)); |
| client_signal_strategy_ = |
| std::make_unique<FakeSignalStrategy>(SignalingAddress(kClientJid)); |
| |
| FakeSignalStrategy::Connect(host_signal_strategy_.get(), |
| client_signal_strategy_.get()); |
| |
| host_server_.reset(new JingleSessionManager(host_signal_strategy_.get())); |
| host_server_->AcceptIncoming( |
| base::Bind(&MockSessionManagerListener::OnIncomingSession, |
| base::Unretained(&host_server_listener_))); |
| |
| std::unique_ptr<AuthenticatorFactory> factory( |
| new FakeHostAuthenticatorFactory(messages_till_start, auth_config)); |
| host_server_->set_authenticator_factory(std::move(factory)); |
| |
| client_server_.reset( |
| new JingleSessionManager(client_signal_strategy_.get())); |
| } |
| |
| void CreateSessionManagers(FakeAuthenticator::Config auth_config) { |
| CreateSessionManagers(auth_config, 0); |
| } |
| |
| void CloseSessionManager() { |
| host_server_.reset(); |
| client_server_.reset(); |
| host_signal_strategy_.reset(); |
| client_signal_strategy_.reset(); |
| } |
| |
| void SetHostExpectation(bool expect_fail) { |
| EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) |
| .WillOnce( |
| DoAll(WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)), |
| SetArgPointee<1>(protocol::SessionManager::ACCEPT))); |
| |
| { |
| InSequence dummy; |
| |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::ACCEPTED)) |
| .Times(AtMost(1)); |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATING)) |
| .Times(AtMost(1)); |
| if (expect_fail) { |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::FAILED)) |
| .Times(1); |
| } else { |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATED)) |
| .Times(1); |
| // Expect that the connection will be closed eventually. |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::CLOSED)) |
| .Times(AtMost(1)); |
| } |
| } |
| } |
| |
| void SetClientExpectation(bool expect_fail) { |
| InSequence dummy; |
| |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::ACCEPTED)) |
| .Times(AtMost(1)); |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATING)) |
| .Times(AtMost(1)); |
| if (expect_fail) { |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::FAILED)) |
| .Times(1); |
| } else { |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATED)) |
| .Times(1); |
| // Expect that the connection will be closed eventually. |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::CLOSED)) |
| .Times(AtMost(1)); |
| } |
| } |
| |
| void ConnectClient(std::unique_ptr<Authenticator> authenticator) { |
| client_session_ = client_server_->Connect( |
| SignalingAddress(kNormalizedHostJid), std::move(authenticator)); |
| client_session_->SetEventHandler(&client_session_event_handler_); |
| client_session_->SetTransport(&client_transport_); |
| client_session_->AddPlugin(&client_plugin_); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void ConnectClient(FakeAuthenticator::Config auth_config) { |
| ConnectClient(std::make_unique<FakeAuthenticator>( |
| FakeAuthenticator::CLIENT, auth_config, |
| client_signal_strategy_->GetLocalAddress().id(), kNormalizedHostJid)); |
| } |
| |
| void InitiateConnection(FakeAuthenticator::Config auth_config, |
| bool expect_fail) { |
| SetHostExpectation(expect_fail); |
| SetClientExpectation(expect_fail); |
| ConnectClient(auth_config); |
| } |
| |
| void ExpectRouteChange(const std::string& channel_name) { |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionRouteChange(channel_name, _)) |
| .Times(AtLeast(1)); |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionRouteChange(channel_name, _)) |
| .Times(AtLeast(1)); |
| } |
| |
| void ExpectPluginMessagesEqual() const { |
| ASSERT_EQ(client_plugin_.outgoing_messages().size(), |
| host_plugin_.incoming_messages().size()); |
| for (size_t i = 0; i < client_plugin_.outgoing_messages().size(); i++) { |
| ASSERT_EQ(client_plugin_.outgoing_messages()[i].Str(), |
| host_plugin_.incoming_messages()[i].Str()); |
| } |
| |
| ASSERT_EQ(client_plugin_.incoming_messages().size(), |
| host_plugin_.outgoing_messages().size()); |
| for (size_t i = 0; i < client_plugin_.incoming_messages().size(); i++) { |
| ASSERT_EQ(client_plugin_.incoming_messages()[i].Str(), |
| host_plugin_.outgoing_messages()[i].Str()); |
| } |
| } |
| |
| std::unique_ptr<base::MessageLoopForIO> message_loop_; |
| |
| NetworkSettings network_settings_; |
| |
| std::unique_ptr<FakeSignalStrategy> host_signal_strategy_; |
| std::unique_ptr<FakeSignalStrategy> client_signal_strategy_; |
| |
| std::unique_ptr<JingleSessionManager> host_server_; |
| MockSessionManagerListener host_server_listener_; |
| std::unique_ptr<JingleSessionManager> client_server_; |
| |
| std::unique_ptr<Session> host_session_; |
| MockSessionEventHandler host_session_event_handler_; |
| FakeTransport host_transport_; |
| std::unique_ptr<Session> client_session_; |
| MockSessionEventHandler client_session_event_handler_; |
| FakeTransport client_transport_; |
| |
| FakePlugin host_plugin_; |
| FakePlugin client_plugin_; |
| }; |
| |
| |
| // Verify that we can create and destroy session managers without a |
| // connection. |
| TEST_F(JingleSessionTest, CreateAndDestoy) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| } |
| |
| // Verify that an incoming session can be rejected, and that the |
| // status of the connection is set to FAILED in this case. |
| TEST_F(JingleSessionTest, RejectConnection) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| |
| // Reject incoming session. |
| EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) |
| .WillOnce(SetArgPointee<1>(protocol::SessionManager::DECLINE)); |
| |
| { |
| InSequence dummy; |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::FAILED)) |
| .Times(1); |
| } |
| |
| ConnectClient(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| client_session_->SetEventHandler(&client_session_event_handler_); |
| |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| // Verify that we can connect two endpoints with single-step authentication. |
| TEST_F(JingleSessionTest, Connect) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| InitiateConnection(FakeAuthenticator::Config(), false); |
| |
| // Verify that the client specified correct initiator value. |
| ASSERT_GT(host_signal_strategy_->received_messages().size(), 0U); |
| const buzz::XmlElement* initiate_xml = |
| host_signal_strategy_->received_messages().front().get(); |
| const buzz::XmlElement* jingle_element = |
| initiate_xml->FirstNamed(buzz::QName("urn:xmpp:jingle:1", "jingle")); |
| ASSERT_TRUE(jingle_element); |
| ASSERT_EQ(client_signal_strategy_->GetLocalAddress().id(), |
| jingle_element->Attr(buzz::QName(std::string(), "initiator"))); |
| } |
| |
| // Verify that we can connect two endpoints with multi-step authentication. |
| TEST_F(JingleSessionTest, ConnectWithMultistep) { |
| const int kAuthRoundtrips = 3; |
| FakeAuthenticator::Config auth_config(kAuthRoundtrips, |
| FakeAuthenticator::ACCEPT, true); |
| CreateSessionManagers(auth_config); |
| InitiateConnection(auth_config, false); |
| } |
| |
| TEST_F(JingleSessionTest, ConnectWithOutOfOrderIqs) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| InitiateConnection(FakeAuthenticator::Config(), false); |
| client_signal_strategy_->SimulateMessageReordering(); |
| |
| // Verify that out of order transport messages are received correctly. |
| host_transport_.send_transport_info_callback().Run(CreateTransportInfo("1")); |
| host_transport_.send_transport_info_callback().Run(CreateTransportInfo("2")); |
| base::RunLoop().RunUntilIdle(); |
| |
| ASSERT_EQ(client_transport_.received_messages().size(), 2U); |
| EXPECT_EQ("1", client_transport_.received_messages()[0]->Attr(buzz::QN_ID)); |
| EXPECT_EQ("2", client_transport_.received_messages()[1]->Attr(buzz::QN_ID)); |
| } |
| |
| // Verify that out-of-order messages are handled correctly when the session is |
| // torn down after the first message. |
| TEST_F(JingleSessionTest, ConnectWithOutOfOrderIqsDestroyOnFirstMessage) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| InitiateConnection(FakeAuthenticator::Config(), false); |
| client_signal_strategy_->SimulateMessageReordering(); |
| |
| // Verify that out of order transport messages are received correctly. |
| host_transport_.send_transport_info_callback().Run(CreateTransportInfo("1")); |
| host_transport_.send_transport_info_callback().Run(CreateTransportInfo("2")); |
| |
| // Destroy the session as soon as the first message is received. |
| client_transport_.set_on_message_callback(base::Bind( |
| &JingleSessionTest::DeleteClientSession, base::Unretained(this))); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| ASSERT_EQ(client_transport_.received_messages().size(), 1U); |
| EXPECT_EQ("1", client_transport_.received_messages()[0]->Attr(buzz::QN_ID)); |
| } |
| |
| // Verify that connection is terminated when single-step auth fails. |
| TEST_F(JingleSessionTest, ConnectWithBadAuth) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::REJECT)); |
| InitiateConnection(FakeAuthenticator::Config(), true); |
| } |
| |
| // Verify that connection is terminated when multi-step auth fails. |
| TEST_F(JingleSessionTest, ConnectWithBadMultistepAuth) { |
| const int kAuthRoundtrips = 3; |
| CreateSessionManagers(FakeAuthenticator::Config( |
| kAuthRoundtrips, FakeAuthenticator::REJECT, false)); |
| InitiateConnection(FakeAuthenticator::Config( |
| kAuthRoundtrips, FakeAuthenticator::ACCEPT, false), |
| true); |
| } |
| |
| // Verify that incompatible protocol configuration is handled properly. |
| TEST_F(JingleSessionTest, TestIncompatibleProtocol) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| |
| EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)).Times(0); |
| |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::FAILED)) |
| .Times(1); |
| |
| std::unique_ptr<CandidateSessionConfig> config = |
| CandidateSessionConfig::CreateDefault(); |
| // Disable all video codecs so the host will reject connection. |
| config->mutable_video_configs()->clear(); |
| client_server_->set_protocol_config(std::move(config)); |
| ConnectClient(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| |
| EXPECT_EQ(INCOMPATIBLE_PROTOCOL, client_session_->error()); |
| EXPECT_FALSE(host_session_); |
| } |
| |
| // Verify that GICE-only client is rejected with an appropriate error code. |
| TEST_F(JingleSessionTest, TestLegacyIceConnection) { |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| |
| EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)).Times(0); |
| |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::FAILED)) |
| .Times(1); |
| |
| std::unique_ptr<CandidateSessionConfig> config = |
| CandidateSessionConfig::CreateDefault(); |
| config->set_ice_supported(false); |
| client_server_->set_protocol_config(std::move(config)); |
| ConnectClient(FakeAuthenticator::Config(FakeAuthenticator::ACCEPT)); |
| |
| EXPECT_EQ(INCOMPATIBLE_PROTOCOL, client_session_->error()); |
| EXPECT_FALSE(host_session_); |
| } |
| |
| TEST_F(JingleSessionTest, DeleteSessionOnIncomingConnection) { |
| const int kAuthRoundtrips = 3; |
| FakeAuthenticator::Config auth_config(kAuthRoundtrips, |
| FakeAuthenticator::ACCEPT, true); |
| CreateSessionManagers(auth_config); |
| |
| EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) |
| .WillOnce( |
| DoAll(WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)), |
| SetArgPointee<1>(protocol::SessionManager::ACCEPT))); |
| |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::ACCEPTED)) |
| .Times(AtMost(1)); |
| |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATING)) |
| .WillOnce(InvokeWithoutArgs(this, &JingleSessionTest::DeleteHostSession)); |
| |
| ConnectClient(auth_config); |
| } |
| |
| TEST_F(JingleSessionTest, DeleteSessionOnAuth) { |
| // Same as the previous test, but set messages_till_started to 2 in |
| // CreateSessionManagers so that the session will goes into the |
| // AUTHENTICATING state after two message exchanges. |
| const int kMessagesTillStarted = 2; |
| |
| const int kAuthRoundtrips = 3; |
| FakeAuthenticator::Config auth_config(kAuthRoundtrips, |
| FakeAuthenticator::ACCEPT, true); |
| CreateSessionManagers(auth_config, kMessagesTillStarted); |
| |
| EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) |
| .WillOnce( |
| DoAll(WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)), |
| SetArgPointee<1>(protocol::SessionManager::ACCEPT))); |
| |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::ACCEPTED)) |
| .Times(AtMost(1)); |
| |
| EXPECT_CALL(host_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATING)) |
| .WillOnce(InvokeWithoutArgs(this, &JingleSessionTest::DeleteHostSession)); |
| |
| ConnectClient(auth_config); |
| } |
| |
| // Verify that incoming transport-info messages are handled correctly while in |
| // AUTHENTICATING state. |
| TEST_F(JingleSessionTest, TransportInfoDuringAuthentication) { |
| const int kAuthRoundtrips = 2; |
| FakeAuthenticator::Config auth_config(kAuthRoundtrips, |
| FakeAuthenticator::ACCEPT, true); |
| |
| CreateSessionManagers(auth_config); |
| |
| SetHostExpectation(false); |
| { |
| InSequence dummy; |
| |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::ACCEPTED)) |
| .Times(AtMost(1)); |
| EXPECT_CALL(client_session_event_handler_, |
| OnSessionStateChange(Session::AUTHENTICATING)) |
| .Times(AtMost(1)); |
| } |
| |
| // Create connection and pause it before authentication is finished. |
| FakeAuthenticator* authenticator = new FakeAuthenticator( |
| FakeAuthenticator::CLIENT, auth_config, |
| client_signal_strategy_->GetLocalAddress().id(), kNormalizedHostJid); |
| authenticator->set_pause_message_index(4); |
| ConnectClient(base::WrapUnique(authenticator)); |
| |
| // Send 2 transport messages. |
| host_transport_.send_transport_info_callback().Run(CreateTransportInfo("1")); |
| host_transport_.send_transport_info_callback().Run(CreateTransportInfo("2")); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| // The transport-info messages should not be received here because |
| // authentication hasn't finished. |
| EXPECT_TRUE(client_transport_.received_messages().empty()); |
| |
| // Destroy the session as soon as the first message is received. |
| client_transport_.set_on_message_callback(base::Bind( |
| &JingleSessionTest::DeleteClientSession, base::Unretained(this))); |
| |
| // Resume authentication. |
| authenticator->Resume(); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Verify that transport-info that the first transport-info message was |
| // received. |
| ASSERT_EQ(client_transport_.received_messages().size(), 1U); |
| EXPECT_EQ("1", client_transport_.received_messages()[0]->Attr(buzz::QN_ID)); |
| } |
| |
| TEST_F(JingleSessionTest, TestSessionPlugin) { |
| host_plugin_.Clear(); |
| client_plugin_.Clear(); |
| |
| const int kAuthRoundtrips = 3; |
| FakeAuthenticator::Config auth_config(kAuthRoundtrips, |
| FakeAuthenticator::ACCEPT, true); |
| |
| CreateSessionManagers(auth_config); |
| ASSERT_NO_FATAL_FAILURE(InitiateConnection(auth_config, false)); |
| ExpectPluginMessagesEqual(); |
| } |
| |
| TEST_F(JingleSessionTest, SessionPluginShouldNotBeInvolvedInSessionTerminate) { |
| host_plugin_.Clear(); |
| client_plugin_.Clear(); |
| CreateSessionManagers(FakeAuthenticator::Config(FakeAuthenticator::REJECT)); |
| InitiateConnection(FakeAuthenticator::Config(), true); |
| // It's expected the client sends one more plugin message than host, the host |
| // won't send plugin message in the SESSION_TERMINATE message. |
| ASSERT_EQ(client_plugin_.outgoing_messages().size() - 1, |
| client_plugin_.incoming_messages().size()); |
| ExpectPluginMessagesEqual(); |
| } |
| |
| TEST_F(JingleSessionTest, ImmediatelyCloseSessionAfterConnect) { |
| const int kAuthRoundtrips = 3; |
| FakeAuthenticator::Config auth_config(kAuthRoundtrips, |
| FakeAuthenticator::ACCEPT, true); |
| CreateSessionManagers(auth_config); |
| client_session_ = client_server_->Connect( |
| SignalingAddress(kNormalizedHostJid), |
| std::make_unique<FakeAuthenticator>( |
| FakeAuthenticator::CLIENT, auth_config, |
| client_signal_strategy_->GetLocalAddress().id(), kNormalizedHostJid)); |
| |
| client_session_->Close(HOST_OVERLOAD); |
| base::RunLoop().RunUntilIdle(); |
| // We should only send a SESSION_TERMINATE message if the session has been |
| // closed before SESSION_INITIATE message. |
| ASSERT_EQ(1U, host_signal_strategy_->received_messages().size()); |
| } |
| |
| } // namespace protocol |
| } // namespace remoting |