Roll third_party/android_tools to the latest: updated the support library to 19.0.1
[chromium-blink-merge.git] / remoting / host / client_session_unittest.cc
blob7cd21ee831213a6bc42dee1a2c25c9d2d1ff8801
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.
5 #include "base/message_loop/message_loop.h"
6 #include "remoting/base/auto_thread_task_runner.h"
7 #include "remoting/base/constants.h"
8 #include "remoting/host/audio_capturer.h"
9 #include "remoting/host/client_session.h"
10 #include "remoting/host/desktop_environment.h"
11 #include "remoting/host/host_mock_objects.h"
12 #include "remoting/host/screen_capturer_fake.h"
13 #include "remoting/protocol/protocol_mock_objects.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
16 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
17 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
19 namespace remoting {
21 using protocol::MockConnectionToClient;
22 using protocol::MockClientStub;
23 using protocol::MockHostStub;
24 using protocol::MockInputStub;
25 using protocol::MockSession;
26 using protocol::MockVideoStub;
27 using protocol::SessionConfig;
29 using testing::_;
30 using testing::AnyNumber;
31 using testing::AtMost;
32 using testing::DeleteArg;
33 using testing::DoAll;
34 using testing::Expectation;
35 using testing::Return;
36 using testing::ReturnRef;
37 using testing::Sequence;
39 namespace {
41 ACTION_P2(InjectClipboardEvent, connection, event) {
42 connection->clipboard_stub()->InjectClipboardEvent(event);
45 ACTION_P2(InjectKeyEvent, connection, event) {
46 connection->input_stub()->InjectKeyEvent(event);
49 ACTION_P2(InjectMouseEvent, connection, event) {
50 connection->input_stub()->InjectMouseEvent(event);
53 ACTION_P2(LocalMouseMoved, client_session, event) {
54 client_session->OnLocalMouseMoved(
55 webrtc::DesktopVector(event.x(), event.y()));
58 } // namespace
60 class ClientSessionTest : public testing::Test {
61 public:
62 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
64 virtual void SetUp() OVERRIDE;
65 virtual void TearDown() OVERRIDE;
67 // Disconnects the client session.
68 void DisconnectClientSession();
70 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
71 void StopClientSession();
73 protected:
74 // Creates a DesktopEnvironment with a fake webrtc::ScreenCapturer, to mock
75 // DesktopEnvironmentFactory::Create().
76 DesktopEnvironment* CreateDesktopEnvironment();
78 // Returns |input_injector_| created and initialized by SetUp(), to mock
79 // DesktopEnvironment::CreateInputInjector().
80 InputInjector* CreateInputInjector();
82 // Creates a fake webrtc::ScreenCapturer, to mock
83 // DesktopEnvironment::CreateVideoCapturer().
84 webrtc::ScreenCapturer* CreateVideoCapturer();
86 // Notifies the client session that the client connection has been
87 // authenticated and channels have been connected. This effectively enables
88 // the input pipe line and starts video capturing.
89 void ConnectClientSession();
91 // Invoked when the last reference to the AutoThreadTaskRunner has been
92 // released and quits the message loop to finish the test.
93 void QuitMainMessageLoop();
95 // Message loop passed to |client_session_| to perform all functions on.
96 base::MessageLoop message_loop_;
98 // ClientSession instance under test.
99 scoped_ptr<ClientSession> client_session_;
101 // ClientSession::EventHandler mock for use in tests.
102 MockClientSessionEventHandler session_event_handler_;
104 // Storage for values to be returned by the protocol::Session mock.
105 SessionConfig session_config_;
106 const std::string client_jid_;
108 // Stubs returned to |client_session_| components by |connection_|.
109 MockClientStub client_stub_;
110 MockVideoStub video_stub_;
112 // DesktopEnvironment owns |input_injector_|, but input injection tests need
113 // to express expectations on it.
114 scoped_ptr<MockInputInjector> input_injector_;
116 // ClientSession owns |connection_| but tests need it to inject fake events.
117 MockConnectionToClient* connection_;
119 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_;
122 void ClientSessionTest::SetUp() {
123 // Arrange to run |message_loop_| until no components depend on it.
124 scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
125 message_loop_.message_loop_proxy(),
126 base::Bind(&ClientSessionTest::QuitMainMessageLoop,
127 base::Unretained(this)));
129 desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory());
130 EXPECT_CALL(*desktop_environment_factory_, CreatePtr())
131 .Times(AnyNumber())
132 .WillRepeatedly(Invoke(this,
133 &ClientSessionTest::CreateDesktopEnvironment));
134 EXPECT_CALL(*desktop_environment_factory_, SupportsAudioCapture())
135 .Times(AnyNumber())
136 .WillRepeatedly(Return(false));
138 input_injector_.reset(new MockInputInjector());
140 session_config_ = SessionConfig::ForTest();
142 // Mock protocol::Session APIs called directly by ClientSession.
143 protocol::MockSession* session = new MockSession();
144 EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(session_config_));
145 EXPECT_CALL(*session, jid()).WillRepeatedly(ReturnRef(client_jid_));
146 EXPECT_CALL(*session, SetEventHandler(_));
148 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
149 // HostStub is not touched by ClientSession, so we can safely pass NULL.
150 scoped_ptr<MockConnectionToClient> connection(
151 new MockConnectionToClient(session, NULL));
152 EXPECT_CALL(*connection, session()).WillRepeatedly(Return(session));
153 EXPECT_CALL(*connection, client_stub())
154 .WillRepeatedly(Return(&client_stub_));
155 EXPECT_CALL(*connection, video_stub()).WillRepeatedly(Return(&video_stub_));
156 EXPECT_CALL(*connection, Disconnect());
157 connection_ = connection.get();
159 client_session_.reset(new ClientSession(
160 &session_event_handler_,
161 ui_task_runner, // Audio thread.
162 ui_task_runner, // Input thread.
163 ui_task_runner, // Capture thread.
164 ui_task_runner, // Encode thread.
165 ui_task_runner, // Network thread.
166 ui_task_runner, // UI thread.
167 connection.PassAs<protocol::ConnectionToClient>(),
168 desktop_environment_factory_.get(),
169 base::TimeDelta(),
170 NULL));
173 void ClientSessionTest::TearDown() {
174 // Verify that the client session has been stopped.
175 EXPECT_TRUE(!client_session_);
178 void ClientSessionTest::DisconnectClientSession() {
179 client_session_->DisconnectSession();
180 // MockSession won't trigger OnConnectionClosed, so fake it.
181 client_session_->OnConnectionClosed(client_session_->connection(),
182 protocol::OK);
185 void ClientSessionTest::StopClientSession() {
186 client_session_.reset();
188 desktop_environment_factory_.reset();
191 DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
192 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
193 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
194 .Times(0);
195 EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
196 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector));
197 EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
198 .Times(AtMost(1));
199 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
200 .WillOnce(Invoke(this, &ClientSessionTest::CreateVideoCapturer));
201 EXPECT_CALL(*desktop_environment, GetCapabilities())
202 .Times(AtMost(1));
203 EXPECT_CALL(*desktop_environment, SetCapabilities(_))
204 .Times(AtMost(1));
206 return desktop_environment;
209 InputInjector* ClientSessionTest::CreateInputInjector() {
210 EXPECT_TRUE(input_injector_);
211 return input_injector_.release();
214 webrtc::ScreenCapturer* ClientSessionTest::CreateVideoCapturer() {
215 return new ScreenCapturerFake();
218 void ClientSessionTest::ConnectClientSession() {
219 client_session_->OnConnectionAuthenticated(client_session_->connection());
220 client_session_->OnConnectionChannelsConnected(client_session_->connection());
223 void ClientSessionTest::QuitMainMessageLoop() {
224 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
227 MATCHER_P2(EqualsClipboardEvent, m, d, "") {
228 return (strcmp(arg.mime_type().c_str(), m) == 0 &&
229 memcmp(arg.data().data(), d, arg.data().size()) == 0);
232 TEST_F(ClientSessionTest, ClipboardStubFilter) {
233 protocol::ClipboardEvent clipboard_event1;
234 clipboard_event1.set_mime_type(kMimeTypeTextUtf8);
235 clipboard_event1.set_data("a");
237 protocol::ClipboardEvent clipboard_event2;
238 clipboard_event2.set_mime_type(kMimeTypeTextUtf8);
239 clipboard_event2.set_data("b");
241 protocol::ClipboardEvent clipboard_event3;
242 clipboard_event3.set_mime_type(kMimeTypeTextUtf8);
243 clipboard_event3.set_data("c");
245 Expectation authenticated =
246 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
247 .WillOnce(Return(true));
248 EXPECT_CALL(*input_injector_, StartPtr(_))
249 .After(authenticated);
250 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
251 .After(authenticated);
253 // Wait for the first video packet to be captured to make sure that
254 // the injected input will go though. Otherwise mouse events will be blocked
255 // by the mouse clamping filter.
256 Sequence s;
257 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
258 .InSequence(s)
259 .After(authenticated)
260 .WillOnce(DoAll(
261 // This event should get through to the clipboard stub.
262 InjectClipboardEvent(connection_, clipboard_event2),
263 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
264 // This event should not get through to the clipboard stub,
265 // because the client has disconnected.
266 InjectClipboardEvent(connection_, clipboard_event3),
267 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
268 EXPECT_CALL(*input_injector_, InjectClipboardEvent(EqualsClipboardEvent(
269 kMimeTypeTextUtf8, "b")))
270 .InSequence(s);
271 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
272 .InSequence(s);
274 // This event should not get through to the clipboard stub,
275 // because the client isn't authenticated yet.
276 connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event1);
278 ConnectClientSession();
279 message_loop_.Run();
282 namespace {
284 MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") {
285 return arg.usb_keycode() == (unsigned int)usb_keycode &&
286 arg.pressed() == pressed;
289 MATCHER_P2(EqualsMouseEvent, x, y, "") {
290 return arg.x() == x && arg.y() == y;
293 MATCHER_P2(EqualsMouseButtonEvent, button, down, "") {
294 return arg.button() == button && arg.button_down() == down;
299 TEST_F(ClientSessionTest, InputStubFilter) {
300 protocol::KeyEvent key_event1;
301 key_event1.set_pressed(true);
302 key_event1.set_usb_keycode(1);
304 protocol::KeyEvent key_event2_down;
305 key_event2_down.set_pressed(true);
306 key_event2_down.set_usb_keycode(2);
308 protocol::KeyEvent key_event2_up;
309 key_event2_up.set_pressed(false);
310 key_event2_up.set_usb_keycode(2);
312 protocol::KeyEvent key_event3;
313 key_event3.set_pressed(true);
314 key_event3.set_usb_keycode(3);
316 protocol::MouseEvent mouse_event1;
317 mouse_event1.set_x(100);
318 mouse_event1.set_y(101);
320 protocol::MouseEvent mouse_event2;
321 mouse_event2.set_x(200);
322 mouse_event2.set_y(201);
324 protocol::MouseEvent mouse_event3;
325 mouse_event3.set_x(300);
326 mouse_event3.set_y(301);
328 Expectation authenticated =
329 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
330 .WillOnce(Return(true));
331 EXPECT_CALL(*input_injector_, StartPtr(_))
332 .After(authenticated);
333 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
334 .After(authenticated);
336 // Wait for the first video packet to be captured to make sure that
337 // the injected input will go though. Otherwise mouse events will be blocked
338 // by the mouse clamping filter.
339 Sequence s;
340 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
341 .InSequence(s)
342 .After(authenticated)
343 .WillOnce(DoAll(
344 // These events should get through to the input stub.
345 InjectKeyEvent(connection_, key_event2_down),
346 InjectKeyEvent(connection_, key_event2_up),
347 InjectMouseEvent(connection_, mouse_event2),
348 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
349 // These events should not get through to the input stub,
350 // because the client has disconnected.
351 InjectKeyEvent(connection_, key_event3),
352 InjectMouseEvent(connection_, mouse_event3),
353 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
354 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
355 .InSequence(s);
356 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
357 .InSequence(s);
358 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
359 .InSequence(s);
360 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
361 .InSequence(s);
363 // These events should not get through to the input stub,
364 // because the client isn't authenticated yet.
365 connection_->input_stub()->InjectKeyEvent(key_event1);
366 connection_->input_stub()->InjectMouseEvent(mouse_event1);
368 ConnectClientSession();
369 message_loop_.Run();
372 TEST_F(ClientSessionTest, LocalInputTest) {
373 protocol::MouseEvent mouse_event1;
374 mouse_event1.set_x(100);
375 mouse_event1.set_y(101);
376 protocol::MouseEvent mouse_event2;
377 mouse_event2.set_x(200);
378 mouse_event2.set_y(201);
379 protocol::MouseEvent mouse_event3;
380 mouse_event3.set_x(300);
381 mouse_event3.set_y(301);
383 Expectation authenticated =
384 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
385 .WillOnce(Return(true));
386 EXPECT_CALL(*input_injector_, StartPtr(_))
387 .After(authenticated);
388 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
389 .After(authenticated);
391 // Wait for the first video packet to be captured to make sure that
392 // the injected input will go though. Otherwise mouse events will be blocked
393 // by the mouse clamping filter.
394 Sequence s;
395 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
396 .InSequence(s)
397 .After(authenticated)
398 .WillOnce(DoAll(
399 // This event should get through to the input stub.
400 InjectMouseEvent(connection_, mouse_event1),
401 #if !defined(OS_WIN)
402 // The OS echoes the injected event back.
403 LocalMouseMoved(client_session_.get(), mouse_event1),
404 #endif // !defined(OS_WIN)
405 // This one should get throught as well.
406 InjectMouseEvent(connection_, mouse_event2),
407 // Now this is a genuine local event.
408 LocalMouseMoved(client_session_.get(), mouse_event1),
409 // This one should be blocked because of the previous local input
410 // event.
411 InjectMouseEvent(connection_, mouse_event3),
412 // TODO(jamiewalch): Verify that remote inputs are re-enabled
413 // eventually (via dependency injection, not sleep!)
414 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
415 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
416 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(100, 101)))
417 .InSequence(s);
418 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
419 .InSequence(s);
420 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
421 .InSequence(s);
423 ConnectClientSession();
424 message_loop_.Run();
427 TEST_F(ClientSessionTest, RestoreEventState) {
428 protocol::KeyEvent key1;
429 key1.set_pressed(true);
430 key1.set_usb_keycode(1);
432 protocol::KeyEvent key2;
433 key2.set_pressed(true);
434 key2.set_usb_keycode(2);
436 protocol::MouseEvent mousedown;
437 mousedown.set_button(protocol::MouseEvent::BUTTON_LEFT);
438 mousedown.set_button_down(true);
440 Expectation authenticated =
441 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
442 .WillOnce(Return(true));
443 EXPECT_CALL(*input_injector_, StartPtr(_))
444 .After(authenticated);
445 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
446 .After(authenticated);
448 // Wait for the first video packet to be captured to make sure that
449 // the injected input will go though. Otherwise mouse events will be blocked
450 // by the mouse clamping filter.
451 Sequence s;
452 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
453 .InSequence(s)
454 .After(authenticated)
455 .WillOnce(DoAll(
456 InjectKeyEvent(connection_, key1),
457 InjectKeyEvent(connection_, key2),
458 InjectMouseEvent(connection_, mousedown),
459 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
460 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
461 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, true)))
462 .InSequence(s);
463 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
464 .InSequence(s);
465 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
466 protocol::MouseEvent::BUTTON_LEFT, true)))
467 .InSequence(s);
468 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, false)))
469 .InSequence(s);
470 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
471 .InSequence(s);
472 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
473 protocol::MouseEvent::BUTTON_LEFT, false)))
474 .InSequence(s);
475 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
476 .InSequence(s);
478 ConnectClientSession();
479 message_loop_.Run();
482 TEST_F(ClientSessionTest, ClampMouseEvents) {
483 Expectation authenticated =
484 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
485 .WillOnce(Return(true));
486 EXPECT_CALL(*input_injector_, StartPtr(_))
487 .After(authenticated);
488 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
489 .After(authenticated);
490 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
491 .After(authenticated);
493 Expectation connected = authenticated;
495 int input_x[3] = { -999, 100, 999 };
496 int expected_x[3] = { 0, 100, ScreenCapturerFake::kWidth - 1 };
497 int input_y[3] = { -999, 50, 999 };
498 int expected_y[3] = { 0, 50, ScreenCapturerFake::kHeight - 1 };
500 protocol::MouseEvent expected_event;
501 for (int j = 0; j < 3; j++) {
502 for (int i = 0; i < 3; i++) {
503 protocol::MouseEvent injected_event;
504 injected_event.set_x(input_x[i]);
505 injected_event.set_y(input_y[j]);
507 if (i == 0 && j == 0) {
508 // Inject the 1st event once a video packet has been received.
509 connected =
510 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
511 .After(connected)
512 .WillOnce(InjectMouseEvent(connection_, injected_event));
513 } else {
514 // Every next event is injected once the previous event has been
515 // received.
516 connected =
517 EXPECT_CALL(*input_injector_,
518 InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
519 expected_event.y())))
520 .After(connected)
521 .WillOnce(InjectMouseEvent(connection_, injected_event));
524 expected_event.set_x(expected_x[i]);
525 expected_event.set_y(expected_y[j]);
529 // Shutdown the connection once the last event has been received.
530 EXPECT_CALL(*input_injector_,
531 InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
532 expected_event.y())))
533 .After(connected)
534 .WillOnce(DoAll(
535 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
536 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
538 ConnectClientSession();
539 message_loop_.Run();
542 } // namespace remoting