Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(617)

Side by Side Diff: remoting/host/win/worker_process_launcher_unittest.cc

Issue 11040065: [Chromoting] Reimplemented the worker process launcher to take into account the encountered issues: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Count the worker exiting too such as a failure. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "base/bind.h"
6 #include "base/memory/ref_counted.h"
7 #include "base/message_loop.h"
8 #include "base/win/scoped_handle.h"
9 #include "ipc/ipc_channel.h"
10 #include "ipc/ipc_channel_proxy.h"
11 #include "ipc/ipc_listener.h"
12 #include "ipc/ipc_message.h"
13 #include "remoting/base/auto_thread_task_runner.h"
14 #include "remoting/host/host_exit_codes.h"
15 #include "remoting/host/win/worker_process_launcher.h"
16 #include "remoting/host/worker_process_ipc_delegate.h"
17 #include "testing/gmock_mutant.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 using base::win::ScopedHandle;
22 using testing::_;
23 using testing::AnyNumber;
24 using testing::CreateFunctor;
25 using testing::DoAll;
26 using testing::Expectation;
27 using testing::Invoke;
28 using testing::Return;
29 using testing::ReturnPointee;
30
31 namespace remoting {
32
33 namespace {
34
35 const char kIpcSecurityDescriptor[] = "D:(A;;GA;;;AU)";
36
37 class MockProcessLauncherDelegate
38 : public WorkerProcessLauncher::Delegate {
39 public:
40 MockProcessLauncherDelegate() {}
41 virtual ~MockProcessLauncherDelegate() {}
42
43 // WorkerProcessLauncher::Delegate implementation
44 MOCK_METHOD0(GetExitCode, DWORD());
45 MOCK_METHOD1(KillProcess, void(DWORD));
46 MOCK_METHOD2(LaunchProcess, bool(const std::string&, ScopedHandle*));
47
48 private:
49 DISALLOW_COPY_AND_ASSIGN(MockProcessLauncherDelegate);
50 };
51
52 class MockIpcDelegate
53 : public WorkerProcessIpcDelegate {
54 public:
55 MockIpcDelegate() {}
56 virtual ~MockIpcDelegate() {}
57
58 // WorkerProcessIpcDelegate implementation
59 MOCK_METHOD0(OnChannelConnected, void());
60 MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message&));
61 MOCK_METHOD0(OnPermanentError, void());
62
63 private:
64 DISALLOW_COPY_AND_ASSIGN(MockIpcDelegate);
65 };
66
67 } // namespace
68
69 class WorkerProcessLauncherTest
70 : public testing::Test,
71 public IPC::Listener {
72 public:
73 WorkerProcessLauncherTest();
74 virtual ~WorkerProcessLauncherTest();
75
76 virtual void SetUp() OVERRIDE;
77 virtual void TearDown() OVERRIDE;
78
79 // IPC::Listener implementation
80 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
81
82 // WorkerProcessLauncher::Delegate mocks
83 void KillProcess(DWORD exit_code);
84 bool LaunchProcess(const std::string& channel_name,
85 ScopedHandle* process_exit_event_out);
86 bool LaunchProcessAndConnect(const std::string& channel_name,
87 ScopedHandle* process_exit_event_out);
88
89 void ConnectTo(const std::string& channel_name);
90 void Disconnect();
91
92 // Starts the worker.
93 void StartWorker();
94
95 // Stops the worker.
96 void StopWorker();
97
98 // Quits |message_loop_|.
99 void QuitMainMessageLoop();
100
101 protected:
102 MessageLoop message_loop_;
103 scoped_refptr<AutoThreadTaskRunner> task_runner_;
104
105 // Exit code of the worker process.
106 DWORD exit_code_;
107
108 MockIpcDelegate ipc_delegate_;
109 scoped_ptr<MockProcessLauncherDelegate> launcher_delegate_;
110
111 // Client end of the IPC channel.
112 scoped_ptr<IPC::ChannelProxy> ipc_channel_;
113
114 // The worker process launcher.
115 scoped_ptr<WorkerProcessLauncher> launcher_;
116
117 // The event signalling termination of the worker process.
118 ScopedHandle process_exit_event_;
119 };
120
121
122 WorkerProcessLauncherTest::WorkerProcessLauncherTest()
123 : message_loop_(MessageLoop::TYPE_IO) {
124 }
125
126 WorkerProcessLauncherTest::~WorkerProcessLauncherTest() {
127 }
128
129 void WorkerProcessLauncherTest::SetUp() {
130 task_runner_ = new AutoThreadTaskRunner(
131 message_loop_.message_loop_proxy(),
132 base::Bind(&WorkerProcessLauncherTest::QuitMainMessageLoop,
133 base::Unretained(this)));
134
135 exit_code_ = STILL_ACTIVE;
136
137 // Set up process launcher delegate
138 launcher_delegate_.reset(new MockProcessLauncherDelegate());
139 EXPECT_CALL(*launcher_delegate_, GetExitCode())
140 .Times(AnyNumber())
141 .WillRepeatedly(ReturnPointee(&exit_code_));
142 EXPECT_CALL(*launcher_delegate_, KillProcess(_))
143 .Times(AnyNumber())
144 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::KillProcess));
145
146 // Set up IPC delegate.
147 EXPECT_CALL(ipc_delegate_, OnMessageReceived(_))
148 .Times(AnyNumber())
149 .WillRepeatedly(Return(false));
150 }
151
152 void WorkerProcessLauncherTest::TearDown() {
153 }
154
155 bool WorkerProcessLauncherTest::OnMessageReceived(const IPC::Message& message) {
156 return false;
157 }
158
159 void WorkerProcessLauncherTest::KillProcess(DWORD exit_code) {
160 exit_code_ = exit_code;
161 BOOL result = SetEvent(process_exit_event_);
162 EXPECT_TRUE(result);
163 }
164
165 bool WorkerProcessLauncherTest::LaunchProcess(
166 const std::string& channel_name,
167 ScopedHandle* process_exit_event_out) {
168 return LaunchProcessAndConnect("", process_exit_event_out);
169 }
170
171 bool WorkerProcessLauncherTest::LaunchProcessAndConnect(
172 const std::string& channel_name,
173 ScopedHandle* process_exit_event_out) {
174 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
175 if (!process_exit_event_.IsValid())
176 return false;
177
178 if (!channel_name.empty()) {
179 task_runner_->PostTask(
180 FROM_HERE,
181 base::Bind(&WorkerProcessLauncherTest::ConnectTo,
182 base::Unretained(this),
183 channel_name));
184 }
185
186 exit_code_ = STILL_ACTIVE;
187 return DuplicateHandle(GetCurrentProcess(),
188 process_exit_event_,
189 GetCurrentProcess(),
190 process_exit_event_out->Receive(),
191 0,
192 FALSE,
193 DUPLICATE_SAME_ACCESS) != FALSE;
194 }
195
196 void WorkerProcessLauncherTest::ConnectTo(const std::string& channel_name) {
197 ipc_channel_.reset(new IPC::ChannelProxy(
198 IPC::ChannelHandle(channel_name),
199 IPC::Channel::MODE_CLIENT,
200 this,
201 task_runner_));
202 }
203
204 void WorkerProcessLauncherTest::Disconnect() {
205 ipc_channel_.reset();
206 }
207
208 void WorkerProcessLauncherTest::StartWorker() {
209 launcher_.reset(new WorkerProcessLauncher(task_runner_,
210 task_runner_,
211 launcher_delegate_.Pass(),
212 &ipc_delegate_,
213 kIpcSecurityDescriptor));
214 }
215
216 void WorkerProcessLauncherTest::StopWorker() {
217 launcher_.reset();
218 Disconnect();
219 task_runner_ = NULL;
220 }
221
222 void WorkerProcessLauncherTest::QuitMainMessageLoop() {
223 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
224 }
225
226 TEST_F(WorkerProcessLauncherTest, Start) {
227 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _))
228 .Times(1)
229 .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::LaunchProcess));
230
231 EXPECT_CALL(ipc_delegate_, OnChannelConnected())
232 .Times(0);
233 EXPECT_CALL(ipc_delegate_, OnPermanentError())
234 .Times(0);
235
236 StartWorker();
237 StopWorker();
238 message_loop_.Run();
239
240 EXPECT_EQ(exit_code_, CONTROL_C_EXIT);
241 }
242
243 // Starts and connects to the worker process. Expect OnChannelConnected to be
244 // called.
245 TEST_F(WorkerProcessLauncherTest, StartAndConnect) {
246 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _))
247 .Times(1)
248 .WillRepeatedly(Invoke(
249 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
250
251 EXPECT_CALL(ipc_delegate_, OnChannelConnected())
252 .Times(1)
253 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker));
254 EXPECT_CALL(ipc_delegate_, OnPermanentError())
255 .Times(0);
256
257 StartWorker();
258 message_loop_.Run();
259
260 EXPECT_EQ(exit_code_, CONTROL_C_EXIT);
261 }
262
263 // Kills the worker process after the 1st connect and expects it to be
264 // restarted.
265 TEST_F(WorkerProcessLauncherTest, Restart) {
266 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _))
267 .Times(2)
268 .WillRepeatedly(Invoke(
269 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
270 Expectation first_connect =
271 EXPECT_CALL(ipc_delegate_, OnChannelConnected())
272 .Times(2)
273 .WillOnce(Invoke(CreateFunctor(
274 this, &WorkerProcessLauncherTest::KillProcess, CONTROL_C_EXIT)))
275 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker));
276
277 EXPECT_CALL(ipc_delegate_, OnPermanentError())
278 .Times(0);
279
280 StartWorker();
281 message_loop_.Run();
282
283 EXPECT_EQ(exit_code_, CONTROL_C_EXIT);
284 }
285
286 // Drops the ipc channel to the worker process after the 1st connect and expects
Wez 2012/10/10 00:52:03 nit: ipc -> IPC
alexeypa (please no reviews) 2012/10/10 16:58:19 Done.
287 // the worker process to be restarted.
288 // restarted.
289 TEST_F(WorkerProcessLauncherTest, DropIpcChannel) {
290 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _))
291 .Times(2)
292 .WillRepeatedly(Invoke(
293 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
294
295 Expectation first_connect =
296 EXPECT_CALL(ipc_delegate_, OnChannelConnected())
297 .Times(2)
298 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::Disconnect))
299 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker));
300
301 EXPECT_CALL(ipc_delegate_, OnPermanentError())
302 .Times(0);
303
304 StartWorker();
305 message_loop_.Run();
306
307 EXPECT_EQ(exit_code_, CONTROL_C_EXIT);
308 }
309
310 // Returns a permanent error exit code and expects OnPermanentError() to be
311 // invoked.
312 TEST_F(WorkerProcessLauncherTest, PermanentError) {
313 EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _))
314 .Times(1)
315 .WillRepeatedly(Invoke(
316 this, &WorkerProcessLauncherTest::LaunchProcessAndConnect));
317
318 base::Closure terminate_permanently =
319 base::Bind(&WorkerProcessLauncherTest::KillProcess,
320 base::Unretained(this),
321 kInvalidHostConfigurationExitCode);
322 EXPECT_CALL(ipc_delegate_, OnChannelConnected())
323 .Times(1)
324 .WillRepeatedly(Invoke(&terminate_permanently, &base::Closure::Run));
325
326 EXPECT_CALL(ipc_delegate_, OnPermanentError())
327 .Times(1)
328 .WillOnce(Invoke(this, &WorkerProcessLauncherTest::StopWorker));
329
330 StartWorker();
331 message_loop_.Run();
332
333 EXPECT_EQ(exit_code_, kInvalidHostConfigurationExitCode);
334 }
335
336 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698