1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/logging.h"
6 #include "base/message_loop.h"
7 #include "base/platform_thread.h"
8 #include "base/ref_counted.h"
9 #include "base/thread.h"
10 #include "testing/gtest/include/gtest/gtest.h"
13 #include "base/message_pump_win.h"
14 #include "base/scoped_handle.h"
17 #include "base/message_pump_libevent.h"
22 using base::TimeDelta
;
24 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
25 // to avoid chopping this file up with so many #ifdefs.
29 class MessageLoopTest
: public testing::Test
{};
31 class Foo
: public base::RefCounted
<Foo
> {
33 Foo() : test_count_(0) {
40 void Test1ConstRef(const std::string
& a
) {
45 void Test1Ptr(std::string
* a
) {
50 void Test1Int(int a
) {
54 void Test2Ptr(std::string
* a
, std::string
* b
) {
60 void Test2Mixed(const std::string
& a
, std::string
* b
) {
66 int test_count() const { return test_count_
; }
67 const std::string
& result() const { return result_
; }
70 friend class base::RefCounted
<Foo
>;
78 class QuitMsgLoop
: public base::RefCounted
<QuitMsgLoop
> {
81 MessageLoop::current()->Quit();
85 friend class base::RefCounted
<QuitMsgLoop
>;
90 void RunTest_PostTask(MessageLoop::Type message_loop_type
) {
91 MessageLoop
loop(message_loop_type
);
93 // Add tests to message loop
94 scoped_refptr
<Foo
> foo
= new Foo();
95 std::string
a("a"), b("b"), c("c"), d("d");
96 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
97 foo
.get(), &Foo::Test0
));
98 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
99 foo
.get(), &Foo::Test1ConstRef
, a
));
100 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
101 foo
.get(), &Foo::Test1Ptr
, &b
));
102 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
103 foo
.get(), &Foo::Test1Int
, 100));
104 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
105 foo
.get(), &Foo::Test2Ptr
, &a
, &c
));
106 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
107 foo
.get(), &Foo::Test2Mixed
, a
, &d
));
109 // After all tests, post a message that will shut down the message loop
110 scoped_refptr
<QuitMsgLoop
> quit
= new QuitMsgLoop();
111 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
112 quit
.get(), &QuitMsgLoop::QuitNow
));
114 // Now kick things off
115 MessageLoop::current()->Run();
117 EXPECT_EQ(foo
->test_count(), 105);
118 EXPECT_EQ(foo
->result(), "abacad");
121 void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type
) {
122 MessageLoop
loop(message_loop_type
);
124 // Add tests to message loop
125 scoped_refptr
<Foo
> foo
= new Foo();
126 std::string
a("a"), b("b"), c("c"), d("d");
127 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
128 foo
.get(), &Foo::Test0
));
129 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
130 foo
.get(), &Foo::Test1ConstRef
, a
));
131 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
132 foo
.get(), &Foo::Test1Ptr
, &b
));
133 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
134 foo
.get(), &Foo::Test1Int
, 100));
135 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
136 foo
.get(), &Foo::Test2Ptr
, &a
, &c
));
137 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
138 foo
.get(), &Foo::Test2Mixed
, a
, &d
));
140 // After all tests, post a message that will shut down the message loop
141 scoped_refptr
<QuitMsgLoop
> quit
= new QuitMsgLoop();
142 MessageLoop::current()->PostTask(FROM_HERE
, NewRunnableMethod(
143 quit
.get(), &QuitMsgLoop::QuitNow
));
145 // Now kick things off with the SEH block active.
146 MessageLoop::current()->set_exception_restoration(true);
147 MessageLoop::current()->Run();
148 MessageLoop::current()->set_exception_restoration(false);
150 EXPECT_EQ(foo
->test_count(), 105);
151 EXPECT_EQ(foo
->result(), "abacad");
154 // This class runs slowly to simulate a large amount of work being done.
155 class SlowTask
: public Task
{
157 SlowTask(int pause_ms
, int* quit_counter
)
158 : pause_ms_(pause_ms
), quit_counter_(quit_counter
) {
161 PlatformThread::Sleep(pause_ms_
);
162 if (--(*quit_counter_
) == 0)
163 MessageLoop::current()->Quit();
170 // This class records the time when Run was called in a Time object, which is
171 // useful for building a variety of MessageLoop tests.
172 class RecordRunTimeTask
: public SlowTask
{
174 RecordRunTimeTask(Time
* run_time
, int* quit_counter
)
175 : SlowTask(10, quit_counter
), run_time_(run_time
) {
178 *run_time_
= Time::Now();
179 // Cause our Run function to take some time to execute. As a result we can
180 // count on subsequent RecordRunTimeTask objects running at a future time,
181 // without worry about the resolution of our system clock being an issue.
188 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type
) {
189 MessageLoop
loop(message_loop_type
);
191 // Test that PostDelayedTask results in a delayed task.
193 const int kDelayMS
= 100;
198 loop
.PostDelayedTask(
199 FROM_HERE
, new RecordRunTimeTask(&run_time
, &num_tasks
), kDelayMS
);
201 Time time_before_run
= Time::Now();
203 Time time_after_run
= Time::Now();
205 EXPECT_EQ(0, num_tasks
);
206 EXPECT_LT(kDelayMS
, (time_after_run
- time_before_run
).InMilliseconds());
209 void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type
) {
210 MessageLoop
loop(message_loop_type
);
212 // Test that two tasks with different delays run in the right order.
215 Time run_time1
, run_time2
;
217 loop
.PostDelayedTask(
218 FROM_HERE
, new RecordRunTimeTask(&run_time1
, &num_tasks
), 200);
219 // If we get a large pause in execution (due to a context switch) here, this
221 loop
.PostDelayedTask(
222 FROM_HERE
, new RecordRunTimeTask(&run_time2
, &num_tasks
), 10);
225 EXPECT_EQ(0, num_tasks
);
227 EXPECT_TRUE(run_time2
< run_time1
);
230 void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type
) {
231 MessageLoop
loop(message_loop_type
);
233 // Test that two tasks with the same delay run in the order in which they
236 // NOTE: This is actually an approximate test since the API only takes a
237 // "delay" parameter, so we are not exactly simulating two tasks that get
238 // posted at the exact same time. It would be nice if the API allowed us to
239 // specify the desired run time.
241 const int kDelayMS
= 100;
244 Time run_time1
, run_time2
;
246 loop
.PostDelayedTask(
247 FROM_HERE
, new RecordRunTimeTask(&run_time1
, &num_tasks
), kDelayMS
);
248 loop
.PostDelayedTask(
249 FROM_HERE
, new RecordRunTimeTask(&run_time2
, &num_tasks
), kDelayMS
);
252 EXPECT_EQ(0, num_tasks
);
254 EXPECT_TRUE(run_time1
< run_time2
);
257 void RunTest_PostDelayedTask_InPostOrder_2(
258 MessageLoop::Type message_loop_type
) {
259 MessageLoop
loop(message_loop_type
);
261 // Test that a delayed task still runs after a normal tasks even if the
262 // normal tasks take a long time to run.
264 const int kPauseMS
= 50;
270 FROM_HERE
, new SlowTask(kPauseMS
, &num_tasks
));
271 loop
.PostDelayedTask(
272 FROM_HERE
, new RecordRunTimeTask(&run_time
, &num_tasks
), 10);
274 Time time_before_run
= Time::Now();
276 Time time_after_run
= Time::Now();
278 EXPECT_EQ(0, num_tasks
);
280 EXPECT_LT(kPauseMS
, (time_after_run
- time_before_run
).InMilliseconds());
283 void RunTest_PostDelayedTask_InPostOrder_3(
284 MessageLoop::Type message_loop_type
) {
285 MessageLoop
loop(message_loop_type
);
287 // Test that a delayed task still runs after a pile of normal tasks. The key
288 // difference between this test and the previous one is that here we return
289 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities
290 // to maybe run the delayed task. It should know not to do so until the
291 // delayed task's delay has passed.
294 Time run_time1
, run_time2
;
296 // Clutter the ML with tasks.
297 for (int i
= 1; i
< num_tasks
; ++i
)
298 loop
.PostTask(FROM_HERE
, new RecordRunTimeTask(&run_time1
, &num_tasks
));
300 loop
.PostDelayedTask(
301 FROM_HERE
, new RecordRunTimeTask(&run_time2
, &num_tasks
), 1);
304 EXPECT_EQ(0, num_tasks
);
306 EXPECT_TRUE(run_time2
> run_time1
);
309 void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type
) {
310 MessageLoop
loop(message_loop_type
);
312 // Test that the interval of the timer, used to run the next delayed task, is
313 // set to a value corresponding to when the next delayed task should run.
315 // By setting num_tasks to 1, we ensure that the first task to run causes the
318 Time run_time1
, run_time2
;
320 loop
.PostDelayedTask(
321 FROM_HERE
, new RecordRunTimeTask(&run_time1
, &num_tasks
), 1000000);
322 loop
.PostDelayedTask(
323 FROM_HERE
, new RecordRunTimeTask(&run_time2
, &num_tasks
), 10);
325 Time start_time
= Time::Now();
328 EXPECT_EQ(0, num_tasks
);
330 // Ensure that we ran in far less time than the slower timer.
331 TimeDelta total_time
= Time::Now() - start_time
;
332 EXPECT_GT(5000, total_time
.InMilliseconds());
334 // In case both timers somehow run at nearly the same time, sleep a little
335 // and then run all pending to force them both to have run. This is just
336 // encouraging flakiness if there is any.
337 PlatformThread::Sleep(100);
338 loop
.RunAllPending();
340 EXPECT_TRUE(run_time1
.is_null());
341 EXPECT_FALSE(run_time2
.is_null());
346 class SubPumpTask
: public Task
{
349 MessageLoop::current()->SetNestableTasksAllowed(true);
351 while (GetMessage(&msg
, NULL
, 0, 0)) {
352 TranslateMessage(&msg
);
353 DispatchMessage(&msg
);
355 MessageLoop::current()->Quit();
359 class SubPumpQuitTask
: public Task
{
368 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
369 MessageLoop
loop(MessageLoop::TYPE_UI
);
371 // Test that the interval of the timer, used to run the next delayed task, is
372 // set to a value corresponding to when the next delayed task should run.
374 // By setting num_tasks to 1, we ensure that the first task to run causes the
379 loop
.PostTask(FROM_HERE
, new SubPumpTask());
381 // This very delayed task should never run.
382 loop
.PostDelayedTask(
383 FROM_HERE
, new RecordRunTimeTask(&run_time
, &num_tasks
), 1000000);
385 // This slightly delayed task should run from within SubPumpTask::Run().
386 loop
.PostDelayedTask(
387 FROM_HERE
, new SubPumpQuitTask(), 10);
389 Time start_time
= Time::Now();
392 EXPECT_EQ(1, num_tasks
);
394 // Ensure that we ran in far less time than the slower timer.
395 TimeDelta total_time
= Time::Now() - start_time
;
396 EXPECT_GT(5000, total_time
.InMilliseconds());
398 // In case both timers somehow run at nearly the same time, sleep a little
399 // and then run all pending to force them both to have run. This is just
400 // encouraging flakiness if there is any.
401 PlatformThread::Sleep(100);
402 loop
.RunAllPending();
404 EXPECT_TRUE(run_time
.is_null());
407 #endif // defined(OS_WIN)
409 class RecordDeletionTask
: public Task
{
411 RecordDeletionTask(Task
* post_on_delete
, bool* was_deleted
)
412 : post_on_delete_(post_on_delete
), was_deleted_(was_deleted
) {
414 ~RecordDeletionTask() {
415 *was_deleted_
= true;
417 MessageLoop::current()->PostTask(FROM_HERE
, post_on_delete_
);
419 virtual void Run() {}
421 Task
* post_on_delete_
;
425 void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type
) {
426 bool a_was_deleted
= false;
427 bool b_was_deleted
= false;
429 MessageLoop
loop(message_loop_type
);
431 FROM_HERE
, new RecordDeletionTask(NULL
, &a_was_deleted
));
432 loop
.PostDelayedTask(
433 FROM_HERE
, new RecordDeletionTask(NULL
, &b_was_deleted
), 1000);
435 EXPECT_TRUE(a_was_deleted
);
436 EXPECT_TRUE(b_was_deleted
);
439 void RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type
) {
440 bool a_was_deleted
= false;
441 bool b_was_deleted
= false;
442 bool c_was_deleted
= false;
444 MessageLoop
loop(message_loop_type
);
445 RecordDeletionTask
* a
= new RecordDeletionTask(NULL
, &a_was_deleted
);
446 RecordDeletionTask
* b
= new RecordDeletionTask(a
, &b_was_deleted
);
447 RecordDeletionTask
* c
= new RecordDeletionTask(b
, &c_was_deleted
);
448 loop
.PostTask(FROM_HERE
, c
);
450 EXPECT_TRUE(a_was_deleted
);
451 EXPECT_TRUE(b_was_deleted
);
452 EXPECT_TRUE(c_was_deleted
);
455 class NestingTest
: public Task
{
457 explicit NestingTest(int* depth
) : depth_(depth
) {
462 MessageLoop::current()->PostTask(FROM_HERE
, new NestingTest(depth_
));
464 MessageLoop::current()->SetNestableTasksAllowed(true);
465 MessageLoop::current()->Run();
467 MessageLoop::current()->Quit();
475 LONG WINAPI
BadExceptionHandler(EXCEPTION_POINTERS
*ex_info
) {
476 ADD_FAILURE() << "bad exception handler";
477 ::ExitProcess(ex_info
->ExceptionRecord
->ExceptionCode
);
478 return EXCEPTION_EXECUTE_HANDLER
;
481 // This task throws an SEH exception: initially write to an invalid address.
482 // If the right SEH filter is installed, it will fix the error.
483 class CrasherTask
: public Task
{
485 // Ctor. If trash_SEH_handler is true, the task will override the unhandled
486 // exception handler with one sure to crash this test.
487 explicit CrasherTask(bool trash_SEH_handler
)
488 : trash_SEH_handler_(trash_SEH_handler
) {
491 PlatformThread::Sleep(1);
492 if (trash_SEH_handler_
)
493 ::SetUnhandledExceptionFilter(&BadExceptionHandler
);
494 // Generate a SEH fault. We do it in asm to make sure we know how to undo
500 mov eax
, dword ptr
[CrasherTask::bad_array_
]
501 mov byte ptr
[eax
], 66
504 #elif defined(_M_X64)
509 #error "needs architecture support"
512 MessageLoop::current()->Quit();
514 // Points the bad array to a valid memory location.
515 static void FixError() {
516 bad_array_
= &valid_store_
;
520 bool trash_SEH_handler_
;
521 static volatile char* bad_array_
;
522 static char valid_store_
;
525 volatile char* CrasherTask::bad_array_
= 0;
526 char CrasherTask::valid_store_
= 0;
528 // This SEH filter fixes the problem and retries execution. Fixing requires
529 // that the last instruction: mov eax, [CrasherTask::bad_array_] to be retried
530 // so we move the instruction pointer 5 bytes back.
531 LONG WINAPI
HandleCrasherTaskException(EXCEPTION_POINTERS
*ex_info
) {
532 if (ex_info
->ExceptionRecord
->ExceptionCode
!= EXCEPTION_ACCESS_VIOLATION
)
533 return EXCEPTION_EXECUTE_HANDLER
;
535 CrasherTask::FixError();
539 ex_info
->ContextRecord
->Eip
-= 5;
541 #elif defined(_M_X64)
543 ex_info
->ContextRecord
->Rip
-= 5;
547 return EXCEPTION_CONTINUE_EXECUTION
;
550 void RunTest_Crasher(MessageLoop::Type message_loop_type
) {
551 MessageLoop
loop(message_loop_type
);
553 if (::IsDebuggerPresent())
556 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter
=
557 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException
);
559 MessageLoop::current()->PostTask(FROM_HERE
, new CrasherTask(false));
560 MessageLoop::current()->set_exception_restoration(true);
561 MessageLoop::current()->Run();
562 MessageLoop::current()->set_exception_restoration(false);
564 ::SetUnhandledExceptionFilter(old_SEH_filter
);
567 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type
) {
568 MessageLoop
loop(message_loop_type
);
570 if (::IsDebuggerPresent())
573 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter
=
574 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException
);
576 MessageLoop::current()->PostTask(FROM_HERE
, new CrasherTask(true));
577 MessageLoop::current()->set_exception_restoration(true);
578 MessageLoop::current()->Run();
579 MessageLoop::current()->set_exception_restoration(false);
581 ::SetUnhandledExceptionFilter(old_SEH_filter
);
584 #endif // defined(OS_WIN)
586 void RunTest_Nesting(MessageLoop::Type message_loop_type
) {
587 MessageLoop
loop(message_loop_type
);
590 MessageLoop::current()->PostTask(FROM_HERE
, new NestingTest(&depth
));
591 MessageLoop::current()->Run();
595 const wchar_t* const kMessageBoxTitle
= L
"MessageLoop Unit Test";
608 // Saves the order in which the tasks executed.
610 TaskItem(TaskType t
, int c
, bool s
)
620 bool operator == (const TaskItem
& other
) const {
621 return type
== other
.type
&& cookie
== other
.cookie
&& start
== other
.start
;
625 typedef std::vector
<TaskItem
> TaskList
;
627 std::ostream
& operator <<(std::ostream
& os
, TaskType type
) {
629 case MESSAGEBOX
: os
<< "MESSAGEBOX"; break;
630 case ENDDIALOG
: os
<< "ENDDIALOG"; break;
631 case RECURSIVE
: os
<< "RECURSIVE"; break;
632 case TIMEDMESSAGELOOP
: os
<< "TIMEDMESSAGELOOP"; break;
633 case QUITMESSAGELOOP
: os
<< "QUITMESSAGELOOP"; break;
634 case ORDERERD
: os
<< "ORDERERD"; break;
635 case PUMPS
: os
<< "PUMPS"; break;
636 case SLEEP
: os
<< "SLEEP"; break;
639 os
<< "Unknown TaskType";
645 std::ostream
& operator <<(std::ostream
& os
, const TaskItem
& item
) {
647 return os
<< item
.type
<< " " << item
.cookie
<< " starts";
649 return os
<< item
.type
<< " " << item
.cookie
<< " ends";
652 // Saves the order the tasks ran.
653 class OrderedTasks
: public Task
{
655 OrderedTasks(TaskList
* order
, int cookie
)
660 OrderedTasks(TaskList
* order
, TaskType type
, int cookie
)
667 TaskItem
item(type_
, cookie_
, true);
669 order_
->push_back(item
);
672 TaskItem
item(type_
, cookie_
, false);
674 order_
->push_back(item
);
683 TaskList
* order() const {
699 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
700 // common controls (like OpenFile) and StartDoc printing function can cause
701 // implicit message loops.
702 class MessageBoxTask
: public OrderedTasks
{
704 MessageBoxTask(TaskList
* order
, int cookie
, bool is_reentrant
)
705 : OrderedTasks(order
, MESSAGEBOX
, cookie
),
706 is_reentrant_(is_reentrant
) {
712 MessageLoop::current()->SetNestableTasksAllowed(true);
713 MessageBox(NULL
, L
"Please wait...", kMessageBoxTitle
, MB_OK
);
721 // Will end the MessageBox.
722 class EndDialogTask
: public OrderedTasks
{
724 EndDialogTask(TaskList
* order
, int cookie
)
725 : OrderedTasks(order
, ENDDIALOG
, cookie
) {
730 HWND window
= GetActiveWindow();
731 if (window
!= NULL
) {
732 EXPECT_NE(EndDialog(window
, IDCONTINUE
), 0);
733 // Cheap way to signal that the window wasn't found if RunEnd() isn't
740 #endif // defined(OS_WIN)
742 class RecursiveTask
: public OrderedTasks
{
744 RecursiveTask(int depth
, TaskList
* order
, int cookie
, bool is_reentrant
)
745 : OrderedTasks(order
, RECURSIVE
, cookie
),
747 is_reentrant_(is_reentrant
) {
754 MessageLoop::current()->SetNestableTasksAllowed(true);
755 MessageLoop::current()->PostTask(FROM_HERE
,
756 new RecursiveTask(depth_
- 1, order(), cookie(), is_reentrant_
));
766 class QuitTask
: public OrderedTasks
{
768 QuitTask(TaskList
* order
, int cookie
)
769 : OrderedTasks(order
, QUITMESSAGELOOP
, cookie
) {
774 MessageLoop::current()->Quit();
779 class SleepTask
: public OrderedTasks
{
781 SleepTask(TaskList
* order
, int cookie
, int ms
)
782 : OrderedTasks(order
, SLEEP
, cookie
), ms_(ms
) {
787 PlatformThread::Sleep(ms_
);
797 class Recursive2Tasks
: public Task
{
799 Recursive2Tasks(MessageLoop
* target
,
806 expect_window_(expect_window
),
808 is_reentrant_(is_reentrant
) {
812 target_
->PostTask(FROM_HERE
,
813 new RecursiveTask(2, order_
, 1, is_reentrant_
));
814 target_
->PostTask(FROM_HERE
,
815 new MessageBoxTask(order_
, 2, is_reentrant_
));
816 target_
->PostTask(FROM_HERE
,
817 new RecursiveTask(2, order_
, 3, is_reentrant_
));
818 // The trick here is that for recursive task processing, this task will be
819 // ran _inside_ the MessageBox message loop, dismissing the MessageBox
821 // For non-recursive task processing, this will be executed _after_ the
822 // MessageBox will have been dismissed by the code below, where
823 // expect_window_ is true.
824 target_
->PostTask(FROM_HERE
, new EndDialogTask(order_
, 4));
825 target_
->PostTask(FROM_HERE
, new QuitTask(order_
, 5));
827 // Enforce that every tasks are sent before starting to run the main thread
829 ASSERT_TRUE(SetEvent(event_
));
831 // Poll for the MessageBox. Don't do this at home! At the speed we do it,
832 // you will never realize one MessageBox was shown.
833 for (; expect_window_
;) {
834 HWND window
= FindWindow(L
"#32770", kMessageBoxTitle
);
838 HWND button
= FindWindowEx(window
, NULL
, L
"Button", NULL
);
839 if (button
!= NULL
) {
840 EXPECT_TRUE(0 == SendMessage(button
, WM_LBUTTONDOWN
, 0, 0));
841 EXPECT_TRUE(0 == SendMessage(button
, WM_LBUTTONUP
, 0, 0));
851 MessageLoop
* target_
;
858 #endif // defined(OS_WIN)
860 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type
) {
861 MessageLoop
loop(message_loop_type
);
863 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
865 MessageLoop::current()->PostTask(FROM_HERE
,
866 new RecursiveTask(2, &order
, 1, false));
867 MessageLoop::current()->PostTask(FROM_HERE
,
868 new RecursiveTask(2, &order
, 2, false));
869 MessageLoop::current()->PostTask(FROM_HERE
, new QuitTask(&order
, 3));
871 MessageLoop::current()->Run();
874 ASSERT_EQ(14U, order
.size());
875 EXPECT_EQ(order
[ 0], TaskItem(RECURSIVE
, 1, true));
876 EXPECT_EQ(order
[ 1], TaskItem(RECURSIVE
, 1, false));
877 EXPECT_EQ(order
[ 2], TaskItem(RECURSIVE
, 2, true));
878 EXPECT_EQ(order
[ 3], TaskItem(RECURSIVE
, 2, false));
879 EXPECT_EQ(order
[ 4], TaskItem(QUITMESSAGELOOP
, 3, true));
880 EXPECT_EQ(order
[ 5], TaskItem(QUITMESSAGELOOP
, 3, false));
881 EXPECT_EQ(order
[ 6], TaskItem(RECURSIVE
, 1, true));
882 EXPECT_EQ(order
[ 7], TaskItem(RECURSIVE
, 1, false));
883 EXPECT_EQ(order
[ 8], TaskItem(RECURSIVE
, 2, true));
884 EXPECT_EQ(order
[ 9], TaskItem(RECURSIVE
, 2, false));
885 EXPECT_EQ(order
[10], TaskItem(RECURSIVE
, 1, true));
886 EXPECT_EQ(order
[11], TaskItem(RECURSIVE
, 1, false));
887 EXPECT_EQ(order
[12], TaskItem(RECURSIVE
, 2, true));
888 EXPECT_EQ(order
[13], TaskItem(RECURSIVE
, 2, false));
891 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type
) {
892 MessageLoop
loop(message_loop_type
);
895 MessageLoop::current()->PostTask(FROM_HERE
,
896 new RecursiveTask(2, &order
, 1, true));
897 MessageLoop::current()->PostTask(FROM_HERE
,
898 new RecursiveTask(2, &order
, 2, true));
899 MessageLoop::current()->PostTask(FROM_HERE
,
900 new QuitTask(&order
, 3));
902 MessageLoop::current()->Run();
905 ASSERT_EQ(14U, order
.size());
906 EXPECT_EQ(order
[ 0], TaskItem(RECURSIVE
, 1, true));
907 EXPECT_EQ(order
[ 1], TaskItem(RECURSIVE
, 1, false));
908 EXPECT_EQ(order
[ 2], TaskItem(RECURSIVE
, 2, true));
909 EXPECT_EQ(order
[ 3], TaskItem(RECURSIVE
, 2, false));
910 EXPECT_EQ(order
[ 4], TaskItem(QUITMESSAGELOOP
, 3, true));
911 EXPECT_EQ(order
[ 5], TaskItem(QUITMESSAGELOOP
, 3, false));
912 EXPECT_EQ(order
[ 6], TaskItem(RECURSIVE
, 1, true));
913 EXPECT_EQ(order
[ 7], TaskItem(RECURSIVE
, 1, false));
914 EXPECT_EQ(order
[ 8], TaskItem(RECURSIVE
, 2, true));
915 EXPECT_EQ(order
[ 9], TaskItem(RECURSIVE
, 2, false));
916 EXPECT_EQ(order
[10], TaskItem(RECURSIVE
, 1, true));
917 EXPECT_EQ(order
[11], TaskItem(RECURSIVE
, 1, false));
918 EXPECT_EQ(order
[12], TaskItem(RECURSIVE
, 2, true));
919 EXPECT_EQ(order
[13], TaskItem(RECURSIVE
, 2, false));
923 // TODO(darin): These tests need to be ported since they test critical
924 // message loop functionality.
926 // A side effect of this test is the generation a beep. Sorry.
927 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type
) {
928 MessageLoop
loop(message_loop_type
);
930 Thread
worker("RecursiveDenial2_worker");
931 Thread::Options options
;
932 options
.message_loop_type
= message_loop_type
;
933 ASSERT_EQ(true, worker
.StartWithOptions(options
));
935 ScopedHandle
event(CreateEvent(NULL
, FALSE
, FALSE
, NULL
));
936 worker
.message_loop()->PostTask(FROM_HERE
,
937 new Recursive2Tasks(MessageLoop::current(),
942 // Let the other thread execute.
943 WaitForSingleObject(event
, INFINITE
);
944 MessageLoop::current()->Run();
946 ASSERT_EQ(order
.size(), 17);
947 EXPECT_EQ(order
[ 0], TaskItem(RECURSIVE
, 1, true));
948 EXPECT_EQ(order
[ 1], TaskItem(RECURSIVE
, 1, false));
949 EXPECT_EQ(order
[ 2], TaskItem(MESSAGEBOX
, 2, true));
950 EXPECT_EQ(order
[ 3], TaskItem(MESSAGEBOX
, 2, false));
951 EXPECT_EQ(order
[ 4], TaskItem(RECURSIVE
, 3, true));
952 EXPECT_EQ(order
[ 5], TaskItem(RECURSIVE
, 3, false));
953 // When EndDialogTask is processed, the window is already dismissed, hence no
955 EXPECT_EQ(order
[ 6], TaskItem(ENDDIALOG
, 4, true));
956 EXPECT_EQ(order
[ 7], TaskItem(QUITMESSAGELOOP
, 5, true));
957 EXPECT_EQ(order
[ 8], TaskItem(QUITMESSAGELOOP
, 5, false));
958 EXPECT_EQ(order
[ 9], TaskItem(RECURSIVE
, 1, true));
959 EXPECT_EQ(order
[10], TaskItem(RECURSIVE
, 1, false));
960 EXPECT_EQ(order
[11], TaskItem(RECURSIVE
, 3, true));
961 EXPECT_EQ(order
[12], TaskItem(RECURSIVE
, 3, false));
962 EXPECT_EQ(order
[13], TaskItem(RECURSIVE
, 1, true));
963 EXPECT_EQ(order
[14], TaskItem(RECURSIVE
, 1, false));
964 EXPECT_EQ(order
[15], TaskItem(RECURSIVE
, 3, true));
965 EXPECT_EQ(order
[16], TaskItem(RECURSIVE
, 3, false));
968 // A side effect of this test is the generation a beep. Sorry. This test also
969 // needs to process windows messages on the current thread.
970 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type
) {
971 MessageLoop
loop(message_loop_type
);
973 Thread
worker("RecursiveSupport2_worker");
974 Thread::Options options
;
975 options
.message_loop_type
= message_loop_type
;
976 ASSERT_EQ(true, worker
.StartWithOptions(options
));
978 ScopedHandle
event(CreateEvent(NULL
, FALSE
, FALSE
, NULL
));
979 worker
.message_loop()->PostTask(FROM_HERE
,
980 new Recursive2Tasks(MessageLoop::current(),
985 // Let the other thread execute.
986 WaitForSingleObject(event
, INFINITE
);
987 MessageLoop::current()->Run();
989 ASSERT_EQ(order
.size(), 18);
990 EXPECT_EQ(order
[ 0], TaskItem(RECURSIVE
, 1, true));
991 EXPECT_EQ(order
[ 1], TaskItem(RECURSIVE
, 1, false));
992 EXPECT_EQ(order
[ 2], TaskItem(MESSAGEBOX
, 2, true));
993 // Note that this executes in the MessageBox modal loop.
994 EXPECT_EQ(order
[ 3], TaskItem(RECURSIVE
, 3, true));
995 EXPECT_EQ(order
[ 4], TaskItem(RECURSIVE
, 3, false));
996 EXPECT_EQ(order
[ 5], TaskItem(ENDDIALOG
, 4, true));
997 EXPECT_EQ(order
[ 6], TaskItem(ENDDIALOG
, 4, false));
998 EXPECT_EQ(order
[ 7], TaskItem(MESSAGEBOX
, 2, false));
999 /* The order can subtly change here. The reason is that when RecursiveTask(1)
1000 is called in the main thread, if it is faster than getting to the
1001 PostTask(FROM_HERE, QuitTask) execution, the order of task execution can
1002 change. We don't care anyway that the order isn't correct.
1003 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true));
1004 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false));
1005 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
1006 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
1008 EXPECT_EQ(order
[12], TaskItem(RECURSIVE
, 3, true));
1009 EXPECT_EQ(order
[13], TaskItem(RECURSIVE
, 3, false));
1010 EXPECT_EQ(order
[14], TaskItem(RECURSIVE
, 1, true));
1011 EXPECT_EQ(order
[15], TaskItem(RECURSIVE
, 1, false));
1012 EXPECT_EQ(order
[16], TaskItem(RECURSIVE
, 3, true));
1013 EXPECT_EQ(order
[17], TaskItem(RECURSIVE
, 3, false));
1016 #endif // defined(OS_WIN)
1018 class TaskThatPumps
: public OrderedTasks
{
1020 TaskThatPumps(TaskList
* order
, int cookie
)
1021 : OrderedTasks(order
, PUMPS
, cookie
) {
1024 virtual void Run() {
1026 bool old_state
= MessageLoop::current()->NestableTasksAllowed();
1027 MessageLoop::current()->SetNestableTasksAllowed(true);
1028 MessageLoop::current()->RunAllPending();
1029 MessageLoop::current()->SetNestableTasksAllowed(old_state
);
1034 // Tests that non nestable tasks run in FIFO if there are no nested loops.
1035 void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type
) {
1036 MessageLoop
loop(message_loop_type
);
1040 Task
* task
= new OrderedTasks(&order
, 1);
1041 MessageLoop::current()->PostNonNestableTask(FROM_HERE
, task
);
1042 MessageLoop::current()->PostTask(FROM_HERE
, new OrderedTasks(&order
, 2));
1043 MessageLoop::current()->PostTask(FROM_HERE
, new QuitTask(&order
, 3));
1044 MessageLoop::current()->Run();
1047 ASSERT_EQ(6U, order
.size());
1048 EXPECT_EQ(order
[ 0], TaskItem(ORDERERD
, 1, true));
1049 EXPECT_EQ(order
[ 1], TaskItem(ORDERERD
, 1, false));
1050 EXPECT_EQ(order
[ 2], TaskItem(ORDERERD
, 2, true));
1051 EXPECT_EQ(order
[ 3], TaskItem(ORDERERD
, 2, false));
1052 EXPECT_EQ(order
[ 4], TaskItem(QUITMESSAGELOOP
, 3, true));
1053 EXPECT_EQ(order
[ 5], TaskItem(QUITMESSAGELOOP
, 3, false));
1056 // Tests that non nestable tasks don't run when there's code in the call stack.
1057 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type
,
1059 MessageLoop
loop(message_loop_type
);
1063 MessageLoop::current()->PostTask(FROM_HERE
,
1064 new TaskThatPumps(&order
, 1));
1065 Task
* task
= new OrderedTasks(&order
, 2);
1067 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE
, task
, 1);
1069 MessageLoop::current()->PostNonNestableTask(FROM_HERE
, task
);
1071 MessageLoop::current()->PostTask(FROM_HERE
, new OrderedTasks(&order
, 3));
1072 MessageLoop::current()->PostTask(FROM_HERE
, new SleepTask(&order
, 4, 50));
1073 MessageLoop::current()->PostTask(FROM_HERE
, new OrderedTasks(&order
, 5));
1074 Task
* non_nestable_quit
= new QuitTask(&order
, 6);
1076 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE
,
1080 MessageLoop::current()->PostNonNestableTask(FROM_HERE
, non_nestable_quit
);
1083 MessageLoop::current()->Run();
1086 ASSERT_EQ(12U, order
.size());
1087 EXPECT_EQ(order
[ 0], TaskItem(PUMPS
, 1, true));
1088 EXPECT_EQ(order
[ 1], TaskItem(ORDERERD
, 3, true));
1089 EXPECT_EQ(order
[ 2], TaskItem(ORDERERD
, 3, false));
1090 EXPECT_EQ(order
[ 3], TaskItem(SLEEP
, 4, true));
1091 EXPECT_EQ(order
[ 4], TaskItem(SLEEP
, 4, false));
1092 EXPECT_EQ(order
[ 5], TaskItem(ORDERERD
, 5, true));
1093 EXPECT_EQ(order
[ 6], TaskItem(ORDERERD
, 5, false));
1094 EXPECT_EQ(order
[ 7], TaskItem(PUMPS
, 1, false));
1095 EXPECT_EQ(order
[ 8], TaskItem(ORDERERD
, 2, true));
1096 EXPECT_EQ(order
[ 9], TaskItem(ORDERERD
, 2, false));
1097 EXPECT_EQ(order
[10], TaskItem(QUITMESSAGELOOP
, 6, true));
1098 EXPECT_EQ(order
[11], TaskItem(QUITMESSAGELOOP
, 6, false));
1103 class DispatcherImpl
: public MessageLoopForUI::Dispatcher
{
1105 DispatcherImpl() : dispatch_count_(0) {}
1107 virtual bool Dispatch(const MSG
& msg
) {
1108 ::TranslateMessage(&msg
);
1109 ::DispatchMessage(&msg
);
1110 // Do not count WM_TIMER since it is not what we post and it will cause
1112 if (msg
.message
!= WM_TIMER
)
1114 // We treat WM_LBUTTONUP as the last message.
1115 return msg
.message
!= WM_LBUTTONUP
;
1118 int dispatch_count_
;
1121 void RunTest_Dispatcher(MessageLoop::Type message_loop_type
) {
1122 MessageLoop
loop(message_loop_type
);
1124 class MyTask
: public Task
{
1126 virtual void Run() {
1127 PostMessage(NULL
, WM_LBUTTONDOWN
, 0, 0);
1128 PostMessage(NULL
, WM_LBUTTONUP
, 'A', 0);
1131 Task
* task
= new MyTask();
1132 MessageLoop::current()->PostDelayedTask(FROM_HERE
, task
, 100);
1133 DispatcherImpl dispatcher
;
1134 MessageLoopForUI::current()->Run(&dispatcher
);
1135 ASSERT_EQ(2, dispatcher
.dispatch_count_
);
1138 LRESULT CALLBACK
MsgFilterProc(int code
, WPARAM wparam
, LPARAM lparam
) {
1139 if (code
== base::MessagePumpForUI::kMessageFilterCode
) {
1140 MSG
* msg
= reinterpret_cast<MSG
*>(lparam
);
1141 if (msg
->message
== WM_LBUTTONDOWN
)
1147 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type
) {
1148 MessageLoop
loop(message_loop_type
);
1150 class MyTask
: public Task
{
1152 virtual void Run() {
1153 PostMessage(NULL
, WM_LBUTTONDOWN
, 0, 0);
1154 PostMessage(NULL
, WM_LBUTTONUP
, 'A', 0);
1157 Task
* task
= new MyTask();
1158 MessageLoop::current()->PostDelayedTask(FROM_HERE
, task
, 100);
1159 HHOOK msg_hook
= SetWindowsHookEx(WH_MSGFILTER
,
1162 GetCurrentThreadId());
1163 DispatcherImpl dispatcher
;
1164 MessageLoopForUI::current()->Run(&dispatcher
);
1165 ASSERT_EQ(1, dispatcher
.dispatch_count_
);
1166 UnhookWindowsHookEx(msg_hook
);
1169 class TestIOHandler
: public MessageLoopForIO::IOHandler
{
1171 TestIOHandler(const wchar_t* name
, HANDLE signal
, bool wait
);
1173 virtual void OnIOCompleted(MessageLoopForIO::IOContext
* context
,
1174 DWORD bytes_transfered
, DWORD error
);
1178 OVERLAPPED
* context() { return &context_
.overlapped
; }
1179 DWORD
size() { return sizeof(buffer_
); }
1183 MessageLoopForIO::IOContext context_
;
1189 TestIOHandler::TestIOHandler(const wchar_t* name
, HANDLE signal
, bool wait
)
1190 : signal_(signal
), wait_(wait
) {
1191 memset(buffer_
, 0, sizeof(buffer_
));
1192 memset(&context_
, 0, sizeof(context_
));
1193 context_
.handler
= this;
1195 file_
.Set(CreateFile(name
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1196 FILE_FLAG_OVERLAPPED
, NULL
));
1197 EXPECT_TRUE(file_
.IsValid());
1200 void TestIOHandler::Init() {
1201 MessageLoopForIO::current()->RegisterIOHandler(file_
, this);
1204 EXPECT_FALSE(ReadFile(file_
, buffer_
, size(), &read
, context()));
1205 EXPECT_EQ(ERROR_IO_PENDING
, GetLastError());
1210 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext
* context
,
1211 DWORD bytes_transfered
, DWORD error
) {
1212 ASSERT_TRUE(context
== &context_
);
1213 ASSERT_TRUE(SetEvent(signal_
));
1216 void TestIOHandler::WaitForIO() {
1217 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
1218 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
1221 class IOHandlerTask
: public Task
{
1223 explicit IOHandlerTask(TestIOHandler
* handler
) : handler_(handler
) {}
1224 virtual void Run() {
1229 TestIOHandler
* handler_
;
1232 void RunTest_IOHandler() {
1233 ScopedHandle
callback_called(CreateEvent(NULL
, TRUE
, FALSE
, NULL
));
1234 ASSERT_TRUE(callback_called
.IsValid());
1236 const wchar_t* kPipeName
= L
"\\\\.\\pipe\\iohandler_pipe";
1237 ScopedHandle
server(CreateNamedPipe(kPipeName
, PIPE_ACCESS_OUTBOUND
, 0, 1,
1239 ASSERT_TRUE(server
.IsValid());
1241 Thread
thread("IOHandler test");
1242 Thread::Options options
;
1243 options
.message_loop_type
= MessageLoop::TYPE_IO
;
1244 ASSERT_TRUE(thread
.StartWithOptions(options
));
1246 MessageLoop
* thread_loop
= thread
.message_loop();
1247 ASSERT_TRUE(NULL
!= thread_loop
);
1249 TestIOHandler
handler(kPipeName
, callback_called
, false);
1250 IOHandlerTask
* task
= new IOHandlerTask(&handler
);
1251 thread_loop
->PostTask(FROM_HERE
, task
);
1252 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1254 const char buffer
[] = "Hello there!";
1256 EXPECT_TRUE(WriteFile(server
, buffer
, sizeof(buffer
), &written
, NULL
));
1258 DWORD result
= WaitForSingleObject(callback_called
, 1000);
1259 EXPECT_EQ(WAIT_OBJECT_0
, result
);
1264 void RunTest_WaitForIO() {
1265 ScopedHandle
callback1_called(CreateEvent(NULL
, TRUE
, FALSE
, NULL
));
1266 ScopedHandle
callback2_called(CreateEvent(NULL
, TRUE
, FALSE
, NULL
));
1267 ASSERT_TRUE(callback1_called
.IsValid());
1268 ASSERT_TRUE(callback2_called
.IsValid());
1270 const wchar_t* kPipeName1
= L
"\\\\.\\pipe\\iohandler_pipe1";
1271 const wchar_t* kPipeName2
= L
"\\\\.\\pipe\\iohandler_pipe2";
1272 ScopedHandle
server1(CreateNamedPipe(kPipeName1
, PIPE_ACCESS_OUTBOUND
, 0, 1,
1274 ScopedHandle
server2(CreateNamedPipe(kPipeName2
, PIPE_ACCESS_OUTBOUND
, 0, 1,
1276 ASSERT_TRUE(server1
.IsValid());
1277 ASSERT_TRUE(server2
.IsValid());
1279 Thread
thread("IOHandler test");
1280 Thread::Options options
;
1281 options
.message_loop_type
= MessageLoop::TYPE_IO
;
1282 ASSERT_TRUE(thread
.StartWithOptions(options
));
1284 MessageLoop
* thread_loop
= thread
.message_loop();
1285 ASSERT_TRUE(NULL
!= thread_loop
);
1287 TestIOHandler
handler1(kPipeName1
, callback1_called
, false);
1288 TestIOHandler
handler2(kPipeName2
, callback2_called
, true);
1289 IOHandlerTask
* task1
= new IOHandlerTask(&handler1
);
1290 IOHandlerTask
* task2
= new IOHandlerTask(&handler2
);
1291 thread_loop
->PostTask(FROM_HERE
, task1
);
1292 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1293 thread_loop
->PostTask(FROM_HERE
, task2
);
1296 // At this time handler1 is waiting to be called, and the thread is waiting
1297 // on the Init method of handler2, filtering only handler2 callbacks.
1299 const char buffer
[] = "Hello there!";
1301 EXPECT_TRUE(WriteFile(server1
, buffer
, sizeof(buffer
), &written
, NULL
));
1303 EXPECT_EQ(WAIT_TIMEOUT
, WaitForSingleObject(callback1_called
, 0)) <<
1304 "handler1 has not been called";
1306 EXPECT_TRUE(WriteFile(server2
, buffer
, sizeof(buffer
), &written
, NULL
));
1308 HANDLE objects
[2] = { callback1_called
.Get(), callback2_called
.Get() };
1309 DWORD result
= WaitForMultipleObjects(2, objects
, TRUE
, 1000);
1310 EXPECT_EQ(WAIT_OBJECT_0
, result
);
1315 #endif // defined(OS_WIN)
1319 //-----------------------------------------------------------------------------
1320 // Each test is run against each type of MessageLoop. That way we are sure
1321 // that message loops work properly in all configurations. Of course, in some
1322 // cases, a unit test may only be for a particular type of loop.
1324 TEST(MessageLoopTest
, PostTask
) {
1325 RunTest_PostTask(MessageLoop::TYPE_DEFAULT
);
1326 RunTest_PostTask(MessageLoop::TYPE_UI
);
1327 RunTest_PostTask(MessageLoop::TYPE_IO
);
1330 TEST(MessageLoopTest
, PostTask_SEH
) {
1331 RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT
);
1332 RunTest_PostTask_SEH(MessageLoop::TYPE_UI
);
1333 RunTest_PostTask_SEH(MessageLoop::TYPE_IO
);
1336 TEST(MessageLoopTest
, PostDelayedTask_Basic
) {
1337 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_DEFAULT
);
1338 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_UI
);
1339 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_IO
);
1342 TEST(MessageLoopTest
, PostDelayedTask_InDelayOrder
) {
1343 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_DEFAULT
);
1344 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_UI
);
1345 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_IO
);
1348 TEST(MessageLoopTest
, PostDelayedTask_InPostOrder
) {
1349 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_DEFAULT
);
1350 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_UI
);
1351 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_IO
);
1354 TEST(MessageLoopTest
, PostDelayedTask_InPostOrder_2
) {
1355 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_DEFAULT
);
1356 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_UI
);
1357 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_IO
);
1360 TEST(MessageLoopTest
, PostDelayedTask_InPostOrder_3
) {
1361 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_DEFAULT
);
1362 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_UI
);
1363 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_IO
);
1366 TEST(MessageLoopTest
, PostDelayedTask_SharedTimer
) {
1367 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_DEFAULT
);
1368 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_UI
);
1369 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_IO
);
1373 TEST(MessageLoopTest
, PostDelayedTask_SharedTimer_SubPump
) {
1374 RunTest_PostDelayedTask_SharedTimer_SubPump();
1378 // TODO(darin): re-enable these tests once MessageLoop supports them again.
1380 TEST(MessageLoopTest
, EnsureTaskDeletion
) {
1381 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT
);
1382 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI
);
1383 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO
);
1386 TEST(MessageLoopTest
, EnsureTaskDeletion_Chain
) {
1387 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT
);
1388 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI
);
1389 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO
);
1394 TEST(MessageLoopTest
, Crasher
) {
1395 RunTest_Crasher(MessageLoop::TYPE_DEFAULT
);
1396 RunTest_Crasher(MessageLoop::TYPE_UI
);
1397 RunTest_Crasher(MessageLoop::TYPE_IO
);
1400 TEST(MessageLoopTest
, CrasherNasty
) {
1401 RunTest_CrasherNasty(MessageLoop::TYPE_DEFAULT
);
1402 RunTest_CrasherNasty(MessageLoop::TYPE_UI
);
1403 RunTest_CrasherNasty(MessageLoop::TYPE_IO
);
1405 #endif // defined(OS_WIN)
1407 TEST(MessageLoopTest
, Nesting
) {
1408 RunTest_Nesting(MessageLoop::TYPE_DEFAULT
);
1409 RunTest_Nesting(MessageLoop::TYPE_UI
);
1410 RunTest_Nesting(MessageLoop::TYPE_IO
);
1413 TEST(MessageLoopTest
, RecursiveDenial1
) {
1414 RunTest_RecursiveDenial1(MessageLoop::TYPE_DEFAULT
);
1415 RunTest_RecursiveDenial1(MessageLoop::TYPE_UI
);
1416 RunTest_RecursiveDenial1(MessageLoop::TYPE_IO
);
1419 TEST(MessageLoopTest
, RecursiveSupport1
) {
1420 RunTest_RecursiveSupport1(MessageLoop::TYPE_DEFAULT
);
1421 RunTest_RecursiveSupport1(MessageLoop::TYPE_UI
);
1422 RunTest_RecursiveSupport1(MessageLoop::TYPE_IO
);
1426 TEST(MessageLoopTest
, RecursiveDenial2
) {
1427 RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT
);
1428 RunTest_RecursiveDenial2(MessageLoop::TYPE_UI
);
1429 RunTest_RecursiveDenial2(MessageLoop::TYPE_IO
);
1432 TEST(MessageLoopTest
, RecursiveSupport2
) {
1433 // This test requires a UI loop
1434 RunTest_RecursiveSupport2(MessageLoop::TYPE_UI
);
1436 #endif // defined(OS_WIN)
1438 TEST(MessageLoopTest
, NonNestableWithNoNesting
) {
1439 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_DEFAULT
);
1440 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_UI
);
1441 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO
);
1444 TEST(MessageLoopTest
, NonNestableInNestedLoop
) {
1445 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT
, false);
1446 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI
, false);
1447 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO
, false);
1450 TEST(MessageLoopTest
, NonNestableDelayedInNestedLoop
) {
1451 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT
, true);
1452 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI
, true);
1453 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO
, true);
1457 TEST(MessageLoopTest
, Dispatcher
) {
1458 // This test requires a UI loop
1459 RunTest_Dispatcher(MessageLoop::TYPE_UI
);
1462 TEST(MessageLoopTest
, DispatcherWithMessageHook
) {
1463 // This test requires a UI loop
1464 RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI
);
1467 TEST(MessageLoopTest
, IOHandler
) {
1468 RunTest_IOHandler();
1471 TEST(MessageLoopTest
, WaitForIO
) {
1472 RunTest_WaitForIO();
1474 #endif // defined(OS_WIN)
1476 #if defined(OS_POSIX)
1480 class QuitDelegate
: public
1481 base::MessagePumpLibevent::Watcher
{
1483 virtual void OnFileCanWriteWithoutBlocking(int fd
) {
1484 MessageLoop::current()->Quit();
1486 virtual void OnFileCanReadWithoutBlocking(int fd
) {
1487 MessageLoop::current()->Quit();
1493 TEST(MessageLoopTest
, DISABLED_FileDescriptorWatcherOutlivesMessageLoop
) {
1494 // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
1495 // This could happen when people use the Singleton pattern or atexit.
1496 // This is disabled for now because it fails (valgrind shows
1497 // invalid reads), and it's not clear any code relies on this...
1498 // TODO(dkegel): enable if it turns out we rely on this
1500 // Create a file descriptor. Doesn't need to be readable or writable,
1501 // as we don't need to actually get any notifications.
1502 // pipe() is just the easiest way to do it.
1504 int err
= pipe(pipefds
);
1505 ASSERT_TRUE(err
== 0);
1506 int fd
= pipefds
[1];
1508 // Arrange for controller to live longer than message loop.
1509 base::MessagePumpLibevent::FileDescriptorWatcher controller
;
1511 MessageLoopForIO message_loop
;
1513 QuitDelegate delegate
;
1514 message_loop
.WatchFileDescriptor(fd
,
1515 true, MessageLoopForIO::WATCH_WRITE
, &controller
, &delegate
);
1516 // and don't run the message loop, just destroy it.
1523 TEST(MessageLoopTest
, FileDescriptorWatcherDoubleStop
) {
1524 // Verify that it's ok to call StopWatchingFileDescriptor().
1525 // (Errors only showed up in valgrind.)
1527 int err
= pipe(pipefds
);
1528 ASSERT_TRUE(err
== 0);
1529 int fd
= pipefds
[1];
1531 // Arrange for message loop to live longer than controller.
1532 MessageLoopForIO message_loop
;
1534 base::MessagePumpLibevent::FileDescriptorWatcher controller
;
1536 QuitDelegate delegate
;
1537 message_loop
.WatchFileDescriptor(fd
,
1538 true, MessageLoopForIO::WATCH_WRITE
, &controller
, &delegate
);
1539 controller
.StopWatchingFileDescriptor();
1546 #endif // defined(OS_POSIX)