Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / remoting / host / chromoting_host_unittest.cc
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