Fix mouse warp with 2x displays
[chromium-blink-merge.git] / remoting / host / desktop_process_unittest.cc
blob0f2a89b4642b7c90d326539db54a9f712089ad2c
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 "remoting/host/desktop_process.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/location.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "ipc/ipc_channel.h"
15 #include "ipc/ipc_channel_proxy.h"
16 #include "ipc/ipc_listener.h"
17 #include "ipc/ipc_message.h"
18 #include "remoting/base/auto_thread.h"
19 #include "remoting/base/auto_thread_task_runner.h"
20 #include "remoting/host/chromoting_messages.h"
21 #include "remoting/host/desktop_process.h"
22 #include "remoting/host/fake_desktop_capturer.h"
23 #include "remoting/host/host_exit_codes.h"
24 #include "remoting/host/host_mock_objects.h"
25 #include "remoting/host/screen_resolution.h"
26 #include "remoting/protocol/protocol_mock_objects.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gmock_mutant.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 using testing::_;
32 using testing::AnyNumber;
33 using testing::AtMost;
34 using testing::InSequence;
35 using testing::Return;
37 namespace remoting {
39 namespace {
41 class MockDaemonListener : public IPC::Listener {
42 public:
43 MockDaemonListener() {}
44 ~MockDaemonListener() override {}
46 bool OnMessageReceived(const IPC::Message& message) override;
48 MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit));
49 MOCK_METHOD1(OnChannelConnected, void(int32));
50 MOCK_METHOD0(OnChannelError, void());
52 private:
53 DISALLOW_COPY_AND_ASSIGN(MockDaemonListener);
56 class MockNetworkListener : public IPC::Listener {
57 public:
58 MockNetworkListener() {}
59 ~MockNetworkListener() override {}
61 bool OnMessageReceived(const IPC::Message& message) override;
63 MOCK_METHOD1(OnChannelConnected, void(int32));
64 MOCK_METHOD0(OnChannelError, void());
66 MOCK_METHOD0(OnDesktopEnvironmentCreated, void());
68 private:
69 DISALLOW_COPY_AND_ASSIGN(MockNetworkListener);
72 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
73 bool handled = true;
74 IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message)
75 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
76 OnDesktopAttached)
77 IPC_MESSAGE_UNHANDLED(handled = false)
78 IPC_END_MESSAGE_MAP()
80 EXPECT_TRUE(handled);
81 return handled;
84 bool MockNetworkListener::OnMessageReceived(const IPC::Message& message) {
85 bool handled = true;
87 // TODO(alexeypa): handle received messages here.
89 EXPECT_TRUE(handled);
90 return handled;
93 } // namespace
95 class DesktopProcessTest : public testing::Test {
96 public:
97 DesktopProcessTest();
98 ~DesktopProcessTest() override;
100 // testing::Test overrides
101 void SetUp() override;
102 void TearDown() override;
104 // MockDaemonListener mocks
105 void ConnectNetworkChannel(IPC::PlatformFileForTransit desktop_process);
106 void OnDesktopAttached(IPC::PlatformFileForTransit desktop_process);
108 // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
109 // DesktopEnvironmentFactory::Create().
110 DesktopEnvironment* CreateDesktopEnvironment();
112 // Creates a dummy InputInjector, to mock
113 // DesktopEnvironment::CreateInputInjector().
114 InputInjector* CreateInputInjector();
116 // Creates a fake webrtc::DesktopCapturer, to mock
117 // DesktopEnvironment::CreateVideoCapturer().
118 webrtc::DesktopCapturer* CreateVideoCapturer();
120 // Disconnects the daemon-to-desktop channel causing the desktop process to
121 // exit.
122 void DisconnectChannels();
124 // Posts DisconnectChannels() to |message_loop_|.
125 void PostDisconnectChannels();
127 // Runs the desktop process code in a separate thread.
128 void RunDesktopProcess();
130 // Creates the desktop process and sends a crash request to it.
131 void RunDeathTest();
133 // Sends a crash request to the desktop process.
134 void SendCrashRequest();
136 // Requests the desktop process to start the desktop session agent.
137 void SendStartSessionAgent();
139 protected:
140 // The daemon's end of the daemon-to-desktop channel.
141 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
143 // Delegate that is passed to |daemon_channel_|.
144 MockDaemonListener daemon_listener_;
146 // Runs the daemon's end of the channel.
147 base::MessageLoopForUI message_loop_;
149 scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
151 // The network's end of the network-to-desktop channel.
152 scoped_ptr<IPC::ChannelProxy> network_channel_;
154 // Delegate that is passed to |network_channel_|.
155 MockNetworkListener network_listener_;
158 DesktopProcessTest::DesktopProcessTest() {}
160 DesktopProcessTest::~DesktopProcessTest() {
163 void DesktopProcessTest::SetUp() {
166 void DesktopProcessTest::TearDown() {
169 void DesktopProcessTest::ConnectNetworkChannel(
170 IPC::PlatformFileForTransit desktop_process) {
172 #if defined(OS_POSIX)
173 IPC::ChannelHandle channel_handle(std::string(), desktop_process);
174 #elif defined(OS_WIN)
175 IPC::ChannelHandle channel_handle(desktop_process);
176 #endif // defined(OS_WIN)
178 network_channel_ = IPC::ChannelProxy::Create(channel_handle,
179 IPC::Channel::MODE_CLIENT,
180 &network_listener_,
181 io_task_runner_.get());
184 void DesktopProcessTest::OnDesktopAttached(
185 IPC::PlatformFileForTransit desktop_process) {
186 #if defined(OS_POSIX)
187 DCHECK(desktop_process.auto_close);
189 base::File closer(IPC::PlatformFileForTransitToFile(desktop_process));
190 #endif // defined(OS_POSIX)
193 DesktopEnvironment* DesktopProcessTest::CreateDesktopEnvironment() {
194 MockDesktopEnvironment* desktop_environment = new MockDesktopEnvironment();
195 EXPECT_CALL(*desktop_environment, CreateAudioCapturerPtr())
196 .Times(0);
197 EXPECT_CALL(*desktop_environment, CreateInputInjectorPtr())
198 .Times(AtMost(1))
199 .WillOnce(Invoke(this, &DesktopProcessTest::CreateInputInjector));
200 EXPECT_CALL(*desktop_environment, CreateScreenControlsPtr())
201 .Times(AtMost(1));
202 EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
203 .Times(AtMost(1))
204 .WillOnce(Invoke(this, &DesktopProcessTest::CreateVideoCapturer));
205 EXPECT_CALL(*desktop_environment, GetCapabilities())
206 .Times(AtMost(1));
207 EXPECT_CALL(*desktop_environment, SetCapabilities(_))
208 .Times(AtMost(1));
210 // Notify the test that the desktop environment has been created.
211 network_listener_.OnDesktopEnvironmentCreated();
212 return desktop_environment;
215 InputInjector* DesktopProcessTest::CreateInputInjector() {
216 MockInputInjector* input_injector = new MockInputInjector();
217 EXPECT_CALL(*input_injector, StartPtr(_));
218 return input_injector;
221 webrtc::DesktopCapturer* DesktopProcessTest::CreateVideoCapturer() {
222 return new FakeDesktopCapturer();
225 void DesktopProcessTest::DisconnectChannels() {
226 daemon_channel_.reset();
227 network_channel_.reset();
228 io_task_runner_ = nullptr;
231 void DesktopProcessTest::PostDisconnectChannels() {
232 message_loop_.PostTask(FROM_HERE, base::Bind(
233 &DesktopProcessTest::DisconnectChannels, base::Unretained(this)));
236 void DesktopProcessTest::RunDesktopProcess() {
237 base::RunLoop run_loop;
238 base::Closure quit_ui_task_runner = base::Bind(
239 base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
240 message_loop_.task_runner(),
241 FROM_HERE, run_loop.QuitClosure());
242 scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
243 message_loop_.task_runner(), quit_ui_task_runner);
245 io_task_runner_ = AutoThread::CreateWithType(
246 "IPC thread", ui_task_runner, base::MessageLoop::TYPE_IO);
248 std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID();
249 daemon_channel_ = IPC::ChannelProxy::Create(IPC::ChannelHandle(channel_name),
250 IPC::Channel::MODE_SERVER,
251 &daemon_listener_,
252 io_task_runner_.get());
254 scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory(
255 new MockDesktopEnvironmentFactory());
256 EXPECT_CALL(*desktop_environment_factory, CreatePtr())
257 .Times(AnyNumber())
258 .WillRepeatedly(Invoke(this,
259 &DesktopProcessTest::CreateDesktopEnvironment));
260 EXPECT_CALL(*desktop_environment_factory, SupportsAudioCapture())
261 .Times(AnyNumber())
262 .WillRepeatedly(Return(false));
264 DesktopProcess desktop_process(ui_task_runner, io_task_runner_, channel_name);
265 EXPECT_TRUE(desktop_process.Start(desktop_environment_factory.Pass()));
267 ui_task_runner = nullptr;
268 run_loop.Run();
271 void DesktopProcessTest::RunDeathTest() {
272 InSequence s;
273 EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
274 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
275 .WillOnce(DoAll(
276 Invoke(this, &DesktopProcessTest::OnDesktopAttached),
277 InvokeWithoutArgs(this, &DesktopProcessTest::SendCrashRequest)));
279 RunDesktopProcess();
282 void DesktopProcessTest::SendCrashRequest() {
283 tracked_objects::Location location = FROM_HERE;
284 daemon_channel_->Send(new ChromotingDaemonMsg_Crash(
285 location.function_name(), location.file_name(), location.line_number()));
288 void DesktopProcessTest::SendStartSessionAgent() {
289 network_channel_->Send(new ChromotingNetworkDesktopMsg_StartSessionAgent(
290 "user@domain/rest-of-jid", ScreenResolution(), false));
293 // Launches the desktop process and waits when it connects back.
294 TEST_F(DesktopProcessTest, Basic) {
295 InSequence s;
296 EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
297 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
298 .WillOnce(DoAll(
299 Invoke(this, &DesktopProcessTest::OnDesktopAttached),
300 InvokeWithoutArgs(this, &DesktopProcessTest::DisconnectChannels)));
302 RunDesktopProcess();
305 // Launches the desktop process and waits when it connects back.
306 TEST_F(DesktopProcessTest, ConnectNetworkChannel) {
307 InSequence s;
308 EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
309 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
310 .WillOnce(Invoke(this, &DesktopProcessTest::ConnectNetworkChannel));
311 EXPECT_CALL(network_listener_, OnChannelConnected(_))
312 .WillOnce(InvokeWithoutArgs(
313 this, &DesktopProcessTest::DisconnectChannels));
315 RunDesktopProcess();
318 // Launches the desktop process, waits when it connects back and starts
319 // the desktop session agent.
320 TEST_F(DesktopProcessTest, StartSessionAgent) {
322 InSequence s;
323 EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
324 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
325 .WillOnce(Invoke(this, &DesktopProcessTest::ConnectNetworkChannel));
326 EXPECT_CALL(network_listener_, OnChannelConnected(_))
327 .WillOnce(InvokeWithoutArgs(
328 this, &DesktopProcessTest::SendStartSessionAgent));
331 EXPECT_CALL(network_listener_, OnDesktopEnvironmentCreated())
332 .WillOnce(InvokeWithoutArgs(
333 this, &DesktopProcessTest::PostDisconnectChannels));
335 RunDesktopProcess();
338 // Run the desktop process and ask it to crash.
339 TEST_F(DesktopProcessTest, DeathTest) {
340 testing::GTEST_FLAG(death_test_style) = "threadsafe";
342 EXPECT_DEATH(RunDeathTest(), "");
345 } // namespace remoting