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 "base/bind.h" 6 #include "base/bind_helpers.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/message_loop/message_loop_proxy.h" 9 #include "remoting/base/auto_thread_task_runner.h" 10 #include "remoting/host/audio_capturer.h" 11 #include "remoting/host/chromoting_host.h" 12 #include "remoting/host/chromoting_host_context.h" 13 #include "remoting/host/desktop_environment.h" 14 #include "remoting/host/fake_desktop_capturer.h" 15 #include "remoting/host/fake_mouse_cursor_monitor.h" 16 #include "remoting/host/host_mock_objects.h" 17 #include "remoting/proto/video.pb.h" 18 #include "remoting/protocol/errors.h" 19 #include "remoting/protocol/protocol_mock_objects.h" 20 #include "remoting/protocol/session_config.h" 21 #include "remoting/signaling/mock_signal_strategy.h" 22 #include "testing/gmock/include/gmock/gmock.h" 23 #include "testing/gmock_mutant.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 using ::remoting::protocol::MockClientStub; 27 using ::remoting::protocol::MockConnectionToClient; 28 using ::remoting::protocol::MockConnectionToClientEventHandler; 29 using ::remoting::protocol::MockHostStub; 30 using ::remoting::protocol::MockSession; 31 using ::remoting::protocol::MockVideoStub; 32 using ::remoting::protocol::Session; 33 using ::remoting::protocol::SessionConfig; 34 35 using testing::_; 36 using testing::AnyNumber; 37 using testing::AtLeast; 38 using testing::AtMost; 39 using testing::CreateFunctor; 40 using testing::DeleteArg; 41 using testing::DoAll; 42 using testing::Expectation; 43 using testing::InSequence; 44 using testing::Invoke; 45 using testing::InvokeArgument; 46 using testing::InvokeWithoutArgs; 47 using testing::Return; 48 using testing::ReturnRef; 49 using testing::SaveArg; 50 using testing::Sequence; 51 52 namespace remoting { 53 54 namespace { 55 56 void PostQuitTask(base::MessageLoop* message_loop) { 57 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); 58 } 59 60 // Run the task and delete it afterwards. This action is used to deal with 61 // done callbacks. 62 ACTION(RunDoneTask) { 63 arg1.Run(); 64 } 65 66 } // namespace 67 68 class ChromotingHostTest : public testing::Test { 69 public: 70 ChromotingHostTest() { 71 } 72 73 virtual void SetUp() OVERRIDE { 74 task_runner_ = new AutoThreadTaskRunner( 75 message_loop_.message_loop_proxy(), 76 base::Bind(&ChromotingHostTest::QuitMainMessageLoop, 77 base::Unretained(this))); 78 79 desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory()); 80 EXPECT_CALL(*desktop_environment_factory_, CreatePtr()) 81 .Times(AnyNumber()) 82 .WillRepeatedly(Invoke(this, 83 &ChromotingHostTest::CreateDesktopEnvironment)); 84 EXPECT_CALL(*desktop_environment_factory_, SupportsAudioCapture()) 85 .Times(AnyNumber()) 86 .WillRepeatedly(Return(false)); 87 88 session_manager_ = new protocol::MockSessionManager(); 89 90 host_.reset(new ChromotingHost( 91 &signal_strategy_, 92 desktop_environment_factory_.get(), 93 scoped_ptr<protocol::SessionManager>(session_manager_), 94 task_runner_, // Audio 95 task_runner_, // Input 96 task_runner_, // Video capture 97 task_runner_, // Video encode 98 task_runner_, // Network 99 task_runner_)); // UI 100 host_->AddStatusObserver(&host_status_observer_); 101 102 xmpp_login_ = "host@domain"; 103 session1_ = new MockSession(); 104 session2_ = new MockSession(); 105 session_unowned1_.reset(new MockSession()); 106 session_unowned2_.reset(new MockSession()); 107 session_config1_ = SessionConfig::ForTest(); 108 session_jid1_ = "user@domain/rest-of-jid"; 109 session_config2_ = SessionConfig::ForTest(); 110 session_jid2_ = "user2@domain/rest-of-jid"; 111 session_unowned_config1_ = SessionConfig::ForTest(); 112 session_unowned_jid1_ = "user3@doman/rest-of-jid"; 113 session_unowned_config2_ = SessionConfig::ForTest(); 114 session_unowned_jid2_ = "user4@doman/rest-of-jid"; 115 116 EXPECT_CALL(*session1_, jid()) 117 .WillRepeatedly(ReturnRef(session_jid1_)); 118 EXPECT_CALL(*session2_, jid()) 119 .WillRepeatedly(ReturnRef(session_jid2_)); 120 EXPECT_CALL(*session_unowned1_, jid()) 121 .WillRepeatedly(ReturnRef(session_unowned_jid1_)); 122 EXPECT_CALL(*session_unowned2_, jid()) 123 .WillRepeatedly(ReturnRef(session_unowned_jid2_)); 124 EXPECT_CALL(*session1_, SetEventHandler(_)) 125 .Times(AnyNumber()); 126 EXPECT_CALL(*session2_, SetEventHandler(_)) 127 .Times(AnyNumber()); 128 EXPECT_CALL(*session_unowned1_, SetEventHandler(_)) 129 .Times(AnyNumber()) 130 .WillRepeatedly(SaveArg<0>(&session_unowned1_event_handler_)); 131 EXPECT_CALL(*session_unowned2_, SetEventHandler(_)) 132 .Times(AnyNumber()) 133 .WillRepeatedly(SaveArg<0>(&session_unowned2_event_handler_)); 134 EXPECT_CALL(*session1_, config()) 135 .WillRepeatedly(ReturnRef(session_config1_)); 136 EXPECT_CALL(*session2_, config()) 137 .WillRepeatedly(ReturnRef(session_config2_)); 138 139 owned_connection1_.reset(new MockConnectionToClient(session1_, 140 &host_stub1_)); 141 connection1_ = owned_connection1_.get(); 142 owned_connection2_.reset(new MockConnectionToClient(session2_, 143 &host_stub2_)); 144 connection2_ = owned_connection2_.get(); 145 146 ON_CALL(video_stub1_, ProcessVideoPacketPtr(_, _)) 147 .WillByDefault(DeleteArg<0>()); 148 ON_CALL(video_stub2_, ProcessVideoPacketPtr(_, _)) 149 .WillByDefault(DeleteArg<0>()); 150 ON_CALL(*connection1_, video_stub()) 151 .WillByDefault(Return(&video_stub1_)); 152 ON_CALL(*connection1_, client_stub()) 153 .WillByDefault(Return(&client_stub1_)); 154 ON_CALL(*connection1_, session()) 155 .WillByDefault(Return(session1_)); 156 ON_CALL(*connection2_, video_stub()) 157 .WillByDefault(Return(&video_stub2_)); 158 ON_CALL(*connection2_, client_stub()) 159 .WillByDefault(Return(&client_stub2_)); 160 ON_CALL(*connection2_, session()) 161 .WillByDefault(Return(session2_)); 162 EXPECT_CALL(*connection1_, video_stub()) 163 .Times(AnyNumber()); 164 EXPECT_CALL(*connection1_, client_stub()) 165 .Times(AnyNumber()); 166 EXPECT_CALL(*connection1_, session()) 167 .Times(AnyNumber()); 168 EXPECT_CALL(*connection2_, video_stub()) 169 .Times(AnyNumber()); 170 EXPECT_CALL(*connection2_, client_stub()) 171 .Times(AnyNumber()); 172 EXPECT_CALL(*connection2_, session()) 173 .Times(AnyNumber()); 174 175 empty_candidate_config_ = 176 protocol::CandidateSessionConfig::CreateEmpty(); 177 default_candidate_config_ = 178 protocol::CandidateSessionConfig::CreateDefault(); 179 } 180 181 // Helper method to pretend a client is connected to ChromotingHost. 182 void SimulateClientConnection(int connection_index, bool authenticate, 183 bool reject) { 184 scoped_ptr<protocol::ConnectionToClient> connection = 185 ((connection_index == 0) ? owned_connection1_ : owned_connection2_). 186 PassAs<protocol::ConnectionToClient>(); 187 protocol::ConnectionToClient* connection_ptr = connection.get(); 188 scoped_ptr<ClientSession> client(new ClientSession( 189 host_.get(), 190 task_runner_, // Audio 191 task_runner_, // Input 192 task_runner_, // Video capture 193 task_runner_, // Video encode 194 task_runner_, // Network 195 task_runner_, // UI 196 connection.Pass(), 197 desktop_environment_factory_.get(), 198 base::TimeDelta(), 199 NULL, 200 std::vector<HostExtension*>())); 201 202 connection_ptr->set_host_stub(client.get()); 203 204 if (authenticate) { 205 task_runner_->PostTask( 206 FROM_HERE, 207 base::Bind(&ClientSession::OnConnectionAuthenticated, 208 base::Unretained(client.get()), connection_ptr)); 209 if (!reject) { 210 task_runner_->PostTask( 211 FROM_HERE, 212 base::Bind(&ClientSession::OnConnectionChannelsConnected, 213 base::Unretained(client.get()), connection_ptr)); 214 } 215 } else { 216 task_runner_->PostTask( 217 FROM_HERE, base::Bind(&ClientSession::OnConnectionClosed, 218 base::Unretained(client.get()), connection_ptr, 219 protocol::AUTHENTICATION_FAILED)); 220 } 221 222 get_client(connection_index) = client.get(); 223 224 // |host| is responsible for deleting |client| from now on. 225 host_->clients_.push_back(client.release()); 226 } 227 228 virtual void TearDown() OVERRIDE { 229 // Make sure that the host has been properly deleted. 230 DCHECK(host_.get() == NULL); 231 } 232 233 // Change the session route for |client1_|. 234 void ChangeSessionRoute(const std::string& channel_name, 235 const protocol::TransportRoute& route) { 236 host_->OnSessionRouteChange(get_client(0), channel_name, route); 237 } 238 239 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock 240 // DesktopEnvironmentFactory::Create(). 241 DesktopEnvironment* CreateDesktopEnvironment() { 242 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment(); 243 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr()) 244 .Times(0); 245 EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr()) 246 .Times(AtMost(1)) 247 .WillOnce(Invoke(this, &ChromotingHostTest::CreateInputInjector)); 248 EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr()) 249 .Times(AtMost(1)); 250 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr()) 251 .Times(AtMost(1)) 252 .WillOnce(Invoke(this, &ChromotingHostTest::CreateVideoCapturer)); 253 EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr()) 254 .Times(AtMost(1)) 255 .WillOnce(Invoke(this, &ChromotingHostTest::CreateMouseCursorMonitor)); 256 EXPECT_CALL(*desktop_environment, GetCapabilities()) 257 .Times(AtMost(1)); 258 EXPECT_CALL(*desktop_environment, SetCapabilities(_)) 259 .Times(AtMost(1)); 260 261 return desktop_environment; 262 } 263 264 // Creates a dummy InputInjector, to mock 265 // DesktopEnvironment::CreateInputInjector(). 266 InputInjector* CreateInputInjector() { 267 MockInputInjector* input_injector = new MockInputInjector(); 268 EXPECT_CALL(*input_injector, StartPtr(_)); 269 return input_injector; 270 } 271 272 // Creates a fake webrtc::DesktopCapturer, to mock 273 // DesktopEnvironment::CreateVideoCapturer(). 274 webrtc::DesktopCapturer* CreateVideoCapturer() { 275 return new FakeDesktopCapturer(); 276 } 277 278 // Creates a MockMouseCursorMonitor, to mock 279 // DesktopEnvironment::CreateMouseCursorMonitor(). 280 webrtc::MouseCursorMonitor* CreateMouseCursorMonitor() { 281 return new FakeMouseCursorMonitor(); 282 } 283 284 void DisconnectAllClients() { 285 host_->DisconnectAllClients(); 286 } 287 288 // Helper method to disconnect client 1 from the host. 289 void DisconnectClient1() { 290 NotifyClientSessionClosed(0); 291 } 292 293 // Notify |host_| that the authenticating client has been rejected. 294 void RejectAuthenticatingClient() { 295 host_->RejectAuthenticatingClient(); 296 } 297 298 // Notify |host_| that a client session has closed. 299 void NotifyClientSessionClosed(int connection_index) { 300 get_client(connection_index)->OnConnectionClosed( 301 get_connection(connection_index), protocol::OK); 302 } 303 304 void NotifyConnectionClosed1() { 305 if (session_unowned1_event_handler_) { 306 session_unowned1_event_handler_->OnSessionStateChange(Session::CLOSED); 307 } 308 } 309 310 void NotifyConnectionClosed2() { 311 if (session_unowned2_event_handler_) { 312 session_unowned2_event_handler_->OnSessionStateChange(Session::CLOSED); 313 } 314 } 315 316 void ShutdownHost() { 317 task_runner_->PostTask( 318 FROM_HERE, 319 base::Bind(&ChromotingHostTest::StopAndReleaseTaskRunner, 320 base::Unretained(this))); 321 } 322 323 void StopAndReleaseTaskRunner() { 324 host_.reset(); 325 task_runner_ = NULL; 326 desktop_environment_factory_.reset(); 327 } 328 329 void QuitMainMessageLoop() { 330 PostQuitTask(&message_loop_); 331 } 332 333 // Expect the host and session manager to start, and return the expectation 334 // that the session manager has started. 335 Expectation ExpectHostAndSessionManagerStart() { 336 EXPECT_CALL(host_status_observer_, OnStart(xmpp_login_)); 337 return EXPECT_CALL(*session_manager_, Init(_, host_.get())); 338 } 339 340 // Expect a client to connect. 341 // Return an expectation that a session has started, and that the first 342 // video packet has been sent to the client. 343 // Do |action| when that happens. 344 template <class A> 345 Expectation ExpectClientConnected(int connection_index, A action) { 346 const std::string& session_jid = get_session_jid(connection_index); 347 MockVideoStub& video_stub = get_video_stub(connection_index); 348 349 Expectation client_authenticated = 350 EXPECT_CALL(host_status_observer_, OnClientAuthenticated(session_jid)); 351 EXPECT_CALL(host_status_observer_, OnClientConnected(session_jid)) 352 .After(client_authenticated); 353 Expectation video_packet_sent = 354 EXPECT_CALL(video_stub, ProcessVideoPacketPtr(_, _)) 355 .After(client_authenticated) 356 .WillOnce(DoAll( 357 action, 358 RunDoneTask())) 359 .RetiresOnSaturation(); 360 EXPECT_CALL(video_stub, ProcessVideoPacketPtr(_, _)) 361 .Times(AnyNumber()) 362 .After(video_packet_sent) 363 .WillRepeatedly(RunDoneTask()); 364 return video_packet_sent; 365 } 366 367 // Return an expectation that a client will disconnect after a given 368 // expectation. The given action will be done after the event executor is 369 // notified that the session has finished. 370 template <class A> 371 Expectation ExpectClientDisconnected(int connection_index, 372 bool expect_host_status_change, 373 Expectation after, 374 A action) { 375 MockConnectionToClient* connection = get_connection(connection_index); 376 377 Expectation client_disconnected = 378 EXPECT_CALL(*connection, Disconnect()) 379 .After(after) 380 .WillOnce(InvokeWithoutArgs(CreateFunctor( 381 this, &ChromotingHostTest::NotifyClientSessionClosed, 382 connection_index))) 383 .RetiresOnSaturation(); 384 ExpectClientDisconnectEffects(connection_index, 385 expect_host_status_change, 386 after, 387 action); 388 return client_disconnected; 389 } 390 391 // Expect the side-effects of a client disconnection, after a given 392 // expectation. The given action will be done after the event executor is 393 // notifed that the session has finished. 394 template <class A> 395 void ExpectClientDisconnectEffects(int connection_index, 396 bool expect_host_status_change, 397 Expectation after, 398 A action) { 399 const std::string& session_jid = get_session_jid(connection_index); 400 401 if (expect_host_status_change) { 402 EXPECT_CALL(host_status_observer_, OnClientDisconnected(session_jid)) 403 .After(after) 404 .WillOnce(action) 405 .RetiresOnSaturation(); 406 } 407 } 408 409 protected: 410 base::MessageLoop message_loop_; 411 scoped_refptr<AutoThreadTaskRunner> task_runner_; 412 MockConnectionToClientEventHandler handler_; 413 MockSignalStrategy signal_strategy_; 414 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_; 415 scoped_ptr<ChromotingHost> host_; 416 MockHostStatusObserver host_status_observer_; 417 protocol::MockSessionManager* session_manager_; 418 std::string xmpp_login_; 419 MockConnectionToClient* connection1_; 420 scoped_ptr<MockConnectionToClient> owned_connection1_; 421 ClientSession* client1_; 422 std::string session_jid1_; 423 MockSession* session1_; // Owned by |connection_|. 424 SessionConfig session_config1_; 425 MockVideoStub video_stub1_; 426 MockClientStub client_stub1_; 427 MockHostStub host_stub1_; 428 MockConnectionToClient* connection2_; 429 scoped_ptr<MockConnectionToClient> owned_connection2_; 430 ClientSession* client2_; 431 std::string session_jid2_; 432 MockSession* session2_; // Owned by |connection2_|. 433 SessionConfig session_config2_; 434 MockVideoStub video_stub2_; 435 MockClientStub client_stub2_; 436 MockHostStub host_stub2_; 437 scoped_ptr<MockSession> session_unowned1_; // Not owned by a connection. 438 SessionConfig session_unowned_config1_; 439 std::string session_unowned_jid1_; 440 scoped_ptr<MockSession> session_unowned2_; // Not owned by a connection. 441 SessionConfig session_unowned_config2_; 442 std::string session_unowned_jid2_; 443 protocol::Session::EventHandler* session_unowned1_event_handler_; 444 protocol::Session::EventHandler* session_unowned2_event_handler_; 445 scoped_ptr<protocol::CandidateSessionConfig> empty_candidate_config_; 446 scoped_ptr<protocol::CandidateSessionConfig> default_candidate_config_; 447 448 MockConnectionToClient*& get_connection(int connection_index) { 449 return (connection_index == 0) ? connection1_ : connection2_; 450 } 451 452 // Returns the cached client pointers client1_ or client2_. 453 ClientSession*& get_client(int connection_index) { 454 return (connection_index == 0) ? client1_ : client2_; 455 } 456 457 // Returns the list of clients of the host_. 458 std::list<ClientSession*>& get_clients_from_host() { 459 return host_->clients_; 460 } 461 462 const std::string& get_session_jid(int connection_index) { 463 return (connection_index == 0) ? session_jid1_ : session_jid2_; 464 } 465 466 MockVideoStub& get_video_stub(int connection_index) { 467 return (connection_index == 0) ? video_stub1_ : video_stub2_; 468 } 469 }; 470 471 TEST_F(ChromotingHostTest, StartAndShutdown) { 472 Expectation start = ExpectHostAndSessionManagerStart(); 473 EXPECT_CALL(host_status_observer_, OnShutdown()).After(start); 474 475 host_->Start(xmpp_login_); 476 ShutdownHost(); 477 message_loop_.Run(); 478 } 479 480 TEST_F(ChromotingHostTest, Connect) { 481 ExpectHostAndSessionManagerStart(); 482 483 // Shut down the host when the first video packet is received. 484 Expectation video_packet_sent = ExpectClientConnected( 485 0, InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 486 Expectation client_disconnected = ExpectClientDisconnected( 487 0, true, video_packet_sent, InvokeWithoutArgs(base::DoNothing)); 488 EXPECT_CALL(host_status_observer_, OnShutdown()).After(client_disconnected); 489 490 host_->Start(xmpp_login_); 491 SimulateClientConnection(0, true, false); 492 message_loop_.Run(); 493 } 494 495 TEST_F(ChromotingHostTest, RejectAuthenticatingClient) { 496 Expectation start = ExpectHostAndSessionManagerStart(); 497 EXPECT_CALL(host_status_observer_, OnClientAuthenticated(session_jid1_)) 498 .WillOnce(InvokeWithoutArgs( 499 this, &ChromotingHostTest::RejectAuthenticatingClient)); 500 ExpectClientDisconnected( 501 0, true, start, 502 InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 503 EXPECT_CALL(host_status_observer_, OnShutdown()); 504 505 host_->Start(xmpp_login_); 506 SimulateClientConnection(0, true, true); 507 message_loop_.Run(); 508 } 509 510 TEST_F(ChromotingHostTest, AuthenticationFailed) { 511 ExpectHostAndSessionManagerStart(); 512 EXPECT_CALL(host_status_observer_, OnAccessDenied(session_jid1_)) 513 .WillOnce(InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 514 EXPECT_CALL(host_status_observer_, OnShutdown()); 515 516 host_->Start(xmpp_login_); 517 SimulateClientConnection(0, false, false); 518 message_loop_.Run(); 519 } 520 521 TEST_F(ChromotingHostTest, Reconnect) { 522 ExpectHostAndSessionManagerStart(); 523 524 // When a video packet is received on the first connection, disconnect it, 525 // then quit the message loop. 526 Expectation video_packet_sent1 = ExpectClientConnected(0, DoAll( 527 InvokeWithoutArgs(this, &ChromotingHostTest::DisconnectClient1), 528 InvokeWithoutArgs(this, &ChromotingHostTest::QuitMainMessageLoop))); 529 ExpectClientDisconnectEffects( 530 0, true, video_packet_sent1, InvokeWithoutArgs(base::DoNothing)); 531 532 // When a video packet is received on the second connection, shut down the 533 // host. 534 Expectation video_packet_sent2 = ExpectClientConnected( 535 1, InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 536 Expectation client_disconnected2 = ExpectClientDisconnected( 537 1, true, video_packet_sent2, InvokeWithoutArgs(base::DoNothing)); 538 EXPECT_CALL(host_status_observer_, OnShutdown()).After(client_disconnected2); 539 540 host_->Start(xmpp_login_); 541 SimulateClientConnection(0, true, false); 542 message_loop_.Run(); 543 SimulateClientConnection(1, true, false); 544 message_loop_.Run(); 545 } 546 547 TEST_F(ChromotingHostTest, ConnectWhenAnotherClientIsConnected) { 548 ExpectHostAndSessionManagerStart(); 549 550 // When a video packet is received, connect the second connection. 551 // This should disconnect the first connection. 552 Expectation video_packet_sent1 = ExpectClientConnected( 553 0, 554 InvokeWithoutArgs( 555 CreateFunctor( 556 this, 557 &ChromotingHostTest::SimulateClientConnection, 1, true, false))); 558 ExpectClientDisconnected( 559 0, true, video_packet_sent1, InvokeWithoutArgs(base::DoNothing)); 560 Expectation video_packet_sent2 = ExpectClientConnected( 561 1, InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 562 Expectation client_disconnected2 = ExpectClientDisconnected( 563 1, true, video_packet_sent2, InvokeWithoutArgs(base::DoNothing)); 564 EXPECT_CALL(host_status_observer_, OnShutdown()).After(client_disconnected2); 565 566 host_->Start(xmpp_login_); 567 SimulateClientConnection(0, true, false); 568 message_loop_.Run(); 569 } 570 571 TEST_F(ChromotingHostTest, IncomingSessionDeclined) { 572 protocol::SessionManager::IncomingSessionResponse response = 573 protocol::SessionManager::ACCEPT; 574 host_->OnIncomingSession(session1_, &response); 575 EXPECT_EQ(protocol::SessionManager::DECLINE, response); 576 577 ShutdownHost(); 578 message_loop_.Run(); 579 } 580 581 TEST_F(ChromotingHostTest, IncomingSessionIncompatible) { 582 ExpectHostAndSessionManagerStart(); 583 EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce(Return( 584 empty_candidate_config_.get())); 585 EXPECT_CALL(host_status_observer_, OnShutdown()); 586 587 host_->Start(xmpp_login_); 588 589 protocol::SessionManager::IncomingSessionResponse response = 590 protocol::SessionManager::ACCEPT; 591 host_->OnIncomingSession(session_unowned1_.get(), &response); 592 EXPECT_EQ(protocol::SessionManager::INCOMPATIBLE, response); 593 594 ShutdownHost(); 595 message_loop_.Run(); 596 } 597 598 TEST_F(ChromotingHostTest, IncomingSessionAccepted) { 599 ExpectHostAndSessionManagerStart(); 600 EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce(Return( 601 default_candidate_config_.get())); 602 EXPECT_CALL(*session_unowned1_, set_config(_)); 603 EXPECT_CALL(*session_unowned1_, Close()).WillOnce(InvokeWithoutArgs( 604 this, &ChromotingHostTest::NotifyConnectionClosed1)); 605 EXPECT_CALL(host_status_observer_, OnAccessDenied(_)); 606 EXPECT_CALL(host_status_observer_, OnShutdown()); 607 608 host_->Start(xmpp_login_); 609 610 protocol::SessionManager::IncomingSessionResponse response = 611 protocol::SessionManager::DECLINE; 612 host_->OnIncomingSession(session_unowned1_.release(), &response); 613 EXPECT_EQ(protocol::SessionManager::ACCEPT, response); 614 615 ShutdownHost(); 616 message_loop_.Run(); 617 } 618 619 TEST_F(ChromotingHostTest, LoginBackOffUponConnection) { 620 ExpectHostAndSessionManagerStart(); 621 EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce( 622 Return(default_candidate_config_.get())); 623 EXPECT_CALL(*session_unowned1_, set_config(_)); 624 EXPECT_CALL(*session_unowned1_, Close()).WillOnce( 625 InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed1)); 626 EXPECT_CALL(host_status_observer_, OnAccessDenied(_)); 627 EXPECT_CALL(host_status_observer_, OnShutdown()); 628 629 host_->Start(xmpp_login_); 630 631 protocol::SessionManager::IncomingSessionResponse response = 632 protocol::SessionManager::DECLINE; 633 634 host_->OnIncomingSession(session_unowned1_.release(), &response); 635 EXPECT_EQ(protocol::SessionManager::ACCEPT, response); 636 637 host_->OnSessionAuthenticating(get_clients_from_host().front()); 638 host_->OnIncomingSession(session_unowned2_.get(), &response); 639 EXPECT_EQ(protocol::SessionManager::OVERLOAD, response); 640 641 ShutdownHost(); 642 message_loop_.Run(); 643 } 644 645 TEST_F(ChromotingHostTest, LoginBackOffUponAuthenticating) { 646 Expectation start = ExpectHostAndSessionManagerStart(); 647 EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce( 648 Return(default_candidate_config_.get())); 649 EXPECT_CALL(*session_unowned1_, set_config(_)); 650 EXPECT_CALL(*session_unowned1_, Close()).WillOnce( 651 InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed1)); 652 653 EXPECT_CALL(*session_unowned2_, candidate_config()).WillOnce( 654 Return(default_candidate_config_.get())); 655 EXPECT_CALL(*session_unowned2_, set_config(_)); 656 EXPECT_CALL(*session_unowned2_, Close()).WillOnce( 657 InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed2)); 658 659 EXPECT_CALL(host_status_observer_, OnShutdown()); 660 661 host_->Start(xmpp_login_); 662 663 protocol::SessionManager::IncomingSessionResponse response = 664 protocol::SessionManager::DECLINE; 665 666 host_->OnIncomingSession(session_unowned1_.release(), &response); 667 EXPECT_EQ(protocol::SessionManager::ACCEPT, response); 668 669 host_->OnIncomingSession(session_unowned2_.release(), &response); 670 EXPECT_EQ(protocol::SessionManager::ACCEPT, response); 671 672 // This will set the backoff. 673 host_->OnSessionAuthenticating(get_clients_from_host().front()); 674 675 // This should disconnect client2. 676 host_->OnSessionAuthenticating(get_clients_from_host().back()); 677 678 // Verify that the host only has 1 client at this point. 679 EXPECT_EQ(get_clients_from_host().size(), 1U); 680 681 ShutdownHost(); 682 message_loop_.Run(); 683 } 684 685 TEST_F(ChromotingHostTest, OnSessionRouteChange) { 686 std::string channel_name("ChannelName"); 687 protocol::TransportRoute route; 688 689 ExpectHostAndSessionManagerStart(); 690 Expectation video_packet_sent = ExpectClientConnected( 691 0, InvokeWithoutArgs(CreateFunctor( 692 this, &ChromotingHostTest::ChangeSessionRoute, channel_name, route))); 693 Expectation route_change = 694 EXPECT_CALL(host_status_observer_, OnClientRouteChange( 695 session_jid1_, channel_name, _)) 696 .After(video_packet_sent) 697 .WillOnce(InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 698 ExpectClientDisconnected(0, true, route_change, 699 InvokeWithoutArgs(base::DoNothing)); 700 EXPECT_CALL(host_status_observer_, OnShutdown()); 701 702 host_->Start(xmpp_login_); 703 SimulateClientConnection(0, true, false); 704 message_loop_.Run(); 705 } 706 707 TEST_F(ChromotingHostTest, DisconnectAllClients) { 708 ExpectHostAndSessionManagerStart(); 709 Expectation video_packet_sent = ExpectClientConnected( 710 0, InvokeWithoutArgs(this, &ChromotingHostTest::DisconnectAllClients)); 711 ExpectClientDisconnected(0, true, video_packet_sent, 712 InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); 713 EXPECT_CALL(host_status_observer_, OnShutdown()); 714 715 host_->Start(xmpp_login_); 716 SimulateClientConnection(0, true, false); 717 message_loop_.Run(); 718 } 719 720 } // namespace remoting 721