blob: 51093b547bcb57a813eea1cf52df72ebd5c34809 [file] [log] [blame]
[email protected]1fdc9df2011-02-23 11:33:591// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]1e72daa2011-01-28 21:25:422// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4ea2c7c2011-03-31 14:20:065#include "base/bind.h"
[email protected]37961b12011-03-30 12:39:006#include "base/scoped_ptr.h"
[email protected]1e72daa2011-01-28 21:25:427#include "base/task.h"
8#include "remoting/host/capturer_fake.h"
9#include "remoting/host/chromoting_host.h"
10#include "remoting/host/chromoting_host_context.h"
[email protected]0a071a32011-02-08 00:18:2411#include "remoting/host/host_mock_objects.h"
[email protected]1e72daa2011-01-28 21:25:4212#include "remoting/host/in_memory_host_config.h"
[email protected]1e72daa2011-01-28 21:25:4213#include "remoting/proto/video.pb.h"
[email protected]0a071a32011-02-08 00:18:2414#include "remoting/protocol/protocol_mock_objects.h"
[email protected]1e72daa2011-01-28 21:25:4215#include "remoting/protocol/session_config.h"
[email protected]44f60762011-03-23 12:13:3516#include "testing/gmock_mutant.h"
[email protected]1e72daa2011-01-28 21:25:4217#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
[email protected]f0a9d1b2011-03-04 21:31:4420using ::remoting::protocol::LocalLoginCredentials;
21using ::remoting::protocol::MockClientStub;
22using ::remoting::protocol::MockConnectionToClient;
23using ::remoting::protocol::MockConnectionToClientEventHandler;
24using ::remoting::protocol::MockHostStub;
[email protected]f0a9d1b2011-03-04 21:31:4425using ::remoting::protocol::MockSession;
26using ::remoting::protocol::MockVideoStub;
27using ::remoting::protocol::SessionConfig;
28
[email protected]1e72daa2011-01-28 21:25:4229using testing::_;
30using testing::AnyNumber;
[email protected]37961b12011-03-30 12:39:0031using testing::AtLeast;
[email protected]44f60762011-03-23 12:13:3532using testing::CreateFunctor;
[email protected]1e72daa2011-01-28 21:25:4233using testing::DeleteArg;
34using testing::DoAll;
35using testing::InSequence;
36using testing::InvokeWithoutArgs;
37using testing::Return;
[email protected]37961b12011-03-30 12:39:0038using testing::Sequence;
[email protected]1e72daa2011-01-28 21:25:4239
40namespace remoting {
41
42namespace {
43
44void PostQuitTask(MessageLoop* message_loop) {
45 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
46}
47
48// Run the task and delete it afterwards. This action is used to deal with
49// done callbacks.
50ACTION(RunDoneTask) {
51 arg1->Run();
52 delete arg1;
53}
54
55ACTION_P(QuitMainMessageLoop, message_loop) {
56 PostQuitTask(message_loop);
57}
58
[email protected]4ea2c7c2011-03-31 14:20:0659void DummyDoneTask() {
60}
61
[email protected]44f60762011-03-23 12:13:3562} // namespace
[email protected]1e72daa2011-01-28 21:25:4263
64class ChromotingHostTest : public testing::Test {
65 public:
66 ChromotingHostTest() {
67 }
68
69 virtual void SetUp() {
70 config_ = new InMemoryHostConfig();
71 ON_CALL(context_, main_message_loop())
72 .WillByDefault(Return(&message_loop_));
73 ON_CALL(context_, encode_message_loop())
74 .WillByDefault(Return(&message_loop_));
75 ON_CALL(context_, network_message_loop())
76 .WillByDefault(Return(&message_loop_));
77 EXPECT_CALL(context_, main_message_loop())
78 .Times(AnyNumber());
79 EXPECT_CALL(context_, encode_message_loop())
80 .Times(AnyNumber());
81 EXPECT_CALL(context_, network_message_loop())
82 .Times(AnyNumber());
83
[email protected]bab76b9b2011-03-29 14:40:2084 Capturer* capturer = new CapturerFake();
[email protected]f0a9d1b2011-03-04 21:31:4485 host_stub_ = new MockHostStub();
[email protected]44f60762011-03-23 12:13:3586 host_stub2_ = new MockHostStub();
[email protected]0b7e4282011-04-04 22:44:1187 event_executor_ = new MockEventExecutor();
88 event_executor2_ = new MockEventExecutor();
[email protected]37961b12011-03-30 12:39:0089 curtain_ = new MockCurtain();
[email protected]1fdc9df2011-02-23 11:33:5990 DesktopEnvironment* desktop =
[email protected]0b7e4282011-04-04 22:44:1191 new DesktopEnvironment(capturer, event_executor_, curtain_);
[email protected]1fdc9df2011-02-23 11:33:5992 host_ = ChromotingHost::Create(&context_, config_, desktop);
[email protected]0b7e4282011-04-04 22:44:1193 credentials_.set_type(protocol::PASSWORD);
94 credentials_.set_username("user");
95 credentials_.set_credential("password");
[email protected]f0a9d1b2011-03-04 21:31:4496 connection_ = new MockConnectionToClient(
[email protected]0b7e4282011-04-04 22:44:1197 &message_loop_, &handler_, host_stub_, event_executor_);
[email protected]44f60762011-03-23 12:13:3598 connection2_ = new MockConnectionToClient(
[email protected]0b7e4282011-04-04 22:44:1199 &message_loop_, &handler_, host_stub2_, event_executor2_);
[email protected]f0a9d1b2011-03-04 21:31:44100 session_ = new MockSession();
[email protected]44f60762011-03-23 12:13:35101 session2_ = new MockSession();
[email protected]f0a9d1b2011-03-04 21:31:44102 session_config_.reset(SessionConfig::CreateDefault());
[email protected]44f60762011-03-23 12:13:35103 session_config2_.reset(SessionConfig::CreateDefault());
[email protected]1e72daa2011-01-28 21:25:42104
[email protected]9cabbaf02011-01-29 00:59:59105 ON_CALL(video_stub_, ProcessVideoPacket(_, _))
106 .WillByDefault(
107 DoAll(DeleteArg<0>(), DeleteArg<1>()));
[email protected]44f60762011-03-23 12:13:35108 ON_CALL(video_stub2_, ProcessVideoPacket(_, _))
109 .WillByDefault(
110 DoAll(DeleteArg<0>(), DeleteArg<1>()));
[email protected]1e72daa2011-01-28 21:25:42111 ON_CALL(*connection_.get(), video_stub())
112 .WillByDefault(Return(&video_stub_));
[email protected]9cabbaf02011-01-29 00:59:59113 ON_CALL(*connection_.get(), client_stub())
114 .WillByDefault(Return(&client_stub_));
[email protected]1e72daa2011-01-28 21:25:42115 ON_CALL(*connection_.get(), session())
116 .WillByDefault(Return(session_));
[email protected]44f60762011-03-23 12:13:35117 ON_CALL(*connection2_.get(), video_stub())
118 .WillByDefault(Return(&video_stub2_));
119 ON_CALL(*connection2_.get(), client_stub())
120 .WillByDefault(Return(&client_stub2_));
121 ON_CALL(*connection2_.get(), session())
122 .WillByDefault(Return(session2_));
[email protected]1e72daa2011-01-28 21:25:42123 ON_CALL(*session_.get(), config())
124 .WillByDefault(Return(session_config_.get()));
[email protected]44f60762011-03-23 12:13:35125 ON_CALL(*session2_.get(), config())
126 .WillByDefault(Return(session_config2_.get()));
[email protected]9cabbaf02011-01-29 00:59:59127 EXPECT_CALL(*connection_.get(), video_stub())
128 .Times(AnyNumber());
129 EXPECT_CALL(*connection_.get(), client_stub())
130 .Times(AnyNumber());
131 EXPECT_CALL(*connection_.get(), session())
132 .Times(AnyNumber());
[email protected]44f60762011-03-23 12:13:35133 EXPECT_CALL(*connection2_.get(), video_stub())
134 .Times(AnyNumber());
135 EXPECT_CALL(*connection2_.get(), client_stub())
136 .Times(AnyNumber());
137 EXPECT_CALL(*connection2_.get(), session())
138 .Times(AnyNumber());
[email protected]9cabbaf02011-01-29 00:59:59139 EXPECT_CALL(*session_.get(), config())
140 .Times(AnyNumber());
[email protected]44f60762011-03-23 12:13:35141 EXPECT_CALL(*session2_.get(), config())
142 .Times(AnyNumber());
[email protected]1e72daa2011-01-28 21:25:42143 }
144
[email protected]44f60762011-03-23 12:13:35145 // Helper method to pretend a client is connected to ChromotingHost.
[email protected]37961b12011-03-30 12:39:00146 void SimulateClientConnection(int connection_index, bool authenticate) {
[email protected]44f60762011-03-23 12:13:35147 scoped_refptr<MockConnectionToClient> connection =
148 (connection_index == 0) ? connection_ : connection2_;
[email protected]0b7e4282011-04-04 22:44:11149
150 MockUserAuthenticator *user_authenticator = new MockUserAuthenticator;
151 EXPECT_CALL(*user_authenticator, Authenticate(_, _))
152 .WillOnce(Return(authenticate));
153
[email protected]4ea2c7c2011-03-31 14:20:06154 scoped_refptr<ClientSession> client = new ClientSession(
155 host_.get(),
[email protected]0b7e4282011-04-04 22:44:11156 user_authenticator,
[email protected]4ea2c7c2011-03-31 14:20:06157 connection,
[email protected]0b7e4282011-04-04 22:44:11158 event_executor_);
[email protected]44f60762011-03-23 12:13:35159 connection->set_host_stub(client.get());
160
[email protected]1e72daa2011-01-28 21:25:42161 context_.network_message_loop()->PostTask(
162 FROM_HERE,
163 NewRunnableMethod(host_.get(),
[email protected]44f60762011-03-23 12:13:35164 &ChromotingHost::AddClient,
165 client));
[email protected]9cabbaf02011-01-29 00:59:59166 context_.network_message_loop()->PostTask(
167 FROM_HERE,
168 NewRunnableMethod(host_.get(),
169 &ChromotingHost::OnClientConnected,
[email protected]44f60762011-03-23 12:13:35170 connection));
[email protected]4ea2c7c2011-03-31 14:20:06171 context_.network_message_loop()->PostTask(
172 FROM_HERE,
173 NewRunnableMethod(client.get(),
174 &ClientSession::BeginSessionRequest,
[email protected]0b7e4282011-04-04 22:44:11175 &credentials_,
[email protected]4ea2c7c2011-03-31 14:20:06176 NewRunnableFunction(&DummyDoneTask)));
[email protected]1e72daa2011-01-28 21:25:42177 }
178
[email protected]44f60762011-03-23 12:13:35179 // Helper method to remove a client connection from ChromotingHost.
[email protected]1e72daa2011-01-28 21:25:42180 void RemoveClientConnection() {
181 context_.network_message_loop()->PostTask(
182 FROM_HERE,
183 NewRunnableMethod(host_.get(),
[email protected]9cabbaf02011-01-29 00:59:59184 &ChromotingHost::OnClientDisconnected,
[email protected]1e72daa2011-01-28 21:25:42185 connection_));
186 }
187
188 protected:
189 MessageLoop message_loop_;
[email protected]f0a9d1b2011-03-04 21:31:44190 MockConnectionToClientEventHandler handler_;
[email protected]1e72daa2011-01-28 21:25:42191 scoped_refptr<ChromotingHost> host_;
192 scoped_refptr<InMemoryHostConfig> config_;
193 MockChromotingHostContext context_;
[email protected]0b7e4282011-04-04 22:44:11194 protocol::LocalLoginCredentials credentials_;
[email protected]f0a9d1b2011-03-04 21:31:44195 scoped_refptr<MockConnectionToClient> connection_;
196 scoped_refptr<MockSession> session_;
197 scoped_ptr<SessionConfig> session_config_;
198 MockVideoStub video_stub_;
199 MockClientStub client_stub_;
200 MockHostStub* host_stub_;
[email protected]0b7e4282011-04-04 22:44:11201 MockEventExecutor* event_executor_;
[email protected]37961b12011-03-30 12:39:00202 MockCurtain* curtain_;
[email protected]44f60762011-03-23 12:13:35203 scoped_refptr<MockConnectionToClient> connection2_;
204 scoped_refptr<MockSession> session2_;
205 scoped_ptr<SessionConfig> session_config2_;
206 MockVideoStub video_stub2_;
207 MockClientStub client_stub2_;
208 MockHostStub* host_stub2_;
[email protected]0b7e4282011-04-04 22:44:11209 MockEventExecutor* event_executor2_;
[email protected]1e72daa2011-01-28 21:25:42210};
211
212TEST_F(ChromotingHostTest, StartAndShutdown) {
213 host_->Start(NewRunnableFunction(&PostQuitTask, &message_loop_));
214
215 message_loop_.PostTask(FROM_HERE,
216 NewRunnableMethod(host_.get(),
217 &ChromotingHost::Shutdown));
218 message_loop_.Run();
219}
220
221TEST_F(ChromotingHostTest, Connect) {
222 host_->Start(NewRunnableFunction(&PostQuitTask, &message_loop_));
223
[email protected]9cabbaf02011-01-29 00:59:59224 EXPECT_CALL(client_stub_, BeginSessionResponse(_, _))
225 .WillOnce(RunDoneTask());
[email protected]1e72daa2011-01-28 21:25:42226
227 // When the video packet is received we first shutdown ChromotingHost
228 // then execute the done task.
[email protected]0b7e4282011-04-04 22:44:11229 {
230 InSequence s;
231 EXPECT_CALL(*curtain_, EnableCurtainMode(true))
232 .Times(1);
233 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
234 .WillOnce(DoAll(
235 InvokeWithoutArgs(host_.get(), &ChromotingHost::Shutdown),
236 RunDoneTask()))
237 .RetiresOnSaturation();
238 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
239 .Times(AnyNumber());
240 EXPECT_CALL(*connection_.get(), Disconnect())
241 .RetiresOnSaturation();
242 }
[email protected]37961b12011-03-30 12:39:00243 SimulateClientConnection(0, true);
[email protected]1e72daa2011-01-28 21:25:42244 message_loop_.Run();
245}
246
247TEST_F(ChromotingHostTest, Reconnect) {
248 host_->Start(NewRunnableFunction(&PostQuitTask, &message_loop_));
249
[email protected]9cabbaf02011-01-29 00:59:59250 EXPECT_CALL(client_stub_, BeginSessionResponse(_, _))
251 .Times(2)
252 .WillRepeatedly(RunDoneTask());
[email protected]1e72daa2011-01-28 21:25:42253
254 // When the video packet is received we first disconnect the mock
255 // connection.
[email protected]9cabbaf02011-01-29 00:59:59256 {
257 InSequence s;
[email protected]ef37f222011-03-30 16:59:42258 // Ensure that curtain mode is activated before the first video packet.
[email protected]37961b12011-03-30 12:39:00259 EXPECT_CALL(*curtain_, EnableCurtainMode(true))
260 .Times(1);
[email protected]9cabbaf02011-01-29 00:59:59261 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
262 .WillOnce(DoAll(
263 InvokeWithoutArgs(this,
264 &ChromotingHostTest::RemoveClientConnection),
265 RunDoneTask()))
266 .RetiresOnSaturation();
267 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
268 .Times(AnyNumber());
[email protected]37961b12011-03-30 12:39:00269 EXPECT_CALL(*curtain_, EnableCurtainMode(false))
270 .Times(1);
[email protected]ef37f222011-03-30 16:59:42271 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
272 .Times(AnyNumber());
[email protected]9cabbaf02011-01-29 00:59:59273 }
[email protected]1e72daa2011-01-28 21:25:42274
275 // If Disconnect() is called we can break the main message loop.
276 EXPECT_CALL(*connection_.get(), Disconnect())
277 .WillOnce(QuitMainMessageLoop(&message_loop_))
278 .RetiresOnSaturation();
279
[email protected]37961b12011-03-30 12:39:00280 SimulateClientConnection(0, true);
[email protected]1e72daa2011-01-28 21:25:42281 message_loop_.Run();
282
283 // Connect the client again.
[email protected]9cabbaf02011-01-29 00:59:59284 {
285 InSequence s;
[email protected]37961b12011-03-30 12:39:00286 EXPECT_CALL(*curtain_, EnableCurtainMode(true))
287 .Times(1);
[email protected]9cabbaf02011-01-29 00:59:59288 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
289 .WillOnce(DoAll(
290 InvokeWithoutArgs(host_.get(), &ChromotingHost::Shutdown),
291 RunDoneTask()))
292 .RetiresOnSaturation();
293 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
294 .Times(AnyNumber());
295 }
296 EXPECT_CALL(*connection_.get(), Disconnect())
[email protected]1e72daa2011-01-28 21:25:42297 .RetiresOnSaturation();
[email protected]1e72daa2011-01-28 21:25:42298
[email protected]37961b12011-03-30 12:39:00299 SimulateClientConnection(0, true);
[email protected]44f60762011-03-23 12:13:35300 message_loop_.Run();
301}
302
303TEST_F(ChromotingHostTest, ConnectTwice) {
304 host_->Start(NewRunnableFunction(&PostQuitTask, &message_loop_));
305
306 EXPECT_CALL(client_stub_, BeginSessionResponse(_, _))
307 .Times(1)
308 .WillRepeatedly(RunDoneTask());
309
310 EXPECT_CALL(client_stub2_, BeginSessionResponse(_, _))
311 .Times(1)
312 .WillRepeatedly(RunDoneTask());
313
314 // When a video packet is received we connect the second mock
315 // connection.
316 {
317 InSequence s;
[email protected]37961b12011-03-30 12:39:00318 EXPECT_CALL(*curtain_, EnableCurtainMode(true))
319 .Times(1)
320 .WillOnce(QuitMainMessageLoop(&message_loop_));
[email protected]44f60762011-03-23 12:13:35321 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
322 .WillOnce(DoAll(
323 InvokeWithoutArgs(
324 CreateFunctor(
[email protected]37961b12011-03-30 12:39:00325 this,
326 &ChromotingHostTest::SimulateClientConnection, 1, true)),
[email protected]44f60762011-03-23 12:13:35327 RunDoneTask()))
328 .RetiresOnSaturation();
[email protected]37961b12011-03-30 12:39:00329 // Check that the second connection does not affect curtain mode.
330 EXPECT_CALL(*curtain_, EnableCurtainMode(_))
331 .Times(0);
[email protected]44f60762011-03-23 12:13:35332 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
333 .Times(AnyNumber());
334 EXPECT_CALL(video_stub2_, ProcessVideoPacket(_, _))
335 .WillOnce(DoAll(
336 InvokeWithoutArgs(host_.get(), &ChromotingHost::Shutdown),
337 RunDoneTask()))
338 .RetiresOnSaturation();
339 EXPECT_CALL(video_stub2_, ProcessVideoPacket(_, _))
340 .Times(AnyNumber());
341 }
342
343 EXPECT_CALL(*connection_.get(), Disconnect())
344 .RetiresOnSaturation();
345 EXPECT_CALL(*connection2_.get(), Disconnect())
346 .RetiresOnSaturation();
347
[email protected]37961b12011-03-30 12:39:00348 SimulateClientConnection(0, true);
349 message_loop_.Run();
350}
351
352TEST_F(ChromotingHostTest, CurtainModeFail) {
353 host_->Start(NewRunnableFunction(&PostQuitTask, &message_loop_));
354
355 EXPECT_CALL(client_stub_, BeginSessionResponse(_, _))
[email protected]0b7e4282011-04-04 22:44:11356 .WillOnce(RunDoneTask());
[email protected]37961b12011-03-30 12:39:00357
358 // Ensure that curtain mode is not activated if a connection does not
359 // authenticate.
360 EXPECT_CALL(*curtain_, EnableCurtainMode(_))
361 .Times(0);
362 EXPECT_CALL(*connection_.get(), Disconnect())
363 .WillOnce(QuitMainMessageLoop(&message_loop_));
364 SimulateClientConnection(0, false);
365 RemoveClientConnection();
366 message_loop_.Run();
367}
368
369TEST_F(ChromotingHostTest, CurtainModeFailSecond) {
370 host_->Start(NewRunnableFunction(&PostQuitTask, &message_loop_));
371
372 EXPECT_CALL(client_stub_, BeginSessionResponse(_, _))
[email protected]0b7e4282011-04-04 22:44:11373 .WillOnce(RunDoneTask());
[email protected]37961b12011-03-30 12:39:00374
375 EXPECT_CALL(client_stub2_, BeginSessionResponse(_, _))
[email protected]0b7e4282011-04-04 22:44:11376 .WillOnce(RunDoneTask());
377
[email protected]37961b12011-03-30 12:39:00378
379 // When a video packet is received we connect the second mock
380 // connection.
381 {
382 InSequence s;
383 EXPECT_CALL(*curtain_, EnableCurtainMode(true))
[email protected]37961b12011-03-30 12:39:00384 .WillOnce(QuitMainMessageLoop(&message_loop_));
385 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
386 .WillOnce(DoAll(
387 InvokeWithoutArgs(
388 CreateFunctor(
389 this,
390 &ChromotingHostTest::SimulateClientConnection, 1, false)),
391 RunDoneTask()))
392 .RetiresOnSaturation();
393 // Check that the second connection does not affect curtain mode.
394 EXPECT_CALL(*curtain_, EnableCurtainMode(_))
395 .Times(0);
396 EXPECT_CALL(video_stub_, ProcessVideoPacket(_, _))
397 .Times(AnyNumber());
398 EXPECT_CALL(video_stub2_, ProcessVideoPacket(_, _))
399 .Times(0);
400 }
401
402 SimulateClientConnection(0, true);
[email protected]1e72daa2011-01-28 21:25:42403 message_loop_.Run();
404}
405
406} // namespace remoting