Home | History | Annotate | Download | only in host
      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::Session;
     32 using ::remoting::protocol::SessionConfig;
     33 
     34 using testing::_;
     35 using testing::AnyNumber;
     36 using testing::AtLeast;
     37 using testing::AtMost;
     38 using testing::CreateFunctor;
     39 using testing::DeleteArg;
     40 using testing::DoAll;
     41 using testing::Expectation;
     42 using testing::InSequence;
     43 using testing::Invoke;
     44 using testing::InvokeArgument;
     45 using testing::InvokeWithoutArgs;
     46 using testing::Return;
     47 using testing::ReturnRef;
     48 using testing::SaveArg;
     49 using testing::Sequence;
     50 
     51 namespace remoting {
     52 
     53 namespace {
     54 
     55 void 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.
     61 ACTION(RunDoneTask) {
     62   arg1.Run();
     63 }
     64 
     65 }  // namespace
     66 
     67 class 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 
    460 TEST_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 
    469 TEST_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 
    484 TEST_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 
    499 TEST_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 
    510 TEST_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 
    536 TEST_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 
    560 TEST_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 
    570 TEST_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 
    587 TEST_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 
    608 TEST_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 
    634 TEST_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 
    674 TEST_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 
    696 TEST_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