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