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/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