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