Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / remoting / host / win / worker_process_launcher_unittest.cc
blobde38a0017cda42131ddf01f8e912c27d6d2e109a
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/basictypes.h"
6 #include "base/bind.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/win/scoped_handle.h"
10 #include "base/win/scoped_process_information.h"
11 #include "ipc/ipc_channel.h"
12 #include "ipc/ipc_channel_proxy.h"
13 #include "ipc/ipc_listener.h"
14 #include "ipc/ipc_message.h"
15 #include "remoting/base/auto_thread_task_runner.h"
16 #include "remoting/host/chromoting_messages.h"
17 #include "remoting/host/host_exit_codes.h"
18 #include "remoting/host/ipc_util.h"
19 #include "remoting/host/win/launch_process_with_token.h"
20 #include "remoting/host/win/worker_process_launcher.h"
21 #include "remoting/host/worker_process_ipc_delegate.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gmock_mutant.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using base::win::ScopedHandle;
27 using testing::_;
28 using testing::AnyNumber;
29 using testing::CreateFunctor;
30 using testing::DoAll;
31 using testing::Expectation;
32 using testing::Invoke;
33 using testing::InvokeWithoutArgs;
34 using testing::Return;
36 namespace remoting {
38 namespace {
40 const char kIpcSecurityDescriptor[] = "D:(A;;GA;;;AU)";
42 class MockProcessLauncherDelegate : public WorkerProcessLauncher::Delegate {
43 public:
44 MockProcessLauncherDelegate() {}
45 ~MockProcessLauncherDelegate() override {}
47 // WorkerProcessLauncher::Delegate interface.
48 MOCK_METHOD1(LaunchProcess, void(WorkerProcessLauncher*));
49 MOCK_METHOD1(Send, void(IPC::Message*));
50 MOCK_METHOD0(CloseChannel, void());
51 MOCK_METHOD0(KillProcess, void());
53 private:
54 DISALLOW_COPY_AND_ASSIGN(MockProcessLauncherDelegate);
57 class MockIpcDelegate : public WorkerProcessIpcDelegate {
58 public:
59 MockIpcDelegate() {}
60 ~MockIpcDelegate() override {}
62 // WorkerProcessIpcDelegate interface.
63 MOCK_METHOD1(OnChannelConnected, void(int32));
64 MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message&));
65 MOCK_METHOD1(OnPermanentError, void(int));
67 private:
68 DISALLOW_COPY_AND_ASSIGN(MockIpcDelegate);
71 class MockWorkerListener : public IPC::Listener {
72 public:
73 MockWorkerListener() {}
74 ~MockWorkerListener() override {}
76 MOCK_METHOD3(OnCrash, void(const std::string&, const std::string&, int));
78 // IPC::Listener implementation
79 bool OnMessageReceived(const IPC::Message& message) override;
81 private:
82 DISALLOW_COPY_AND_ASSIGN(MockWorkerListener);
85 bool MockWorkerListener::OnMessageReceived(const IPC::Message& message) {
86 bool handled = true;
87 IPC_BEGIN_MESSAGE_MAP(MockWorkerListener, message)
88 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
89 IPC_MESSAGE_UNHANDLED(handled = false)
90 IPC_END_MESSAGE_MAP()
92 EXPECT_TRUE(handled);
94 return handled;
97 } // namespace
99 class WorkerProcessLauncherTest
100 : public testing::Test,
101 public IPC::Listener {
102 public:
103 WorkerProcessLauncherTest();
104 ~WorkerProcessLauncherTest() override;
106 void SetUp() override;
107 void TearDown() override;
109 // IPC::Listener implementation.
110 bool OnMessageReceived(const IPC::Message& message) override;
111 void OnChannelConnected(int32 peer_pid) override;
112 void OnChannelError() override;
114 // WorkerProcessLauncher::Delegate mocks
115 void LaunchProcess(
116 WorkerProcessLauncher* event_handler);
117 void LaunchProcessAndConnect(
118 WorkerProcessLauncher* event_handler);
119 void FailLaunchAndStopWorker(
120 WorkerProcessLauncher* event_handler);
121 void KillProcess();
123 void TerminateWorker(DWORD exit_code);
125 // Connects the client end of the channel (the worker process's end).
126 void ConnectClient();
128 // Disconnects the client end of the channel.
129 void DisconnectClient();
131 // Disconnects the server end of the channel (the launcher's end).
132 void DisconnectServer();
134 // Sends a message to the worker process.
135 void SendToProcess(IPC::Message* message);
137 // Sends a fake message to the launcher.
138 void SendFakeMessageToLauncher();
140 // Requests the worker to crash.
141 void CrashWorker();
143 // Starts the worker.
144 void StartWorker();
146 // Stops the worker.
147 void StopWorker();
149 // Quits |message_loop_|.
150 void QuitMainMessageLoop();
152 protected:
153 void DoLaunchProcess();
155 base::MessageLoopForIO message_loop_;
156 scoped_refptr<AutoThreadTaskRunner> task_runner_;
158 // Receives messages sent to the worker process.
159 MockWorkerListener client_listener_;
161 // Receives messages sent from the worker process.
162 MockIpcDelegate server_listener_;
164 // Implements WorkerProcessLauncher::Delegate.
165 scoped_ptr<MockProcessLauncherDelegate> launcher_delegate_;
167 // The name of the IPC channel.
168 std::string channel_name_;
170 // Client and server ends of the IPC channel.
171 scoped_ptr<IPC::ChannelProxy> channel_client_;
172 scoped_ptr<IPC::ChannelProxy> channel_server_;
174 WorkerProcessLauncher* event_handler_;
176 // The worker process launcher.
177 scoped_ptr<WorkerProcessLauncher> launcher_;
179 // An event that is used to emulate the worker process's handle.
180 ScopedHandle worker_process_;
183 WorkerProcessLauncherTest::WorkerProcessLauncherTest()
184 : event_handler_(nullptr) {
187 WorkerProcessLauncherTest::~WorkerProcessLauncherTest() {
190 void WorkerProcessLauncherTest::SetUp() {
191 task_runner_ = new AutoThreadTaskRunner(
192 message_loop_.task_runner(),
193 base::Bind(&WorkerProcessLauncherTest::QuitMainMessageLoop,
194 base::Unretained(this)));
196 // Set up process launcher delegate
197 launcher_delegate_.reset(new MockProcessLauncherDelegate());
198 EXPECT_CALL(*launcher_delegate_, Send(_))
199 .Times(AnyNumber())
200 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::SendToProcess));
201 EXPECT_CALL(*launcher_delegate_, CloseChannel())
202 .Times(AnyNumber())
203 .WillRepeatedly(Invoke(this,
204 &WorkerProcessLauncherTest::DisconnectServer));
205 EXPECT_CALL(*launcher_delegate_, KillProcess())
206 .Times(AnyNumber())
207 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::KillProcess));
209 // Set up IPC delegate.
210 EXPECT_CALL(server_listener_, OnMessageReceived(_))
211 .Times(0);
214 void WorkerProcessLauncherTest::TearDown() {
217 bool WorkerProcessLauncherTest::OnMessageReceived(const IPC::Message& message) {
218 return event_handler_->OnMessageReceived(message);
221 void WorkerProcessLauncherTest::OnChannelConnected(int32 peer_pid) {
222 event_handler_->OnChannelConnected(peer_pid);
225 void WorkerProcessLauncherTest::OnChannelError() {
226 event_handler_->OnChannelError();
229 void WorkerProcessLauncherTest::LaunchProcess(
230 WorkerProcessLauncher* event_handler) {
231 EXPECT_FALSE(event_handler_);
232 event_handler_ = event_handler;
234 DoLaunchProcess();
237 void WorkerProcessLauncherTest::LaunchProcessAndConnect(
238 WorkerProcessLauncher* event_handler) {
239 EXPECT_FALSE(event_handler_);
240 event_handler_ = event_handler;
242 DoLaunchProcess();
244 task_runner_->PostTask(
245 FROM_HERE,
246 base::Bind(&WorkerProcessLauncherTest::ConnectClient,
247 base::Unretained(this)));
250 void WorkerProcessLauncherTest::FailLaunchAndStopWorker(
251 WorkerProcessLauncher* event_handler) {
252 EXPECT_FALSE(event_handler_);
254 event_handler->OnFatalError();
256 task_runner_->PostTask(
257 FROM_HERE,
258 base::Bind(&WorkerProcessLauncherTest::StopWorker,
259 base::Unretained(this)));
262 void WorkerProcessLauncherTest::KillProcess() {
263 event_handler_ = nullptr;
265 if (worker_process_.IsValid()) {
266 TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT);
267 worker_process_.Close();
271 void WorkerProcessLauncherTest::TerminateWorker(DWORD exit_code) {
272 if (worker_process_.IsValid())
273 TerminateProcess(worker_process_.Get(), exit_code);
276 void WorkerProcessLauncherTest::ConnectClient() {
277 channel_client_ = IPC::ChannelProxy::Create(IPC::ChannelHandle(channel_name_),
278 IPC::Channel::MODE_CLIENT,
279 &client_listener_,
280 task_runner_,
281 nullptr);
283 // Pretend that |kLaunchSuccessTimeoutSeconds| passed since launching
284 // the worker process. This will make the backoff algorithm think that this
285 // launch attempt was successful and it will not delay the next launch.
286 launcher_->RecordSuccessfulLaunchForTest();
289 void WorkerProcessLauncherTest::DisconnectClient() {
290 channel_client_.reset();
293 void WorkerProcessLauncherTest::DisconnectServer() {
294 channel_server_.reset();
297 void WorkerProcessLauncherTest::SendToProcess(IPC::Message* message) {
298 if (channel_server_) {
299 channel_server_->Send(message);
300 return;
303 delete message;
306 void WorkerProcessLauncherTest::SendFakeMessageToLauncher() {
307 if (channel_client_)
308 channel_client_->Send(new ChromotingDesktopNetworkMsg_DisconnectSession());
311 void WorkerProcessLauncherTest::CrashWorker() {
312 launcher_->Crash(FROM_HERE);
315 void WorkerProcessLauncherTest::StartWorker() {
316 launcher_.reset(new WorkerProcessLauncher(
317 launcher_delegate_.Pass(),
318 &server_listener_));
320 launcher_->SetKillProcessTimeoutForTest(base::TimeDelta::FromMilliseconds(0));
323 void WorkerProcessLauncherTest::StopWorker() {
324 launcher_.reset();
325 DisconnectClient();
326 channel_name_.clear();
327 channel_server_.reset();
328 task_runner_ = nullptr;
331 void WorkerProcessLauncherTest::QuitMainMessageLoop() {
332 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
335 void WorkerProcessLauncherTest::DoLaunchProcess() {
336 EXPECT_TRUE(event_handler_);
337 EXPECT_FALSE(worker_process_.IsValid());
339 WCHAR notepad[MAX_PATH + 1];
340 ASSERT_GT(ExpandEnvironmentStrings(
341 L"\045SystemRoot\045\\system32\\notepad.exe", notepad, MAX_PATH), 0u);
343 STARTUPINFOW startup_info = { 0 };
344 startup_info.cb = sizeof(startup_info);
346 PROCESS_INFORMATION temp_process_info = {};
347 ASSERT_TRUE(CreateProcess(nullptr,
348 notepad,
349 nullptr, // default process attibutes
350 nullptr, // default thread attibutes
351 FALSE, // do not inherit handles
352 CREATE_SUSPENDED,
353 nullptr, // no environment
354 nullptr, // default current directory
355 &startup_info,
356 &temp_process_info));
357 base::win::ScopedProcessInformation process_information(temp_process_info);
358 worker_process_.Set(process_information.TakeProcessHandle());
359 ASSERT_TRUE(worker_process_.IsValid());
361 channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID();
362 ScopedHandle pipe;
363 ASSERT_TRUE(CreateIpcChannel(channel_name_, kIpcSecurityDescriptor, &pipe));
365 // Wrap the pipe into an IPC channel.
366 channel_server_ = IPC::ChannelProxy::Create(
367 IPC::ChannelHandle(pipe.Get()), IPC::Channel::MODE_SERVER, this,
368 task_runner_, nullptr);
370 HANDLE temp_handle;
371 ASSERT_TRUE(DuplicateHandle(GetCurrentProcess(),
372 worker_process_.Get(),
373 GetCurrentProcess(),
374 &temp_handle,
376 FALSE,
377 DUPLICATE_SAME_ACCESS));
378 ScopedHandle copy(temp_handle);
380 event_handler_->OnProcessLaunched(copy.Pass());
383 TEST_F(WorkerProcessLauncherTest, Start) {
384 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
385 .Times(1)
386 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::LaunchProcess));
388 EXPECT_CALL(server_listener_, OnChannelConnected(_))
389 .Times(0);
390 EXPECT_CALL(server_listener_, OnPermanentError(_))
391 .Times(0);
393 StartWorker();
394 StopWorker();
395 message_loop_.Run();
398 // Starts and connects to the worker process. Expect OnChannelConnected to be
399 // called.
400 TEST_F(WorkerProcessLauncherTest, StartAndConnect) {
401 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
402 .Times(1)
403 .WillRepeatedly(Invoke(
404 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
406 EXPECT_CALL(server_listener_, OnChannelConnected(_))
407 .Times(1)
408 .WillOnce(InvokeWithoutArgs(this,
409 &WorkerProcessLauncherTest::StopWorker));
410 EXPECT_CALL(server_listener_, OnPermanentError(_))
411 .Times(0);
413 StartWorker();
414 message_loop_.Run();
417 // Kills the worker process after the 1st connect and expects it to be
418 // restarted.
419 TEST_F(WorkerProcessLauncherTest, Restart) {
420 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
421 .Times(2)
422 .WillRepeatedly(Invoke(
423 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
424 Expectation first_connect =
425 EXPECT_CALL(server_listener_, OnChannelConnected(_))
426 .Times(2)
427 .WillOnce(InvokeWithoutArgs(CreateFunctor(
428 this, &WorkerProcessLauncherTest::TerminateWorker,
429 CONTROL_C_EXIT)))
430 .WillOnce(InvokeWithoutArgs(this,
431 &WorkerProcessLauncherTest::StopWorker));
433 EXPECT_CALL(server_listener_, OnPermanentError(_))
434 .Times(0);
436 StartWorker();
437 message_loop_.Run();
440 // Drops the IPC channel to the worker process after the 1st connect and expects
441 // the worker process to be restarted.
442 TEST_F(WorkerProcessLauncherTest, DropIpcChannel) {
443 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
444 .Times(2)
445 .WillRepeatedly(Invoke(
446 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
448 Expectation first_connect =
449 EXPECT_CALL(server_listener_, OnChannelConnected(_))
450 .Times(2)
451 .WillOnce(InvokeWithoutArgs(
452 this, &WorkerProcessLauncherTest::DisconnectClient))
453 .WillOnce(InvokeWithoutArgs(
454 this, &WorkerProcessLauncherTest::StopWorker));
456 EXPECT_CALL(server_listener_, OnPermanentError(_))
457 .Times(0);
459 StartWorker();
460 message_loop_.Run();
463 // Returns a permanent error exit code and expects OnPermanentError() to be
464 // invoked.
465 TEST_F(WorkerProcessLauncherTest, PermanentError) {
466 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
467 .Times(1)
468 .WillRepeatedly(Invoke(
469 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
471 EXPECT_CALL(server_listener_, OnChannelConnected(_))
472 .Times(1)
473 .WillOnce(InvokeWithoutArgs(CreateFunctor(
474 this, &WorkerProcessLauncherTest::TerminateWorker,
475 kMinPermanentErrorExitCode)));
476 EXPECT_CALL(server_listener_, OnPermanentError(_))
477 .Times(1)
478 .WillOnce(InvokeWithoutArgs(this,
479 &WorkerProcessLauncherTest::StopWorker));
481 StartWorker();
482 message_loop_.Run();
485 // Requests the worker to crash and expects it to honor the request.
486 TEST_F(WorkerProcessLauncherTest, Crash) {
487 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
488 .Times(2)
489 .WillRepeatedly(Invoke(
490 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
492 EXPECT_CALL(server_listener_, OnChannelConnected(_))
493 .Times(2)
494 .WillOnce(InvokeWithoutArgs(this,
495 &WorkerProcessLauncherTest::CrashWorker))
496 .WillOnce(InvokeWithoutArgs(this,
497 &WorkerProcessLauncherTest::StopWorker));
499 EXPECT_CALL(client_listener_, OnCrash(_, _, _))
500 .Times(1)
501 .WillOnce(InvokeWithoutArgs(CreateFunctor(
502 this, &WorkerProcessLauncherTest::TerminateWorker,
503 EXCEPTION_BREAKPOINT)));
505 StartWorker();
506 message_loop_.Run();
509 // Requests the worker to crash and terminates the worker even if it does not
510 // comply.
511 TEST_F(WorkerProcessLauncherTest, CrashAnyway) {
512 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_))
513 .Times(2)
514 .WillRepeatedly(Invoke(
515 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
517 EXPECT_CALL(server_listener_, OnChannelConnected(_))
518 .Times(2)
519 .WillOnce(InvokeWithoutArgs(this,
520 &WorkerProcessLauncherTest::CrashWorker))
521 .WillOnce(InvokeWithoutArgs(this,
522 &WorkerProcessLauncherTest::StopWorker));
524 // Ignore the crash request and try send another message to the launcher.
525 EXPECT_CALL(client_listener_, OnCrash(_, _, _))
526 .Times(1)
527 .WillOnce(InvokeWithoutArgs(
528 this, &WorkerProcessLauncherTest::SendFakeMessageToLauncher));
530 StartWorker();
531 message_loop_.Run();
534 } // namespace remoting