• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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"
11 
12 #if defined(OS_WIN)
13 #include "base/message_pump_win.h"
14 #include "base/scoped_handle.h"
15 #endif
16 #if defined(OS_POSIX)
17 #include "base/message_pump_libevent.h"
18 #endif
19 
20 using base::Thread;
21 using base::Time;
22 using base::TimeDelta;
23 
24 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
25 // to avoid chopping this file up with so many #ifdefs.
26 
27 namespace {
28 
29 class MessageLoopTest : public testing::Test {};
30 
31 class Foo : public base::RefCounted<Foo> {
32  public:
Foo()33   Foo() : test_count_(0) {
34   }
35 
Test0()36   void Test0() {
37     ++test_count_;
38   }
39 
Test1ConstRef(const std::string & a)40   void Test1ConstRef(const std::string& a) {
41     ++test_count_;
42     result_.append(a);
43   }
44 
Test1Ptr(std::string * a)45   void Test1Ptr(std::string* a) {
46     ++test_count_;
47     result_.append(*a);
48   }
49 
Test1Int(int a)50   void Test1Int(int a) {
51     test_count_ += a;
52   }
53 
Test2Ptr(std::string * a,std::string * b)54   void Test2Ptr(std::string* a, std::string* b) {
55     ++test_count_;
56     result_.append(*a);
57     result_.append(*b);
58   }
59 
Test2Mixed(const std::string & a,std::string * b)60   void Test2Mixed(const std::string& a, std::string* b) {
61     ++test_count_;
62     result_.append(a);
63     result_.append(*b);
64   }
65 
test_count() const66   int test_count() const { return test_count_; }
result() const67   const std::string& result() const { return result_; }
68 
69  private:
70   friend class base::RefCounted<Foo>;
71 
~Foo()72   ~Foo() {}
73 
74   int test_count_;
75   std::string result_;
76 };
77 
78 class QuitMsgLoop : public base::RefCounted<QuitMsgLoop> {
79  public:
QuitNow()80   void QuitNow() {
81     MessageLoop::current()->Quit();
82   }
83 
84  private:
85   friend class base::RefCounted<QuitMsgLoop>;
86 
~QuitMsgLoop()87   ~QuitMsgLoop() {}
88 };
89 
RunTest_PostTask(MessageLoop::Type message_loop_type)90 void RunTest_PostTask(MessageLoop::Type message_loop_type) {
91   MessageLoop loop(message_loop_type);
92 
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));
108 
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));
113 
114   // Now kick things off
115   MessageLoop::current()->Run();
116 
117   EXPECT_EQ(foo->test_count(), 105);
118   EXPECT_EQ(foo->result(), "abacad");
119 }
120 
RunTest_PostTask_SEH(MessageLoop::Type message_loop_type)121 void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type) {
122   MessageLoop loop(message_loop_type);
123 
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));
139 
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));
144 
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);
149 
150   EXPECT_EQ(foo->test_count(), 105);
151   EXPECT_EQ(foo->result(), "abacad");
152 }
153 
154 // This class runs slowly to simulate a large amount of work being done.
155 class SlowTask : public Task {
156  public:
SlowTask(int pause_ms,int * quit_counter)157   SlowTask(int pause_ms, int* quit_counter)
158       : pause_ms_(pause_ms), quit_counter_(quit_counter) {
159   }
Run()160   virtual void Run() {
161     PlatformThread::Sleep(pause_ms_);
162     if (--(*quit_counter_) == 0)
163       MessageLoop::current()->Quit();
164   }
165  private:
166   int pause_ms_;
167   int* quit_counter_;
168 };
169 
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 {
173  public:
RecordRunTimeTask(Time * run_time,int * quit_counter)174   RecordRunTimeTask(Time* run_time, int* quit_counter)
175       : SlowTask(10, quit_counter), run_time_(run_time) {
176   }
Run()177   virtual void Run() {
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.
182     SlowTask::Run();
183   }
184  private:
185   Time* run_time_;
186 };
187 
RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type)188 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) {
189   MessageLoop loop(message_loop_type);
190 
191   // Test that PostDelayedTask results in a delayed task.
192 
193   const int kDelayMS = 100;
194 
195   int num_tasks = 1;
196   Time run_time;
197 
198   loop.PostDelayedTask(
199       FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), kDelayMS);
200 
201   Time time_before_run = Time::Now();
202   loop.Run();
203   Time time_after_run = Time::Now();
204 
205   EXPECT_EQ(0, num_tasks);
206   EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds());
207 }
208 
RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type)209 void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type) {
210   MessageLoop loop(message_loop_type);
211 
212   // Test that two tasks with different delays run in the right order.
213 
214   int num_tasks = 2;
215   Time run_time1, run_time2;
216 
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
220   // test could fail.
221   loop.PostDelayedTask(
222       FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10);
223 
224   loop.Run();
225   EXPECT_EQ(0, num_tasks);
226 
227   EXPECT_TRUE(run_time2 < run_time1);
228 }
229 
RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type)230 void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type) {
231   MessageLoop loop(message_loop_type);
232 
233   // Test that two tasks with the same delay run in the order in which they
234   // were posted.
235   //
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.
240 
241   const int kDelayMS = 100;
242 
243   int num_tasks = 2;
244   Time run_time1, run_time2;
245 
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);
250 
251   loop.Run();
252   EXPECT_EQ(0, num_tasks);
253 
254   EXPECT_TRUE(run_time1 < run_time2);
255 }
256 
RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::Type message_loop_type)257 void RunTest_PostDelayedTask_InPostOrder_2(
258     MessageLoop::Type message_loop_type) {
259   MessageLoop loop(message_loop_type);
260 
261   // Test that a delayed task still runs after a normal tasks even if the
262   // normal tasks take a long time to run.
263 
264   const int kPauseMS = 50;
265 
266   int num_tasks = 2;
267   Time run_time;
268 
269   loop.PostTask(
270       FROM_HERE, new SlowTask(kPauseMS, &num_tasks));
271   loop.PostDelayedTask(
272       FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 10);
273 
274   Time time_before_run = Time::Now();
275   loop.Run();
276   Time time_after_run = Time::Now();
277 
278   EXPECT_EQ(0, num_tasks);
279 
280   EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds());
281 }
282 
RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::Type message_loop_type)283 void RunTest_PostDelayedTask_InPostOrder_3(
284     MessageLoop::Type message_loop_type) {
285   MessageLoop loop(message_loop_type);
286 
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.
292 
293   int num_tasks = 11;
294   Time run_time1, run_time2;
295 
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));
299 
300   loop.PostDelayedTask(
301       FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 1);
302 
303   loop.Run();
304   EXPECT_EQ(0, num_tasks);
305 
306   EXPECT_TRUE(run_time2 > run_time1);
307 }
308 
RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type)309 void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type) {
310   MessageLoop loop(message_loop_type);
311 
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.
314 
315   // By setting num_tasks to 1, we ensure that the first task to run causes the
316   // run loop to exit.
317   int num_tasks = 1;
318   Time run_time1, run_time2;
319 
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);
324 
325   Time start_time = Time::Now();
326 
327   loop.Run();
328   EXPECT_EQ(0, num_tasks);
329 
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());
333 
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();
339 
340   EXPECT_TRUE(run_time1.is_null());
341   EXPECT_FALSE(run_time2.is_null());
342 }
343 
344 #if defined(OS_WIN)
345 
346 class SubPumpTask : public Task {
347  public:
Run()348   virtual void Run() {
349     MessageLoop::current()->SetNestableTasksAllowed(true);
350     MSG msg;
351     while (GetMessage(&msg, NULL, 0, 0)) {
352       TranslateMessage(&msg);
353       DispatchMessage(&msg);
354     }
355     MessageLoop::current()->Quit();
356   }
357 };
358 
359 class SubPumpQuitTask : public Task {
360  public:
SubPumpQuitTask()361   SubPumpQuitTask() {
362   }
Run()363   virtual void Run() {
364     PostQuitMessage(0);
365   }
366 };
367 
RunTest_PostDelayedTask_SharedTimer_SubPump()368 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
369   MessageLoop loop(MessageLoop::TYPE_UI);
370 
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.
373 
374   // By setting num_tasks to 1, we ensure that the first task to run causes the
375   // run loop to exit.
376   int num_tasks = 1;
377   Time run_time;
378 
379   loop.PostTask(FROM_HERE, new SubPumpTask());
380 
381   // This very delayed task should never run.
382   loop.PostDelayedTask(
383       FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 1000000);
384 
385   // This slightly delayed task should run from within SubPumpTask::Run().
386   loop.PostDelayedTask(
387       FROM_HERE, new SubPumpQuitTask(), 10);
388 
389   Time start_time = Time::Now();
390 
391   loop.Run();
392   EXPECT_EQ(1, num_tasks);
393 
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());
397 
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();
403 
404   EXPECT_TRUE(run_time.is_null());
405 }
406 
407 #endif  // defined(OS_WIN)
408 
409 class RecordDeletionTask : public Task {
410  public:
RecordDeletionTask(Task * post_on_delete,bool * was_deleted)411   RecordDeletionTask(Task* post_on_delete, bool* was_deleted)
412       : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {
413   }
~RecordDeletionTask()414   ~RecordDeletionTask() {
415     *was_deleted_ = true;
416     if (post_on_delete_)
417       MessageLoop::current()->PostTask(FROM_HERE, post_on_delete_);
418   }
Run()419   virtual void Run() {}
420  private:
421   Task* post_on_delete_;
422   bool* was_deleted_;
423 };
424 
RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type)425 void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type) {
426   bool a_was_deleted = false;
427   bool b_was_deleted = false;
428   {
429     MessageLoop loop(message_loop_type);
430     loop.PostTask(
431         FROM_HERE, new RecordDeletionTask(NULL, &a_was_deleted));
432     loop.PostDelayedTask(
433         FROM_HERE, new RecordDeletionTask(NULL, &b_was_deleted), 1000);
434   }
435   EXPECT_TRUE(a_was_deleted);
436   EXPECT_TRUE(b_was_deleted);
437 }
438 
RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type)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;
443   {
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);
449   }
450   EXPECT_TRUE(a_was_deleted);
451   EXPECT_TRUE(b_was_deleted);
452   EXPECT_TRUE(c_was_deleted);
453 }
454 
455 class NestingTest : public Task {
456  public:
NestingTest(int * depth)457   explicit NestingTest(int* depth) : depth_(depth) {
458   }
Run()459   void Run() {
460     if (*depth_ > 0) {
461       *depth_ -= 1;
462       MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(depth_));
463 
464       MessageLoop::current()->SetNestableTasksAllowed(true);
465       MessageLoop::current()->Run();
466     }
467     MessageLoop::current()->Quit();
468   }
469  private:
470   int* depth_;
471 };
472 
473 #if defined(OS_WIN)
474 
BadExceptionHandler(EXCEPTION_POINTERS * ex_info)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;
479 }
480 
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 {
484  public:
485   // Ctor. If trash_SEH_handler is true, the task will override the unhandled
486   // exception handler with one sure to crash this test.
CrasherTask(bool trash_SEH_handler)487   explicit CrasherTask(bool trash_SEH_handler)
488       : trash_SEH_handler_(trash_SEH_handler) {
489   }
Run()490   void Run() {
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
495     // the damage.
496 
497 #if defined(_M_IX86)
498 
499     __asm {
500       mov eax, dword ptr [CrasherTask::bad_array_]
501       mov byte ptr [eax], 66
502     }
503 
504 #elif defined(_M_X64)
505 
506     bad_array_[0] = 66;
507 
508 #else
509 #error "needs architecture support"
510 #endif
511 
512     MessageLoop::current()->Quit();
513   }
514   // Points the bad array to a valid memory location.
FixError()515   static void FixError() {
516     bad_array_ = &valid_store_;
517   }
518 
519  private:
520   bool trash_SEH_handler_;
521   static volatile char* bad_array_;
522   static char valid_store_;
523 };
524 
525 volatile char* CrasherTask::bad_array_ = 0;
526 char CrasherTask::valid_store_ = 0;
527 
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.
HandleCrasherTaskException(EXCEPTION_POINTERS * ex_info)531 LONG WINAPI HandleCrasherTaskException(EXCEPTION_POINTERS *ex_info) {
532   if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
533     return EXCEPTION_EXECUTE_HANDLER;
534 
535   CrasherTask::FixError();
536 
537 #if defined(_M_IX86)
538 
539   ex_info->ContextRecord->Eip -= 5;
540 
541 #elif defined(_M_X64)
542 
543   ex_info->ContextRecord->Rip -= 5;
544 
545 #endif
546 
547   return EXCEPTION_CONTINUE_EXECUTION;
548 }
549 
RunTest_Crasher(MessageLoop::Type message_loop_type)550 void RunTest_Crasher(MessageLoop::Type message_loop_type) {
551   MessageLoop loop(message_loop_type);
552 
553   if (::IsDebuggerPresent())
554     return;
555 
556   LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
557       ::SetUnhandledExceptionFilter(&HandleCrasherTaskException);
558 
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);
563 
564   ::SetUnhandledExceptionFilter(old_SEH_filter);
565 }
566 
RunTest_CrasherNasty(MessageLoop::Type message_loop_type)567 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) {
568   MessageLoop loop(message_loop_type);
569 
570   if (::IsDebuggerPresent())
571     return;
572 
573   LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
574       ::SetUnhandledExceptionFilter(&HandleCrasherTaskException);
575 
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);
580 
581   ::SetUnhandledExceptionFilter(old_SEH_filter);
582 }
583 
584 #endif  // defined(OS_WIN)
585 
RunTest_Nesting(MessageLoop::Type message_loop_type)586 void RunTest_Nesting(MessageLoop::Type message_loop_type) {
587   MessageLoop loop(message_loop_type);
588 
589   int depth = 100;
590   MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(&depth));
591   MessageLoop::current()->Run();
592   EXPECT_EQ(depth, 0);
593 }
594 
595 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test";
596 
597 enum TaskType {
598   MESSAGEBOX,
599   ENDDIALOG,
600   RECURSIVE,
601   TIMEDMESSAGELOOP,
602   QUITMESSAGELOOP,
603   ORDERERD,
604   PUMPS,
605   SLEEP,
606 };
607 
608 // Saves the order in which the tasks executed.
609 struct TaskItem {
TaskItem__anonb47bed490111::TaskItem610   TaskItem(TaskType t, int c, bool s)
611       : type(t),
612         cookie(c),
613         start(s) {
614   }
615 
616   TaskType type;
617   int cookie;
618   bool start;
619 
operator ==__anonb47bed490111::TaskItem620   bool operator == (const TaskItem& other) const {
621     return type == other.type && cookie == other.cookie && start == other.start;
622   }
623 };
624 
625 typedef std::vector<TaskItem> TaskList;
626 
operator <<(std::ostream & os,TaskType type)627 std::ostream& operator <<(std::ostream& os, TaskType type) {
628   switch (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;
637   default:
638     NOTREACHED();
639     os << "Unknown TaskType";
640     break;
641   }
642   return os;
643 }
644 
operator <<(std::ostream & os,const TaskItem & item)645 std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
646   if (item.start)
647     return os << item.type << " " << item.cookie << " starts";
648   else
649     return os << item.type << " " << item.cookie << " ends";
650 }
651 
652 // Saves the order the tasks ran.
653 class OrderedTasks : public Task {
654  public:
OrderedTasks(TaskList * order,int cookie)655   OrderedTasks(TaskList* order, int cookie)
656       : order_(order),
657         type_(ORDERERD),
658         cookie_(cookie) {
659   }
OrderedTasks(TaskList * order,TaskType type,int cookie)660   OrderedTasks(TaskList* order, TaskType type, int cookie)
661       : order_(order),
662         type_(type),
663         cookie_(cookie) {
664   }
665 
RunStart()666   void RunStart() {
667     TaskItem item(type_, cookie_, true);
668     DLOG(INFO) << item;
669     order_->push_back(item);
670   }
RunEnd()671   void RunEnd() {
672     TaskItem item(type_, cookie_, false);
673     DLOG(INFO) << item;
674     order_->push_back(item);
675   }
676 
Run()677   virtual void Run() {
678     RunStart();
679     RunEnd();
680   }
681 
682  protected:
order() const683   TaskList* order() const {
684     return order_;
685   }
686 
cookie() const687   int cookie() const {
688     return cookie_;
689   }
690 
691  private:
692   TaskList* order_;
693   TaskType type_;
694   int cookie_;
695 };
696 
697 #if defined(OS_WIN)
698 
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 {
703  public:
MessageBoxTask(TaskList * order,int cookie,bool is_reentrant)704   MessageBoxTask(TaskList* order, int cookie, bool is_reentrant)
705       : OrderedTasks(order, MESSAGEBOX, cookie),
706         is_reentrant_(is_reentrant) {
707   }
708 
Run()709   virtual void Run() {
710     RunStart();
711     if (is_reentrant_)
712       MessageLoop::current()->SetNestableTasksAllowed(true);
713     MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
714     RunEnd();
715   }
716 
717  private:
718   bool is_reentrant_;
719 };
720 
721 // Will end the MessageBox.
722 class EndDialogTask : public OrderedTasks {
723  public:
EndDialogTask(TaskList * order,int cookie)724   EndDialogTask(TaskList* order, int cookie)
725       : OrderedTasks(order, ENDDIALOG, cookie) {
726   }
727 
Run()728   virtual void Run() {
729     RunStart();
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
734       // called.
735       RunEnd();
736     }
737   }
738 };
739 
740 #endif  // defined(OS_WIN)
741 
742 class RecursiveTask : public OrderedTasks {
743  public:
RecursiveTask(int depth,TaskList * order,int cookie,bool is_reentrant)744   RecursiveTask(int depth, TaskList* order, int cookie, bool is_reentrant)
745       : OrderedTasks(order, RECURSIVE, cookie),
746         depth_(depth),
747         is_reentrant_(is_reentrant) {
748   }
749 
Run()750   virtual void Run() {
751     RunStart();
752     if (depth_ > 0) {
753       if (is_reentrant_)
754         MessageLoop::current()->SetNestableTasksAllowed(true);
755       MessageLoop::current()->PostTask(FROM_HERE,
756           new RecursiveTask(depth_ - 1, order(), cookie(), is_reentrant_));
757     }
758     RunEnd();
759   }
760 
761  private:
762   int depth_;
763   bool is_reentrant_;
764 };
765 
766 class QuitTask : public OrderedTasks {
767  public:
QuitTask(TaskList * order,int cookie)768   QuitTask(TaskList* order, int cookie)
769       : OrderedTasks(order, QUITMESSAGELOOP, cookie) {
770   }
771 
Run()772   virtual void Run() {
773     RunStart();
774     MessageLoop::current()->Quit();
775     RunEnd();
776   }
777 };
778 
779 class SleepTask : public OrderedTasks {
780  public:
SleepTask(TaskList * order,int cookie,int ms)781   SleepTask(TaskList* order, int cookie, int ms)
782       : OrderedTasks(order, SLEEP, cookie), ms_(ms) {
783   }
784 
Run()785   virtual void Run() {
786     RunStart();
787     PlatformThread::Sleep(ms_);
788     RunEnd();
789   }
790 
791  private:
792   int ms_;
793 };
794 
795 #if defined(OS_WIN)
796 
797 class Recursive2Tasks : public Task {
798  public:
Recursive2Tasks(MessageLoop * target,HANDLE event,bool expect_window,TaskList * order,bool is_reentrant)799   Recursive2Tasks(MessageLoop* target,
800                   HANDLE event,
801                   bool expect_window,
802                   TaskList* order,
803                   bool is_reentrant)
804       : target_(target),
805         event_(event),
806         expect_window_(expect_window),
807         order_(order),
808         is_reentrant_(is_reentrant) {
809   }
810 
Run()811   virtual void Run() {
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
820     // without a chance.
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));
826 
827     // Enforce that every tasks are sent before starting to run the main thread
828     // message loop.
829     ASSERT_TRUE(SetEvent(event_));
830 
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);
835       if (window) {
836         // Dismiss it.
837         for (;;) {
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));
842             break;
843           }
844         }
845         break;
846       }
847     }
848   }
849 
850  private:
851   MessageLoop* target_;
852   HANDLE event_;
853   TaskList* order_;
854   bool expect_window_;
855   bool is_reentrant_;
856 };
857 
858 #endif  // defined(OS_WIN)
859 
RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type)860 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) {
861   MessageLoop loop(message_loop_type);
862 
863   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
864   TaskList order;
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));
870 
871   MessageLoop::current()->Run();
872 
873   // FIFO order.
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));
889 }
890 
RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type)891 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) {
892   MessageLoop loop(message_loop_type);
893 
894   TaskList order;
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));
901 
902   MessageLoop::current()->Run();
903 
904   // FIFO order.
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));
920 }
921 
922 #if defined(OS_WIN)
923 // TODO(darin): These tests need to be ported since they test critical
924 // message loop functionality.
925 
926 // A side effect of this test is the generation a beep. Sorry.
RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type)927 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
928   MessageLoop loop(message_loop_type);
929 
930   Thread worker("RecursiveDenial2_worker");
931   Thread::Options options;
932   options.message_loop_type = message_loop_type;
933   ASSERT_EQ(true, worker.StartWithOptions(options));
934   TaskList order;
935   ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
936   worker.message_loop()->PostTask(FROM_HERE,
937                                   new Recursive2Tasks(MessageLoop::current(),
938                                                       event,
939                                                       true,
940                                                       &order,
941                                                       false));
942   // Let the other thread execute.
943   WaitForSingleObject(event, INFINITE);
944   MessageLoop::current()->Run();
945 
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
954   // "end" entry.
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));
966 }
967 
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.
RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type)970 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
971   MessageLoop loop(message_loop_type);
972 
973   Thread worker("RecursiveSupport2_worker");
974   Thread::Options options;
975   options.message_loop_type = message_loop_type;
976   ASSERT_EQ(true, worker.StartWithOptions(options));
977   TaskList order;
978   ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
979   worker.message_loop()->PostTask(FROM_HERE,
980                                   new Recursive2Tasks(MessageLoop::current(),
981                                                       event,
982                                                       false,
983                                                       &order,
984                                                       true));
985   // Let the other thread execute.
986   WaitForSingleObject(event, INFINITE);
987   MessageLoop::current()->Run();
988 
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));
1007   */
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));
1014 }
1015 
1016 #endif  // defined(OS_WIN)
1017 
1018 class TaskThatPumps : public OrderedTasks {
1019  public:
TaskThatPumps(TaskList * order,int cookie)1020   TaskThatPumps(TaskList* order, int cookie)
1021       : OrderedTasks(order, PUMPS, cookie) {
1022   }
1023 
Run()1024   virtual void Run() {
1025     RunStart();
1026     bool old_state = MessageLoop::current()->NestableTasksAllowed();
1027     MessageLoop::current()->SetNestableTasksAllowed(true);
1028     MessageLoop::current()->RunAllPending();
1029     MessageLoop::current()->SetNestableTasksAllowed(old_state);
1030     RunEnd();
1031   }
1032 };
1033 
1034 // Tests that non nestable tasks run in FIFO if there are no nested loops.
RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type)1035 void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) {
1036   MessageLoop loop(message_loop_type);
1037 
1038   TaskList order;
1039 
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();
1045 
1046   // FIFO order.
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));
1054 }
1055 
1056 // Tests that non nestable tasks don't run when there's code in the call stack.
RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type,bool use_delayed)1057 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type,
1058                                      bool use_delayed) {
1059   MessageLoop loop(message_loop_type);
1060 
1061   TaskList order;
1062 
1063   MessageLoop::current()->PostTask(FROM_HERE,
1064                                    new TaskThatPumps(&order, 1));
1065   Task* task = new OrderedTasks(&order, 2);
1066   if (use_delayed) {
1067     MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1);
1068   } else {
1069     MessageLoop::current()->PostNonNestableTask(FROM_HERE, task);
1070   }
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);
1075   if (use_delayed) {
1076     MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE,
1077                                                        non_nestable_quit,
1078                                                        2);
1079   } else {
1080     MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit);
1081   }
1082 
1083   MessageLoop::current()->Run();
1084 
1085   // FIFO order.
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));
1099 }
1100 
1101 #if defined(OS_WIN)
1102 
1103 class DispatcherImpl : public MessageLoopForUI::Dispatcher {
1104  public:
DispatcherImpl()1105   DispatcherImpl() : dispatch_count_(0) {}
1106 
Dispatch(const MSG & msg)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
1111     // flakiness.
1112     if (msg.message != WM_TIMER)
1113       ++dispatch_count_;
1114     // We treat WM_LBUTTONUP as the last message.
1115     return msg.message != WM_LBUTTONUP;
1116   }
1117 
1118   int dispatch_count_;
1119 };
1120 
RunTest_Dispatcher(MessageLoop::Type message_loop_type)1121 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
1122   MessageLoop loop(message_loop_type);
1123 
1124   class MyTask : public Task {
1125   public:
1126     virtual void Run() {
1127       PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1128       PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1129     }
1130   };
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_);
1136 }
1137 
MsgFilterProc(int code,WPARAM wparam,LPARAM lparam)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)
1142       return TRUE;
1143   }
1144   return FALSE;
1145 }
1146 
RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type)1147 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
1148   MessageLoop loop(message_loop_type);
1149 
1150   class MyTask : public Task {
1151   public:
1152     virtual void Run() {
1153       PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1154       PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1155     }
1156   };
1157   Task* task = new MyTask();
1158   MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
1159   HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
1160                                     MsgFilterProc,
1161                                     NULL,
1162                                     GetCurrentThreadId());
1163   DispatcherImpl dispatcher;
1164   MessageLoopForUI::current()->Run(&dispatcher);
1165   ASSERT_EQ(1, dispatcher.dispatch_count_);
1166   UnhookWindowsHookEx(msg_hook);
1167 }
1168 
1169 class TestIOHandler : public MessageLoopForIO::IOHandler {
1170  public:
1171   TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
1172 
1173   virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
1174                              DWORD bytes_transfered, DWORD error);
1175 
1176   void Init();
1177   void WaitForIO();
context()1178   OVERLAPPED* context() { return &context_.overlapped; }
size()1179   DWORD size() { return sizeof(buffer_); }
1180 
1181  private:
1182   char buffer_[48];
1183   MessageLoopForIO::IOContext context_;
1184   HANDLE signal_;
1185   ScopedHandle file_;
1186   bool wait_;
1187 };
1188 
TestIOHandler(const wchar_t * name,HANDLE signal,bool wait)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;
1194 
1195   file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1196                        FILE_FLAG_OVERLAPPED, NULL));
1197   EXPECT_TRUE(file_.IsValid());
1198 }
1199 
Init()1200 void TestIOHandler::Init() {
1201   MessageLoopForIO::current()->RegisterIOHandler(file_, this);
1202 
1203   DWORD read;
1204   EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context()));
1205   EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
1206   if (wait_)
1207     WaitForIO();
1208 }
1209 
OnIOCompleted(MessageLoopForIO::IOContext * context,DWORD bytes_transfered,DWORD error)1210 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
1211                                   DWORD bytes_transfered, DWORD error) {
1212   ASSERT_TRUE(context == &context_);
1213   ASSERT_TRUE(SetEvent(signal_));
1214 }
1215 
WaitForIO()1216 void TestIOHandler::WaitForIO() {
1217   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
1218   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
1219 }
1220 
1221 class IOHandlerTask : public Task {
1222  public:
IOHandlerTask(TestIOHandler * handler)1223   explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {}
Run()1224   virtual void Run() {
1225     handler_->Init();
1226   }
1227 
1228  private:
1229   TestIOHandler* handler_;
1230 };
1231 
RunTest_IOHandler()1232 void RunTest_IOHandler() {
1233   ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1234   ASSERT_TRUE(callback_called.IsValid());
1235 
1236   const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
1237   ScopedHandle server(CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1,
1238                                       0, 0, 0, NULL));
1239   ASSERT_TRUE(server.IsValid());
1240 
1241   Thread thread("IOHandler test");
1242   Thread::Options options;
1243   options.message_loop_type = MessageLoop::TYPE_IO;
1244   ASSERT_TRUE(thread.StartWithOptions(options));
1245 
1246   MessageLoop* thread_loop = thread.message_loop();
1247   ASSERT_TRUE(NULL != thread_loop);
1248 
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.
1253 
1254   const char buffer[] = "Hello there!";
1255   DWORD written;
1256   EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL));
1257 
1258   DWORD result = WaitForSingleObject(callback_called, 1000);
1259   EXPECT_EQ(WAIT_OBJECT_0, result);
1260 
1261   thread.Stop();
1262 }
1263 
RunTest_WaitForIO()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());
1269 
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,
1273                                        0, 0, 0, NULL));
1274   ScopedHandle server2(CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1,
1275                                        0, 0, 0, NULL));
1276   ASSERT_TRUE(server1.IsValid());
1277   ASSERT_TRUE(server2.IsValid());
1278 
1279   Thread thread("IOHandler test");
1280   Thread::Options options;
1281   options.message_loop_type = MessageLoop::TYPE_IO;
1282   ASSERT_TRUE(thread.StartWithOptions(options));
1283 
1284   MessageLoop* thread_loop = thread.message_loop();
1285   ASSERT_TRUE(NULL != thread_loop);
1286 
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);
1294   Sleep(100);
1295 
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.
1298 
1299   const char buffer[] = "Hello there!";
1300   DWORD written;
1301   EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL));
1302   Sleep(200);
1303   EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) <<
1304       "handler1 has not been called";
1305 
1306   EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL));
1307 
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);
1311 
1312   thread.Stop();
1313 }
1314 
1315 #endif  // defined(OS_WIN)
1316 
1317 }  // namespace
1318 
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.
1323 
TEST(MessageLoopTest,PostTask)1324 TEST(MessageLoopTest, PostTask) {
1325   RunTest_PostTask(MessageLoop::TYPE_DEFAULT);
1326   RunTest_PostTask(MessageLoop::TYPE_UI);
1327   RunTest_PostTask(MessageLoop::TYPE_IO);
1328 }
1329 
TEST(MessageLoopTest,PostTask_SEH)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);
1334 }
1335 
TEST(MessageLoopTest,PostDelayedTask_Basic)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);
1340 }
1341 
TEST(MessageLoopTest,PostDelayedTask_InDelayOrder)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);
1346 }
1347 
TEST(MessageLoopTest,PostDelayedTask_InPostOrder)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);
1352 }
1353 
TEST(MessageLoopTest,PostDelayedTask_InPostOrder_2)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);
1358 }
1359 
TEST(MessageLoopTest,PostDelayedTask_InPostOrder_3)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);
1364 }
1365 
TEST(MessageLoopTest,PostDelayedTask_SharedTimer)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);
1370 }
1371 
1372 #if defined(OS_WIN)
TEST(MessageLoopTest,PostDelayedTask_SharedTimer_SubPump)1373 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
1374   RunTest_PostDelayedTask_SharedTimer_SubPump();
1375 }
1376 #endif
1377 
1378 // TODO(darin): re-enable these tests once MessageLoop supports them again.
1379 #if 0
1380 TEST(MessageLoopTest, EnsureTaskDeletion) {
1381   RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT);
1382   RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI);
1383   RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO);
1384 }
1385 
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);
1390 }
1391 #endif
1392 
1393 #if defined(OS_WIN)
TEST(MessageLoopTest,Crasher)1394 TEST(MessageLoopTest, Crasher) {
1395   RunTest_Crasher(MessageLoop::TYPE_DEFAULT);
1396   RunTest_Crasher(MessageLoop::TYPE_UI);
1397   RunTest_Crasher(MessageLoop::TYPE_IO);
1398 }
1399 
TEST(MessageLoopTest,CrasherNasty)1400 TEST(MessageLoopTest, CrasherNasty) {
1401   RunTest_CrasherNasty(MessageLoop::TYPE_DEFAULT);
1402   RunTest_CrasherNasty(MessageLoop::TYPE_UI);
1403   RunTest_CrasherNasty(MessageLoop::TYPE_IO);
1404 }
1405 #endif  // defined(OS_WIN)
1406 
TEST(MessageLoopTest,Nesting)1407 TEST(MessageLoopTest, Nesting) {
1408   RunTest_Nesting(MessageLoop::TYPE_DEFAULT);
1409   RunTest_Nesting(MessageLoop::TYPE_UI);
1410   RunTest_Nesting(MessageLoop::TYPE_IO);
1411 }
1412 
TEST(MessageLoopTest,RecursiveDenial1)1413 TEST(MessageLoopTest, RecursiveDenial1) {
1414   RunTest_RecursiveDenial1(MessageLoop::TYPE_DEFAULT);
1415   RunTest_RecursiveDenial1(MessageLoop::TYPE_UI);
1416   RunTest_RecursiveDenial1(MessageLoop::TYPE_IO);
1417 }
1418 
TEST(MessageLoopTest,RecursiveSupport1)1419 TEST(MessageLoopTest, RecursiveSupport1) {
1420   RunTest_RecursiveSupport1(MessageLoop::TYPE_DEFAULT);
1421   RunTest_RecursiveSupport1(MessageLoop::TYPE_UI);
1422   RunTest_RecursiveSupport1(MessageLoop::TYPE_IO);
1423 }
1424 
1425 #if defined(OS_WIN)
TEST(MessageLoopTest,RecursiveDenial2)1426 TEST(MessageLoopTest, RecursiveDenial2) {
1427   RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
1428   RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
1429   RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
1430 }
1431 
TEST(MessageLoopTest,RecursiveSupport2)1432 TEST(MessageLoopTest, RecursiveSupport2) {
1433   // This test requires a UI loop
1434   RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
1435 }
1436 #endif  // defined(OS_WIN)
1437 
TEST(MessageLoopTest,NonNestableWithNoNesting)1438 TEST(MessageLoopTest, NonNestableWithNoNesting) {
1439   RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_DEFAULT);
1440   RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_UI);
1441   RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO);
1442 }
1443 
TEST(MessageLoopTest,NonNestableInNestedLoop)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);
1448 }
1449 
TEST(MessageLoopTest,NonNestableDelayedInNestedLoop)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);
1454 }
1455 
1456 #if defined(OS_WIN)
TEST(MessageLoopTest,Dispatcher)1457 TEST(MessageLoopTest, Dispatcher) {
1458   // This test requires a UI loop
1459   RunTest_Dispatcher(MessageLoop::TYPE_UI);
1460 }
1461 
TEST(MessageLoopTest,DispatcherWithMessageHook)1462 TEST(MessageLoopTest, DispatcherWithMessageHook) {
1463   // This test requires a UI loop
1464   RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI);
1465 }
1466 
TEST(MessageLoopTest,IOHandler)1467 TEST(MessageLoopTest, IOHandler) {
1468   RunTest_IOHandler();
1469 }
1470 
TEST(MessageLoopTest,WaitForIO)1471 TEST(MessageLoopTest, WaitForIO) {
1472   RunTest_WaitForIO();
1473 }
1474 #endif  // defined(OS_WIN)
1475 
1476 #if defined(OS_POSIX)
1477 
1478 namespace {
1479 
1480 class QuitDelegate : public
1481     base::MessagePumpLibevent::Watcher {
1482  public:
OnFileCanWriteWithoutBlocking(int fd)1483   virtual void OnFileCanWriteWithoutBlocking(int fd) {
1484     MessageLoop::current()->Quit();
1485   }
OnFileCanReadWithoutBlocking(int fd)1486   virtual void OnFileCanReadWithoutBlocking(int fd) {
1487     MessageLoop::current()->Quit();
1488   }
1489 };
1490 
1491 }  // namespace
1492 
TEST(MessageLoopTest,DISABLED_FileDescriptorWatcherOutlivesMessageLoop)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
1499 
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.
1503   int pipefds[2];
1504   int err = pipe(pipefds);
1505   ASSERT_TRUE(err == 0);
1506   int fd = pipefds[1];
1507   {
1508     // Arrange for controller to live longer than message loop.
1509     base::MessagePumpLibevent::FileDescriptorWatcher controller;
1510     {
1511       MessageLoopForIO message_loop;
1512 
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.
1517     }
1518   }
1519   close(pipefds[0]);
1520   close(pipefds[1]);
1521 }
1522 
TEST(MessageLoopTest,FileDescriptorWatcherDoubleStop)1523 TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) {
1524   // Verify that it's ok to call StopWatchingFileDescriptor().
1525   // (Errors only showed up in valgrind.)
1526   int pipefds[2];
1527   int err = pipe(pipefds);
1528   ASSERT_TRUE(err == 0);
1529   int fd = pipefds[1];
1530   {
1531     // Arrange for message loop to live longer than controller.
1532     MessageLoopForIO message_loop;
1533     {
1534       base::MessagePumpLibevent::FileDescriptorWatcher controller;
1535 
1536       QuitDelegate delegate;
1537       message_loop.WatchFileDescriptor(fd,
1538           true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
1539       controller.StopWatchingFileDescriptor();
1540     }
1541   }
1542   close(pipefds[0]);
1543   close(pipefds[1]);
1544 }
1545 
1546 #endif  // defined(OS_POSIX)
1547