OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "mojo/common/handle_watcher.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/at_exit.h" | |
10 #include "base/auto_reset.h" | |
11 #include "base/bind.h" | |
12 #include "base/memory/scoped_vector.h" | |
13 #include "base/run_loop.h" | |
14 #include "base/test/simple_test_tick_clock.h" | |
15 #include "base/threading/thread.h" | |
16 #include "mojo/common/message_pump_mojo.h" | |
17 #include "mojo/common/time_helper.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 #include "third_party/mojo/src/mojo/public/cpp/system/core.h" | |
20 #include "third_party/mojo/src/mojo/public/cpp/test_support/test_utils.h" | |
21 | |
22 namespace mojo { | |
23 namespace common { | |
24 namespace test { | |
25 | |
26 enum MessageLoopConfig { | |
27 MESSAGE_LOOP_CONFIG_DEFAULT = 0, | |
28 MESSAGE_LOOP_CONFIG_MOJO = 1 | |
29 }; | |
30 | |
31 void ObserveCallback(bool* was_signaled, | |
32 MojoResult* result_observed, | |
33 MojoResult result) { | |
34 *was_signaled = true; | |
35 *result_observed = result; | |
36 } | |
37 | |
38 void RunUntilIdle() { | |
39 base::RunLoop run_loop; | |
40 run_loop.RunUntilIdle(); | |
41 } | |
42 | |
43 void DeleteWatcherAndForwardResult( | |
44 HandleWatcher* watcher, | |
45 base::Callback<void(MojoResult)> next_callback, | |
46 MojoResult result) { | |
47 delete watcher; | |
48 next_callback.Run(result); | |
49 } | |
50 | |
51 scoped_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { | |
52 scoped_ptr<base::MessageLoop> loop; | |
53 if (config == MESSAGE_LOOP_CONFIG_DEFAULT) | |
54 loop.reset(new base::MessageLoop()); | |
55 else | |
56 loop.reset(new base::MessageLoop(MessagePumpMojo::Create())); | |
57 return loop.Pass(); | |
58 } | |
59 | |
60 // Helper class to manage the callback and running the message loop waiting for | |
61 // message to be received. Typical usage is something like: | |
62 // Schedule callback returned from GetCallback(). | |
63 // RunUntilGotCallback(); | |
64 // EXPECT_TRUE(got_callback()); | |
65 // clear_callback(); | |
66 class CallbackHelper { | |
67 public: | |
68 CallbackHelper() | |
69 : got_callback_(false), | |
70 run_loop_(NULL), | |
71 weak_factory_(this) {} | |
72 ~CallbackHelper() {} | |
73 | |
74 // See description above |got_callback_|. | |
75 bool got_callback() const { return got_callback_; } | |
76 void clear_callback() { got_callback_ = false; } | |
77 | |
78 // Runs the current MessageLoop until the callback returned from GetCallback() | |
79 // is notified. | |
80 void RunUntilGotCallback() { | |
81 ASSERT_TRUE(run_loop_ == NULL); | |
82 base::RunLoop run_loop; | |
83 base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop); | |
84 run_loop.Run(); | |
85 } | |
86 | |
87 base::Callback<void(MojoResult)> GetCallback() { | |
88 return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr()); | |
89 } | |
90 | |
91 void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) { | |
92 StartWithCallback(watcher, handle, GetCallback()); | |
93 } | |
94 | |
95 void StartWithCallback(HandleWatcher* watcher, | |
96 const MessagePipeHandle& handle, | |
97 const base::Callback<void(MojoResult)>& callback) { | |
98 watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE, | |
99 MOJO_DEADLINE_INDEFINITE, callback); | |
100 } | |
101 | |
102 private: | |
103 void OnCallback(MojoResult result) { | |
104 got_callback_ = true; | |
105 if (run_loop_) | |
106 run_loop_->Quit(); | |
107 } | |
108 | |
109 // Set to true when the callback is called. | |
110 bool got_callback_; | |
111 | |
112 // If non-NULL we're in RunUntilGotCallback(). | |
113 base::RunLoop* run_loop_; | |
114 | |
115 base::WeakPtrFactory<CallbackHelper> weak_factory_; | |
116 | |
117 private: | |
118 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); | |
119 }; | |
120 | |
121 class HandleWatcherTest : public testing::TestWithParam<MessageLoopConfig> { | |
122 public: | |
123 HandleWatcherTest() : message_loop_(CreateMessageLoop(GetParam())) {} | |
124 virtual ~HandleWatcherTest() { | |
125 test::SetTickClockForTest(NULL); | |
126 } | |
127 | |
128 protected: | |
129 void TearDownMessageLoop() { | |
130 message_loop_.reset(); | |
131 } | |
132 | |
133 void InstallTickClock() { | |
134 test::SetTickClockForTest(&tick_clock_); | |
135 } | |
136 | |
137 base::SimpleTestTickClock tick_clock_; | |
138 | |
139 private: | |
140 base::ShadowingAtExitManager at_exit_; | |
141 scoped_ptr<base::MessageLoop> message_loop_; | |
142 | |
143 DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); | |
144 }; | |
145 | |
146 INSTANTIATE_TEST_CASE_P( | |
147 MultipleMessageLoopConfigs, HandleWatcherTest, | |
148 testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, MESSAGE_LOOP_CONFIG_MOJO)); | |
149 | |
150 // Trivial test case with a single handle to watch. | |
151 TEST_P(HandleWatcherTest, SingleHandler) { | |
152 MessagePipe test_pipe; | |
153 ASSERT_TRUE(test_pipe.handle0.is_valid()); | |
154 CallbackHelper callback_helper; | |
155 HandleWatcher watcher; | |
156 callback_helper.Start(&watcher, test_pipe.handle0.get()); | |
157 RunUntilIdle(); | |
158 EXPECT_FALSE(callback_helper.got_callback()); | |
159 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), | |
160 std::string())); | |
161 callback_helper.RunUntilGotCallback(); | |
162 EXPECT_TRUE(callback_helper.got_callback()); | |
163 } | |
164 | |
165 // Creates three handles and notfies them in reverse order ensuring each one is | |
166 // notified appropriately. | |
167 TEST_P(HandleWatcherTest, ThreeHandles) { | |
168 MessagePipe test_pipe1; | |
169 MessagePipe test_pipe2; | |
170 MessagePipe test_pipe3; | |
171 CallbackHelper callback_helper1; | |
172 CallbackHelper callback_helper2; | |
173 CallbackHelper callback_helper3; | |
174 ASSERT_TRUE(test_pipe1.handle0.is_valid()); | |
175 ASSERT_TRUE(test_pipe2.handle0.is_valid()); | |
176 ASSERT_TRUE(test_pipe3.handle0.is_valid()); | |
177 | |
178 HandleWatcher watcher1; | |
179 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); | |
180 RunUntilIdle(); | |
181 EXPECT_FALSE(callback_helper1.got_callback()); | |
182 EXPECT_FALSE(callback_helper2.got_callback()); | |
183 EXPECT_FALSE(callback_helper3.got_callback()); | |
184 | |
185 HandleWatcher watcher2; | |
186 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); | |
187 RunUntilIdle(); | |
188 EXPECT_FALSE(callback_helper1.got_callback()); | |
189 EXPECT_FALSE(callback_helper2.got_callback()); | |
190 EXPECT_FALSE(callback_helper3.got_callback()); | |
191 | |
192 HandleWatcher watcher3; | |
193 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); | |
194 RunUntilIdle(); | |
195 EXPECT_FALSE(callback_helper1.got_callback()); | |
196 EXPECT_FALSE(callback_helper2.got_callback()); | |
197 EXPECT_FALSE(callback_helper3.got_callback()); | |
198 | |
199 // Write to 3 and make sure it's notified. | |
200 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), | |
201 std::string())); | |
202 callback_helper3.RunUntilGotCallback(); | |
203 EXPECT_FALSE(callback_helper1.got_callback()); | |
204 EXPECT_FALSE(callback_helper2.got_callback()); | |
205 EXPECT_TRUE(callback_helper3.got_callback()); | |
206 callback_helper3.clear_callback(); | |
207 | |
208 // Write to 1 and 3. Only 1 should be notified since 3 was is no longer | |
209 // running. | |
210 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), | |
211 std::string())); | |
212 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), | |
213 std::string())); | |
214 callback_helper1.RunUntilGotCallback(); | |
215 EXPECT_TRUE(callback_helper1.got_callback()); | |
216 EXPECT_FALSE(callback_helper2.got_callback()); | |
217 EXPECT_FALSE(callback_helper3.got_callback()); | |
218 callback_helper1.clear_callback(); | |
219 | |
220 // Write to 1 and 2. Only 2 should be notified (since 1 was already notified). | |
221 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), | |
222 std::string())); | |
223 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), | |
224 std::string())); | |
225 callback_helper2.RunUntilGotCallback(); | |
226 EXPECT_FALSE(callback_helper1.got_callback()); | |
227 EXPECT_TRUE(callback_helper2.got_callback()); | |
228 EXPECT_FALSE(callback_helper3.got_callback()); | |
229 } | |
230 | |
231 // Verifies Start() invoked a second time works. | |
232 TEST_P(HandleWatcherTest, Restart) { | |
233 MessagePipe test_pipe1; | |
234 MessagePipe test_pipe2; | |
235 CallbackHelper callback_helper1; | |
236 CallbackHelper callback_helper2; | |
237 ASSERT_TRUE(test_pipe1.handle0.is_valid()); | |
238 ASSERT_TRUE(test_pipe2.handle0.is_valid()); | |
239 | |
240 HandleWatcher watcher1; | |
241 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); | |
242 RunUntilIdle(); | |
243 EXPECT_FALSE(callback_helper1.got_callback()); | |
244 EXPECT_FALSE(callback_helper2.got_callback()); | |
245 | |
246 HandleWatcher watcher2; | |
247 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); | |
248 RunUntilIdle(); | |
249 EXPECT_FALSE(callback_helper1.got_callback()); | |
250 EXPECT_FALSE(callback_helper2.got_callback()); | |
251 | |
252 // Write to 1 and make sure it's notified. | |
253 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), | |
254 std::string())); | |
255 callback_helper1.RunUntilGotCallback(); | |
256 EXPECT_TRUE(callback_helper1.got_callback()); | |
257 EXPECT_FALSE(callback_helper2.got_callback()); | |
258 callback_helper1.clear_callback(); | |
259 EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get())); | |
260 | |
261 // Write to 2 and make sure it's notified. | |
262 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), | |
263 std::string())); | |
264 callback_helper2.RunUntilGotCallback(); | |
265 EXPECT_FALSE(callback_helper1.got_callback()); | |
266 EXPECT_TRUE(callback_helper2.got_callback()); | |
267 callback_helper2.clear_callback(); | |
268 | |
269 // Listen on 1 again. | |
270 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); | |
271 RunUntilIdle(); | |
272 EXPECT_FALSE(callback_helper1.got_callback()); | |
273 EXPECT_FALSE(callback_helper2.got_callback()); | |
274 | |
275 // Write to 1 and make sure it's notified. | |
276 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), | |
277 std::string())); | |
278 callback_helper1.RunUntilGotCallback(); | |
279 EXPECT_TRUE(callback_helper1.got_callback()); | |
280 EXPECT_FALSE(callback_helper2.got_callback()); | |
281 } | |
282 | |
283 // Verifies Start() invoked a second time on the same handle works. | |
284 TEST_P(HandleWatcherTest, RestartOnSameHandle) { | |
285 MessagePipe test_pipe; | |
286 CallbackHelper callback_helper; | |
287 ASSERT_TRUE(test_pipe.handle0.is_valid()); | |
288 | |
289 HandleWatcher watcher; | |
290 callback_helper.Start(&watcher, test_pipe.handle0.get()); | |
291 RunUntilIdle(); | |
292 EXPECT_FALSE(callback_helper.got_callback()); | |
293 | |
294 callback_helper.Start(&watcher, test_pipe.handle0.get()); | |
295 RunUntilIdle(); | |
296 EXPECT_FALSE(callback_helper.got_callback()); | |
297 } | |
298 | |
299 // Verifies deadline is honored. | |
300 TEST_P(HandleWatcherTest, Deadline) { | |
301 InstallTickClock(); | |
302 | |
303 MessagePipe test_pipe1; | |
304 MessagePipe test_pipe2; | |
305 MessagePipe test_pipe3; | |
306 CallbackHelper callback_helper1; | |
307 CallbackHelper callback_helper2; | |
308 CallbackHelper callback_helper3; | |
309 ASSERT_TRUE(test_pipe1.handle0.is_valid()); | |
310 ASSERT_TRUE(test_pipe2.handle0.is_valid()); | |
311 ASSERT_TRUE(test_pipe3.handle0.is_valid()); | |
312 | |
313 // Add a watcher with an infinite timeout. | |
314 HandleWatcher watcher1; | |
315 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); | |
316 RunUntilIdle(); | |
317 EXPECT_FALSE(callback_helper1.got_callback()); | |
318 EXPECT_FALSE(callback_helper2.got_callback()); | |
319 EXPECT_FALSE(callback_helper3.got_callback()); | |
320 | |
321 // Add another watcher wth a timeout of 500 microseconds. | |
322 HandleWatcher watcher2; | |
323 watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500, | |
324 callback_helper2.GetCallback()); | |
325 RunUntilIdle(); | |
326 EXPECT_FALSE(callback_helper1.got_callback()); | |
327 EXPECT_FALSE(callback_helper2.got_callback()); | |
328 EXPECT_FALSE(callback_helper3.got_callback()); | |
329 | |
330 // Advance the clock passed the deadline. We also have to start another | |
331 // watcher to wake up the background thread. | |
332 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501)); | |
333 | |
334 HandleWatcher watcher3; | |
335 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); | |
336 | |
337 callback_helper2.RunUntilGotCallback(); | |
338 EXPECT_FALSE(callback_helper1.got_callback()); | |
339 EXPECT_TRUE(callback_helper2.got_callback()); | |
340 EXPECT_FALSE(callback_helper3.got_callback()); | |
341 } | |
342 | |
343 TEST_P(HandleWatcherTest, DeleteInCallback) { | |
344 MessagePipe test_pipe; | |
345 CallbackHelper callback_helper; | |
346 | |
347 HandleWatcher* watcher = new HandleWatcher(); | |
348 callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(), | |
349 base::Bind(&DeleteWatcherAndForwardResult, | |
350 watcher, | |
351 callback_helper.GetCallback())); | |
352 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(), | |
353 std::string())); | |
354 callback_helper.RunUntilGotCallback(); | |
355 EXPECT_TRUE(callback_helper.got_callback()); | |
356 } | |
357 | |
358 TEST_P(HandleWatcherTest, AbortedOnMessageLoopDestruction) { | |
359 bool was_signaled = false; | |
360 MojoResult result = MOJO_RESULT_OK; | |
361 | |
362 MessagePipe pipe; | |
363 HandleWatcher watcher; | |
364 watcher.Start(pipe.handle0.get(), | |
365 MOJO_HANDLE_SIGNAL_READABLE, | |
366 MOJO_DEADLINE_INDEFINITE, | |
367 base::Bind(&ObserveCallback, &was_signaled, &result)); | |
368 | |
369 // Now, let the MessageLoop get torn down. We expect our callback to run. | |
370 TearDownMessageLoop(); | |
371 | |
372 EXPECT_TRUE(was_signaled); | |
373 EXPECT_EQ(MOJO_RESULT_ABORTED, result); | |
374 } | |
375 | |
376 void NeverReached(MojoResult result) { | |
377 FAIL() << "Callback should never be invoked " << result; | |
378 } | |
379 | |
380 // Called on the main thread when a thread is done. Decrements |active_count| | |
381 // and if |active_count| is zero quits |run_loop|. | |
382 void StressThreadDone(base::RunLoop* run_loop, int* active_count) { | |
383 (*active_count)--; | |
384 EXPECT_GE(*active_count, 0); | |
385 if (*active_count == 0) | |
386 run_loop->Quit(); | |
387 } | |
388 | |
389 // See description of StressTest. This is called on the background thread. | |
390 // |count| is the number of HandleWatchers to create. |active_count| is the | |
391 // number of outstanding threads, |task_runner| the task runner for the main | |
392 // thread and |run_loop| the run loop that should be quit when there are no more | |
393 // threads running. When done StressThreadDone() is invoked on the main thread. | |
394 // |active_count| and |run_loop| should only be used on the main thread. | |
395 void RunStressTest(int count, | |
396 scoped_refptr<base::TaskRunner> task_runner, | |
397 base::RunLoop* run_loop, | |
398 int* active_count) { | |
399 struct TestData { | |
400 MessagePipe pipe; | |
401 HandleWatcher watcher; | |
402 }; | |
403 ScopedVector<TestData> data_vector; | |
404 for (int i = 0; i < count; ++i) { | |
405 if (i % 20 == 0) { | |
406 // Every so often we wait. This results in some level of thread balancing | |
407 // as well as making sure HandleWatcher has time to actually start some | |
408 // watches. | |
409 MessagePipe test_pipe; | |
410 ASSERT_TRUE(test_pipe.handle0.is_valid()); | |
411 CallbackHelper callback_helper; | |
412 HandleWatcher watcher; | |
413 callback_helper.Start(&watcher, test_pipe.handle0.get()); | |
414 RunUntilIdle(); | |
415 EXPECT_FALSE(callback_helper.got_callback()); | |
416 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), | |
417 std::string())); | |
418 base::MessageLoop::ScopedNestableTaskAllower scoper( | |
419 base::MessageLoop::current()); | |
420 callback_helper.RunUntilGotCallback(); | |
421 EXPECT_TRUE(callback_helper.got_callback()); | |
422 } else { | |
423 scoped_ptr<TestData> test_data(new TestData); | |
424 ASSERT_TRUE(test_data->pipe.handle0.is_valid()); | |
425 test_data->watcher.Start(test_data->pipe.handle0.get(), | |
426 MOJO_HANDLE_SIGNAL_READABLE, | |
427 MOJO_DEADLINE_INDEFINITE, | |
428 base::Bind(&NeverReached)); | |
429 data_vector.push_back(test_data.release()); | |
430 } | |
431 if (i % 15 == 0) | |
432 data_vector.clear(); | |
433 } | |
434 task_runner->PostTask(FROM_HERE, | |
435 base::Bind(&StressThreadDone, run_loop, | |
436 active_count)); | |
437 } | |
438 | |
439 // This test is meant to stress HandleWatcher. It uses from various threads | |
440 // repeatedly starting and stopping watches. It spins up kThreadCount | |
441 // threads. Each thread creates kWatchCount watches. Every so often each thread | |
442 // writes to a pipe and waits for the response. | |
443 TEST(HandleWatcherCleanEnvironmentTest, StressTest) { | |
444 #if defined(NDEBUG) | |
445 const int kThreadCount = 15; | |
446 const int kWatchCount = 400; | |
447 #else | |
448 const int kThreadCount = 10; | |
449 const int kWatchCount = 250; | |
450 #endif | |
451 | |
452 base::ShadowingAtExitManager at_exit; | |
453 base::MessageLoop message_loop; | |
454 base::RunLoop run_loop; | |
455 ScopedVector<base::Thread> threads; | |
456 int threads_active_counter = kThreadCount; | |
457 // Starts the threads first and then post the task in hopes of having more | |
458 // threads running at once. | |
459 for (int i = 0; i < kThreadCount; ++i) { | |
460 scoped_ptr<base::Thread> thread(new base::Thread("test thread")); | |
461 if (i % 2) { | |
462 base::Thread::Options thread_options; | |
463 thread_options.message_pump_factory = | |
464 base::Bind(&MessagePumpMojo::Create); | |
465 thread->StartWithOptions(thread_options); | |
466 } else { | |
467 thread->Start(); | |
468 } | |
469 threads.push_back(thread.release()); | |
470 } | |
471 for (int i = 0; i < kThreadCount; ++i) { | |
472 threads[i]->task_runner()->PostTask( | |
473 FROM_HERE, base::Bind(&RunStressTest, kWatchCount, | |
474 message_loop.task_runner(), | |
475 &run_loop, &threads_active_counter)); | |
476 } | |
477 run_loop.Run(); | |
478 ASSERT_EQ(0, threads_active_counter); | |
479 } | |
480 | |
481 } // namespace test | |
482 } // namespace common | |
483 } // namespace mojo | |
OLD | NEW |