jingle_session_unittest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "remoting/protocol/jingle_session.h" 6 7#include "base/bind.h" 8#include "base/message_loop/message_loop.h" 9#include "base/run_loop.h" 10#include "base/test/test_timeouts.h" 11#include "base/time/time.h" 12#include "jingle/glue/thread_wrapper.h" 13#include "net/socket/socket.h" 14#include "net/socket/stream_socket.h" 15#include "net/url_request/url_request_context_getter.h" 16#include "remoting/base/constants.h" 17#include "remoting/jingle_glue/chromium_port_allocator.h" 18#include "remoting/jingle_glue/fake_signal_strategy.h" 19#include "remoting/jingle_glue/network_settings.h" 20#include "remoting/protocol/authenticator.h" 21#include "remoting/protocol/channel_authenticator.h" 22#include "remoting/protocol/connection_tester.h" 23#include "remoting/protocol/fake_authenticator.h" 24#include "remoting/protocol/jingle_session_manager.h" 25#include "remoting/protocol/libjingle_transport_factory.h" 26#include "testing/gmock/include/gmock/gmock.h" 27#include "testing/gtest/include/gtest/gtest.h" 28 29using testing::_; 30using testing::AtLeast; 31using testing::AtMost; 32using testing::DeleteArg; 33using testing::DoAll; 34using testing::InSequence; 35using testing::Invoke; 36using testing::InvokeWithoutArgs; 37using testing::Return; 38using testing::SaveArg; 39using testing::SetArgumentPointee; 40using testing::WithArg; 41 42namespace remoting { 43namespace protocol { 44 45namespace { 46 47const char kHostJid[] = "host1@gmail.com/123"; 48const char kClientJid[] = "host2@gmail.com/321"; 49 50// Send 100 messages 1024 bytes each. UDP messages are sent with 10ms delay 51// between messages (about 1 second for 100 messages). 52const int kMessageSize = 1024; 53const int kMessages = 100; 54const char kChannelName[] = "test_channel"; 55 56void QuitCurrentThread() { 57 base::MessageLoop::current()->PostTask(FROM_HERE, 58 base::MessageLoop::QuitClosure()); 59} 60 61ACTION(QuitThread) { 62 QuitCurrentThread(); 63} 64 65ACTION_P(QuitThreadOnCounter, counter) { 66 --(*counter); 67 EXPECT_GE(*counter, 0); 68 if (*counter == 0) 69 QuitCurrentThread(); 70} 71 72class MockSessionManagerListener : public SessionManager::Listener { 73 public: 74 MOCK_METHOD0(OnSessionManagerReady, void()); 75 MOCK_METHOD2(OnIncomingSession, 76 void(Session*, 77 SessionManager::IncomingSessionResponse*)); 78}; 79 80class MockSessionEventHandler : public Session::EventHandler { 81 public: 82 MOCK_METHOD1(OnSessionStateChange, void(Session::State)); 83 MOCK_METHOD2(OnSessionRouteChange, void(const std::string& channel_name, 84 const TransportRoute& route)); 85}; 86 87class MockStreamChannelCallback { 88 public: 89 MOCK_METHOD1(OnDone, void(net::StreamSocket* socket)); 90}; 91 92} // namespace 93 94class JingleSessionTest : public testing::Test { 95 public: 96 JingleSessionTest() { 97 message_loop_.reset(new base::MessageLoopForIO()); 98 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); 99 } 100 101 // Helper method that handles OnIncomingSession(). 102 void SetHostSession(Session* session) { 103 DCHECK(session); 104 host_session_.reset(session); 105 host_session_->SetEventHandler(&host_session_event_handler_); 106 107 session->set_config(SessionConfig::ForTest()); 108 } 109 110 void DeleteSession() { 111 host_session_.reset(); 112 } 113 114 void OnClientChannelCreated(scoped_ptr<net::StreamSocket> socket) { 115 client_channel_callback_.OnDone(socket.get()); 116 client_socket_ = socket.Pass(); 117 } 118 119 void OnHostChannelCreated(scoped_ptr<net::StreamSocket> socket) { 120 host_channel_callback_.OnDone(socket.get()); 121 host_socket_ = socket.Pass(); 122 } 123 124 protected: 125 virtual void SetUp() { 126 } 127 128 virtual void TearDown() { 129 CloseSessions(); 130 CloseSessionManager(); 131 base::RunLoop().RunUntilIdle(); 132 } 133 134 void CloseSessions() { 135 host_socket_.reset(); 136 host_session_.reset(); 137 client_socket_.reset(); 138 client_session_.reset(); 139 } 140 141 void CreateSessionManagers(int auth_round_trips, int messages_till_start, 142 FakeAuthenticator::Action auth_action) { 143 host_signal_strategy_.reset(new FakeSignalStrategy(kHostJid)); 144 client_signal_strategy_.reset(new FakeSignalStrategy(kClientJid)); 145 FakeSignalStrategy::Connect(host_signal_strategy_.get(), 146 client_signal_strategy_.get()); 147 148 EXPECT_CALL(host_server_listener_, OnSessionManagerReady()) 149 .Times(1); 150 151 NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_OUTGOING); 152 153 scoped_ptr<TransportFactory> host_transport(new LibjingleTransportFactory( 154 NULL, 155 ChromiumPortAllocator::Create(NULL, network_settings) 156 .PassAs<cricket::HttpPortAllocatorBase>(), 157 network_settings)); 158 host_server_.reset(new JingleSessionManager(host_transport.Pass())); 159 host_server_->Init(host_signal_strategy_.get(), &host_server_listener_); 160 161 scoped_ptr<AuthenticatorFactory> factory( 162 new FakeHostAuthenticatorFactory(auth_round_trips, 163 messages_till_start, auth_action, true)); 164 host_server_->set_authenticator_factory(factory.Pass()); 165 166 EXPECT_CALL(client_server_listener_, OnSessionManagerReady()) 167 .Times(1); 168 scoped_ptr<TransportFactory> client_transport(new LibjingleTransportFactory( 169 NULL, 170 ChromiumPortAllocator::Create(NULL, network_settings) 171 .PassAs<cricket::HttpPortAllocatorBase>(), 172 network_settings)); 173 client_server_.reset( 174 new JingleSessionManager(client_transport.Pass())); 175 client_server_->Init(client_signal_strategy_.get(), 176 &client_server_listener_); 177 } 178 179 void CreateSessionManagers(int auth_round_trips, 180 FakeAuthenticator::Action auth_action) { 181 CreateSessionManagers(auth_round_trips, 0, auth_action); 182 } 183 184 void CloseSessionManager() { 185 if (host_server_.get()) { 186 host_server_->Close(); 187 host_server_.reset(); 188 } 189 if (client_server_.get()) { 190 client_server_->Close(); 191 client_server_.reset(); 192 } 193 host_signal_strategy_.reset(); 194 client_signal_strategy_.reset(); 195 } 196 197 void InitiateConnection(int auth_round_trips, 198 FakeAuthenticator::Action auth_action, 199 bool expect_fail) { 200 EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) 201 .WillOnce(DoAll( 202 WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)), 203 SetArgumentPointee<1>(protocol::SessionManager::ACCEPT))); 204 205 { 206 InSequence dummy; 207 208 EXPECT_CALL(host_session_event_handler_, 209 OnSessionStateChange(Session::CONNECTED)) 210 .Times(AtMost(1)); 211 EXPECT_CALL(host_session_event_handler_, 212 OnSessionStateChange(Session::AUTHENTICATING)) 213 .Times(AtMost(1)); 214 if (expect_fail) { 215 EXPECT_CALL(host_session_event_handler_, 216 OnSessionStateChange(Session::FAILED)) 217 .Times(1); 218 } else { 219 EXPECT_CALL(host_session_event_handler_, 220 OnSessionStateChange(Session::AUTHENTICATED)) 221 .Times(1); 222 // Expect that the connection will be closed eventually. 223 EXPECT_CALL(host_session_event_handler_, 224 OnSessionStateChange(Session::CLOSED)) 225 .Times(AtMost(1)); 226 } 227 } 228 229 { 230 InSequence dummy; 231 232 EXPECT_CALL(client_session_event_handler_, 233 OnSessionStateChange(Session::CONNECTED)) 234 .Times(AtMost(1)); 235 EXPECT_CALL(client_session_event_handler_, 236 OnSessionStateChange(Session::AUTHENTICATING)) 237 .Times(AtMost(1)); 238 if (expect_fail) { 239 EXPECT_CALL(client_session_event_handler_, 240 OnSessionStateChange(Session::FAILED)) 241 .Times(1); 242 } else { 243 EXPECT_CALL(client_session_event_handler_, 244 OnSessionStateChange(Session::AUTHENTICATED)) 245 .Times(1); 246 // Expect that the connection will be closed eventually. 247 EXPECT_CALL(client_session_event_handler_, 248 OnSessionStateChange(Session::CLOSED)) 249 .Times(AtMost(1)); 250 } 251 } 252 253 scoped_ptr<Authenticator> authenticator(new FakeAuthenticator( 254 FakeAuthenticator::CLIENT, auth_round_trips, auth_action, true)); 255 256 client_session_ = client_server_->Connect( 257 kHostJid, authenticator.Pass(), 258 CandidateSessionConfig::CreateDefault()); 259 client_session_->SetEventHandler(&client_session_event_handler_); 260 261 base::RunLoop().RunUntilIdle(); 262 } 263 264 void CreateChannel() { 265 client_session_->GetTransportChannelFactory()->CreateStreamChannel( 266 kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated, 267 base::Unretained(this))); 268 host_session_->GetTransportChannelFactory()->CreateStreamChannel( 269 kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated, 270 base::Unretained(this))); 271 272 int counter = 2; 273 ExpectRouteChange(kChannelName); 274 EXPECT_CALL(client_channel_callback_, OnDone(_)) 275 .WillOnce(QuitThreadOnCounter(&counter)); 276 EXPECT_CALL(host_channel_callback_, OnDone(_)) 277 .WillOnce(QuitThreadOnCounter(&counter)); 278 message_loop_->Run(); 279 280 EXPECT_TRUE(client_socket_.get()); 281 EXPECT_TRUE(host_socket_.get()); 282 } 283 284 void ExpectRouteChange(const std::string& channel_name) { 285 EXPECT_CALL(host_session_event_handler_, 286 OnSessionRouteChange(channel_name, _)) 287 .Times(AtLeast(1)); 288 EXPECT_CALL(client_session_event_handler_, 289 OnSessionRouteChange(channel_name, _)) 290 .Times(AtLeast(1)); 291 } 292 293 scoped_ptr<base::MessageLoopForIO> message_loop_; 294 295 scoped_ptr<FakeSignalStrategy> host_signal_strategy_; 296 scoped_ptr<FakeSignalStrategy> client_signal_strategy_; 297 298 scoped_ptr<JingleSessionManager> host_server_; 299 MockSessionManagerListener host_server_listener_; 300 scoped_ptr<JingleSessionManager> client_server_; 301 MockSessionManagerListener client_server_listener_; 302 303 scoped_ptr<Session> host_session_; 304 MockSessionEventHandler host_session_event_handler_; 305 scoped_ptr<Session> client_session_; 306 MockSessionEventHandler client_session_event_handler_; 307 308 MockStreamChannelCallback client_channel_callback_; 309 MockStreamChannelCallback host_channel_callback_; 310 311 scoped_ptr<net::StreamSocket> client_socket_; 312 scoped_ptr<net::StreamSocket> host_socket_; 313}; 314 315 316// Verify that we can create and destroy session managers without a 317// connection. 318TEST_F(JingleSessionTest, CreateAndDestoy) { 319 CreateSessionManagers(1, FakeAuthenticator::ACCEPT); 320} 321 322// Verify that an incoming session can be rejected, and that the 323// status of the connection is set to FAILED in this case. 324TEST_F(JingleSessionTest, RejectConnection) { 325 CreateSessionManagers(1, FakeAuthenticator::ACCEPT); 326 327 // Reject incoming session. 328 EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) 329 .WillOnce(SetArgumentPointee<1>(protocol::SessionManager::DECLINE)); 330 331 { 332 InSequence dummy; 333 EXPECT_CALL(client_session_event_handler_, 334 OnSessionStateChange(Session::FAILED)) 335 .Times(1); 336 } 337 338 scoped_ptr<Authenticator> authenticator(new FakeAuthenticator( 339 FakeAuthenticator::CLIENT, 1, FakeAuthenticator::ACCEPT, true)); 340 client_session_ = client_server_->Connect( 341 kHostJid, authenticator.Pass(), CandidateSessionConfig::CreateDefault()); 342 client_session_->SetEventHandler(&client_session_event_handler_); 343 344 base::RunLoop().RunUntilIdle(); 345} 346 347// Verify that we can connect two endpoints with single-step authentication. 348TEST_F(JingleSessionTest, Connect) { 349 CreateSessionManagers(1, FakeAuthenticator::ACCEPT); 350 InitiateConnection(1, FakeAuthenticator::ACCEPT, false); 351 352 // Verify that the client specified correct initiator value. 353 ASSERT_GT(host_signal_strategy_->received_messages().size(), 0U); 354 const buzz::XmlElement* initiate_xml = 355 host_signal_strategy_->received_messages().front(); 356 const buzz::XmlElement* jingle_element = 357 initiate_xml->FirstNamed(buzz::QName(kJingleNamespace, "jingle")); 358 ASSERT_TRUE(jingle_element); 359 ASSERT_EQ(kClientJid, 360 jingle_element->Attr(buzz::QName(std::string(), "initiator"))); 361} 362 363// Verify that we can connect two endpoints with multi-step authentication. 364TEST_F(JingleSessionTest, ConnectWithMultistep) { 365 CreateSessionManagers(3, FakeAuthenticator::ACCEPT); 366 InitiateConnection(3, FakeAuthenticator::ACCEPT, false); 367} 368 369// Verify that connection is terminated when single-step auth fails. 370TEST_F(JingleSessionTest, ConnectWithBadAuth) { 371 CreateSessionManagers(1, FakeAuthenticator::REJECT); 372 InitiateConnection(1, FakeAuthenticator::ACCEPT, true); 373} 374 375// Verify that connection is terminated when multi-step auth fails. 376TEST_F(JingleSessionTest, ConnectWithBadMultistepAuth) { 377 CreateSessionManagers(3, FakeAuthenticator::REJECT); 378 InitiateConnection(3, FakeAuthenticator::ACCEPT, true); 379} 380 381// Verify that data can be sent over stream channel. 382TEST_F(JingleSessionTest, TestStreamChannel) { 383 CreateSessionManagers(1, FakeAuthenticator::ACCEPT); 384 ASSERT_NO_FATAL_FAILURE( 385 InitiateConnection(1, FakeAuthenticator::ACCEPT, false)); 386 387 ASSERT_NO_FATAL_FAILURE(CreateChannel()); 388 389 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 390 kMessageSize, kMessages); 391 tester.Start(); 392 message_loop_->Run(); 393 tester.CheckResults(); 394} 395 396TEST_F(JingleSessionTest, DeleteSessionOnIncomingConnection) { 397 CreateSessionManagers(3, FakeAuthenticator::ACCEPT); 398 399 EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) 400 .WillOnce(DoAll( 401 WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)), 402 SetArgumentPointee<1>(protocol::SessionManager::ACCEPT))); 403 404 EXPECT_CALL(host_session_event_handler_, 405 OnSessionStateChange(Session::CONNECTED)) 406 .Times(AtMost(1)); 407 408 EXPECT_CALL(host_session_event_handler_, 409 OnSessionStateChange(Session::AUTHENTICATING)) 410 .WillOnce(InvokeWithoutArgs(this, &JingleSessionTest::DeleteSession)); 411 412 scoped_ptr<Authenticator> authenticator(new FakeAuthenticator( 413 FakeAuthenticator::CLIENT, 3, FakeAuthenticator::ACCEPT, true)); 414 415 client_session_ = client_server_->Connect( 416 kHostJid, authenticator.Pass(), 417 CandidateSessionConfig::CreateDefault()); 418 419 base::RunLoop().RunUntilIdle(); 420} 421 422TEST_F(JingleSessionTest, DeleteSessionOnAuth) { 423 // Same as the previous test, but set messages_till_started to 2 in 424 // CreateSessionManagers so that the session will goes into the 425 // AUTHENTICATING state after two message exchanges. 426 CreateSessionManagers(3, 2, FakeAuthenticator::ACCEPT); 427 428 EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) 429 .WillOnce(DoAll( 430 WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)), 431 SetArgumentPointee<1>(protocol::SessionManager::ACCEPT))); 432 433 EXPECT_CALL(host_session_event_handler_, 434 OnSessionStateChange(Session::CONNECTED)) 435 .Times(AtMost(1)); 436 437 EXPECT_CALL(host_session_event_handler_, 438 OnSessionStateChange(Session::AUTHENTICATING)) 439 .WillOnce(InvokeWithoutArgs(this, &JingleSessionTest::DeleteSession)); 440 441 scoped_ptr<Authenticator> authenticator(new FakeAuthenticator( 442 FakeAuthenticator::CLIENT, 3, FakeAuthenticator::ACCEPT, true)); 443 444 client_session_ = client_server_->Connect( 445 kHostJid, authenticator.Pass(), 446 CandidateSessionConfig::CreateDefault()); 447 base::RunLoop().RunUntilIdle(); 448} 449 450// Verify that data can be sent over a multiplexed channel. 451TEST_F(JingleSessionTest, TestMuxStreamChannel) { 452 CreateSessionManagers(1, FakeAuthenticator::ACCEPT); 453 ASSERT_NO_FATAL_FAILURE( 454 InitiateConnection(1, FakeAuthenticator::ACCEPT, false)); 455 456 client_session_->GetMultiplexedChannelFactory()->CreateStreamChannel( 457 kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated, 458 base::Unretained(this))); 459 host_session_->GetMultiplexedChannelFactory()->CreateStreamChannel( 460 kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated, 461 base::Unretained(this))); 462 463 int counter = 2; 464 ExpectRouteChange("mux"); 465 EXPECT_CALL(client_channel_callback_, OnDone(_)) 466 .WillOnce(QuitThreadOnCounter(&counter)); 467 EXPECT_CALL(host_channel_callback_, OnDone(_)) 468 .WillOnce(QuitThreadOnCounter(&counter)); 469 message_loop_->Run(); 470 471 EXPECT_TRUE(client_socket_.get()); 472 EXPECT_TRUE(host_socket_.get()); 473 474 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 475 kMessageSize, kMessages); 476 tester.Start(); 477 message_loop_->Run(); 478 tester.CheckResults(); 479} 480 481// Verify that we can connect channels with multistep auth. 482TEST_F(JingleSessionTest, TestMultistepAuthStreamChannel) { 483 CreateSessionManagers(3, FakeAuthenticator::ACCEPT); 484 ASSERT_NO_FATAL_FAILURE( 485 InitiateConnection(3, FakeAuthenticator::ACCEPT, false)); 486 487 ASSERT_NO_FATAL_FAILURE(CreateChannel()); 488 489 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 490 kMessageSize, kMessages); 491 tester.Start(); 492 message_loop_->Run(); 493 tester.CheckResults(); 494} 495 496// Verify that we shutdown properly when channel authentication fails. 497TEST_F(JingleSessionTest, TestFailedChannelAuth) { 498 CreateSessionManagers(1, FakeAuthenticator::REJECT_CHANNEL); 499 ASSERT_NO_FATAL_FAILURE( 500 InitiateConnection(1, FakeAuthenticator::ACCEPT, false)); 501 502 client_session_->GetTransportChannelFactory()->CreateStreamChannel( 503 kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated, 504 base::Unretained(this))); 505 host_session_->GetTransportChannelFactory()->CreateStreamChannel( 506 kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated, 507 base::Unretained(this))); 508 509 // Terminate the message loop when we get rejection notification 510 // from the host. 511 EXPECT_CALL(host_channel_callback_, OnDone(NULL)) 512 .WillOnce(QuitThread()); 513 EXPECT_CALL(client_channel_callback_, OnDone(_)) 514 .Times(AtMost(1)); 515 ExpectRouteChange(kChannelName); 516 517 message_loop_->Run(); 518 519 EXPECT_TRUE(!host_socket_.get()); 520} 521 522} // namespace protocol 523} // namespace remoting 524