Upstream version 10.39.233.0
[platform/framework/web/crosswalk.git] / src / remoting / host / desktop_process_unittest.cc
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 "remoting/host/desktop_process.h"
6
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"
30
31 using testing::_;
32 using testing::AnyNumber;
33 using testing::AtMost;
34 using testing::InSequence;
35 using testing::Return;
36
37 namespace remoting {
38
39 namespace {
40
41 class MockDaemonListener : public IPC::Listener {
42  public:
43   MockDaemonListener() {}
44   virtual ~MockDaemonListener() {}
45
46   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
47
48   MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit));
49   MOCK_METHOD1(OnChannelConnected, void(int32));
50   MOCK_METHOD0(OnChannelError, void());
51
52  private:
53   DISALLOW_COPY_AND_ASSIGN(MockDaemonListener);
54 };
55
56 class MockNetworkListener : public IPC::Listener {
57  public:
58   MockNetworkListener() {}
59   virtual ~MockNetworkListener() {}
60
61   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
62
63   MOCK_METHOD1(OnChannelConnected, void(int32));
64   MOCK_METHOD0(OnChannelError, void());
65
66   MOCK_METHOD0(OnDesktopEnvironmentCreated, void());
67
68  private:
69   DISALLOW_COPY_AND_ASSIGN(MockNetworkListener);
70 };
71
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()
79
80   EXPECT_TRUE(handled);
81   return handled;
82 }
83
84 bool MockNetworkListener::OnMessageReceived(const IPC::Message& message) {
85   bool handled = true;
86
87   // TODO(alexeypa): handle received messages here.
88
89   EXPECT_TRUE(handled);
90   return handled;
91 }
92
93 }  // namespace
94
95 class DesktopProcessTest : public testing::Test {
96  public:
97   DesktopProcessTest();
98   virtual ~DesktopProcessTest();
99
100   // testing::Test overrides
101   virtual void SetUp() OVERRIDE;
102   virtual void TearDown() OVERRIDE;
103
104   // MockDaemonListener mocks
105   void ConnectNetworkChannel(IPC::PlatformFileForTransit desktop_process);
106   void OnDesktopAttached(IPC::PlatformFileForTransit desktop_process);
107
108   // Creates a DesktopEnvironment with a fake webrtc::DesktopCapturer, to mock
109   // DesktopEnvironmentFactory::Create().
110   DesktopEnvironment* CreateDesktopEnvironment();
111
112   // Creates a dummy InputInjector, to mock
113   // DesktopEnvironment::CreateInputInjector().
114   InputInjector* CreateInputInjector();
115
116   // Creates a fake webrtc::DesktopCapturer, to mock
117   // DesktopEnvironment::CreateVideoCapturer().
118   webrtc::DesktopCapturer* CreateVideoCapturer();
119
120   // Disconnects the daemon-to-desktop channel causing the desktop process to
121   // exit.
122   void DisconnectChannels();
123
124   // Posts DisconnectChannels() to |message_loop_|.
125   void PostDisconnectChannels();
126
127   // Runs the desktop process code in a separate thread.
128   void RunDesktopProcess();
129
130   // Creates the desktop process and sends a crash request to it.
131   void RunDeathTest();
132
133   // Sends a crash request to the desktop process.
134   void SendCrashRequest();
135
136   // Requests the desktop process to start the desktop session agent.
137   void SendStartSessionAgent();
138
139  protected:
140   // The daemon's end of the daemon-to-desktop channel.
141   scoped_ptr<IPC::ChannelProxy> daemon_channel_;
142
143   // Delegate that is passed to |daemon_channel_|.
144   MockDaemonListener daemon_listener_;
145
146   // Runs the daemon's end of the channel.
147   base::MessageLoopForUI message_loop_;
148
149   scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
150
151   // The network's end of the network-to-desktop channel.
152   scoped_ptr<IPC::ChannelProxy> network_channel_;
153
154   // Delegate that is passed to |network_channel_|.
155   MockNetworkListener network_listener_;
156 };
157
158 DesktopProcessTest::DesktopProcessTest() {}
159
160 DesktopProcessTest::~DesktopProcessTest() {
161 }
162
163 void DesktopProcessTest::SetUp() {
164 }
165
166 void DesktopProcessTest::TearDown() {
167 }
168
169 void DesktopProcessTest::ConnectNetworkChannel(
170     IPC::PlatformFileForTransit desktop_process) {
171
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)
177
178   network_channel_ = IPC::ChannelProxy::Create(channel_handle,
179                                                IPC::Channel::MODE_CLIENT,
180                                                &network_listener_,
181                                                io_task_runner_.get());
182 }
183
184 void DesktopProcessTest::OnDesktopAttached(
185     IPC::PlatformFileForTransit desktop_process) {
186 #if defined(OS_POSIX)
187     DCHECK(desktop_process.auto_close);
188
189     base::File closer(IPC::PlatformFileForTransitToFile(desktop_process));
190 #endif  // defined(OS_POSIX)
191 }
192
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));
209
210   // Notify the test that the desktop environment has been created.
211   network_listener_.OnDesktopEnvironmentCreated();
212   return desktop_environment;
213 }
214
215 InputInjector* DesktopProcessTest::CreateInputInjector() {
216   MockInputInjector* input_injector = new MockInputInjector();
217   EXPECT_CALL(*input_injector, StartPtr(_));
218   return input_injector;
219 }
220
221 webrtc::DesktopCapturer* DesktopProcessTest::CreateVideoCapturer() {
222   return new FakeDesktopCapturer();
223 }
224
225 void DesktopProcessTest::DisconnectChannels() {
226   daemon_channel_.reset();
227   network_channel_.reset();
228   io_task_runner_ = NULL;
229 }
230
231 void DesktopProcessTest::PostDisconnectChannels() {
232   message_loop_.PostTask(FROM_HERE, base::Bind(
233       &DesktopProcessTest::DisconnectChannels, base::Unretained(this)));
234 }
235
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_.message_loop_proxy(),
241       FROM_HERE, run_loop.QuitClosure());
242   scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
243       message_loop_.message_loop_proxy(), quit_ui_task_runner);
244
245   io_task_runner_ = AutoThread::CreateWithType(
246       "IPC thread", ui_task_runner, base::MessageLoop::TYPE_IO);
247
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());
253
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));
263
264   DesktopProcess desktop_process(ui_task_runner, io_task_runner_, channel_name);
265   EXPECT_TRUE(desktop_process.Start(
266       desktop_environment_factory.PassAs<DesktopEnvironmentFactory>()));
267
268   ui_task_runner = NULL;
269   run_loop.Run();
270 }
271
272 void DesktopProcessTest::RunDeathTest() {
273   InSequence s;
274   EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
275   EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
276       .WillOnce(DoAll(
277           Invoke(this, &DesktopProcessTest::OnDesktopAttached),
278           InvokeWithoutArgs(this, &DesktopProcessTest::SendCrashRequest)));
279
280   RunDesktopProcess();
281 }
282
283 void DesktopProcessTest::SendCrashRequest() {
284   tracked_objects::Location location = FROM_HERE;
285   daemon_channel_->Send(new ChromotingDaemonMsg_Crash(
286       location.function_name(), location.file_name(), location.line_number()));
287 }
288
289 void DesktopProcessTest::SendStartSessionAgent() {
290   network_channel_->Send(new ChromotingNetworkDesktopMsg_StartSessionAgent(
291       "user@domain/rest-of-jid", ScreenResolution(), false));
292 }
293
294 // Launches the desktop process and waits when it connects back.
295 TEST_F(DesktopProcessTest, Basic) {
296   InSequence s;
297   EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
298   EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
299       .WillOnce(DoAll(
300           Invoke(this, &DesktopProcessTest::OnDesktopAttached),
301           InvokeWithoutArgs(this, &DesktopProcessTest::DisconnectChannels)));
302
303   RunDesktopProcess();
304 }
305
306 // Launches the desktop process and waits when it connects back.
307 TEST_F(DesktopProcessTest, ConnectNetworkChannel) {
308   InSequence s;
309   EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
310   EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
311       .WillOnce(Invoke(this, &DesktopProcessTest::ConnectNetworkChannel));
312   EXPECT_CALL(network_listener_, OnChannelConnected(_))
313       .WillOnce(InvokeWithoutArgs(
314           this, &DesktopProcessTest::DisconnectChannels));
315
316   RunDesktopProcess();
317 }
318
319 // Launches the desktop process, waits when it connects back and starts
320 // the desktop session agent.
321 TEST_F(DesktopProcessTest, StartSessionAgent) {
322   {
323     InSequence s;
324     EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
325     EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
326         .WillOnce(Invoke(this, &DesktopProcessTest::ConnectNetworkChannel));
327     EXPECT_CALL(network_listener_, OnChannelConnected(_))
328         .WillOnce(InvokeWithoutArgs(
329             this, &DesktopProcessTest::SendStartSessionAgent));
330   }
331
332   EXPECT_CALL(network_listener_, OnDesktopEnvironmentCreated())
333       .WillOnce(InvokeWithoutArgs(
334           this, &DesktopProcessTest::PostDisconnectChannels));
335
336   RunDesktopProcess();
337 }
338
339 // Run the desktop process and ask it to crash.
340 TEST_F(DesktopProcessTest, DeathTest) {
341   testing::GTEST_FLAG(death_test_style) = "threadsafe";
342
343   EXPECT_DEATH(RunDeathTest(), "");
344 }
345
346 }  // namespace remoting