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 <stddef.h>
6 #include <stdint.h>
7
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/message_loop/message_loop_current.h"
19 #include "base/message_loop/message_pump_for_io.h"
20 #include "base/pending_task.h"
21 #include "base/posix/eintr_wrapper.h"
22 #include "base/run_loop.h"
23 #include "base/single_thread_task_runner.h"
24 #include "base/synchronization/waitable_event.h"
25 // Unsupported in libchrome
26 // #include "base/task_scheduler/task_scheduler.h"
27 #include "base/test/gtest_util.h"
28 #include "base/test/test_simple_task_runner.h"
29 #include "base/test/test_timeouts.h"
30 #include "base/threading/platform_thread.h"
31 #include "base/threading/sequence_local_storage_slot.h"
32 #include "base/threading/thread.h"
33 #include "base/threading/thread_task_runner_handle.h"
34 #include "build/build_config.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 #if defined(OS_ANDROID)
38 #include "base/android/java_handler_thread.h"
39 #include "base/android/jni_android.h"
40 #include "base/test/android/java_handler_thread_helpers.h"
41 #endif
42
43 #if defined(OS_WIN)
44 #include "base/message_loop/message_pump_win.h"
45 #include "base/process/memory.h"
46 #include "base/strings/string16.h"
47 #include "base/win/current_module.h"
48 #include "base/win/scoped_handle.h"
49 #endif
50
51 namespace base {
52
53 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
54 // to avoid chopping this file up with so many #ifdefs.
55
56 namespace {
57
58 class Foo : public RefCounted<Foo> {
59 public:
Foo()60 Foo() : test_count_(0) {
61 }
62
Test0()63 void Test0() { ++test_count_; }
64
Test1ConstRef(const std::string & a)65 void Test1ConstRef(const std::string& a) {
66 ++test_count_;
67 result_.append(a);
68 }
69
Test1Ptr(std::string * a)70 void Test1Ptr(std::string* a) {
71 ++test_count_;
72 result_.append(*a);
73 }
74
Test1Int(int a)75 void Test1Int(int a) { test_count_ += a; }
76
Test2Ptr(std::string * a,std::string * b)77 void Test2Ptr(std::string* a, std::string* b) {
78 ++test_count_;
79 result_.append(*a);
80 result_.append(*b);
81 }
82
Test2Mixed(const std::string & a,std::string * b)83 void Test2Mixed(const std::string& a, std::string* b) {
84 ++test_count_;
85 result_.append(a);
86 result_.append(*b);
87 }
88
test_count() const89 int test_count() const { return test_count_; }
result() const90 const std::string& result() const { return result_; }
91
92 private:
93 friend class RefCounted<Foo>;
94
95 ~Foo() = default;
96
97 int test_count_;
98 std::string result_;
99
100 DISALLOW_COPY_AND_ASSIGN(Foo);
101 };
102
103 // This function runs slowly to simulate a large amount of work being done.
SlowFunc(TimeDelta pause,int * quit_counter)104 static void SlowFunc(TimeDelta pause, int* quit_counter) {
105 PlatformThread::Sleep(pause);
106 if (--(*quit_counter) == 0)
107 RunLoop::QuitCurrentWhenIdleDeprecated();
108 }
109
110 // This function records the time when Run was called in a Time object, which is
111 // useful for building a variety of MessageLoop tests.
RecordRunTimeFunc(TimeTicks * run_time,int * quit_counter)112 static void RecordRunTimeFunc(TimeTicks* run_time, int* quit_counter) {
113 *run_time = TimeTicks::Now();
114
115 // Cause our Run function to take some time to execute. As a result we can
116 // count on subsequent RecordRunTimeFunc()s running at a future time,
117 // without worry about the resolution of our system clock being an issue.
118 SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter);
119 }
120
121 enum TaskType {
122 MESSAGEBOX,
123 ENDDIALOG,
124 RECURSIVE,
125 TIMEDMESSAGELOOP,
126 QUITMESSAGELOOP,
127 ORDERED,
128 PUMPS,
129 SLEEP,
130 RUNS,
131 };
132
133 // Saves the order in which the tasks executed.
134 struct TaskItem {
TaskItembase::__anon2a3b24860111::TaskItem135 TaskItem(TaskType t, int c, bool s)
136 : type(t),
137 cookie(c),
138 start(s) {
139 }
140
141 TaskType type;
142 int cookie;
143 bool start;
144
operator ==base::__anon2a3b24860111::TaskItem145 bool operator == (const TaskItem& other) const {
146 return type == other.type && cookie == other.cookie && start == other.start;
147 }
148 };
149
operator <<(std::ostream & os,TaskType type)150 std::ostream& operator <<(std::ostream& os, TaskType type) {
151 switch (type) {
152 case MESSAGEBOX: os << "MESSAGEBOX"; break;
153 case ENDDIALOG: os << "ENDDIALOG"; break;
154 case RECURSIVE: os << "RECURSIVE"; break;
155 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break;
156 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break;
157 case ORDERED: os << "ORDERED"; break;
158 case PUMPS: os << "PUMPS"; break;
159 case SLEEP: os << "SLEEP"; break;
160 default:
161 NOTREACHED();
162 os << "Unknown TaskType";
163 break;
164 }
165 return os;
166 }
167
operator <<(std::ostream & os,const TaskItem & item)168 std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
169 if (item.start)
170 return os << item.type << " " << item.cookie << " starts";
171 else
172 return os << item.type << " " << item.cookie << " ends";
173 }
174
175 class TaskList {
176 public:
RecordStart(TaskType type,int cookie)177 void RecordStart(TaskType type, int cookie) {
178 TaskItem item(type, cookie, true);
179 DVLOG(1) << item;
180 task_list_.push_back(item);
181 }
182
RecordEnd(TaskType type,int cookie)183 void RecordEnd(TaskType type, int cookie) {
184 TaskItem item(type, cookie, false);
185 DVLOG(1) << item;
186 task_list_.push_back(item);
187 }
188
Size()189 size_t Size() {
190 return task_list_.size();
191 }
192
Get(int n)193 TaskItem Get(int n) {
194 return task_list_[n];
195 }
196
197 private:
198 std::vector<TaskItem> task_list_;
199 };
200
201 class DummyTaskObserver : public MessageLoop::TaskObserver {
202 public:
DummyTaskObserver(int num_tasks)203 explicit DummyTaskObserver(int num_tasks)
204 : num_tasks_started_(0), num_tasks_processed_(0), num_tasks_(num_tasks) {}
205
DummyTaskObserver(int num_tasks,int num_tasks_started)206 DummyTaskObserver(int num_tasks, int num_tasks_started)
207 : num_tasks_started_(num_tasks_started),
208 num_tasks_processed_(0),
209 num_tasks_(num_tasks) {}
210
211 ~DummyTaskObserver() override = default;
212
WillProcessTask(const PendingTask & pending_task)213 void WillProcessTask(const PendingTask& pending_task) override {
214 num_tasks_started_++;
215 EXPECT_LE(num_tasks_started_, num_tasks_);
216 EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
217 }
218
DidProcessTask(const PendingTask & pending_task)219 void DidProcessTask(const PendingTask& pending_task) override {
220 num_tasks_processed_++;
221 EXPECT_LE(num_tasks_started_, num_tasks_);
222 EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
223 }
224
num_tasks_started() const225 int num_tasks_started() const { return num_tasks_started_; }
num_tasks_processed() const226 int num_tasks_processed() const { return num_tasks_processed_; }
227
228 private:
229 int num_tasks_started_;
230 int num_tasks_processed_;
231 const int num_tasks_;
232
233 DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver);
234 };
235
RecursiveFunc(TaskList * order,int cookie,int depth,bool is_reentrant)236 void RecursiveFunc(TaskList* order, int cookie, int depth,
237 bool is_reentrant) {
238 order->RecordStart(RECURSIVE, cookie);
239 if (depth > 0) {
240 if (is_reentrant)
241 MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
242 ThreadTaskRunnerHandle::Get()->PostTask(
243 FROM_HERE,
244 BindOnce(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
245 }
246 order->RecordEnd(RECURSIVE, cookie);
247 }
248
QuitFunc(TaskList * order,int cookie)249 void QuitFunc(TaskList* order, int cookie) {
250 order->RecordStart(QUITMESSAGELOOP, cookie);
251 RunLoop::QuitCurrentWhenIdleDeprecated();
252 order->RecordEnd(QUITMESSAGELOOP, cookie);
253 }
254
PostNTasks(int posts_remaining)255 void PostNTasks(int posts_remaining) {
256 if (posts_remaining > 1) {
257 ThreadTaskRunnerHandle::Get()->PostTask(
258 FROM_HERE, BindOnce(&PostNTasks, posts_remaining - 1));
259 }
260 }
261
262 enum class TaskSchedulerAvailability {
263 NO_TASK_SCHEDULER,
264 // Unsupported in libchrome.
265 // WITH_TASK_SCHEDULER,
266 };
267
TaskSchedulerAvailabilityToString(TaskSchedulerAvailability availability)268 std::string TaskSchedulerAvailabilityToString(
269 TaskSchedulerAvailability availability) {
270 switch (availability) {
271 case TaskSchedulerAvailability::NO_TASK_SCHEDULER:
272 return "NoTaskScheduler";
273 // Unsupported in libchrome.
274 // case TaskSchedulerAvailability::WITH_TASK_SCHEDULER:
275 // return "WithTaskScheduler";
276 }
277 NOTREACHED();
278 return "Unknown";
279 }
280
281 class MessageLoopTest
282 : public ::testing::TestWithParam<TaskSchedulerAvailability> {
283 public:
284 MessageLoopTest() = default;
285 ~MessageLoopTest() override = default;
286
SetUp()287 void SetUp() override {
288 // Unsupported in libchrome.
289 #if 0
290 if (GetParam() == TaskSchedulerAvailability::WITH_TASK_SCHEDULER)
291 TaskScheduler::CreateAndStartWithDefaultParams("MessageLoopTest");
292 #endif
293 }
294
TearDown()295 void TearDown() override {
296 // Unsupported in libchrome.
297 #if 0
298 if (GetParam() == TaskSchedulerAvailability::WITH_TASK_SCHEDULER) {
299 // Failure to call FlushForTesting() could result in task leaks as tasks
300 // are skipped on shutdown.
301 base::TaskScheduler::GetInstance()->FlushForTesting();
302 base::TaskScheduler::GetInstance()->Shutdown();
303 base::TaskScheduler::GetInstance()->JoinForTesting();
304 base::TaskScheduler::SetInstance(nullptr);
305 }
306 #endif
307 }
308
ParamInfoToString(::testing::TestParamInfo<TaskSchedulerAvailability> param_info)309 static std::string ParamInfoToString(
310 ::testing::TestParamInfo<TaskSchedulerAvailability> param_info) {
311 return TaskSchedulerAvailabilityToString(param_info.param);
312 }
313
314 private:
315 DISALLOW_COPY_AND_ASSIGN(MessageLoopTest);
316 };
317
318 #if defined(OS_ANDROID)
DoNotRun()319 void DoNotRun() {
320 ASSERT_TRUE(false);
321 }
322
RunTest_AbortDontRunMoreTasks(bool delayed,bool init_java_first)323 void RunTest_AbortDontRunMoreTasks(bool delayed, bool init_java_first) {
324 WaitableEvent test_done_event(WaitableEvent::ResetPolicy::MANUAL,
325 WaitableEvent::InitialState::NOT_SIGNALED);
326 std::unique_ptr<android::JavaHandlerThread> java_thread;
327 if (init_java_first) {
328 java_thread = android::JavaHandlerThreadHelpers::CreateJavaFirst();
329 } else {
330 java_thread = std::make_unique<android::JavaHandlerThread>(
331 "JavaHandlerThreadForTesting from AbortDontRunMoreTasks");
332 }
333 java_thread->Start();
334 java_thread->ListenForUncaughtExceptionsForTesting();
335
336 auto target =
337 BindOnce(&android::JavaHandlerThreadHelpers::ThrowExceptionAndAbort,
338 &test_done_event);
339 if (delayed) {
340 java_thread->message_loop()->task_runner()->PostDelayedTask(
341 FROM_HERE, std::move(target), TimeDelta::FromMilliseconds(10));
342 } else {
343 java_thread->message_loop()->task_runner()->PostTask(FROM_HERE,
344 std::move(target));
345 java_thread->message_loop()->task_runner()->PostTask(FROM_HERE,
346 BindOnce(&DoNotRun));
347 }
348 test_done_event.Wait();
349 java_thread->Stop();
350 android::ScopedJavaLocalRef<jthrowable> exception =
351 java_thread->GetUncaughtExceptionIfAny();
352 ASSERT_TRUE(
353 android::JavaHandlerThreadHelpers::IsExceptionTestException(exception));
354 }
355
TEST_P(MessageLoopTest,JavaExceptionAbort)356 TEST_P(MessageLoopTest, JavaExceptionAbort) {
357 constexpr bool delayed = false;
358 constexpr bool init_java_first = false;
359 RunTest_AbortDontRunMoreTasks(delayed, init_java_first);
360 }
TEST_P(MessageLoopTest,DelayedJavaExceptionAbort)361 TEST_P(MessageLoopTest, DelayedJavaExceptionAbort) {
362 constexpr bool delayed = true;
363 constexpr bool init_java_first = false;
364 RunTest_AbortDontRunMoreTasks(delayed, init_java_first);
365 }
TEST_P(MessageLoopTest,JavaExceptionAbortInitJavaFirst)366 TEST_P(MessageLoopTest, JavaExceptionAbortInitJavaFirst) {
367 constexpr bool delayed = false;
368 constexpr bool init_java_first = true;
369 RunTest_AbortDontRunMoreTasks(delayed, init_java_first);
370 }
371
TEST_P(MessageLoopTest,RunTasksWhileShuttingDownJavaThread)372 TEST_P(MessageLoopTest, RunTasksWhileShuttingDownJavaThread) {
373 const int kNumPosts = 6;
374 DummyTaskObserver observer(kNumPosts, 1);
375
376 auto java_thread = std::make_unique<android::JavaHandlerThread>("test");
377 java_thread->Start();
378
379 java_thread->message_loop()->task_runner()->PostTask(
380 FROM_HERE,
381 BindOnce(
382 [](android::JavaHandlerThread* java_thread,
383 DummyTaskObserver* observer, int num_posts) {
384 java_thread->message_loop()->AddTaskObserver(observer);
385 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
386 FROM_HERE, BindOnce([]() { ADD_FAILURE(); }),
387 TimeDelta::FromDays(1));
388 java_thread->StopMessageLoopForTesting();
389 PostNTasks(num_posts);
390 },
391 Unretained(java_thread.get()), Unretained(&observer), kNumPosts));
392
393 java_thread->JoinForTesting();
394 java_thread.reset();
395
396 EXPECT_EQ(kNumPosts, observer.num_tasks_started());
397 EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
398 }
399 #endif // defined(OS_ANDROID)
400
401 #if defined(OS_WIN)
402
SubPumpFunc()403 void SubPumpFunc() {
404 MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
405 MSG msg;
406 while (GetMessage(&msg, NULL, 0, 0)) {
407 TranslateMessage(&msg);
408 DispatchMessage(&msg);
409 }
410 RunLoop::QuitCurrentWhenIdleDeprecated();
411 }
412
RunTest_PostDelayedTask_SharedTimer_SubPump()413 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
414 MessageLoop message_loop(MessageLoop::TYPE_UI);
415
416 // Test that the interval of the timer, used to run the next delayed task, is
417 // set to a value corresponding to when the next delayed task should run.
418
419 // By setting num_tasks to 1, we ensure that the first task to run causes the
420 // run loop to exit.
421 int num_tasks = 1;
422 TimeTicks run_time;
423
424 message_loop.task_runner()->PostTask(FROM_HERE, BindOnce(&SubPumpFunc));
425
426 // This very delayed task should never run.
427 message_loop.task_runner()->PostDelayedTask(
428 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks),
429 TimeDelta::FromSeconds(1000));
430
431 // This slightly delayed task should run from within SubPumpFunc.
432 message_loop.task_runner()->PostDelayedTask(FROM_HERE,
433 BindOnce(&PostQuitMessage, 0),
434 TimeDelta::FromMilliseconds(10));
435
436 Time start_time = Time::Now();
437
438 RunLoop().Run();
439 EXPECT_EQ(1, num_tasks);
440
441 // Ensure that we ran in far less time than the slower timer.
442 TimeDelta total_time = Time::Now() - start_time;
443 EXPECT_GT(5000, total_time.InMilliseconds());
444
445 // In case both timers somehow run at nearly the same time, sleep a little
446 // and then run all pending to force them both to have run. This is just
447 // encouraging flakiness if there is any.
448 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
449 RunLoop().RunUntilIdle();
450
451 EXPECT_TRUE(run_time.is_null());
452 }
453
454 const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test";
455
456 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
457 // common controls (like OpenFile) and StartDoc printing function can cause
458 // implicit message loops.
MessageBoxFunc(TaskList * order,int cookie,bool is_reentrant)459 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
460 order->RecordStart(MESSAGEBOX, cookie);
461 if (is_reentrant)
462 MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
463 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
464 order->RecordEnd(MESSAGEBOX, cookie);
465 }
466
467 // Will end the MessageBox.
EndDialogFunc(TaskList * order,int cookie)468 void EndDialogFunc(TaskList* order, int cookie) {
469 order->RecordStart(ENDDIALOG, cookie);
470 HWND window = GetActiveWindow();
471 if (window != NULL) {
472 EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
473 // Cheap way to signal that the window wasn't found if RunEnd() isn't
474 // called.
475 order->RecordEnd(ENDDIALOG, cookie);
476 }
477 }
478
RecursiveFuncWin(scoped_refptr<SingleThreadTaskRunner> task_runner,HANDLE event,bool expect_window,TaskList * order,bool is_reentrant)479 void RecursiveFuncWin(scoped_refptr<SingleThreadTaskRunner> task_runner,
480 HANDLE event,
481 bool expect_window,
482 TaskList* order,
483 bool is_reentrant) {
484 task_runner->PostTask(FROM_HERE,
485 BindOnce(&RecursiveFunc, order, 1, 2, is_reentrant));
486 task_runner->PostTask(FROM_HERE,
487 BindOnce(&MessageBoxFunc, order, 2, is_reentrant));
488 task_runner->PostTask(FROM_HERE,
489 BindOnce(&RecursiveFunc, order, 3, 2, is_reentrant));
490 // The trick here is that for recursive task processing, this task will be
491 // ran _inside_ the MessageBox message loop, dismissing the MessageBox
492 // without a chance.
493 // For non-recursive task processing, this will be executed _after_ the
494 // MessageBox will have been dismissed by the code below, where
495 // expect_window_ is true.
496 task_runner->PostTask(FROM_HERE, BindOnce(&EndDialogFunc, order, 4));
497 task_runner->PostTask(FROM_HERE, BindOnce(&QuitFunc, order, 5));
498
499 // Enforce that every tasks are sent before starting to run the main thread
500 // message loop.
501 ASSERT_TRUE(SetEvent(event));
502
503 // Poll for the MessageBox. Don't do this at home! At the speed we do it,
504 // you will never realize one MessageBox was shown.
505 for (; expect_window;) {
506 HWND window = FindWindow(L"#32770", kMessageBoxTitle);
507 if (window) {
508 // Dismiss it.
509 for (;;) {
510 HWND button = FindWindowEx(window, NULL, L"Button", NULL);
511 if (button != NULL) {
512 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
513 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
514 break;
515 }
516 }
517 break;
518 }
519 }
520 }
521
522 // TODO(darin): These tests need to be ported since they test critical
523 // message loop functionality.
524
525 // A side effect of this test is the generation a beep. Sorry.
RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type)526 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
527 MessageLoop loop(message_loop_type);
528
529 Thread worker("RecursiveDenial2_worker");
530 Thread::Options options;
531 options.message_loop_type = message_loop_type;
532 ASSERT_EQ(true, worker.StartWithOptions(options));
533 TaskList order;
534 win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
535 worker.task_runner()->PostTask(
536 FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(),
537 event.Get(), true, &order, false));
538 // Let the other thread execute.
539 WaitForSingleObject(event.Get(), INFINITE);
540 RunLoop().Run();
541
542 ASSERT_EQ(17u, order.Size());
543 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
544 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
545 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
546 EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
547 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
548 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
549 // When EndDialogFunc is processed, the window is already dismissed, hence no
550 // "end" entry.
551 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
552 EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
553 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
554 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
555 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
556 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
557 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
558 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
559 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
560 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
561 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
562 }
563
564 // A side effect of this test is the generation a beep. Sorry. This test also
565 // needs to process windows messages on the current thread.
RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type)566 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
567 MessageLoop loop(message_loop_type);
568
569 Thread worker("RecursiveSupport2_worker");
570 Thread::Options options;
571 options.message_loop_type = message_loop_type;
572 ASSERT_EQ(true, worker.StartWithOptions(options));
573 TaskList order;
574 win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
575 worker.task_runner()->PostTask(
576 FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(),
577 event.Get(), false, &order, true));
578 // Let the other thread execute.
579 WaitForSingleObject(event.Get(), INFINITE);
580 RunLoop().Run();
581
582 ASSERT_EQ(18u, order.Size());
583 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
584 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
585 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
586 // Note that this executes in the MessageBox modal loop.
587 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
588 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
589 EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
590 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
591 EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
592 /* The order can subtly change here. The reason is that when RecursiveFunc(1)
593 is called in the main thread, if it is faster than getting to the
594 PostTask(FROM_HERE, BindOnce(&QuitFunc) execution, the order of task
595 execution can change. We don't care anyway that the order isn't correct.
596 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
597 EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
598 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
599 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
600 */
601 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
602 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
603 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
604 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
605 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
606 EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
607 }
608
609 #endif // defined(OS_WIN)
610
PostNTasksThenQuit(int posts_remaining)611 void PostNTasksThenQuit(int posts_remaining) {
612 if (posts_remaining > 1) {
613 ThreadTaskRunnerHandle::Get()->PostTask(
614 FROM_HERE, BindOnce(&PostNTasksThenQuit, posts_remaining - 1));
615 } else {
616 RunLoop::QuitCurrentWhenIdleDeprecated();
617 }
618 }
619
620 #if defined(OS_WIN)
621
622 class TestIOHandler : public MessagePumpForIO::IOHandler {
623 public:
624 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
625
626 void OnIOCompleted(MessagePumpForIO::IOContext* context,
627 DWORD bytes_transfered,
628 DWORD error) override;
629
630 void Init();
631 void WaitForIO();
context()632 OVERLAPPED* context() { return &context_.overlapped; }
size()633 DWORD size() { return sizeof(buffer_); }
634
635 private:
636 char buffer_[48];
637 MessagePumpForIO::IOContext context_;
638 HANDLE signal_;
639 win::ScopedHandle file_;
640 bool wait_;
641 };
642
TestIOHandler(const wchar_t * name,HANDLE signal,bool wait)643 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
644 : signal_(signal), wait_(wait) {
645 memset(buffer_, 0, sizeof(buffer_));
646
647 file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
648 FILE_FLAG_OVERLAPPED, NULL));
649 EXPECT_TRUE(file_.IsValid());
650 }
651
Init()652 void TestIOHandler::Init() {
653 MessageLoopCurrentForIO::Get()->RegisterIOHandler(file_.Get(), this);
654
655 DWORD read;
656 EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context()));
657 EXPECT_EQ(static_cast<DWORD>(ERROR_IO_PENDING), GetLastError());
658 if (wait_)
659 WaitForIO();
660 }
661
OnIOCompleted(MessagePumpForIO::IOContext * context,DWORD bytes_transfered,DWORD error)662 void TestIOHandler::OnIOCompleted(MessagePumpForIO::IOContext* context,
663 DWORD bytes_transfered,
664 DWORD error) {
665 ASSERT_TRUE(context == &context_);
666 ASSERT_TRUE(SetEvent(signal_));
667 }
668
WaitForIO()669 void TestIOHandler::WaitForIO() {
670 EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(300, this));
671 EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(400, this));
672 }
673
RunTest_IOHandler()674 void RunTest_IOHandler() {
675 win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
676 ASSERT_TRUE(callback_called.IsValid());
677
678 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
679 win::ScopedHandle server(
680 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
681 ASSERT_TRUE(server.IsValid());
682
683 Thread thread("IOHandler test");
684 Thread::Options options;
685 options.message_loop_type = MessageLoop::TYPE_IO;
686 ASSERT_TRUE(thread.StartWithOptions(options));
687
688 TestIOHandler handler(kPipeName, callback_called.Get(), false);
689 thread.task_runner()->PostTask(
690 FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler)));
691 // Make sure the thread runs and sleeps for lack of work.
692 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
693
694 const char buffer[] = "Hello there!";
695 DWORD written;
696 EXPECT_TRUE(WriteFile(server.Get(), buffer, sizeof(buffer), &written, NULL));
697
698 DWORD result = WaitForSingleObject(callback_called.Get(), 1000);
699 EXPECT_EQ(WAIT_OBJECT_0, result);
700
701 thread.Stop();
702 }
703
RunTest_WaitForIO()704 void RunTest_WaitForIO() {
705 win::ScopedHandle callback1_called(
706 CreateEvent(NULL, TRUE, FALSE, NULL));
707 win::ScopedHandle callback2_called(
708 CreateEvent(NULL, TRUE, FALSE, NULL));
709 ASSERT_TRUE(callback1_called.IsValid());
710 ASSERT_TRUE(callback2_called.IsValid());
711
712 const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
713 const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
714 win::ScopedHandle server1(
715 CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
716 win::ScopedHandle server2(
717 CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
718 ASSERT_TRUE(server1.IsValid());
719 ASSERT_TRUE(server2.IsValid());
720
721 Thread thread("IOHandler test");
722 Thread::Options options;
723 options.message_loop_type = MessageLoop::TYPE_IO;
724 ASSERT_TRUE(thread.StartWithOptions(options));
725
726 TestIOHandler handler1(kPipeName1, callback1_called.Get(), false);
727 TestIOHandler handler2(kPipeName2, callback2_called.Get(), true);
728 thread.task_runner()->PostTask(
729 FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler1)));
730 // TODO(ajwong): Do we really need such long Sleeps in this function?
731 // Make sure the thread runs and sleeps for lack of work.
732 TimeDelta delay = TimeDelta::FromMilliseconds(100);
733 PlatformThread::Sleep(delay);
734 thread.task_runner()->PostTask(
735 FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler2)));
736 PlatformThread::Sleep(delay);
737
738 // At this time handler1 is waiting to be called, and the thread is waiting
739 // on the Init method of handler2, filtering only handler2 callbacks.
740
741 const char buffer[] = "Hello there!";
742 DWORD written;
743 EXPECT_TRUE(WriteFile(server1.Get(), buffer, sizeof(buffer), &written, NULL));
744 PlatformThread::Sleep(2 * delay);
745 EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
746 WaitForSingleObject(callback1_called.Get(), 0))
747 << "handler1 has not been called";
748
749 EXPECT_TRUE(WriteFile(server2.Get(), buffer, sizeof(buffer), &written, NULL));
750
751 HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
752 DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
753 EXPECT_EQ(WAIT_OBJECT_0, result);
754
755 thread.Stop();
756 }
757
758 #endif // defined(OS_WIN)
759
760 } // namespace
761
762 //-----------------------------------------------------------------------------
763 // Each test is run against each type of MessageLoop. That way we are sure
764 // that message loops work properly in all configurations. Of course, in some
765 // cases, a unit test may only be for a particular type of loop.
766
767 namespace {
768
769 struct MessageLoopTypedTestParams {
MessageLoopTypedTestParamsbase::__anon2a3b24860411::MessageLoopTypedTestParams770 MessageLoopTypedTestParams(
771 MessageLoop::Type type_in,
772 TaskSchedulerAvailability task_scheduler_availability_in) {
773 type = type_in;
774 task_scheduler_availability = task_scheduler_availability_in;
775 }
776
777 MessageLoop::Type type;
778 TaskSchedulerAvailability task_scheduler_availability;
779 };
780
781 class MessageLoopTypedTest
782 : public ::testing::TestWithParam<MessageLoopTypedTestParams> {
783 public:
784 MessageLoopTypedTest() = default;
785 ~MessageLoopTypedTest() = default;
786
SetUp()787 void SetUp() override {
788 // Unsupported in libchrome.
789 #if 0
790 if (GetTaskSchedulerAvailability() ==
791 TaskSchedulerAvailability::WITH_TASK_SCHEDULER) {
792 TaskScheduler::CreateAndStartWithDefaultParams("MessageLoopTypedTest");
793 }
794 #endif
795 }
796
TearDown()797 void TearDown() override {
798 // Unsupported in libchrome.
799 #if 0
800 if (GetTaskSchedulerAvailability() ==
801 TaskSchedulerAvailability::WITH_TASK_SCHEDULER) {
802 // Failure to call FlushForTesting() could result in task leaks as tasks
803 // are skipped on shutdown.
804 base::TaskScheduler::GetInstance()->FlushForTesting();
805 base::TaskScheduler::GetInstance()->Shutdown();
806 base::TaskScheduler::GetInstance()->JoinForTesting();
807 base::TaskScheduler::SetInstance(nullptr);
808 }
809 #endif
810 }
811
ParamInfoToString(::testing::TestParamInfo<MessageLoopTypedTestParams> param_info)812 static std::string ParamInfoToString(
813 ::testing::TestParamInfo<MessageLoopTypedTestParams> param_info) {
814 return MessageLoopTypeToString(param_info.param.type) + "_" +
815 TaskSchedulerAvailabilityToString(
816 param_info.param.task_scheduler_availability);
817 }
818
819 protected:
GetMessageLoopType()820 MessageLoop::Type GetMessageLoopType() { return GetParam().type; }
821
822 private:
MessageLoopTypeToString(MessageLoop::Type type)823 static std::string MessageLoopTypeToString(MessageLoop::Type type) {
824 switch (type) {
825 case MessageLoop::TYPE_DEFAULT:
826 return "Default";
827 case MessageLoop::TYPE_IO:
828 return "IO";
829 case MessageLoop::TYPE_UI:
830 return "UI";
831 case MessageLoop::TYPE_CUSTOM:
832 #if defined(OS_ANDROID)
833 case MessageLoop::TYPE_JAVA:
834 #endif // defined(OS_ANDROID)
835 break;
836 }
837 NOTREACHED();
838 return "NotSupported";
839 }
840
GetTaskSchedulerAvailability()841 TaskSchedulerAvailability GetTaskSchedulerAvailability() {
842 return GetParam().task_scheduler_availability;
843 }
844
845 DISALLOW_COPY_AND_ASSIGN(MessageLoopTypedTest);
846 };
847
848 } // namespace
849
TEST_P(MessageLoopTypedTest,PostTask)850 TEST_P(MessageLoopTypedTest, PostTask) {
851 MessageLoop loop(GetMessageLoopType());
852 // Add tests to message loop
853 scoped_refptr<Foo> foo(new Foo());
854 std::string a("a"), b("b"), c("c"), d("d");
855 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
856 BindOnce(&Foo::Test0, foo));
857 ThreadTaskRunnerHandle::Get()->PostTask(
858 FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, a));
859 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
860 BindOnce(&Foo::Test1Ptr, foo, &b));
861 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
862 BindOnce(&Foo::Test1Int, foo, 100));
863 ThreadTaskRunnerHandle::Get()->PostTask(
864 FROM_HERE, BindOnce(&Foo::Test2Ptr, foo, &a, &c));
865 ThreadTaskRunnerHandle::Get()->PostTask(
866 FROM_HERE, BindOnce(&Foo::Test2Mixed, foo, a, &d));
867 // After all tests, post a message that will shut down the message loop
868 ThreadTaskRunnerHandle::Get()->PostTask(
869 FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
870
871 // Now kick things off
872 RunLoop().Run();
873
874 EXPECT_EQ(foo->test_count(), 105);
875 EXPECT_EQ(foo->result(), "abacad");
876 }
877
TEST_P(MessageLoopTypedTest,PostDelayedTask_Basic)878 TEST_P(MessageLoopTypedTest, PostDelayedTask_Basic) {
879 MessageLoop loop(GetMessageLoopType());
880
881 // Test that PostDelayedTask results in a delayed task.
882
883 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
884
885 int num_tasks = 1;
886 TimeTicks run_time;
887
888 TimeTicks time_before_run = TimeTicks::Now();
889 loop.task_runner()->PostDelayedTask(
890 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks), kDelay);
891 RunLoop().Run();
892 TimeTicks time_after_run = TimeTicks::Now();
893
894 EXPECT_EQ(0, num_tasks);
895 EXPECT_LT(kDelay, time_after_run - time_before_run);
896 }
897
TEST_P(MessageLoopTypedTest,PostDelayedTask_InDelayOrder)898 TEST_P(MessageLoopTypedTest, PostDelayedTask_InDelayOrder) {
899 MessageLoop loop(GetMessageLoopType());
900
901 // Test that two tasks with different delays run in the right order.
902 int num_tasks = 2;
903 TimeTicks run_time1, run_time2;
904
905 loop.task_runner()->PostDelayedTask(
906 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks),
907 TimeDelta::FromMilliseconds(200));
908 // If we get a large pause in execution (due to a context switch) here, this
909 // test could fail.
910 loop.task_runner()->PostDelayedTask(
911 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
912 TimeDelta::FromMilliseconds(10));
913
914 RunLoop().Run();
915 EXPECT_EQ(0, num_tasks);
916
917 EXPECT_TRUE(run_time2 < run_time1);
918 }
919
TEST_P(MessageLoopTypedTest,PostDelayedTask_InPostOrder)920 TEST_P(MessageLoopTypedTest, PostDelayedTask_InPostOrder) {
921 MessageLoop loop(GetMessageLoopType());
922
923 // Test that two tasks with the same delay run in the order in which they
924 // were posted.
925 //
926 // NOTE: This is actually an approximate test since the API only takes a
927 // "delay" parameter, so we are not exactly simulating two tasks that get
928 // posted at the exact same time. It would be nice if the API allowed us to
929 // specify the desired run time.
930
931 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
932
933 int num_tasks = 2;
934 TimeTicks run_time1, run_time2;
935
936 loop.task_runner()->PostDelayedTask(
937 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks), kDelay);
938 loop.task_runner()->PostDelayedTask(
939 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks), kDelay);
940
941 RunLoop().Run();
942 EXPECT_EQ(0, num_tasks);
943
944 EXPECT_TRUE(run_time1 < run_time2);
945 }
946
TEST_P(MessageLoopTypedTest,PostDelayedTask_InPostOrder_2)947 TEST_P(MessageLoopTypedTest, PostDelayedTask_InPostOrder_2) {
948 MessageLoop loop(GetMessageLoopType());
949
950 // Test that a delayed task still runs after a normal tasks even if the
951 // normal tasks take a long time to run.
952
953 const TimeDelta kPause = TimeDelta::FromMilliseconds(50);
954
955 int num_tasks = 2;
956 TimeTicks run_time;
957
958 loop.task_runner()->PostTask(FROM_HERE,
959 BindOnce(&SlowFunc, kPause, &num_tasks));
960 loop.task_runner()->PostDelayedTask(
961 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks),
962 TimeDelta::FromMilliseconds(10));
963
964 TimeTicks time_before_run = TimeTicks::Now();
965 RunLoop().Run();
966 TimeTicks time_after_run = TimeTicks::Now();
967
968 EXPECT_EQ(0, num_tasks);
969
970 EXPECT_LT(kPause, time_after_run - time_before_run);
971 }
972
TEST_P(MessageLoopTypedTest,PostDelayedTask_InPostOrder_3)973 TEST_P(MessageLoopTypedTest, PostDelayedTask_InPostOrder_3) {
974 MessageLoop loop(GetMessageLoopType());
975
976 // Test that a delayed task still runs after a pile of normal tasks. The key
977 // difference between this test and the previous one is that here we return
978 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities
979 // to maybe run the delayed task. It should know not to do so until the
980 // delayed task's delay has passed.
981
982 int num_tasks = 11;
983 TimeTicks run_time1, run_time2;
984
985 // Clutter the ML with tasks.
986 for (int i = 1; i < num_tasks; ++i)
987 loop.task_runner()->PostTask(
988 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks));
989
990 loop.task_runner()->PostDelayedTask(
991 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
992 TimeDelta::FromMilliseconds(1));
993
994 RunLoop().Run();
995 EXPECT_EQ(0, num_tasks);
996
997 EXPECT_TRUE(run_time2 > run_time1);
998 }
999
TEST_P(MessageLoopTypedTest,PostDelayedTask_SharedTimer)1000 TEST_P(MessageLoopTypedTest, PostDelayedTask_SharedTimer) {
1001 MessageLoop loop(GetMessageLoopType());
1002
1003 // Test that the interval of the timer, used to run the next delayed task, is
1004 // set to a value corresponding to when the next delayed task should run.
1005
1006 // By setting num_tasks to 1, we ensure that the first task to run causes the
1007 // run loop to exit.
1008 int num_tasks = 1;
1009 TimeTicks run_time1, run_time2;
1010
1011 loop.task_runner()->PostDelayedTask(
1012 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks),
1013 TimeDelta::FromSeconds(1000));
1014 loop.task_runner()->PostDelayedTask(
1015 FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
1016 TimeDelta::FromMilliseconds(10));
1017
1018 TimeTicks start_time = TimeTicks::Now();
1019
1020 RunLoop().Run();
1021 EXPECT_EQ(0, num_tasks);
1022
1023 // Ensure that we ran in far less time than the slower timer.
1024 TimeDelta total_time = TimeTicks::Now() - start_time;
1025 EXPECT_GT(5000, total_time.InMilliseconds());
1026
1027 // In case both timers somehow run at nearly the same time, sleep a little
1028 // and then run all pending to force them both to have run. This is just
1029 // encouraging flakiness if there is any.
1030 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
1031 RunLoop().RunUntilIdle();
1032
1033 EXPECT_TRUE(run_time1.is_null());
1034 EXPECT_FALSE(run_time2.is_null());
1035 }
1036
1037 namespace {
1038
1039 // This is used to inject a test point for recording the destructor calls for
1040 // Closure objects send to MessageLoop::PostTask(). It is awkward usage since we
1041 // are trying to hook the actual destruction, which is not a common operation.
1042 class RecordDeletionProbe : public RefCounted<RecordDeletionProbe> {
1043 public:
RecordDeletionProbe(RecordDeletionProbe * post_on_delete,bool * was_deleted)1044 RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
1045 : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {}
Run()1046 void Run() {}
1047
1048 private:
1049 friend class RefCounted<RecordDeletionProbe>;
1050
~RecordDeletionProbe()1051 ~RecordDeletionProbe() {
1052 *was_deleted_ = true;
1053 if (post_on_delete_.get())
1054 ThreadTaskRunnerHandle::Get()->PostTask(
1055 FROM_HERE, BindOnce(&RecordDeletionProbe::Run, post_on_delete_));
1056 }
1057
1058 scoped_refptr<RecordDeletionProbe> post_on_delete_;
1059 bool* was_deleted_;
1060 };
1061
1062 } // namespace
1063
1064 /* TODO(darin): MessageLoop does not support deleting all tasks in the */
1065 /* destructor. */
1066 /* Fails, http://crbug.com/50272. */
TEST_P(MessageLoopTypedTest,DISABLED_EnsureDeletion)1067 TEST_P(MessageLoopTypedTest, DISABLED_EnsureDeletion) {
1068 bool a_was_deleted = false;
1069 bool b_was_deleted = false;
1070 {
1071 MessageLoop loop(GetMessageLoopType());
1072 loop.task_runner()->PostTask(
1073 FROM_HERE, BindOnce(&RecordDeletionProbe::Run,
1074 new RecordDeletionProbe(nullptr, &a_was_deleted)));
1075 // TODO(ajwong): Do we really need 1000ms here?
1076 loop.task_runner()->PostDelayedTask(
1077 FROM_HERE,
1078 BindOnce(&RecordDeletionProbe::Run,
1079 new RecordDeletionProbe(nullptr, &b_was_deleted)),
1080 TimeDelta::FromMilliseconds(1000));
1081 }
1082 EXPECT_TRUE(a_was_deleted);
1083 EXPECT_TRUE(b_was_deleted);
1084 }
1085
1086 /* TODO(darin): MessageLoop does not support deleting all tasks in the */
1087 /* destructor. */
1088 /* Fails, http://crbug.com/50272. */
TEST_P(MessageLoopTypedTest,DISABLED_EnsureDeletion_Chain)1089 TEST_P(MessageLoopTypedTest, DISABLED_EnsureDeletion_Chain) {
1090 bool a_was_deleted = false;
1091 bool b_was_deleted = false;
1092 bool c_was_deleted = false;
1093 {
1094 MessageLoop loop(GetMessageLoopType());
1095 // The scoped_refptr for each of the below is held either by the chained
1096 // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback.
1097 RecordDeletionProbe* a = new RecordDeletionProbe(nullptr, &a_was_deleted);
1098 RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted);
1099 RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted);
1100 loop.task_runner()->PostTask(FROM_HERE,
1101 BindOnce(&RecordDeletionProbe::Run, c));
1102 }
1103 EXPECT_TRUE(a_was_deleted);
1104 EXPECT_TRUE(b_was_deleted);
1105 EXPECT_TRUE(c_was_deleted);
1106 }
1107
1108 namespace {
1109
NestingFunc(int * depth)1110 void NestingFunc(int* depth) {
1111 if (*depth > 0) {
1112 *depth -= 1;
1113 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1114 BindOnce(&NestingFunc, depth));
1115
1116 MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
1117 RunLoop().Run();
1118 }
1119 base::RunLoop::QuitCurrentWhenIdleDeprecated();
1120 }
1121
1122 } // namespace
1123
TEST_P(MessageLoopTypedTest,Nesting)1124 TEST_P(MessageLoopTypedTest, Nesting) {
1125 MessageLoop loop(GetMessageLoopType());
1126
1127 int depth = 50;
1128 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1129 BindOnce(&NestingFunc, &depth));
1130 RunLoop().Run();
1131 EXPECT_EQ(depth, 0);
1132 }
1133
TEST_P(MessageLoopTypedTest,RecursiveDenial1)1134 TEST_P(MessageLoopTypedTest, RecursiveDenial1) {
1135 MessageLoop loop(GetMessageLoopType());
1136
1137 EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1138 TaskList order;
1139 ThreadTaskRunnerHandle::Get()->PostTask(
1140 FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, false));
1141 ThreadTaskRunnerHandle::Get()->PostTask(
1142 FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2, false));
1143 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1144 BindOnce(&QuitFunc, &order, 3));
1145
1146 RunLoop().Run();
1147
1148 // FIFO order.
1149 ASSERT_EQ(14U, order.Size());
1150 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1151 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1152 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
1153 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
1154 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
1155 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
1156 EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
1157 EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
1158 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
1159 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
1160 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
1161 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
1162 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
1163 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
1164 }
1165
1166 namespace {
1167
RecursiveSlowFunc(TaskList * order,int cookie,int depth,bool is_reentrant)1168 void RecursiveSlowFunc(TaskList* order,
1169 int cookie,
1170 int depth,
1171 bool is_reentrant) {
1172 RecursiveFunc(order, cookie, depth, is_reentrant);
1173 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
1174 }
1175
OrderedFunc(TaskList * order,int cookie)1176 void OrderedFunc(TaskList* order, int cookie) {
1177 order->RecordStart(ORDERED, cookie);
1178 order->RecordEnd(ORDERED, cookie);
1179 }
1180
1181 } // namespace
1182
TEST_P(MessageLoopTypedTest,RecursiveDenial3)1183 TEST_P(MessageLoopTypedTest, RecursiveDenial3) {
1184 MessageLoop loop(GetMessageLoopType());
1185
1186 EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1187 TaskList order;
1188 ThreadTaskRunnerHandle::Get()->PostTask(
1189 FROM_HERE, BindOnce(&RecursiveSlowFunc, &order, 1, 2, false));
1190 ThreadTaskRunnerHandle::Get()->PostTask(
1191 FROM_HERE, BindOnce(&RecursiveSlowFunc, &order, 2, 2, false));
1192 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1193 FROM_HERE, BindOnce(&OrderedFunc, &order, 3),
1194 TimeDelta::FromMilliseconds(5));
1195 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1196 FROM_HERE, BindOnce(&QuitFunc, &order, 4),
1197 TimeDelta::FromMilliseconds(5));
1198
1199 RunLoop().Run();
1200
1201 // FIFO order.
1202 ASSERT_EQ(16U, order.Size());
1203 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1204 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1205 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
1206 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
1207 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true));
1208 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false));
1209 EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 3, true));
1210 EXPECT_EQ(order.Get(7), TaskItem(ORDERED, 3, false));
1211 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
1212 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
1213 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true));
1214 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false));
1215 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true));
1216 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false));
1217 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true));
1218 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false));
1219 }
1220
TEST_P(MessageLoopTypedTest,RecursiveSupport1)1221 TEST_P(MessageLoopTypedTest, RecursiveSupport1) {
1222 MessageLoop loop(GetMessageLoopType());
1223
1224 TaskList order;
1225 ThreadTaskRunnerHandle::Get()->PostTask(
1226 FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, true));
1227 ThreadTaskRunnerHandle::Get()->PostTask(
1228 FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2, true));
1229 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1230 BindOnce(&QuitFunc, &order, 3));
1231
1232 RunLoop().Run();
1233
1234 // FIFO order.
1235 ASSERT_EQ(14U, order.Size());
1236 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1237 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1238 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
1239 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
1240 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
1241 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
1242 EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
1243 EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
1244 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
1245 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
1246 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
1247 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
1248 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
1249 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
1250 }
1251
1252 // Tests that non nestable tasks run in FIFO if there are no nested loops.
TEST_P(MessageLoopTypedTest,NonNestableWithNoNesting)1253 TEST_P(MessageLoopTypedTest, NonNestableWithNoNesting) {
1254 MessageLoop loop(GetMessageLoopType());
1255
1256 TaskList order;
1257
1258 ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
1259 FROM_HERE, BindOnce(&OrderedFunc, &order, 1));
1260 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1261 BindOnce(&OrderedFunc, &order, 2));
1262 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1263 BindOnce(&QuitFunc, &order, 3));
1264 RunLoop().Run();
1265
1266 // FIFO order.
1267 ASSERT_EQ(6U, order.Size());
1268 EXPECT_EQ(order.Get(0), TaskItem(ORDERED, 1, true));
1269 EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 1, false));
1270 EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 2, true));
1271 EXPECT_EQ(order.Get(3), TaskItem(ORDERED, 2, false));
1272 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
1273 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
1274 }
1275
1276 namespace {
1277
FuncThatPumps(TaskList * order,int cookie)1278 void FuncThatPumps(TaskList* order, int cookie) {
1279 order->RecordStart(PUMPS, cookie);
1280 RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
1281 order->RecordEnd(PUMPS, cookie);
1282 }
1283
SleepFunc(TaskList * order,int cookie,TimeDelta delay)1284 void SleepFunc(TaskList* order, int cookie, TimeDelta delay) {
1285 order->RecordStart(SLEEP, cookie);
1286 PlatformThread::Sleep(delay);
1287 order->RecordEnd(SLEEP, cookie);
1288 }
1289
1290 } // namespace
1291
1292 // Tests that non nestable tasks don't run when there's code in the call stack.
TEST_P(MessageLoopTypedTest,NonNestableDelayedInNestedLoop)1293 TEST_P(MessageLoopTypedTest, NonNestableDelayedInNestedLoop) {
1294 MessageLoop loop(GetMessageLoopType());
1295
1296 TaskList order;
1297
1298 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1299 BindOnce(&FuncThatPumps, &order, 1));
1300 ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
1301 FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
1302 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1303 BindOnce(&OrderedFunc, &order, 3));
1304 ThreadTaskRunnerHandle::Get()->PostTask(
1305 FROM_HERE,
1306 BindOnce(&SleepFunc, &order, 4, TimeDelta::FromMilliseconds(50)));
1307 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1308 BindOnce(&OrderedFunc, &order, 5));
1309 ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
1310 FROM_HERE, BindOnce(&QuitFunc, &order, 6));
1311
1312 RunLoop().Run();
1313
1314 // FIFO order.
1315 ASSERT_EQ(12U, order.Size());
1316 EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
1317 EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 3, true));
1318 EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 3, false));
1319 EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
1320 EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
1321 EXPECT_EQ(order.Get(5), TaskItem(ORDERED, 5, true));
1322 EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 5, false));
1323 EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
1324 EXPECT_EQ(order.Get(8), TaskItem(ORDERED, 2, true));
1325 EXPECT_EQ(order.Get(9), TaskItem(ORDERED, 2, false));
1326 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
1327 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
1328 }
1329
1330 namespace {
1331
FuncThatRuns(TaskList * order,int cookie,RunLoop * run_loop)1332 void FuncThatRuns(TaskList* order, int cookie, RunLoop* run_loop) {
1333 order->RecordStart(RUNS, cookie);
1334 {
1335 MessageLoopCurrent::ScopedNestableTaskAllower allow;
1336 run_loop->Run();
1337 }
1338 order->RecordEnd(RUNS, cookie);
1339 }
1340
FuncThatQuitsNow()1341 void FuncThatQuitsNow() {
1342 base::RunLoop::QuitCurrentDeprecated();
1343 }
1344
1345 } // namespace
1346
1347 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(MessageLoopTypedTest,QuitNow)1348 TEST_P(MessageLoopTypedTest, QuitNow) {
1349 MessageLoop loop(GetMessageLoopType());
1350
1351 TaskList order;
1352
1353 RunLoop run_loop;
1354
1355 ThreadTaskRunnerHandle::Get()->PostTask(
1356 FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
1357 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1358 BindOnce(&OrderedFunc, &order, 2));
1359 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1360 BindOnce(&FuncThatQuitsNow));
1361 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1362 BindOnce(&OrderedFunc, &order, 3));
1363 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1364 BindOnce(&FuncThatQuitsNow));
1365 ThreadTaskRunnerHandle::Get()->PostTask(
1366 FROM_HERE, BindOnce(&OrderedFunc, &order, 4)); // never runs
1367
1368 RunLoop().Run();
1369
1370 ASSERT_EQ(6U, order.Size());
1371 int task_index = 0;
1372 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1373 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1374 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1375 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1376 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
1377 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
1378 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1379 }
1380
1381 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(MessageLoopTypedTest,RunLoopQuitTop)1382 TEST_P(MessageLoopTypedTest, RunLoopQuitTop) {
1383 MessageLoop loop(GetMessageLoopType());
1384
1385 TaskList order;
1386
1387 RunLoop outer_run_loop;
1388 RunLoop nested_run_loop;
1389
1390 ThreadTaskRunnerHandle::Get()->PostTask(
1391 FROM_HERE,
1392 BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
1393 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1394 outer_run_loop.QuitClosure());
1395 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1396 BindOnce(&OrderedFunc, &order, 2));
1397 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1398 nested_run_loop.QuitClosure());
1399
1400 outer_run_loop.Run();
1401
1402 ASSERT_EQ(4U, order.Size());
1403 int task_index = 0;
1404 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1405 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1406 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1407 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1408 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1409 }
1410
1411 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(MessageLoopTypedTest,RunLoopQuitNested)1412 TEST_P(MessageLoopTypedTest, RunLoopQuitNested) {
1413 MessageLoop loop(GetMessageLoopType());
1414
1415 TaskList order;
1416
1417 RunLoop outer_run_loop;
1418 RunLoop nested_run_loop;
1419
1420 ThreadTaskRunnerHandle::Get()->PostTask(
1421 FROM_HERE,
1422 BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
1423 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1424 nested_run_loop.QuitClosure());
1425 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1426 BindOnce(&OrderedFunc, &order, 2));
1427 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1428 outer_run_loop.QuitClosure());
1429
1430 outer_run_loop.Run();
1431
1432 ASSERT_EQ(4U, order.Size());
1433 int task_index = 0;
1434 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1435 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1436 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1437 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1438 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1439 }
1440
1441 // Quits current loop and immediately runs a nested loop.
QuitAndRunNestedLoop(TaskList * order,int cookie,RunLoop * outer_run_loop,RunLoop * nested_run_loop)1442 void QuitAndRunNestedLoop(TaskList* order,
1443 int cookie,
1444 RunLoop* outer_run_loop,
1445 RunLoop* nested_run_loop) {
1446 order->RecordStart(RUNS, cookie);
1447 outer_run_loop->Quit();
1448 nested_run_loop->Run();
1449 order->RecordEnd(RUNS, cookie);
1450 }
1451
1452 // Test that we can run nested loop after quitting the current one.
TEST_P(MessageLoopTypedTest,RunLoopNestedAfterQuit)1453 TEST_P(MessageLoopTypedTest, RunLoopNestedAfterQuit) {
1454 MessageLoop loop(GetMessageLoopType());
1455
1456 TaskList order;
1457
1458 RunLoop outer_run_loop;
1459 RunLoop nested_run_loop;
1460
1461 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1462 nested_run_loop.QuitClosure());
1463 ThreadTaskRunnerHandle::Get()->PostTask(
1464 FROM_HERE, BindOnce(&QuitAndRunNestedLoop, &order, 1, &outer_run_loop,
1465 &nested_run_loop));
1466
1467 outer_run_loop.Run();
1468
1469 ASSERT_EQ(2U, order.Size());
1470 int task_index = 0;
1471 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1472 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1473 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1474 }
1475
1476 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(MessageLoopTypedTest,RunLoopQuitBogus)1477 TEST_P(MessageLoopTypedTest, RunLoopQuitBogus) {
1478 MessageLoop loop(GetMessageLoopType());
1479
1480 TaskList order;
1481
1482 RunLoop outer_run_loop;
1483 RunLoop nested_run_loop;
1484 RunLoop bogus_run_loop;
1485
1486 ThreadTaskRunnerHandle::Get()->PostTask(
1487 FROM_HERE,
1488 BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
1489 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1490 bogus_run_loop.QuitClosure());
1491 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1492 BindOnce(&OrderedFunc, &order, 2));
1493 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1494 outer_run_loop.QuitClosure());
1495 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1496 nested_run_loop.QuitClosure());
1497
1498 outer_run_loop.Run();
1499
1500 ASSERT_EQ(4U, order.Size());
1501 int task_index = 0;
1502 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1503 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1504 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1505 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1506 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1507 }
1508
1509 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(MessageLoopTypedTest,RunLoopQuitDeep)1510 TEST_P(MessageLoopTypedTest, RunLoopQuitDeep) {
1511 MessageLoop loop(GetMessageLoopType());
1512
1513 TaskList order;
1514
1515 RunLoop outer_run_loop;
1516 RunLoop nested_loop1;
1517 RunLoop nested_loop2;
1518 RunLoop nested_loop3;
1519 RunLoop nested_loop4;
1520
1521 ThreadTaskRunnerHandle::Get()->PostTask(
1522 FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_loop1)));
1523 ThreadTaskRunnerHandle::Get()->PostTask(
1524 FROM_HERE, BindOnce(&FuncThatRuns, &order, 2, Unretained(&nested_loop2)));
1525 ThreadTaskRunnerHandle::Get()->PostTask(
1526 FROM_HERE, BindOnce(&FuncThatRuns, &order, 3, Unretained(&nested_loop3)));
1527 ThreadTaskRunnerHandle::Get()->PostTask(
1528 FROM_HERE, BindOnce(&FuncThatRuns, &order, 4, Unretained(&nested_loop4)));
1529 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1530 BindOnce(&OrderedFunc, &order, 5));
1531 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1532 outer_run_loop.QuitClosure());
1533 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1534 BindOnce(&OrderedFunc, &order, 6));
1535 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1536 nested_loop1.QuitClosure());
1537 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1538 BindOnce(&OrderedFunc, &order, 7));
1539 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1540 nested_loop2.QuitClosure());
1541 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1542 BindOnce(&OrderedFunc, &order, 8));
1543 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1544 nested_loop3.QuitClosure());
1545 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1546 BindOnce(&OrderedFunc, &order, 9));
1547 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1548 nested_loop4.QuitClosure());
1549 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1550 BindOnce(&OrderedFunc, &order, 10));
1551
1552 outer_run_loop.Run();
1553
1554 ASSERT_EQ(18U, order.Size());
1555 int task_index = 0;
1556 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1557 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, true));
1558 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, true));
1559 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, true));
1560 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, true));
1561 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, false));
1562 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, true));
1563 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, false));
1564 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, true));
1565 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, false));
1566 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, true));
1567 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, false));
1568 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, true));
1569 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, false));
1570 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, false));
1571 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, false));
1572 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, false));
1573 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1574 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1575 }
1576
1577 // Tests RunLoopQuit works before RunWithID.
TEST_P(MessageLoopTypedTest,RunLoopQuitOrderBefore)1578 TEST_P(MessageLoopTypedTest, RunLoopQuitOrderBefore) {
1579 MessageLoop loop(GetMessageLoopType());
1580
1581 TaskList order;
1582
1583 RunLoop run_loop;
1584
1585 run_loop.Quit();
1586
1587 ThreadTaskRunnerHandle::Get()->PostTask(
1588 FROM_HERE, BindOnce(&OrderedFunc, &order, 1)); // never runs
1589 ThreadTaskRunnerHandle::Get()->PostTask(
1590 FROM_HERE, BindOnce(&FuncThatQuitsNow)); // never runs
1591
1592 run_loop.Run();
1593
1594 ASSERT_EQ(0U, order.Size());
1595 }
1596
1597 // Tests RunLoopQuit works during RunWithID.
TEST_P(MessageLoopTypedTest,RunLoopQuitOrderDuring)1598 TEST_P(MessageLoopTypedTest, RunLoopQuitOrderDuring) {
1599 MessageLoop loop(GetMessageLoopType());
1600
1601 TaskList order;
1602
1603 RunLoop run_loop;
1604
1605 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1606 BindOnce(&OrderedFunc, &order, 1));
1607 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
1608 ThreadTaskRunnerHandle::Get()->PostTask(
1609 FROM_HERE, BindOnce(&OrderedFunc, &order, 2)); // never runs
1610 ThreadTaskRunnerHandle::Get()->PostTask(
1611 FROM_HERE, BindOnce(&FuncThatQuitsNow)); // never runs
1612
1613 run_loop.Run();
1614
1615 ASSERT_EQ(2U, order.Size());
1616 int task_index = 0;
1617 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, true));
1618 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, false));
1619 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1620 }
1621
1622 // Tests RunLoopQuit works after RunWithID.
TEST_P(MessageLoopTypedTest,RunLoopQuitOrderAfter)1623 TEST_P(MessageLoopTypedTest, RunLoopQuitOrderAfter) {
1624 MessageLoop loop(GetMessageLoopType());
1625
1626 TaskList order;
1627
1628 RunLoop run_loop;
1629
1630 ThreadTaskRunnerHandle::Get()->PostTask(
1631 FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
1632 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1633 BindOnce(&OrderedFunc, &order, 2));
1634 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1635 BindOnce(&FuncThatQuitsNow));
1636 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1637 BindOnce(&OrderedFunc, &order, 3));
1638 ThreadTaskRunnerHandle::Get()->PostTask(
1639 FROM_HERE, run_loop.QuitClosure()); // has no affect
1640 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1641 BindOnce(&OrderedFunc, &order, 4));
1642 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1643 BindOnce(&FuncThatQuitsNow));
1644
1645 run_loop.allow_quit_current_deprecated_ = true;
1646
1647 RunLoop outer_run_loop;
1648 outer_run_loop.Run();
1649
1650 ASSERT_EQ(8U, order.Size());
1651 int task_index = 0;
1652 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1653 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1654 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1655 EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1656 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
1657 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
1658 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, true));
1659 EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, false));
1660 EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1661 }
1662
1663 // There was a bug in the MessagePumpGLib where posting tasks recursively
1664 // caused the message loop to hang, due to the buffer of the internal pipe
1665 // becoming full. Test all MessageLoop types to ensure this issue does not
1666 // exist in other MessagePumps.
1667 //
1668 // On Linux, the pipe buffer size is 64KiB by default. The bug caused one
1669 // byte accumulated in the pipe per two posts, so we should repeat 128K
1670 // times to reproduce the bug.
1671 #if defined(OS_FUCHSIA)
1672 // TODO(crbug.com/810077): This is flaky on Fuchsia.
1673 #define MAYBE_RecursivePosts DISABLED_RecursivePosts
1674 #else
1675 #define MAYBE_RecursivePosts RecursivePosts
1676 #endif
TEST_P(MessageLoopTypedTest,MAYBE_RecursivePosts)1677 TEST_P(MessageLoopTypedTest, MAYBE_RecursivePosts) {
1678 const int kNumTimes = 1 << 17;
1679 MessageLoop loop(GetMessageLoopType());
1680 loop.task_runner()->PostTask(FROM_HERE,
1681 BindOnce(&PostNTasksThenQuit, kNumTimes));
1682 RunLoop().Run();
1683 }
1684
TEST_P(MessageLoopTypedTest,NestableTasksAllowedAtTopLevel)1685 TEST_P(MessageLoopTypedTest, NestableTasksAllowedAtTopLevel) {
1686 MessageLoop loop(GetMessageLoopType());
1687 EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1688 }
1689
1690 // Nestable tasks shouldn't be allowed to run reentrantly by default (regression
1691 // test for https://crbug.com/754112).
TEST_P(MessageLoopTypedTest,NestableTasksDisallowedByDefault)1692 TEST_P(MessageLoopTypedTest, NestableTasksDisallowedByDefault) {
1693 MessageLoop loop(GetMessageLoopType());
1694 RunLoop run_loop;
1695 loop.task_runner()->PostTask(
1696 FROM_HERE,
1697 BindOnce(
1698 [](RunLoop* run_loop) {
1699 EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1700 run_loop->Quit();
1701 },
1702 Unretained(&run_loop)));
1703 run_loop.Run();
1704 }
1705
TEST_P(MessageLoopTypedTest,NestableTasksProcessedWhenRunLoopAllows)1706 TEST_P(MessageLoopTypedTest, NestableTasksProcessedWhenRunLoopAllows) {
1707 MessageLoop loop(GetMessageLoopType());
1708 RunLoop run_loop;
1709 loop.task_runner()->PostTask(
1710 FROM_HERE,
1711 BindOnce(
1712 [](RunLoop* run_loop) {
1713 // This test would hang if this RunLoop wasn't of type
1714 // kNestableTasksAllowed (i.e. this is testing that this is
1715 // processed and doesn't hang).
1716 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
1717 ThreadTaskRunnerHandle::Get()->PostTask(
1718 FROM_HERE,
1719 BindOnce(
1720 [](RunLoop* nested_run_loop) {
1721 // Each additional layer of application task nesting
1722 // requires its own allowance. The kNestableTasksAllowed
1723 // RunLoop allowed this task to be processed but further
1724 // nestable tasks are by default disallowed from this
1725 // layer.
1726 EXPECT_FALSE(
1727 MessageLoopCurrent::Get()->NestableTasksAllowed());
1728 nested_run_loop->Quit();
1729 },
1730 Unretained(&nested_run_loop)));
1731 nested_run_loop.Run();
1732
1733 run_loop->Quit();
1734 },
1735 Unretained(&run_loop)));
1736 run_loop.Run();
1737 }
1738
TEST_P(MessageLoopTypedTest,NestableTasksAllowedExplicitlyInScope)1739 TEST_P(MessageLoopTypedTest, NestableTasksAllowedExplicitlyInScope) {
1740 MessageLoop loop(GetMessageLoopType());
1741 RunLoop run_loop;
1742 loop.task_runner()->PostTask(
1743 FROM_HERE,
1744 BindOnce(
1745 [](RunLoop* run_loop) {
1746 {
1747 MessageLoopCurrent::ScopedNestableTaskAllower
1748 allow_nestable_tasks;
1749 EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1750 }
1751 EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1752 run_loop->Quit();
1753 },
1754 Unretained(&run_loop)));
1755 run_loop.Run();
1756 }
1757
TEST_P(MessageLoopTypedTest,NestableTasksAllowedManually)1758 TEST_P(MessageLoopTypedTest, NestableTasksAllowedManually) {
1759 MessageLoop loop(GetMessageLoopType());
1760 RunLoop run_loop;
1761 loop.task_runner()->PostTask(
1762 FROM_HERE,
1763 BindOnce(
1764 [](RunLoop* run_loop) {
1765 EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1766 MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
1767 EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1768 MessageLoopCurrent::Get()->SetNestableTasksAllowed(false);
1769 EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
1770 run_loop->Quit();
1771 },
1772 Unretained(&run_loop)));
1773 run_loop.Run();
1774 }
1775
1776 INSTANTIATE_TEST_CASE_P(
1777 ,
1778 MessageLoopTypedTest,
1779 ::testing::Values(MessageLoopTypedTestParams(
1780 MessageLoop::TYPE_DEFAULT,
1781 TaskSchedulerAvailability::NO_TASK_SCHEDULER),
1782 MessageLoopTypedTestParams(
1783 MessageLoop::TYPE_IO,
1784 TaskSchedulerAvailability::NO_TASK_SCHEDULER),
1785 MessageLoopTypedTestParams(
1786 MessageLoop::TYPE_UI,
1787 TaskSchedulerAvailability::NO_TASK_SCHEDULER)
1788 // Unsupported in libchrome.
1789 #if 0
1790 ,MessageLoopTypedTestParams(
1791 MessageLoop::TYPE_DEFAULT,
1792 TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
1793 MessageLoopTypedTestParams(
1794 MessageLoop::TYPE_IO,
1795 TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
1796 MessageLoopTypedTestParams(
1797 MessageLoop::TYPE_UI,
1798 TaskSchedulerAvailability::WITH_TASK_SCHEDULER)
1799 #endif
1800 ),
1801 MessageLoopTypedTest::ParamInfoToString);
1802
1803 #if defined(OS_WIN)
1804 // Verifies that the MessageLoop ignores WM_QUIT, rather than quitting.
1805 // Users of MessageLoop typically expect to control when their RunLoops stop
1806 // Run()ning explicitly, via QuitClosure() etc (see https://crbug.com/720078)
TEST_P(MessageLoopTest,WmQuitIsIgnored)1807 TEST_P(MessageLoopTest, WmQuitIsIgnored) {
1808 MessageLoop loop(MessageLoop::TYPE_UI);
1809
1810 // Post a WM_QUIT message to the current thread.
1811 ::PostQuitMessage(0);
1812
1813 // Post a task to the current thread, with a small delay to make it less
1814 // likely that we process the posted task before looking for WM_* messages.
1815 bool task_was_run = false;
1816 RunLoop run_loop;
1817 loop.task_runner()->PostDelayedTask(
1818 FROM_HERE,
1819 BindOnce(
1820 [](bool* flag, OnceClosure closure) {
1821 *flag = true;
1822 std::move(closure).Run();
1823 },
1824 &task_was_run, run_loop.QuitClosure()),
1825 TestTimeouts::tiny_timeout());
1826
1827 // Run the loop, and ensure that the posted task is processed before we quit.
1828 run_loop.Run();
1829 EXPECT_TRUE(task_was_run);
1830 }
1831
TEST_P(MessageLoopTest,WmQuitIsNotIgnoredWithEnableWmQuit)1832 TEST_P(MessageLoopTest, WmQuitIsNotIgnoredWithEnableWmQuit) {
1833 MessageLoop loop(MessageLoop::TYPE_UI);
1834 static_cast<MessageLoopForUI*>(&loop)->EnableWmQuit();
1835
1836 // Post a WM_QUIT message to the current thread.
1837 ::PostQuitMessage(0);
1838
1839 // Post a task to the current thread, with a small delay to make it less
1840 // likely that we process the posted task before looking for WM_* messages.
1841 RunLoop run_loop;
1842 loop.task_runner()->PostDelayedTask(FROM_HERE,
1843 BindOnce(
1844 [](OnceClosure closure) {
1845 ADD_FAILURE();
1846 std::move(closure).Run();
1847 },
1848 run_loop.QuitClosure()),
1849 TestTimeouts::tiny_timeout());
1850
1851 // Run the loop. It should not result in ADD_FAILURE() getting called.
1852 run_loop.Run();
1853 }
1854
TEST_P(MessageLoopTest,PostDelayedTask_SharedTimer_SubPump)1855 TEST_P(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
1856 RunTest_PostDelayedTask_SharedTimer_SubPump();
1857 }
1858
1859 // This test occasionally hangs. See http://crbug.com/44567.
TEST_P(MessageLoopTest,DISABLED_RecursiveDenial2)1860 TEST_P(MessageLoopTest, DISABLED_RecursiveDenial2) {
1861 RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
1862 RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
1863 RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
1864 }
1865
TEST_P(MessageLoopTest,RecursiveSupport2)1866 TEST_P(MessageLoopTest, RecursiveSupport2) {
1867 // This test requires a UI loop.
1868 RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
1869 }
1870 #endif // defined(OS_WIN)
1871
TEST_P(MessageLoopTest,TaskObserver)1872 TEST_P(MessageLoopTest, TaskObserver) {
1873 const int kNumPosts = 6;
1874 DummyTaskObserver observer(kNumPosts);
1875
1876 MessageLoop loop;
1877 loop.AddTaskObserver(&observer);
1878 loop.task_runner()->PostTask(FROM_HERE,
1879 BindOnce(&PostNTasksThenQuit, kNumPosts));
1880 RunLoop().Run();
1881 loop.RemoveTaskObserver(&observer);
1882
1883 EXPECT_EQ(kNumPosts, observer.num_tasks_started());
1884 EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
1885 }
1886
1887 #if defined(OS_WIN)
TEST_P(MessageLoopTest,IOHandler)1888 TEST_P(MessageLoopTest, IOHandler) {
1889 RunTest_IOHandler();
1890 }
1891
TEST_P(MessageLoopTest,WaitForIO)1892 TEST_P(MessageLoopTest, WaitForIO) {
1893 RunTest_WaitForIO();
1894 }
1895
TEST_P(MessageLoopTest,HighResolutionTimer)1896 TEST_P(MessageLoopTest, HighResolutionTimer) {
1897 MessageLoop message_loop;
1898 Time::EnableHighResolutionTimer(true);
1899
1900 constexpr TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5);
1901 constexpr TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100);
1902
1903 {
1904 // Post a fast task to enable the high resolution timers.
1905 RunLoop run_loop;
1906 message_loop.task_runner()->PostDelayedTask(
1907 FROM_HERE,
1908 BindOnce(
1909 [](RunLoop* run_loop) {
1910 EXPECT_TRUE(Time::IsHighResolutionTimerInUse());
1911 run_loop->QuitWhenIdle();
1912 },
1913 &run_loop),
1914 kFastTimer);
1915 run_loop.Run();
1916 }
1917 EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
1918 {
1919 // Check that a slow task does not trigger the high resolution logic.
1920 RunLoop run_loop;
1921 message_loop.task_runner()->PostDelayedTask(
1922 FROM_HERE,
1923 BindOnce(
1924 [](RunLoop* run_loop) {
1925 EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
1926 run_loop->QuitWhenIdle();
1927 },
1928 &run_loop),
1929 kSlowTimer);
1930 run_loop.Run();
1931 }
1932 Time::EnableHighResolutionTimer(false);
1933 Time::ResetHighResolutionTimerUsage();
1934 }
1935
1936 #endif // defined(OS_WIN)
1937
1938 namespace {
1939 // Inject a test point for recording the destructor calls for Closure objects
1940 // send to MessageLoop::PostTask(). It is awkward usage since we are trying to
1941 // hook the actual destruction, which is not a common operation.
1942 class DestructionObserverProbe :
1943 public RefCounted<DestructionObserverProbe> {
1944 public:
DestructionObserverProbe(bool * task_destroyed,bool * destruction_observer_called)1945 DestructionObserverProbe(bool* task_destroyed,
1946 bool* destruction_observer_called)
1947 : task_destroyed_(task_destroyed),
1948 destruction_observer_called_(destruction_observer_called) {
1949 }
Run()1950 virtual void Run() {
1951 // This task should never run.
1952 ADD_FAILURE();
1953 }
1954 private:
1955 friend class RefCounted<DestructionObserverProbe>;
1956
~DestructionObserverProbe()1957 virtual ~DestructionObserverProbe() {
1958 EXPECT_FALSE(*destruction_observer_called_);
1959 *task_destroyed_ = true;
1960 }
1961
1962 bool* task_destroyed_;
1963 bool* destruction_observer_called_;
1964 };
1965
1966 class MLDestructionObserver : public MessageLoopCurrent::DestructionObserver {
1967 public:
MLDestructionObserver(bool * task_destroyed,bool * destruction_observer_called)1968 MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
1969 : task_destroyed_(task_destroyed),
1970 destruction_observer_called_(destruction_observer_called),
1971 task_destroyed_before_message_loop_(false) {
1972 }
WillDestroyCurrentMessageLoop()1973 void WillDestroyCurrentMessageLoop() override {
1974 task_destroyed_before_message_loop_ = *task_destroyed_;
1975 *destruction_observer_called_ = true;
1976 }
task_destroyed_before_message_loop() const1977 bool task_destroyed_before_message_loop() const {
1978 return task_destroyed_before_message_loop_;
1979 }
1980 private:
1981 bool* task_destroyed_;
1982 bool* destruction_observer_called_;
1983 bool task_destroyed_before_message_loop_;
1984 };
1985
1986 } // namespace
1987
TEST_P(MessageLoopTest,DestructionObserverTest)1988 TEST_P(MessageLoopTest, DestructionObserverTest) {
1989 // Verify that the destruction observer gets called at the very end (after
1990 // all the pending tasks have been destroyed).
1991 MessageLoop* loop = new MessageLoop;
1992 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
1993
1994 bool task_destroyed = false;
1995 bool destruction_observer_called = false;
1996
1997 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
1998 loop->AddDestructionObserver(&observer);
1999 loop->task_runner()->PostDelayedTask(
2000 FROM_HERE,
2001 BindOnce(&DestructionObserverProbe::Run,
2002 new DestructionObserverProbe(&task_destroyed,
2003 &destruction_observer_called)),
2004 kDelay);
2005 delete loop;
2006 EXPECT_TRUE(observer.task_destroyed_before_message_loop());
2007 // The task should have been destroyed when we deleted the loop.
2008 EXPECT_TRUE(task_destroyed);
2009 EXPECT_TRUE(destruction_observer_called);
2010 }
2011
2012
2013 // Verify that MessageLoop sets ThreadMainTaskRunner::current() and it
2014 // posts tasks on that message loop.
TEST_P(MessageLoopTest,ThreadMainTaskRunner)2015 TEST_P(MessageLoopTest, ThreadMainTaskRunner) {
2016 MessageLoop loop;
2017
2018 scoped_refptr<Foo> foo(new Foo());
2019 std::string a("a");
2020 ThreadTaskRunnerHandle::Get()->PostTask(
2021 FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, a));
2022
2023 // Post quit task;
2024 ThreadTaskRunnerHandle::Get()->PostTask(
2025 FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
2026
2027 // Now kick things off
2028 RunLoop().Run();
2029
2030 EXPECT_EQ(foo->test_count(), 1);
2031 EXPECT_EQ(foo->result(), "a");
2032 }
2033
TEST_P(MessageLoopTest,IsType)2034 TEST_P(MessageLoopTest, IsType) {
2035 MessageLoop loop(MessageLoop::TYPE_UI);
2036 EXPECT_TRUE(loop.IsType(MessageLoop::TYPE_UI));
2037 EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_IO));
2038 EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT));
2039 }
2040
2041 #if defined(OS_WIN)
EmptyFunction()2042 void EmptyFunction() {}
2043
PostMultipleTasks()2044 void PostMultipleTasks() {
2045 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2046 base::BindOnce(&EmptyFunction));
2047 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2048 base::BindOnce(&EmptyFunction));
2049 }
2050
2051 static const int kSignalMsg = WM_USER + 2;
2052
PostWindowsMessage(HWND message_hwnd)2053 void PostWindowsMessage(HWND message_hwnd) {
2054 PostMessage(message_hwnd, kSignalMsg, 0, 2);
2055 }
2056
EndTest(bool * did_run,HWND hwnd)2057 void EndTest(bool* did_run, HWND hwnd) {
2058 *did_run = true;
2059 PostMessage(hwnd, WM_CLOSE, 0, 0);
2060 }
2061
2062 int kMyMessageFilterCode = 0x5002;
2063
TestWndProcThunk(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)2064 LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
2065 WPARAM wparam, LPARAM lparam) {
2066 if (message == WM_CLOSE)
2067 EXPECT_TRUE(DestroyWindow(hwnd));
2068 if (message != kSignalMsg)
2069 return DefWindowProc(hwnd, message, wparam, lparam);
2070
2071 switch (lparam) {
2072 case 1:
2073 // First, we post a task that will post multiple no-op tasks to make sure
2074 // that the pump's incoming task queue does not become empty during the
2075 // test.
2076 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2077 base::BindOnce(&PostMultipleTasks));
2078 // Next, we post a task that posts a windows message to trigger the second
2079 // stage of the test.
2080 ThreadTaskRunnerHandle::Get()->PostTask(
2081 FROM_HERE, base::BindOnce(&PostWindowsMessage, hwnd));
2082 break;
2083 case 2:
2084 // Since we're about to enter a modal loop, tell the message loop that we
2085 // intend to nest tasks.
2086 MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
2087 bool did_run = false;
2088 ThreadTaskRunnerHandle::Get()->PostTask(
2089 FROM_HERE, base::BindOnce(&EndTest, &did_run, hwnd));
2090 // Run a nested windows-style message loop and verify that our task runs. If
2091 // it doesn't, then we'll loop here until the test times out.
2092 MSG msg;
2093 while (GetMessage(&msg, 0, 0, 0)) {
2094 if (!CallMsgFilter(&msg, kMyMessageFilterCode))
2095 DispatchMessage(&msg);
2096 // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting
2097 // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats
2098 // WM_QUIT messages even when running inside a modal loop.
2099 if (msg.message == WM_CLOSE)
2100 break;
2101 }
2102 EXPECT_TRUE(did_run);
2103 RunLoop::QuitCurrentWhenIdleDeprecated();
2104 break;
2105 }
2106 return 0;
2107 }
2108
TEST_P(MessageLoopTest,AlwaysHaveUserMessageWhenNesting)2109 TEST_P(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) {
2110 MessageLoop loop(MessageLoop::TYPE_UI);
2111 HINSTANCE instance = CURRENT_MODULE();
2112 WNDCLASSEX wc = {0};
2113 wc.cbSize = sizeof(wc);
2114 wc.lpfnWndProc = TestWndProcThunk;
2115 wc.hInstance = instance;
2116 wc.lpszClassName = L"MessageLoopTest_HWND";
2117 ATOM atom = RegisterClassEx(&wc);
2118 ASSERT_TRUE(atom);
2119
2120 HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
2121 HWND_MESSAGE, 0, instance, 0);
2122 ASSERT_TRUE(message_hwnd) << GetLastError();
2123
2124 ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
2125
2126 RunLoop().Run();
2127
2128 ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
2129 }
2130 #endif // defined(OS_WIN)
2131
TEST_P(MessageLoopTest,SetTaskRunner)2132 TEST_P(MessageLoopTest, SetTaskRunner) {
2133 MessageLoop loop;
2134 scoped_refptr<SingleThreadTaskRunner> new_runner(new TestSimpleTaskRunner());
2135
2136 loop.SetTaskRunner(new_runner);
2137 EXPECT_EQ(new_runner, loop.task_runner());
2138 EXPECT_EQ(new_runner, ThreadTaskRunnerHandle::Get());
2139 }
2140
TEST_P(MessageLoopTest,OriginalRunnerWorks)2141 TEST_P(MessageLoopTest, OriginalRunnerWorks) {
2142 MessageLoop loop;
2143 scoped_refptr<SingleThreadTaskRunner> new_runner(new TestSimpleTaskRunner());
2144 scoped_refptr<SingleThreadTaskRunner> original_runner(loop.task_runner());
2145 loop.SetTaskRunner(new_runner);
2146
2147 scoped_refptr<Foo> foo(new Foo());
2148 original_runner->PostTask(FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, "a"));
2149 RunLoop().RunUntilIdle();
2150 EXPECT_EQ(1, foo->test_count());
2151 }
2152
TEST_P(MessageLoopTest,DeleteUnboundLoop)2153 TEST_P(MessageLoopTest, DeleteUnboundLoop) {
2154 // It should be possible to delete an unbound message loop on a thread which
2155 // already has another active loop. This happens when thread creation fails.
2156 MessageLoop loop;
2157 std::unique_ptr<MessageLoop> unbound_loop(MessageLoop::CreateUnbound(
2158 MessageLoop::TYPE_DEFAULT, MessageLoop::MessagePumpFactoryCallback()));
2159 unbound_loop.reset();
2160 EXPECT_EQ(&loop, MessageLoop::current());
2161 EXPECT_EQ(loop.task_runner(), ThreadTaskRunnerHandle::Get());
2162 }
2163
TEST_P(MessageLoopTest,ThreadName)2164 TEST_P(MessageLoopTest, ThreadName) {
2165 {
2166 std::string kThreadName("foo");
2167 MessageLoop loop;
2168 PlatformThread::SetName(kThreadName);
2169 EXPECT_EQ(kThreadName, loop.GetThreadName());
2170 }
2171
2172 {
2173 std::string kThreadName("bar");
2174 base::Thread thread(kThreadName);
2175 ASSERT_TRUE(thread.StartAndWaitForTesting());
2176 EXPECT_EQ(kThreadName, thread.message_loop()->GetThreadName());
2177 }
2178 }
2179
2180 // Verify that tasks posted to and code running in the scope of the same
2181 // MessageLoop access the same SequenceLocalStorage values.
TEST_P(MessageLoopTest,SequenceLocalStorageSetGet)2182 TEST_P(MessageLoopTest, SequenceLocalStorageSetGet) {
2183 MessageLoop loop;
2184
2185 SequenceLocalStorageSlot<int> slot;
2186
2187 ThreadTaskRunnerHandle::Get()->PostTask(
2188 FROM_HERE,
2189 BindOnce(&SequenceLocalStorageSlot<int>::Set, Unretained(&slot), 11));
2190
2191 ThreadTaskRunnerHandle::Get()->PostTask(
2192 FROM_HERE, BindOnce(
2193 [](SequenceLocalStorageSlot<int>* slot) {
2194 EXPECT_EQ(slot->Get(), 11);
2195 },
2196 &slot));
2197
2198 RunLoop().RunUntilIdle();
2199 EXPECT_EQ(slot.Get(), 11);
2200 }
2201
2202 // Verify that tasks posted to and code running in different MessageLoops access
2203 // different SequenceLocalStorage values.
TEST_P(MessageLoopTest,SequenceLocalStorageDifferentMessageLoops)2204 TEST_P(MessageLoopTest, SequenceLocalStorageDifferentMessageLoops) {
2205 SequenceLocalStorageSlot<int> slot;
2206
2207 {
2208 MessageLoop loop;
2209 ThreadTaskRunnerHandle::Get()->PostTask(
2210 FROM_HERE,
2211 BindOnce(&SequenceLocalStorageSlot<int>::Set, Unretained(&slot), 11));
2212
2213 RunLoop().RunUntilIdle();
2214 EXPECT_EQ(slot.Get(), 11);
2215 }
2216
2217 MessageLoop loop;
2218 ThreadTaskRunnerHandle::Get()->PostTask(
2219 FROM_HERE, BindOnce(
2220 [](SequenceLocalStorageSlot<int>* slot) {
2221 EXPECT_NE(slot->Get(), 11);
2222 },
2223 &slot));
2224
2225 RunLoop().RunUntilIdle();
2226 EXPECT_NE(slot.Get(), 11);
2227 }
2228
2229 INSTANTIATE_TEST_CASE_P(
2230 ,
2231 MessageLoopTest,
2232 ::testing::Values(TaskSchedulerAvailability::NO_TASK_SCHEDULER
2233 // Unsupported in libchrome
2234 //, TaskSchedulerAvailability::WITH_TASK_SCHEDULER
2235 ),
2236 MessageLoopTest::ParamInfoToString);
2237
2238 namespace {
2239
2240 class PostTaskOnDestroy {
2241 public:
PostTaskOnDestroy(int times)2242 PostTaskOnDestroy(int times) : times_remaining_(times) {}
~PostTaskOnDestroy()2243 ~PostTaskOnDestroy() { PostTaskWithPostingDestructor(times_remaining_); }
2244
2245 // Post a task that will repost itself on destruction |times| times.
PostTaskWithPostingDestructor(int times)2246 static void PostTaskWithPostingDestructor(int times) {
2247 if (times > 0) {
2248 ThreadTaskRunnerHandle::Get()->PostTask(
2249 FROM_HERE, BindOnce([](std::unique_ptr<PostTaskOnDestroy>) {},
2250 std::make_unique<PostTaskOnDestroy>(times - 1)));
2251 }
2252 }
2253
2254 private:
2255 const int times_remaining_;
2256
2257 DISALLOW_COPY_AND_ASSIGN(PostTaskOnDestroy);
2258 };
2259
2260 } // namespace
2261
2262 // Test that MessageLoop destruction handles a task's destructor posting another
2263 // task by:
2264 // 1) Not getting stuck clearing its task queue.
2265 // 2) DCHECKing when clearing pending tasks many times still doesn't yield an
2266 // empty queue.
TEST(MessageLoopDestructionTest,ExpectDeathWithStubbornPostTaskOnDestroy)2267 TEST(MessageLoopDestructionTest, ExpectDeathWithStubbornPostTaskOnDestroy) {
2268 std::unique_ptr<MessageLoop> loop = std::make_unique<MessageLoop>();
2269
2270 EXPECT_DCHECK_DEATH({
2271 PostTaskOnDestroy::PostTaskWithPostingDestructor(1000);
2272 loop.reset();
2273 });
2274 }
2275
TEST(MessageLoopDestructionTest,DestroysFineWithReasonablePostTaskOnDestroy)2276 TEST(MessageLoopDestructionTest, DestroysFineWithReasonablePostTaskOnDestroy) {
2277 std::unique_ptr<MessageLoop> loop = std::make_unique<MessageLoop>();
2278
2279 PostTaskOnDestroy::PostTaskWithPostingDestructor(10);
2280 loop.reset();
2281 }
2282
2283 } // namespace base
2284