Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / remoting / host / client_session_unittest.cc
blobb3dfa45396606fc3f1f086191c026bf284bfe2dc
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 <algorithm>
6 #include <string>
7 #include <vector>
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/test/test_simple_task_runner.h"
13 #include "remoting/base/auto_thread_task_runner.h"
14 #include "remoting/base/constants.h"
15 #include "remoting/host/audio_capturer.h"
16 #include "remoting/host/client_session.h"
17 #include "remoting/host/desktop_environment.h"
18 #include "remoting/host/fake_desktop_capturer.h"
19 #include "remoting/host/fake_host_extension.h"
20 #include "remoting/host/fake_mouse_cursor_monitor.h"
21 #include "remoting/host/host_extension.h"
22 #include "remoting/host/host_extension_session.h"
23 #include "remoting/host/host_mock_objects.h"
24 #include "remoting/protocol/protocol_mock_objects.h"
25 #include "testing/gmock/include/gmock/gmock-matchers.h"
26 #include "testing/gmock_mutant.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
29 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
30 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
32 namespace remoting {
34 using protocol::MockConnectionToClient;
35 using protocol::MockClientStub;
36 using protocol::MockHostStub;
37 using protocol::MockInputStub;
38 using protocol::MockSession;
39 using protocol::MockVideoStub;
40 using protocol::SessionConfig;
42 using testing::_;
43 using testing::AnyNumber;
44 using testing::AtMost;
45 using testing::CreateFunctor;
46 using testing::DeleteArg;
47 using testing::DoAll;
48 using testing::Expectation;
49 using testing::Invoke;
50 using testing::Return;
51 using testing::ReturnRef;
52 using testing::Sequence;
53 using testing::StrEq;
54 using testing::StrictMock;
56 namespace {
58 const char kDefaultTestCapability[] = "default";
60 ACTION_P2(InjectClipboardEvent, connection, event) {
61 connection->clipboard_stub()->InjectClipboardEvent(event);
64 ACTION_P2(InjectKeyEvent, connection, event) {
65 connection->input_stub()->InjectKeyEvent(event);
68 ACTION_P2(InjectMouseEvent, connection, event) {
69 connection->input_stub()->InjectMouseEvent(event);
72 ACTION_P2(LocalMouseMoved, client_session, event) {
73 client_session->OnLocalMouseMoved(
74 webrtc::DesktopVector(event.x(), event.y()));
77 ACTION_P2(SetGnubbyAuthHandlerForTesting, client_session, gnubby_auth_handler) {
78 client_session->SetGnubbyAuthHandlerForTesting(gnubby_auth_handler);
81 ACTION_P2(DeliverClientMessage, client_session, message) {
82 client_session->DeliverClientMessage(message);
85 ACTION_P2(SetCapabilities, client_session, capabilities) {
86 protocol::Capabilities capabilities_message;
87 capabilities_message.set_capabilities(capabilities);
88 client_session->SetCapabilities(capabilities_message);
91 MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") {
92 return arg.usb_keycode() == (unsigned int)usb_keycode &&
93 arg.pressed() == pressed;
96 MATCHER_P2(EqualsMouseEvent, x, y, "") {
97 return arg.x() == x && arg.y() == y;
100 MATCHER_P2(EqualsMouseButtonEvent, button, down, "") {
101 return arg.button() == button && arg.button_down() == down;
104 // Matches a |protocol::Capabilities| argument against a list of capabilities
105 // formatted as a space-separated string.
106 MATCHER_P(EqCapabilities, expected_capabilities, "") {
107 if (!arg.has_capabilities())
108 return false;
110 std::vector<std::string> words_args;
111 std::vector<std::string> words_expected;
112 Tokenize(arg.capabilities(), " ", &words_args);
113 Tokenize(expected_capabilities, " ", &words_expected);
114 std::sort(words_args.begin(), words_args.end());
115 std::sort(words_expected.begin(), words_expected.end());
116 return words_args == words_expected;
119 } // namespace
121 class ClientSessionTest : public testing::Test {
122 public:
123 ClientSessionTest() : client_jid_("user@domain/rest-of-jid") {}
125 virtual void SetUp() OVERRIDE;
126 virtual void TearDown() OVERRIDE;
128 // Creates the client session.
129 void CreateClientSession();
131 // Disconnects the client session.
132 void DisconnectClientSession();
134 // Stops and releases the ClientSession, allowing the MessageLoop to quit.
135 void StopClientSession();
137 protected:
138 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
139 // DesktopEnvironmentFactory::Create().
140 DesktopEnvironment* CreateDesktopEnvironment();
142 // Returns |input_injector_| created and initialized by SetUp(), to mock
143 // DesktopEnvironment::CreateInputInjector().
144 InputInjector* CreateInputInjector();
146 // Creates a fake webrtc::DesktopCapturer, to mock
147 // DesktopEnvironment::CreateVideoCapturer().
148 webrtc::DesktopCapturer* CreateVideoCapturer();
150 // Creates a MockMouseCursorMonitor, to mock
151 // DesktopEnvironment::CreateMouseCursorMonitor
152 webrtc::MouseCursorMonitor* CreateMouseCursorMonitor();
154 // Notifies the client session that the client connection has been
155 // authenticated and channels have been connected. This effectively enables
156 // the input pipe line and starts video capturing.
157 void ConnectClientSession();
159 // Creates expectation that simulates client supporting same capabilities as
160 // host.
161 void SetMatchCapabilitiesExpectation();
163 // Creates expectations to send an extension message and to disconnect
164 // afterwards.
165 void SetSendMessageAndDisconnectExpectation(const std::string& message_type);
167 // Message loop that will process all ClientSession tasks.
168 base::MessageLoop message_loop_;
170 // AutoThreadTaskRunner on which |client_session_| will be run.
171 scoped_refptr<AutoThreadTaskRunner> task_runner_;
173 // Used to run |message_loop_| after each test, until no objects remain that
174 // require it.
175 base::RunLoop run_loop_;
177 // HostExtensions to pass when creating the ClientSession. Caller retains
178 // ownership of the HostExtensions themselves.
179 std::vector<HostExtension*> extensions_;
181 // ClientSession instance under test.
182 scoped_ptr<ClientSession> client_session_;
184 // ClientSession::EventHandler mock for use in tests.
185 MockClientSessionEventHandler session_event_handler_;
187 // Storage for values to be returned by the protocol::Session mock.
188 SessionConfig session_config_;
189 const std::string client_jid_;
191 // Stubs returned to |client_session_| components by |connection_|.
192 MockClientStub client_stub_;
193 MockVideoStub video_stub_;
195 // DesktopEnvironment owns |input_injector_|, but input injection tests need
196 // to express expectations on it.
197 scoped_ptr<MockInputInjector> input_injector_;
199 // ClientSession owns |connection_| but tests need it to inject fake events.
200 MockConnectionToClient* connection_;
202 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_;
205 void ClientSessionTest::SetUp() {
206 // Arrange to run |message_loop_| until no components depend on it.
207 task_runner_ = new AutoThreadTaskRunner(
208 message_loop_.message_loop_proxy(), run_loop_.QuitClosure());
210 desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory());
211 EXPECT_CALL(*desktop_environment_factory_, CreatePtr())
212 .Times(AnyNumber())
213 .WillRepeatedly(Invoke(this,
214 &ClientSessionTest::CreateDesktopEnvironment));
215 EXPECT_CALL(*desktop_environment_factory_, SupportsAudioCapture())
216 .Times(AnyNumber())
217 .WillRepeatedly(Return(false));
219 input_injector_.reset(new MockInputInjector());
221 session_config_ = SessionConfig::ForTest();
224 void ClientSessionTest::TearDown() {
225 // Clear out |task_runner_| reference so the loop can quit, and run it until
226 // it does.
227 task_runner_ = NULL;
228 run_loop_.Run();
231 void ClientSessionTest::CreateClientSession() {
232 // Mock protocol::Session APIs called directly by ClientSession.
233 protocol::MockSession* session = new MockSession();
234 EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(session_config_));
235 EXPECT_CALL(*session, jid()).WillRepeatedly(ReturnRef(client_jid_));
236 EXPECT_CALL(*session, SetEventHandler(_));
238 // Mock protocol::ConnectionToClient APIs called directly by ClientSession.
239 // HostStub is not touched by ClientSession, so we can safely pass NULL.
240 scoped_ptr<MockConnectionToClient> connection(
241 new MockConnectionToClient(session, NULL));
242 EXPECT_CALL(*connection, session()).WillRepeatedly(Return(session));
243 EXPECT_CALL(*connection, client_stub())
244 .WillRepeatedly(Return(&client_stub_));
245 EXPECT_CALL(*connection, video_stub()).WillRepeatedly(Return(&video_stub_));
246 EXPECT_CALL(*connection, Disconnect());
247 connection_ = connection.get();
249 client_session_.reset(new ClientSession(
250 &session_event_handler_,
251 task_runner_, // Audio thread.
252 task_runner_, // Input thread.
253 task_runner_, // Capture thread.
254 task_runner_, // Encode thread.
255 task_runner_, // Network thread.
256 task_runner_, // UI thread.
257 connection.PassAs<protocol::ConnectionToClient>(),
258 desktop_environment_factory_.get(),
259 base::TimeDelta(),
260 NULL,
261 extensions_));
264 void ClientSessionTest::DisconnectClientSession() {
265 client_session_->DisconnectSession();
266 // MockSession won't trigger OnConnectionClosed, so fake it.
267 client_session_->OnConnectionClosed(client_session_->connection(),
268 protocol::OK);
271 void ClientSessionTest::StopClientSession() {
272 client_session_.reset();
274 desktop_environment_factory_.reset();
277 DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
278 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
279 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
280 .Times(0);
281 EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
282 .WillOnce(Invoke(this, &ClientSessionTest::CreateInputInjector));
283 EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
284 .Times(AtMost(1));
285 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
286 .WillRepeatedly(Invoke(this, &ClientSessionTest::CreateVideoCapturer));
287 EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
288 .WillRepeatedly(
289 Invoke(this, &ClientSessionTest::CreateMouseCursorMonitor));
290 EXPECT_CALL(*desktop_environment, GetCapabilities())
291 .Times(AtMost(1))
292 .WillOnce(Return(kDefaultTestCapability));
293 EXPECT_CALL(*desktop_environment, SetCapabilities(_))
294 .Times(AtMost(1));
296 return desktop_environment;
299 InputInjector* ClientSessionTest::CreateInputInjector() {
300 EXPECT_TRUE(input_injector_);
301 return input_injector_.release();
304 webrtc::DesktopCapturer* ClientSessionTest::CreateVideoCapturer() {
305 return new FakeDesktopCapturer();
308 webrtc::MouseCursorMonitor* ClientSessionTest::CreateMouseCursorMonitor() {
309 return new FakeMouseCursorMonitor();
312 void ClientSessionTest::ConnectClientSession() {
313 client_session_->OnConnectionAuthenticated(client_session_->connection());
314 client_session_->OnConnectionChannelsConnected(client_session_->connection());
317 void ClientSessionTest::SetMatchCapabilitiesExpectation() {
318 // Set the client to report the same capabilities as the host.
319 EXPECT_CALL(client_stub_, SetCapabilities(_))
320 .Times(AtMost(1))
321 .WillOnce(Invoke(client_session_.get(), &ClientSession::SetCapabilities));
324 void ClientSessionTest::SetSendMessageAndDisconnectExpectation(
325 const std::string& message_type) {
326 protocol::ExtensionMessage message;
327 message.set_type(message_type);
328 message.set_data("data");
330 Expectation authenticated =
331 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
332 .WillOnce(Return(true));
333 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
334 .After(authenticated)
335 .WillOnce(DoAll(
336 DeliverClientMessage(client_session_.get(), message),
337 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
338 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
341 MATCHER_P2(EqualsClipboardEvent, m, d, "") {
342 return (strcmp(arg.mime_type().c_str(), m) == 0 &&
343 memcmp(arg.data().data(), d, arg.data().size()) == 0);
346 TEST_F(ClientSessionTest, ClipboardStubFilter) {
347 CreateClientSession();
349 protocol::ClipboardEvent clipboard_event1;
350 clipboard_event1.set_mime_type(kMimeTypeTextUtf8);
351 clipboard_event1.set_data("a");
353 protocol::ClipboardEvent clipboard_event2;
354 clipboard_event2.set_mime_type(kMimeTypeTextUtf8);
355 clipboard_event2.set_data("b");
357 protocol::ClipboardEvent clipboard_event3;
358 clipboard_event3.set_mime_type(kMimeTypeTextUtf8);
359 clipboard_event3.set_data("c");
361 Expectation authenticated =
362 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
363 .WillOnce(Return(true));
364 EXPECT_CALL(*input_injector_, StartPtr(_))
365 .After(authenticated);
366 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
367 .After(authenticated);
369 // Wait for the first video packet to be captured to make sure that
370 // the injected input will go though. Otherwise mouse events will be blocked
371 // by the mouse clamping filter.
372 Sequence s;
373 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
374 .InSequence(s)
375 .After(authenticated)
376 .WillOnce(DoAll(
377 // This event should get through to the clipboard stub.
378 InjectClipboardEvent(connection_, clipboard_event2),
379 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
380 // This event should not get through to the clipboard stub,
381 // because the client has disconnected.
382 InjectClipboardEvent(connection_, clipboard_event3),
383 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
384 EXPECT_CALL(*input_injector_, InjectClipboardEvent(EqualsClipboardEvent(
385 kMimeTypeTextUtf8, "b")))
386 .InSequence(s);
387 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
388 .InSequence(s);
390 // This event should not get through to the clipboard stub,
391 // because the client isn't authenticated yet.
392 connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event1);
394 ConnectClientSession();
397 TEST_F(ClientSessionTest, InputStubFilter) {
398 CreateClientSession();
400 protocol::KeyEvent key_event1;
401 key_event1.set_pressed(true);
402 key_event1.set_usb_keycode(1);
404 protocol::KeyEvent key_event2_down;
405 key_event2_down.set_pressed(true);
406 key_event2_down.set_usb_keycode(2);
408 protocol::KeyEvent key_event2_up;
409 key_event2_up.set_pressed(false);
410 key_event2_up.set_usb_keycode(2);
412 protocol::KeyEvent key_event3;
413 key_event3.set_pressed(true);
414 key_event3.set_usb_keycode(3);
416 protocol::MouseEvent mouse_event1;
417 mouse_event1.set_x(100);
418 mouse_event1.set_y(101);
420 protocol::MouseEvent mouse_event2;
421 mouse_event2.set_x(200);
422 mouse_event2.set_y(201);
424 protocol::MouseEvent mouse_event3;
425 mouse_event3.set_x(300);
426 mouse_event3.set_y(301);
428 Expectation authenticated =
429 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
430 .WillOnce(Return(true));
431 EXPECT_CALL(*input_injector_, StartPtr(_))
432 .After(authenticated);
433 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
434 .After(authenticated);
436 // Wait for the first video packet to be captured to make sure that
437 // the injected input will go though. Otherwise mouse events will be blocked
438 // by the mouse clamping filter.
439 Sequence s;
440 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
441 .InSequence(s)
442 .After(authenticated)
443 .WillOnce(DoAll(
444 // These events should get through to the input stub.
445 InjectKeyEvent(connection_, key_event2_down),
446 InjectKeyEvent(connection_, key_event2_up),
447 InjectMouseEvent(connection_, mouse_event2),
448 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
449 // These events should not get through to the input stub,
450 // because the client has disconnected.
451 InjectKeyEvent(connection_, key_event3),
452 InjectMouseEvent(connection_, mouse_event3),
453 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
454 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
455 .InSequence(s);
456 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
457 .InSequence(s);
458 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
459 .InSequence(s);
460 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
461 .InSequence(s);
463 // These events should not get through to the input stub,
464 // because the client isn't authenticated yet.
465 connection_->input_stub()->InjectKeyEvent(key_event1);
466 connection_->input_stub()->InjectMouseEvent(mouse_event1);
468 ConnectClientSession();
471 TEST_F(ClientSessionTest, LocalInputTest) {
472 CreateClientSession();
474 protocol::MouseEvent mouse_event1;
475 mouse_event1.set_x(100);
476 mouse_event1.set_y(101);
477 protocol::MouseEvent mouse_event2;
478 mouse_event2.set_x(200);
479 mouse_event2.set_y(201);
480 protocol::MouseEvent mouse_event3;
481 mouse_event3.set_x(300);
482 mouse_event3.set_y(301);
484 Expectation authenticated =
485 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
486 .WillOnce(Return(true));
487 EXPECT_CALL(*input_injector_, StartPtr(_))
488 .After(authenticated);
489 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
490 .After(authenticated);
492 // Wait for the first video packet to be captured to make sure that
493 // the injected input will go though. Otherwise mouse events will be blocked
494 // by the mouse clamping filter.
495 Sequence s;
496 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
497 .InSequence(s)
498 .After(authenticated)
499 .WillOnce(DoAll(
500 // This event should get through to the input stub.
501 InjectMouseEvent(connection_, mouse_event1),
502 #if !defined(OS_WIN)
503 // The OS echoes the injected event back.
504 LocalMouseMoved(client_session_.get(), mouse_event1),
505 #endif // !defined(OS_WIN)
506 // This one should get throught as well.
507 InjectMouseEvent(connection_, mouse_event2),
508 // Now this is a genuine local event.
509 LocalMouseMoved(client_session_.get(), mouse_event1),
510 // This one should be blocked because of the previous local input
511 // event.
512 InjectMouseEvent(connection_, mouse_event3),
513 // TODO(jamiewalch): Verify that remote inputs are re-enabled
514 // eventually (via dependency injection, not sleep!)
515 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
516 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
517 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(100, 101)))
518 .InSequence(s);
519 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseEvent(200, 201)))
520 .InSequence(s);
521 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
522 .InSequence(s);
524 ConnectClientSession();
527 TEST_F(ClientSessionTest, RestoreEventState) {
528 CreateClientSession();
530 protocol::KeyEvent key1;
531 key1.set_pressed(true);
532 key1.set_usb_keycode(1);
534 protocol::KeyEvent key2;
535 key2.set_pressed(true);
536 key2.set_usb_keycode(2);
538 protocol::MouseEvent mousedown;
539 mousedown.set_button(protocol::MouseEvent::BUTTON_LEFT);
540 mousedown.set_button_down(true);
542 Expectation authenticated =
543 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
544 .WillOnce(Return(true));
545 EXPECT_CALL(*input_injector_, StartPtr(_))
546 .After(authenticated);
547 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
548 .After(authenticated);
550 // Wait for the first video packet to be captured to make sure that
551 // the injected input will go though. Otherwise mouse events will be blocked
552 // by the mouse clamping filter.
553 Sequence s;
554 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
555 .InSequence(s)
556 .After(authenticated)
557 .WillOnce(DoAll(
558 InjectKeyEvent(connection_, key1),
559 InjectKeyEvent(connection_, key2),
560 InjectMouseEvent(connection_, mousedown),
561 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
562 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
563 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, true)))
564 .InSequence(s);
565 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, true)))
566 .InSequence(s);
567 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
568 protocol::MouseEvent::BUTTON_LEFT, true)))
569 .InSequence(s);
570 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(1, false)))
571 .InSequence(s);
572 EXPECT_CALL(*input_injector_, InjectKeyEvent(EqualsUsbEvent(2, false)))
573 .InSequence(s);
574 EXPECT_CALL(*input_injector_, InjectMouseEvent(EqualsMouseButtonEvent(
575 protocol::MouseEvent::BUTTON_LEFT, false)))
576 .InSequence(s);
577 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
578 .InSequence(s);
580 ConnectClientSession();
583 TEST_F(ClientSessionTest, ClampMouseEvents) {
584 CreateClientSession();
586 Expectation authenticated =
587 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
588 .WillOnce(Return(true));
589 EXPECT_CALL(*input_injector_, StartPtr(_))
590 .After(authenticated);
591 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
592 .After(authenticated);
593 EXPECT_CALL(session_event_handler_, OnSessionClosed(_))
594 .After(authenticated);
596 Expectation connected = authenticated;
598 int input_x[3] = { -999, 100, 999 };
599 int expected_x[3] = { 0, 100, FakeDesktopCapturer::kWidth - 1 };
600 int input_y[3] = { -999, 50, 999 };
601 int expected_y[3] = { 0, 50, FakeDesktopCapturer::kHeight - 1 };
603 protocol::MouseEvent expected_event;
604 for (int j = 0; j < 3; j++) {
605 for (int i = 0; i < 3; i++) {
606 protocol::MouseEvent injected_event;
607 injected_event.set_x(input_x[i]);
608 injected_event.set_y(input_y[j]);
610 if (i == 0 && j == 0) {
611 // Inject the 1st event once a video packet has been received.
612 connected =
613 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
614 .After(connected)
615 .WillOnce(InjectMouseEvent(connection_, injected_event));
616 } else {
617 // Every next event is injected once the previous event has been
618 // received.
619 connected =
620 EXPECT_CALL(*input_injector_,
621 InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
622 expected_event.y())))
623 .After(connected)
624 .WillOnce(InjectMouseEvent(connection_, injected_event));
627 expected_event.set_x(expected_x[i]);
628 expected_event.set_y(expected_y[j]);
632 // Shutdown the connection once the last event has been received.
633 EXPECT_CALL(*input_injector_,
634 InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
635 expected_event.y())))
636 .After(connected)
637 .WillOnce(DoAll(
638 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
639 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
641 ConnectClientSession();
644 TEST_F(ClientSessionTest, NoGnubbyAuth) {
645 CreateClientSession();
647 protocol::ExtensionMessage message;
648 message.set_type("gnubby-auth");
649 message.set_data("test");
651 Expectation authenticated =
652 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
653 .WillOnce(Return(true));
654 EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated);
655 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
656 .After(authenticated)
657 .WillOnce(DoAll(
658 DeliverClientMessage(client_session_.get(), message),
659 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
660 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
661 EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
663 ConnectClientSession();
666 TEST_F(ClientSessionTest, EnableGnubbyAuth) {
667 CreateClientSession();
669 // Lifetime controlled by object under test.
670 MockGnubbyAuthHandler* gnubby_auth_handler = new MockGnubbyAuthHandler();
672 protocol::ExtensionMessage message;
673 message.set_type("gnubby-auth");
674 message.set_data("test");
676 Expectation authenticated =
677 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
678 .WillOnce(Return(true));
679 EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated);
680 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
681 .After(authenticated)
682 .WillOnce(DoAll(
683 SetGnubbyAuthHandlerForTesting(client_session_.get(),
684 gnubby_auth_handler),
685 DeliverClientMessage(client_session_.get(), message),
686 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
687 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
688 EXPECT_CALL(*gnubby_auth_handler, DeliverClientMessage(_));
689 EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
691 ConnectClientSession();
694 // Verifies that the client's video pipeline can be reset mid-session.
695 TEST_F(ClientSessionTest, ResetVideoPipeline) {
696 CreateClientSession();
698 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
699 .WillOnce(Return(true));
701 EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
702 .WillOnce(DoAll(
703 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
704 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
706 ConnectClientSession();
708 client_session_->ResetVideoPipeline();
711 // Verifies that clients can have extensions registered, resulting in the
712 // correct capabilities being reported, and messages delivered correctly.
713 // The extension system is tested more extensively in the
714 // HostExtensionSessionManager unit-tests.
715 TEST_F(ClientSessionTest, Extensions) {
716 // Configure fake extensions for testing.
717 FakeExtension extension1("ext1", "cap1");
718 extensions_.push_back(&extension1);
719 FakeExtension extension2("ext2", "");
720 extensions_.push_back(&extension2);
721 FakeExtension extension3("ext3", "cap3");
722 extensions_.push_back(&extension3);
724 // Set the second extension to request to modify the video pipeline.
725 extension2.set_steal_video_capturer(true);
727 CreateClientSession();
729 Expectation authenticated =
730 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
731 .WillOnce(Return(true));
733 // Verify that the ClientSession reports the correct capabilities, and mimic
734 // the client reporting an overlapping set of capabilities.
735 EXPECT_CALL(client_stub_,
736 SetCapabilities(EqCapabilities("cap1 cap3 default")))
737 .After(authenticated)
738 .WillOnce(SetCapabilities(client_session_.get(), "cap1 cap4 default"));
740 // Verify that the correct extension messages are delivered, and dropped.
741 protocol::ExtensionMessage message1;
742 message1.set_type("ext1");
743 message1.set_data("data");
744 protocol::ExtensionMessage message3;
745 message3.set_type("ext3");
746 message3.set_data("data");
747 protocol::ExtensionMessage message4;
748 message4.set_type("ext4");
749 message4.set_data("data");
750 EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_))
751 .WillOnce(DoAll(
752 DeliverClientMessage(client_session_.get(), message1),
753 DeliverClientMessage(client_session_.get(), message3),
754 DeliverClientMessage(client_session_.get(), message4),
755 InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
756 InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
758 // Simulate the ClientSession connect and extension negotiation.
759 ConnectClientSession();
760 base::RunLoop().RunUntilIdle();
762 // ext1 was instantiated and sent a message, and did not wrap anything.
763 EXPECT_TRUE(extension1.was_instantiated());
764 EXPECT_TRUE(extension1.has_handled_message());
765 EXPECT_FALSE(extension1.has_wrapped_video_encoder());
767 // ext2 was instantiated but not sent a message, and wrapped video encoder.
768 EXPECT_TRUE(extension2.was_instantiated());
769 EXPECT_FALSE(extension2.has_handled_message());
770 EXPECT_TRUE(extension2.has_wrapped_video_encoder());
772 // ext3 was sent a message but not instantiated.
773 EXPECT_FALSE(extension3.was_instantiated());
776 // Verifies that an extension can "steal" the video capture, in which case no
777 // VideoScheduler is instantiated.
778 TEST_F(ClientSessionTest, StealVideoCapturer) {
779 FakeExtension extension("ext1", "cap1");
780 extensions_.push_back(&extension);
782 CreateClientSession();
784 SetMatchCapabilitiesExpectation();
786 EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_))
787 .WillOnce(Return(true));
789 ConnectClientSession();
791 base::RunLoop().RunUntilIdle();
793 extension.set_steal_video_capturer(true);
794 client_session_->ResetVideoPipeline();
796 base::RunLoop().RunUntilIdle();
798 // Verify that video control messages received while there is no video
799 // scheduler active won't crash things.
800 protocol::VideoControl video_control;
801 video_control.set_enable(false);
802 video_control.set_lossless_encode(true);
803 video_control.set_lossless_color(true);
804 client_session_->ControlVideo(video_control);
806 // TODO(wez): Find a way to verify that the ClientSession never captures any
807 // frames in this case.
809 DisconnectClientSession();
810 StopClientSession();
812 // ext1 was instantiated and wrapped the video capturer.
813 EXPECT_TRUE(extension.was_instantiated());
814 EXPECT_TRUE(extension.has_wrapped_video_capturer());
817 } // namespace remoting