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