message_loop_unittest.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 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 <vector>
6
7#include "base/eintr_wrapper.h"
8#include "base/logging.h"
9#include "base/message_loop.h"
10#include "base/platform_thread.h"
11#include "base/ref_counted.h"
12#include "base/task.h"
13#include "base/thread.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16#if defined(OS_WIN)
17#include "base/message_pump_win.h"
18#include "base/scoped_handle.h"
19#endif
20#if defined(OS_POSIX)
21#include "base/message_pump_libevent.h"
22#endif
23
24using base::Thread;
25using base::Time;
26using base::TimeDelta;
27
28// TODO(darin): Platform-specific MessageLoop tests should be grouped together
29// to avoid chopping this file up with so many #ifdefs.
30
31namespace {
32
33class MessageLoopTest : public testing::Test {};
34
35class Foo : public base::RefCounted<Foo> {
36 public:
37  Foo() : test_count_(0) {
38  }
39
40  void Test0() {
41    ++test_count_;
42  }
43
44  void Test1ConstRef(const std::string& a) {
45    ++test_count_;
46    result_.append(a);
47  }
48
49  void Test1Ptr(std::string* a) {
50    ++test_count_;
51    result_.append(*a);
52  }
53
54  void Test1Int(int a) {
55    test_count_ += a;
56  }
57
58  void Test2Ptr(std::string* a, std::string* b) {
59    ++test_count_;
60    result_.append(*a);
61    result_.append(*b);
62  }
63
64  void Test2Mixed(const std::string& a, std::string* b) {
65    ++test_count_;
66    result_.append(a);
67    result_.append(*b);
68  }
69
70  int test_count() const { return test_count_; }
71  const std::string& result() const { return result_; }
72
73 private:
74  friend class base::RefCounted<Foo>;
75
76  ~Foo() {}
77
78  int test_count_;
79  std::string result_;
80};
81
82class QuitMsgLoop : public base::RefCounted<QuitMsgLoop> {
83 public:
84  void QuitNow() {
85    MessageLoop::current()->Quit();
86  }
87
88 private:
89  friend class base::RefCounted<QuitMsgLoop>;
90
91  ~QuitMsgLoop() {}
92};
93
94void RunTest_PostTask(MessageLoop::Type message_loop_type) {
95  MessageLoop loop(message_loop_type);
96
97  // Add tests to message loop
98  scoped_refptr<Foo> foo(new Foo());
99  std::string a("a"), b("b"), c("c"), d("d");
100  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
101      foo.get(), &Foo::Test0));
102  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
103    foo.get(), &Foo::Test1ConstRef, a));
104  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
105      foo.get(), &Foo::Test1Ptr, &b));
106  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
107      foo.get(), &Foo::Test1Int, 100));
108  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
109      foo.get(), &Foo::Test2Ptr, &a, &c));
110  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
111    foo.get(), &Foo::Test2Mixed, a, &d));
112
113  // After all tests, post a message that will shut down the message loop
114  scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop());
115  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
116      quit.get(), &QuitMsgLoop::QuitNow));
117
118  // Now kick things off
119  MessageLoop::current()->Run();
120
121  EXPECT_EQ(foo->test_count(), 105);
122  EXPECT_EQ(foo->result(), "abacad");
123}
124
125void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type) {
126  MessageLoop loop(message_loop_type);
127
128  // Add tests to message loop
129  scoped_refptr<Foo> foo(new Foo());
130  std::string a("a"), b("b"), c("c"), d("d");
131  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
132      foo.get(), &Foo::Test0));
133  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
134      foo.get(), &Foo::Test1ConstRef, a));
135  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
136      foo.get(), &Foo::Test1Ptr, &b));
137  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
138      foo.get(), &Foo::Test1Int, 100));
139  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
140      foo.get(), &Foo::Test2Ptr, &a, &c));
141  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
142      foo.get(), &Foo::Test2Mixed, a, &d));
143
144  // After all tests, post a message that will shut down the message loop
145  scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop());
146  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
147      quit.get(), &QuitMsgLoop::QuitNow));
148
149  // Now kick things off with the SEH block active.
150  MessageLoop::current()->set_exception_restoration(true);
151  MessageLoop::current()->Run();
152  MessageLoop::current()->set_exception_restoration(false);
153
154  EXPECT_EQ(foo->test_count(), 105);
155  EXPECT_EQ(foo->result(), "abacad");
156}
157
158// This class runs slowly to simulate a large amount of work being done.
159class SlowTask : public Task {
160 public:
161  SlowTask(int pause_ms, int* quit_counter)
162      : pause_ms_(pause_ms), quit_counter_(quit_counter) {
163  }
164  virtual void Run() {
165    PlatformThread::Sleep(pause_ms_);
166    if (--(*quit_counter_) == 0)
167      MessageLoop::current()->Quit();
168  }
169 private:
170  int pause_ms_;
171  int* quit_counter_;
172};
173
174// This class records the time when Run was called in a Time object, which is
175// useful for building a variety of MessageLoop tests.
176class RecordRunTimeTask : public SlowTask {
177 public:
178  RecordRunTimeTask(Time* run_time, int* quit_counter)
179      : SlowTask(10, quit_counter), run_time_(run_time) {
180  }
181  virtual void Run() {
182    *run_time_ = Time::Now();
183    // Cause our Run function to take some time to execute.  As a result we can
184    // count on subsequent RecordRunTimeTask objects running at a future time,
185    // without worry about the resolution of our system clock being an issue.
186    SlowTask::Run();
187  }
188 private:
189  Time* run_time_;
190};
191
192void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) {
193  MessageLoop loop(message_loop_type);
194
195  // Test that PostDelayedTask results in a delayed task.
196
197  const int kDelayMS = 100;
198
199  int num_tasks = 1;
200  Time run_time;
201
202  loop.PostDelayedTask(
203      FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), kDelayMS);
204
205  Time time_before_run = Time::Now();
206  loop.Run();
207  Time time_after_run = Time::Now();
208
209  EXPECT_EQ(0, num_tasks);
210  EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds());
211}
212
213void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type) {
214  MessageLoop loop(message_loop_type);
215
216  // Test that two tasks with different delays run in the right order.
217
218  int num_tasks = 2;
219  Time run_time1, run_time2;
220
221  loop.PostDelayedTask(
222      FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 200);
223  // If we get a large pause in execution (due to a context switch) here, this
224  // test could fail.
225  loop.PostDelayedTask(
226      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10);
227
228  loop.Run();
229  EXPECT_EQ(0, num_tasks);
230
231  EXPECT_TRUE(run_time2 < run_time1);
232}
233
234void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type) {
235  MessageLoop loop(message_loop_type);
236
237  // Test that two tasks with the same delay run in the order in which they
238  // were posted.
239  //
240  // NOTE: This is actually an approximate test since the API only takes a
241  // "delay" parameter, so we are not exactly simulating two tasks that get
242  // posted at the exact same time.  It would be nice if the API allowed us to
243  // specify the desired run time.
244
245  const int kDelayMS = 100;
246
247  int num_tasks = 2;
248  Time run_time1, run_time2;
249
250  loop.PostDelayedTask(
251      FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), kDelayMS);
252  loop.PostDelayedTask(
253      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), kDelayMS);
254
255  loop.Run();
256  EXPECT_EQ(0, num_tasks);
257
258  EXPECT_TRUE(run_time1 < run_time2);
259}
260
261void RunTest_PostDelayedTask_InPostOrder_2(
262    MessageLoop::Type message_loop_type) {
263  MessageLoop loop(message_loop_type);
264
265  // Test that a delayed task still runs after a normal tasks even if the
266  // normal tasks take a long time to run.
267
268  const int kPauseMS = 50;
269
270  int num_tasks = 2;
271  Time run_time;
272
273  loop.PostTask(
274      FROM_HERE, new SlowTask(kPauseMS, &num_tasks));
275  loop.PostDelayedTask(
276      FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 10);
277
278  Time time_before_run = Time::Now();
279  loop.Run();
280  Time time_after_run = Time::Now();
281
282  EXPECT_EQ(0, num_tasks);
283
284  EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds());
285}
286
287void RunTest_PostDelayedTask_InPostOrder_3(
288    MessageLoop::Type message_loop_type) {
289  MessageLoop loop(message_loop_type);
290
291  // Test that a delayed task still runs after a pile of normal tasks.  The key
292  // difference between this test and the previous one is that here we return
293  // the MessageLoop a lot so we give the MessageLoop plenty of opportunities
294  // to maybe run the delayed task.  It should know not to do so until the
295  // delayed task's delay has passed.
296
297  int num_tasks = 11;
298  Time run_time1, run_time2;
299
300  // Clutter the ML with tasks.
301  for (int i = 1; i < num_tasks; ++i)
302    loop.PostTask(FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks));
303
304  loop.PostDelayedTask(
305      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 1);
306
307  loop.Run();
308  EXPECT_EQ(0, num_tasks);
309
310  EXPECT_TRUE(run_time2 > run_time1);
311}
312
313void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type) {
314  MessageLoop loop(message_loop_type);
315
316  // Test that the interval of the timer, used to run the next delayed task, is
317  // set to a value corresponding to when the next delayed task should run.
318
319  // By setting num_tasks to 1, we ensure that the first task to run causes the
320  // run loop to exit.
321  int num_tasks = 1;
322  Time run_time1, run_time2;
323
324  loop.PostDelayedTask(
325      FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 1000000);
326  loop.PostDelayedTask(
327      FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10);
328
329  Time start_time = Time::Now();
330
331  loop.Run();
332  EXPECT_EQ(0, num_tasks);
333
334  // Ensure that we ran in far less time than the slower timer.
335  TimeDelta total_time = Time::Now() - start_time;
336  EXPECT_GT(5000, total_time.InMilliseconds());
337
338  // In case both timers somehow run at nearly the same time, sleep a little
339  // and then run all pending to force them both to have run.  This is just
340  // encouraging flakiness if there is any.
341  PlatformThread::Sleep(100);
342  loop.RunAllPending();
343
344  EXPECT_TRUE(run_time1.is_null());
345  EXPECT_FALSE(run_time2.is_null());
346}
347
348#if defined(OS_WIN)
349
350class SubPumpTask : public Task {
351 public:
352  virtual void Run() {
353    MessageLoop::current()->SetNestableTasksAllowed(true);
354    MSG msg;
355    while (GetMessage(&msg, NULL, 0, 0)) {
356      TranslateMessage(&msg);
357      DispatchMessage(&msg);
358    }
359    MessageLoop::current()->Quit();
360  }
361};
362
363class SubPumpQuitTask : public Task {
364 public:
365  SubPumpQuitTask() {
366  }
367  virtual void Run() {
368    PostQuitMessage(0);
369  }
370};
371
372void RunTest_PostDelayedTask_SharedTimer_SubPump() {
373  MessageLoop loop(MessageLoop::TYPE_UI);
374
375  // Test that the interval of the timer, used to run the next delayed task, is
376  // set to a value corresponding to when the next delayed task should run.
377
378  // By setting num_tasks to 1, we ensure that the first task to run causes the
379  // run loop to exit.
380  int num_tasks = 1;
381  Time run_time;
382
383  loop.PostTask(FROM_HERE, new SubPumpTask());
384
385  // This very delayed task should never run.
386  loop.PostDelayedTask(
387      FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 1000000);
388
389  // This slightly delayed task should run from within SubPumpTask::Run().
390  loop.PostDelayedTask(
391      FROM_HERE, new SubPumpQuitTask(), 10);
392
393  Time start_time = Time::Now();
394
395  loop.Run();
396  EXPECT_EQ(1, num_tasks);
397
398  // Ensure that we ran in far less time than the slower timer.
399  TimeDelta total_time = Time::Now() - start_time;
400  EXPECT_GT(5000, total_time.InMilliseconds());
401
402  // In case both timers somehow run at nearly the same time, sleep a little
403  // and then run all pending to force them both to have run.  This is just
404  // encouraging flakiness if there is any.
405  PlatformThread::Sleep(100);
406  loop.RunAllPending();
407
408  EXPECT_TRUE(run_time.is_null());
409}
410
411#endif  // defined(OS_WIN)
412
413class RecordDeletionTask : public Task {
414 public:
415  RecordDeletionTask(Task* post_on_delete, bool* was_deleted)
416      : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {
417  }
418  ~RecordDeletionTask() {
419    *was_deleted_ = true;
420    if (post_on_delete_)
421      MessageLoop::current()->PostTask(FROM_HERE, post_on_delete_);
422  }
423  virtual void Run() {}
424 private:
425  Task* post_on_delete_;
426  bool* was_deleted_;
427};
428
429void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type) {
430  bool a_was_deleted = false;
431  bool b_was_deleted = false;
432  {
433    MessageLoop loop(message_loop_type);
434    loop.PostTask(
435        FROM_HERE, new RecordDeletionTask(NULL, &a_was_deleted));
436    loop.PostDelayedTask(
437        FROM_HERE, new RecordDeletionTask(NULL, &b_was_deleted), 1000);
438  }
439  EXPECT_TRUE(a_was_deleted);
440  EXPECT_TRUE(b_was_deleted);
441}
442
443void RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type) {
444  bool a_was_deleted = false;
445  bool b_was_deleted = false;
446  bool c_was_deleted = false;
447  {
448    MessageLoop loop(message_loop_type);
449    RecordDeletionTask* a = new RecordDeletionTask(NULL, &a_was_deleted);
450    RecordDeletionTask* b = new RecordDeletionTask(a, &b_was_deleted);
451    RecordDeletionTask* c = new RecordDeletionTask(b, &c_was_deleted);
452    loop.PostTask(FROM_HERE, c);
453  }
454  EXPECT_TRUE(a_was_deleted);
455  EXPECT_TRUE(b_was_deleted);
456  EXPECT_TRUE(c_was_deleted);
457}
458
459class NestingTest : public Task {
460 public:
461  explicit NestingTest(int* depth) : depth_(depth) {
462  }
463  void Run() {
464    if (*depth_ > 0) {
465      *depth_ -= 1;
466      MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(depth_));
467
468      MessageLoop::current()->SetNestableTasksAllowed(true);
469      MessageLoop::current()->Run();
470    }
471    MessageLoop::current()->Quit();
472  }
473 private:
474  int* depth_;
475};
476
477#if defined(OS_WIN)
478
479LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) {
480  ADD_FAILURE() << "bad exception handler";
481  ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode);
482  return EXCEPTION_EXECUTE_HANDLER;
483}
484
485// This task throws an SEH exception: initially write to an invalid address.
486// If the right SEH filter is installed, it will fix the error.
487class CrasherTask : public Task {
488 public:
489  // Ctor. If trash_SEH_handler is true, the task will override the unhandled
490  // exception handler with one sure to crash this test.
491  explicit CrasherTask(bool trash_SEH_handler)
492      : trash_SEH_handler_(trash_SEH_handler) {
493  }
494  void Run() {
495    PlatformThread::Sleep(1);
496    if (trash_SEH_handler_)
497      ::SetUnhandledExceptionFilter(&BadExceptionHandler);
498    // Generate a SEH fault. We do it in asm to make sure we know how to undo
499    // the damage.
500
501#if defined(_M_IX86)
502
503    __asm {
504      mov eax, dword ptr [CrasherTask::bad_array_]
505      mov byte ptr [eax], 66
506    }
507
508#elif defined(_M_X64)
509
510    bad_array_[0] = 66;
511
512#else
513#error "needs architecture support"
514#endif
515
516    MessageLoop::current()->Quit();
517  }
518  // Points the bad array to a valid memory location.
519  static void FixError() {
520    bad_array_ = &valid_store_;
521  }
522
523 private:
524  bool trash_SEH_handler_;
525  static volatile char* bad_array_;
526  static char valid_store_;
527};
528
529volatile char* CrasherTask::bad_array_ = 0;
530char CrasherTask::valid_store_ = 0;
531
532// This SEH filter fixes the problem and retries execution. Fixing requires
533// that the last instruction: mov eax, [CrasherTask::bad_array_] to be retried
534// so we move the instruction pointer 5 bytes back.
535LONG WINAPI HandleCrasherTaskException(EXCEPTION_POINTERS *ex_info) {
536  if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
537    return EXCEPTION_EXECUTE_HANDLER;
538
539  CrasherTask::FixError();
540
541#if defined(_M_IX86)
542
543  ex_info->ContextRecord->Eip -= 5;
544
545#elif defined(_M_X64)
546
547  ex_info->ContextRecord->Rip -= 5;
548
549#endif
550
551  return EXCEPTION_CONTINUE_EXECUTION;
552}
553
554void RunTest_Crasher(MessageLoop::Type message_loop_type) {
555  MessageLoop loop(message_loop_type);
556
557  if (::IsDebuggerPresent())
558    return;
559
560  LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
561      ::SetUnhandledExceptionFilter(&HandleCrasherTaskException);
562
563  MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(false));
564  MessageLoop::current()->set_exception_restoration(true);
565  MessageLoop::current()->Run();
566  MessageLoop::current()->set_exception_restoration(false);
567
568  ::SetUnhandledExceptionFilter(old_SEH_filter);
569}
570
571void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) {
572  MessageLoop loop(message_loop_type);
573
574  if (::IsDebuggerPresent())
575    return;
576
577  LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
578      ::SetUnhandledExceptionFilter(&HandleCrasherTaskException);
579
580  MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(true));
581  MessageLoop::current()->set_exception_restoration(true);
582  MessageLoop::current()->Run();
583  MessageLoop::current()->set_exception_restoration(false);
584
585  ::SetUnhandledExceptionFilter(old_SEH_filter);
586}
587
588#endif  // defined(OS_WIN)
589
590void RunTest_Nesting(MessageLoop::Type message_loop_type) {
591  MessageLoop loop(message_loop_type);
592
593  int depth = 100;
594  MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(&depth));
595  MessageLoop::current()->Run();
596  EXPECT_EQ(depth, 0);
597}
598
599const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test";
600
601enum TaskType {
602  MESSAGEBOX,
603  ENDDIALOG,
604  RECURSIVE,
605  TIMEDMESSAGELOOP,
606  QUITMESSAGELOOP,
607  ORDERERD,
608  PUMPS,
609  SLEEP,
610};
611
612// Saves the order in which the tasks executed.
613struct TaskItem {
614  TaskItem(TaskType t, int c, bool s)
615      : type(t),
616        cookie(c),
617        start(s) {
618  }
619
620  TaskType type;
621  int cookie;
622  bool start;
623
624  bool operator == (const TaskItem& other) const {
625    return type == other.type && cookie == other.cookie && start == other.start;
626  }
627};
628
629typedef std::vector<TaskItem> TaskList;
630
631std::ostream& operator <<(std::ostream& os, TaskType type) {
632  switch (type) {
633  case MESSAGEBOX:        os << "MESSAGEBOX"; break;
634  case ENDDIALOG:         os << "ENDDIALOG"; break;
635  case RECURSIVE:         os << "RECURSIVE"; break;
636  case TIMEDMESSAGELOOP:  os << "TIMEDMESSAGELOOP"; break;
637  case QUITMESSAGELOOP:   os << "QUITMESSAGELOOP"; break;
638  case ORDERERD:          os << "ORDERERD"; break;
639  case PUMPS:             os << "PUMPS"; break;
640  case SLEEP:             os << "SLEEP"; break;
641  default:
642    NOTREACHED();
643    os << "Unknown TaskType";
644    break;
645  }
646  return os;
647}
648
649std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
650  if (item.start)
651    return os << item.type << " " << item.cookie << " starts";
652  else
653    return os << item.type << " " << item.cookie << " ends";
654}
655
656// Saves the order the tasks ran.
657class OrderedTasks : public Task {
658 public:
659  OrderedTasks(TaskList* order, int cookie)
660      : order_(order),
661        type_(ORDERERD),
662        cookie_(cookie) {
663  }
664  OrderedTasks(TaskList* order, TaskType type, int cookie)
665      : order_(order),
666        type_(type),
667        cookie_(cookie) {
668  }
669
670  void RunStart() {
671    TaskItem item(type_, cookie_, true);
672    DVLOG(1) << item;
673    order_->push_back(item);
674  }
675  void RunEnd() {
676    TaskItem item(type_, cookie_, false);
677    DVLOG(1) << item;
678    order_->push_back(item);
679  }
680
681  virtual void Run() {
682    RunStart();
683    RunEnd();
684  }
685
686 protected:
687  TaskList* order() const {
688    return order_;
689  }
690
691  int cookie() const {
692    return cookie_;
693  }
694
695 private:
696  TaskList* order_;
697  TaskType type_;
698  int cookie_;
699};
700
701#if defined(OS_WIN)
702
703// MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
704// common controls (like OpenFile) and StartDoc printing function can cause
705// implicit message loops.
706class MessageBoxTask : public OrderedTasks {
707 public:
708  MessageBoxTask(TaskList* order, int cookie, bool is_reentrant)
709      : OrderedTasks(order, MESSAGEBOX, cookie),
710        is_reentrant_(is_reentrant) {
711  }
712
713  virtual void Run() {
714    RunStart();
715    if (is_reentrant_)
716      MessageLoop::current()->SetNestableTasksAllowed(true);
717    MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
718    RunEnd();
719  }
720
721 private:
722  bool is_reentrant_;
723};
724
725// Will end the MessageBox.
726class EndDialogTask : public OrderedTasks {
727 public:
728  EndDialogTask(TaskList* order, int cookie)
729      : OrderedTasks(order, ENDDIALOG, cookie) {
730  }
731
732  virtual void Run() {
733    RunStart();
734    HWND window = GetActiveWindow();
735    if (window != NULL) {
736      EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
737      // Cheap way to signal that the window wasn't found if RunEnd() isn't
738      // called.
739      RunEnd();
740    }
741  }
742};
743
744#endif  // defined(OS_WIN)
745
746class RecursiveTask : public OrderedTasks {
747 public:
748  RecursiveTask(int depth, TaskList* order, int cookie, bool is_reentrant)
749      : OrderedTasks(order, RECURSIVE, cookie),
750        depth_(depth),
751        is_reentrant_(is_reentrant) {
752  }
753
754  virtual void Run() {
755    RunStart();
756    if (depth_ > 0) {
757      if (is_reentrant_)
758        MessageLoop::current()->SetNestableTasksAllowed(true);
759      MessageLoop::current()->PostTask(FROM_HERE,
760          new RecursiveTask(depth_ - 1, order(), cookie(), is_reentrant_));
761    }
762    RunEnd();
763  }
764
765 private:
766  int depth_;
767  bool is_reentrant_;
768};
769
770class QuitTask : public OrderedTasks {
771 public:
772  QuitTask(TaskList* order, int cookie)
773      : OrderedTasks(order, QUITMESSAGELOOP, cookie) {
774  }
775
776  virtual void Run() {
777    RunStart();
778    MessageLoop::current()->Quit();
779    RunEnd();
780  }
781};
782
783class SleepTask : public OrderedTasks {
784 public:
785  SleepTask(TaskList* order, int cookie, int ms)
786      : OrderedTasks(order, SLEEP, cookie), ms_(ms) {
787  }
788
789  virtual void Run() {
790    RunStart();
791    PlatformThread::Sleep(ms_);
792    RunEnd();
793  }
794
795 private:
796  int ms_;
797};
798
799#if defined(OS_WIN)
800
801class Recursive2Tasks : public Task {
802 public:
803  Recursive2Tasks(MessageLoop* target,
804                  HANDLE event,
805                  bool expect_window,
806                  TaskList* order,
807                  bool is_reentrant)
808      : target_(target),
809        event_(event),
810        expect_window_(expect_window),
811        order_(order),
812        is_reentrant_(is_reentrant) {
813  }
814
815  virtual void Run() {
816    target_->PostTask(FROM_HERE,
817                      new RecursiveTask(2, order_, 1, is_reentrant_));
818    target_->PostTask(FROM_HERE,
819                      new MessageBoxTask(order_, 2, is_reentrant_));
820    target_->PostTask(FROM_HERE,
821                      new RecursiveTask(2, order_, 3, is_reentrant_));
822    // The trick here is that for recursive task processing, this task will be
823    // ran _inside_ the MessageBox message loop, dismissing the MessageBox
824    // without a chance.
825    // For non-recursive task processing, this will be executed _after_ the
826    // MessageBox will have been dismissed by the code below, where
827    // expect_window_ is true.
828    target_->PostTask(FROM_HERE, new EndDialogTask(order_, 4));
829    target_->PostTask(FROM_HERE, new QuitTask(order_, 5));
830
831    // Enforce that every tasks are sent before starting to run the main thread
832    // message loop.
833    ASSERT_TRUE(SetEvent(event_));
834
835    // Poll for the MessageBox. Don't do this at home! At the speed we do it,
836    // you will never realize one MessageBox was shown.
837    for (; expect_window_;) {
838      HWND window = FindWindow(L"#32770", kMessageBoxTitle);
839      if (window) {
840        // Dismiss it.
841        for (;;) {
842          HWND button = FindWindowEx(window, NULL, L"Button", NULL);
843          if (button != NULL) {
844            EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
845            EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
846            break;
847          }
848        }
849        break;
850      }
851    }
852  }
853
854 private:
855  MessageLoop* target_;
856  HANDLE event_;
857  TaskList* order_;
858  bool expect_window_;
859  bool is_reentrant_;
860};
861
862#endif  // defined(OS_WIN)
863
864void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) {
865  MessageLoop loop(message_loop_type);
866
867  EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
868  TaskList order;
869  MessageLoop::current()->PostTask(FROM_HERE,
870                                   new RecursiveTask(2, &order, 1, false));
871  MessageLoop::current()->PostTask(FROM_HERE,
872                                   new RecursiveTask(2, &order, 2, false));
873  MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3));
874
875  MessageLoop::current()->Run();
876
877  // FIFO order.
878  ASSERT_EQ(14U, order.size());
879  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
880  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
881  EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true));
882  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false));
883  EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true));
884  EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false));
885  EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true));
886  EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false));
887  EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true));
888  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false));
889  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
890  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
891  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true));
892  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false));
893}
894
895void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) {
896  MessageLoop loop(message_loop_type);
897
898  TaskList order;
899  MessageLoop::current()->PostTask(FROM_HERE,
900                                   new RecursiveTask(2, &order, 1, true));
901  MessageLoop::current()->PostTask(FROM_HERE,
902                                   new RecursiveTask(2, &order, 2, true));
903  MessageLoop::current()->PostTask(FROM_HERE,
904                                   new QuitTask(&order, 3));
905
906  MessageLoop::current()->Run();
907
908  // FIFO order.
909  ASSERT_EQ(14U, order.size());
910  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
911  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
912  EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true));
913  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false));
914  EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true));
915  EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false));
916  EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true));
917  EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false));
918  EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true));
919  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false));
920  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
921  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
922  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true));
923  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false));
924}
925
926#if defined(OS_WIN)
927// TODO(darin): These tests need to be ported since they test critical
928// message loop functionality.
929
930// A side effect of this test is the generation a beep. Sorry.
931void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
932  MessageLoop loop(message_loop_type);
933
934  Thread worker("RecursiveDenial2_worker");
935  Thread::Options options;
936  options.message_loop_type = message_loop_type;
937  ASSERT_EQ(true, worker.StartWithOptions(options));
938  TaskList order;
939  ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
940  worker.message_loop()->PostTask(FROM_HERE,
941                                  new Recursive2Tasks(MessageLoop::current(),
942                                                      event,
943                                                      true,
944                                                      &order,
945                                                      false));
946  // Let the other thread execute.
947  WaitForSingleObject(event, INFINITE);
948  MessageLoop::current()->Run();
949
950  ASSERT_EQ(order.size(), 17);
951  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
952  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
953  EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true));
954  EXPECT_EQ(order[ 3], TaskItem(MESSAGEBOX, 2, false));
955  EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, true));
956  EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 3, false));
957  // When EndDialogTask is processed, the window is already dismissed, hence no
958  // "end" entry.
959  EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, true));
960  EXPECT_EQ(order[ 7], TaskItem(QUITMESSAGELOOP, 5, true));
961  EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, false));
962  EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 1, true));
963  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, false));
964  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 3, true));
965  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, false));
966  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, true));
967  EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, false));
968  EXPECT_EQ(order[15], TaskItem(RECURSIVE, 3, true));
969  EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, false));
970}
971
972// A side effect of this test is the generation a beep. Sorry.  This test also
973// needs to process windows messages on the current thread.
974void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
975  MessageLoop loop(message_loop_type);
976
977  Thread worker("RecursiveSupport2_worker");
978  Thread::Options options;
979  options.message_loop_type = message_loop_type;
980  ASSERT_EQ(true, worker.StartWithOptions(options));
981  TaskList order;
982  ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
983  worker.message_loop()->PostTask(FROM_HERE,
984                                  new Recursive2Tasks(MessageLoop::current(),
985                                                      event,
986                                                      false,
987                                                      &order,
988                                                      true));
989  // Let the other thread execute.
990  WaitForSingleObject(event, INFINITE);
991  MessageLoop::current()->Run();
992
993  ASSERT_EQ(order.size(), 18);
994  EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true));
995  EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false));
996  EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true));
997  // Note that this executes in the MessageBox modal loop.
998  EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 3, true));
999  EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, false));
1000  EXPECT_EQ(order[ 5], TaskItem(ENDDIALOG, 4, true));
1001  EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, false));
1002  EXPECT_EQ(order[ 7], TaskItem(MESSAGEBOX, 2, false));
1003  /* The order can subtly change here. The reason is that when RecursiveTask(1)
1004     is called in the main thread, if it is faster than getting to the
1005     PostTask(FROM_HERE, QuitTask) execution, the order of task execution can
1006     change. We don't care anyway that the order isn't correct.
1007  EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true));
1008  EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false));
1009  EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true));
1010  EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false));
1011  */
1012  EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, true));
1013  EXPECT_EQ(order[13], TaskItem(RECURSIVE, 3, false));
1014  EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, true));
1015  EXPECT_EQ(order[15], TaskItem(RECURSIVE, 1, false));
1016  EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, true));
1017  EXPECT_EQ(order[17], TaskItem(RECURSIVE, 3, false));
1018}
1019
1020#endif  // defined(OS_WIN)
1021
1022class TaskThatPumps : public OrderedTasks {
1023 public:
1024  TaskThatPumps(TaskList* order, int cookie)
1025      : OrderedTasks(order, PUMPS, cookie) {
1026  }
1027
1028  virtual void Run() {
1029    RunStart();
1030    bool old_state = MessageLoop::current()->NestableTasksAllowed();
1031    MessageLoop::current()->SetNestableTasksAllowed(true);
1032    MessageLoop::current()->RunAllPending();
1033    MessageLoop::current()->SetNestableTasksAllowed(old_state);
1034    RunEnd();
1035  }
1036};
1037
1038// Tests that non nestable tasks run in FIFO if there are no nested loops.
1039void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) {
1040  MessageLoop loop(message_loop_type);
1041
1042  TaskList order;
1043
1044  Task* task = new OrderedTasks(&order, 1);
1045  MessageLoop::current()->PostNonNestableTask(FROM_HERE, task);
1046  MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 2));
1047  MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3));
1048  MessageLoop::current()->Run();
1049
1050  // FIFO order.
1051  ASSERT_EQ(6U, order.size());
1052  EXPECT_EQ(order[ 0], TaskItem(ORDERERD, 1, true));
1053  EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 1, false));
1054  EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 2, true));
1055  EXPECT_EQ(order[ 3], TaskItem(ORDERERD, 2, false));
1056  EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true));
1057  EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false));
1058}
1059
1060// Tests that non nestable tasks don't run when there's code in the call stack.
1061void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type,
1062                                     bool use_delayed) {
1063  MessageLoop loop(message_loop_type);
1064
1065  TaskList order;
1066
1067  MessageLoop::current()->PostTask(FROM_HERE,
1068                                   new TaskThatPumps(&order, 1));
1069  Task* task = new OrderedTasks(&order, 2);
1070  if (use_delayed) {
1071    MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1);
1072  } else {
1073    MessageLoop::current()->PostNonNestableTask(FROM_HERE, task);
1074  }
1075  MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 3));
1076  MessageLoop::current()->PostTask(FROM_HERE, new SleepTask(&order, 4, 50));
1077  MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 5));
1078  Task* non_nestable_quit = new QuitTask(&order, 6);
1079  if (use_delayed) {
1080    MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE,
1081                                                       non_nestable_quit,
1082                                                       2);
1083  } else {
1084    MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit);
1085  }
1086
1087  MessageLoop::current()->Run();
1088
1089  // FIFO order.
1090  ASSERT_EQ(12U, order.size());
1091  EXPECT_EQ(order[ 0], TaskItem(PUMPS, 1, true));
1092  EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 3, true));
1093  EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 3, false));
1094  EXPECT_EQ(order[ 3], TaskItem(SLEEP, 4, true));
1095  EXPECT_EQ(order[ 4], TaskItem(SLEEP, 4, false));
1096  EXPECT_EQ(order[ 5], TaskItem(ORDERERD, 5, true));
1097  EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 5, false));
1098  EXPECT_EQ(order[ 7], TaskItem(PUMPS, 1, false));
1099  EXPECT_EQ(order[ 8], TaskItem(ORDERERD, 2, true));
1100  EXPECT_EQ(order[ 9], TaskItem(ORDERERD, 2, false));
1101  EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 6, true));
1102  EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 6, false));
1103}
1104
1105#if defined(OS_WIN)
1106
1107class DispatcherImpl : public MessageLoopForUI::Dispatcher {
1108 public:
1109  DispatcherImpl() : dispatch_count_(0) {}
1110
1111  virtual bool Dispatch(const MSG& msg) {
1112    ::TranslateMessage(&msg);
1113    ::DispatchMessage(&msg);
1114    // Do not count WM_TIMER since it is not what we post and it will cause
1115    // flakiness.
1116    if (msg.message != WM_TIMER)
1117      ++dispatch_count_;
1118    // We treat WM_LBUTTONUP as the last message.
1119    return msg.message != WM_LBUTTONUP;
1120  }
1121
1122  int dispatch_count_;
1123};
1124
1125void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
1126  MessageLoop loop(message_loop_type);
1127
1128  class MyTask : public Task {
1129  public:
1130    virtual void Run() {
1131      PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1132      PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1133    }
1134  };
1135  Task* task = new MyTask();
1136  MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
1137  DispatcherImpl dispatcher;
1138  MessageLoopForUI::current()->Run(&dispatcher);
1139  ASSERT_EQ(2, dispatcher.dispatch_count_);
1140}
1141
1142LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) {
1143  if (code == base::MessagePumpForUI::kMessageFilterCode) {
1144    MSG* msg = reinterpret_cast<MSG*>(lparam);
1145    if (msg->message == WM_LBUTTONDOWN)
1146      return TRUE;
1147  }
1148  return FALSE;
1149}
1150
1151void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
1152  MessageLoop loop(message_loop_type);
1153
1154  class MyTask : public Task {
1155  public:
1156    virtual void Run() {
1157      PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1158      PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1159    }
1160  };
1161  Task* task = new MyTask();
1162  MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
1163  HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
1164                                    MsgFilterProc,
1165                                    NULL,
1166                                    GetCurrentThreadId());
1167  DispatcherImpl dispatcher;
1168  MessageLoopForUI::current()->Run(&dispatcher);
1169  ASSERT_EQ(1, dispatcher.dispatch_count_);
1170  UnhookWindowsHookEx(msg_hook);
1171}
1172
1173class TestIOHandler : public MessageLoopForIO::IOHandler {
1174 public:
1175  TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
1176
1177  virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
1178                             DWORD bytes_transfered, DWORD error);
1179
1180  void Init();
1181  void WaitForIO();
1182  OVERLAPPED* context() { return &context_.overlapped; }
1183  DWORD size() { return sizeof(buffer_); }
1184
1185 private:
1186  char buffer_[48];
1187  MessageLoopForIO::IOContext context_;
1188  HANDLE signal_;
1189  ScopedHandle file_;
1190  bool wait_;
1191};
1192
1193TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
1194    : signal_(signal), wait_(wait) {
1195  memset(buffer_, 0, sizeof(buffer_));
1196  memset(&context_, 0, sizeof(context_));
1197  context_.handler = this;
1198
1199  file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1200                       FILE_FLAG_OVERLAPPED, NULL));
1201  EXPECT_TRUE(file_.IsValid());
1202}
1203
1204void TestIOHandler::Init() {
1205  MessageLoopForIO::current()->RegisterIOHandler(file_, this);
1206
1207  DWORD read;
1208  EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context()));
1209  EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
1210  if (wait_)
1211    WaitForIO();
1212}
1213
1214void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
1215                                  DWORD bytes_transfered, DWORD error) {
1216  ASSERT_TRUE(context == &context_);
1217  ASSERT_TRUE(SetEvent(signal_));
1218}
1219
1220void TestIOHandler::WaitForIO() {
1221  EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
1222  EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
1223}
1224
1225class IOHandlerTask : public Task {
1226 public:
1227  explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {}
1228  virtual void Run() {
1229    handler_->Init();
1230  }
1231
1232 private:
1233  TestIOHandler* handler_;
1234};
1235
1236void RunTest_IOHandler() {
1237  ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1238  ASSERT_TRUE(callback_called.IsValid());
1239
1240  const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
1241  ScopedHandle server(CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1,
1242                                      0, 0, 0, NULL));
1243  ASSERT_TRUE(server.IsValid());
1244
1245  Thread thread("IOHandler test");
1246  Thread::Options options;
1247  options.message_loop_type = MessageLoop::TYPE_IO;
1248  ASSERT_TRUE(thread.StartWithOptions(options));
1249
1250  MessageLoop* thread_loop = thread.message_loop();
1251  ASSERT_TRUE(NULL != thread_loop);
1252
1253  TestIOHandler handler(kPipeName, callback_called, false);
1254  IOHandlerTask* task = new IOHandlerTask(&handler);
1255  thread_loop->PostTask(FROM_HERE, task);
1256  Sleep(100);  // Make sure the thread runs and sleeps for lack of work.
1257
1258  const char buffer[] = "Hello there!";
1259  DWORD written;
1260  EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL));
1261
1262  DWORD result = WaitForSingleObject(callback_called, 1000);
1263  EXPECT_EQ(WAIT_OBJECT_0, result);
1264
1265  thread.Stop();
1266}
1267
1268void RunTest_WaitForIO() {
1269  ScopedHandle callback1_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1270  ScopedHandle callback2_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1271  ASSERT_TRUE(callback1_called.IsValid());
1272  ASSERT_TRUE(callback2_called.IsValid());
1273
1274  const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
1275  const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
1276  ScopedHandle server1(CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1,
1277                                       0, 0, 0, NULL));
1278  ScopedHandle server2(CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1,
1279                                       0, 0, 0, NULL));
1280  ASSERT_TRUE(server1.IsValid());
1281  ASSERT_TRUE(server2.IsValid());
1282
1283  Thread thread("IOHandler test");
1284  Thread::Options options;
1285  options.message_loop_type = MessageLoop::TYPE_IO;
1286  ASSERT_TRUE(thread.StartWithOptions(options));
1287
1288  MessageLoop* thread_loop = thread.message_loop();
1289  ASSERT_TRUE(NULL != thread_loop);
1290
1291  TestIOHandler handler1(kPipeName1, callback1_called, false);
1292  TestIOHandler handler2(kPipeName2, callback2_called, true);
1293  IOHandlerTask* task1 = new IOHandlerTask(&handler1);
1294  IOHandlerTask* task2 = new IOHandlerTask(&handler2);
1295  thread_loop->PostTask(FROM_HERE, task1);
1296  Sleep(100);  // Make sure the thread runs and sleeps for lack of work.
1297  thread_loop->PostTask(FROM_HERE, task2);
1298  Sleep(100);
1299
1300  // At this time handler1 is waiting to be called, and the thread is waiting
1301  // on the Init method of handler2, filtering only handler2 callbacks.
1302
1303  const char buffer[] = "Hello there!";
1304  DWORD written;
1305  EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL));
1306  Sleep(200);
1307  EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) <<
1308      "handler1 has not been called";
1309
1310  EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL));
1311
1312  HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
1313  DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
1314  EXPECT_EQ(WAIT_OBJECT_0, result);
1315
1316  thread.Stop();
1317}
1318
1319#endif  // defined(OS_WIN)
1320
1321}  // namespace
1322
1323//-----------------------------------------------------------------------------
1324// Each test is run against each type of MessageLoop.  That way we are sure
1325// that message loops work properly in all configurations.  Of course, in some
1326// cases, a unit test may only be for a particular type of loop.
1327
1328TEST(MessageLoopTest, PostTask) {
1329  RunTest_PostTask(MessageLoop::TYPE_DEFAULT);
1330  RunTest_PostTask(MessageLoop::TYPE_UI);
1331  RunTest_PostTask(MessageLoop::TYPE_IO);
1332}
1333
1334TEST(MessageLoopTest, PostTask_SEH) {
1335  RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT);
1336  RunTest_PostTask_SEH(MessageLoop::TYPE_UI);
1337  RunTest_PostTask_SEH(MessageLoop::TYPE_IO);
1338}
1339
1340TEST(MessageLoopTest, PostDelayedTask_Basic) {
1341  RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_DEFAULT);
1342  RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_UI);
1343  RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_IO);
1344}
1345
1346TEST(MessageLoopTest, PostDelayedTask_InDelayOrder) {
1347  RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_DEFAULT);
1348  RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_UI);
1349  RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_IO);
1350}
1351
1352TEST(MessageLoopTest, PostDelayedTask_InPostOrder) {
1353  RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_DEFAULT);
1354  RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_UI);
1355  RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_IO);
1356}
1357
1358TEST(MessageLoopTest, PostDelayedTask_InPostOrder_2) {
1359  RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_DEFAULT);
1360  RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_UI);
1361  RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_IO);
1362}
1363
1364TEST(MessageLoopTest, PostDelayedTask_InPostOrder_3) {
1365  RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_DEFAULT);
1366  RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_UI);
1367  RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_IO);
1368}
1369
1370TEST(MessageLoopTest, PostDelayedTask_SharedTimer) {
1371  RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_DEFAULT);
1372  RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_UI);
1373  RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_IO);
1374}
1375
1376#if defined(OS_WIN)
1377TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
1378  RunTest_PostDelayedTask_SharedTimer_SubPump();
1379}
1380#endif
1381
1382// TODO(darin): MessageLoop does not support deleting all tasks in the
1383// destructor.
1384// Fails, http://crbug.com/50272.
1385TEST(MessageLoopTest, FAILS_EnsureTaskDeletion) {
1386  RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT);
1387  RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI);
1388  RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO);
1389}
1390
1391// TODO(darin): MessageLoop does not support deleting all tasks in the
1392// destructor.
1393// Fails, http://crbug.com/50272.
1394TEST(MessageLoopTest, FAILS_EnsureTaskDeletion_Chain) {
1395  RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT);
1396  RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI);
1397  RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO);
1398}
1399
1400#if defined(OS_WIN)
1401TEST(MessageLoopTest, Crasher) {
1402  RunTest_Crasher(MessageLoop::TYPE_DEFAULT);
1403  RunTest_Crasher(MessageLoop::TYPE_UI);
1404  RunTest_Crasher(MessageLoop::TYPE_IO);
1405}
1406
1407TEST(MessageLoopTest, CrasherNasty) {
1408  RunTest_CrasherNasty(MessageLoop::TYPE_DEFAULT);
1409  RunTest_CrasherNasty(MessageLoop::TYPE_UI);
1410  RunTest_CrasherNasty(MessageLoop::TYPE_IO);
1411}
1412#endif  // defined(OS_WIN)
1413
1414TEST(MessageLoopTest, Nesting) {
1415  RunTest_Nesting(MessageLoop::TYPE_DEFAULT);
1416  RunTest_Nesting(MessageLoop::TYPE_UI);
1417  RunTest_Nesting(MessageLoop::TYPE_IO);
1418}
1419
1420TEST(MessageLoopTest, RecursiveDenial1) {
1421  RunTest_RecursiveDenial1(MessageLoop::TYPE_DEFAULT);
1422  RunTest_RecursiveDenial1(MessageLoop::TYPE_UI);
1423  RunTest_RecursiveDenial1(MessageLoop::TYPE_IO);
1424}
1425
1426TEST(MessageLoopTest, RecursiveSupport1) {
1427  RunTest_RecursiveSupport1(MessageLoop::TYPE_DEFAULT);
1428  RunTest_RecursiveSupport1(MessageLoop::TYPE_UI);
1429  RunTest_RecursiveSupport1(MessageLoop::TYPE_IO);
1430}
1431
1432#if defined(OS_WIN)
1433// This test occasionally hangs http://crbug.com/44567
1434TEST(MessageLoopTest, DISABLED_RecursiveDenial2) {
1435  RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
1436  RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
1437  RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
1438}
1439
1440TEST(MessageLoopTest, RecursiveSupport2) {
1441  // This test requires a UI loop
1442  RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
1443}
1444#endif  // defined(OS_WIN)
1445
1446TEST(MessageLoopTest, NonNestableWithNoNesting) {
1447  RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_DEFAULT);
1448  RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_UI);
1449  RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO);
1450}
1451
1452TEST(MessageLoopTest, NonNestableInNestedLoop) {
1453  RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, false);
1454  RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false);
1455  RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false);
1456}
1457
1458TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) {
1459  RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true);
1460  RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true);
1461  RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true);
1462}
1463
1464class DummyTask : public Task {
1465 public:
1466  explicit DummyTask(int num_tasks) : num_tasks_(num_tasks) {}
1467
1468  virtual void Run() {
1469    if (num_tasks_ > 1) {
1470      MessageLoop::current()->PostTask(
1471          FROM_HERE,
1472          new DummyTask(num_tasks_ - 1));
1473    } else {
1474      MessageLoop::current()->Quit();
1475    }
1476  }
1477
1478 private:
1479  const int num_tasks_;
1480};
1481
1482class DummyTaskObserver : public MessageLoop::TaskObserver {
1483 public:
1484  explicit DummyTaskObserver(int num_tasks)
1485      : num_tasks_started_(0),
1486        num_tasks_processed_(0),
1487        num_tasks_(num_tasks) {}
1488
1489  virtual ~DummyTaskObserver() {}
1490
1491  virtual void WillProcessTask(const Task* task) {
1492    num_tasks_started_++;
1493    EXPECT_TRUE(task != NULL);
1494    EXPECT_LE(num_tasks_started_, num_tasks_);
1495    EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
1496  }
1497
1498  virtual void DidProcessTask(const Task* task) {
1499    num_tasks_processed_++;
1500    EXPECT_TRUE(task != NULL);
1501    EXPECT_LE(num_tasks_started_, num_tasks_);
1502    EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
1503  }
1504
1505  int num_tasks_started() const { return num_tasks_started_; }
1506  int num_tasks_processed() const { return num_tasks_processed_; }
1507
1508 private:
1509  int num_tasks_started_;
1510  int num_tasks_processed_;
1511  const int num_tasks_;
1512
1513  DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver);
1514};
1515
1516TEST(MessageLoopTest, TaskObserver) {
1517  const int kNumTasks = 6;
1518  DummyTaskObserver observer(kNumTasks);
1519
1520  MessageLoop loop;
1521  loop.AddTaskObserver(&observer);
1522  loop.PostTask(FROM_HERE, new DummyTask(kNumTasks));
1523  loop.Run();
1524  loop.RemoveTaskObserver(&observer);
1525
1526  EXPECT_EQ(kNumTasks, observer.num_tasks_started());
1527  EXPECT_EQ(kNumTasks, observer.num_tasks_processed());
1528}
1529
1530#if defined(OS_WIN)
1531TEST(MessageLoopTest, Dispatcher) {
1532  // This test requires a UI loop
1533  RunTest_Dispatcher(MessageLoop::TYPE_UI);
1534}
1535
1536TEST(MessageLoopTest, DispatcherWithMessageHook) {
1537  // This test requires a UI loop
1538  RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI);
1539}
1540
1541TEST(MessageLoopTest, IOHandler) {
1542  RunTest_IOHandler();
1543}
1544
1545TEST(MessageLoopTest, WaitForIO) {
1546  RunTest_WaitForIO();
1547}
1548
1549TEST(MessageLoopTest, HighResolutionTimer) {
1550  MessageLoop loop;
1551
1552  const int kFastTimerMs = 5;
1553  const int kSlowTimerMs = 100;
1554
1555  EXPECT_EQ(false, loop.high_resolution_timers_enabled());
1556
1557  // Post a fast task to enable the high resolution timers.
1558  loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kFastTimerMs);
1559  loop.Run();
1560  EXPECT_EQ(true, loop.high_resolution_timers_enabled());
1561
1562  // Post a slow task and verify high resolution timers
1563  // are still enabled.
1564  loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs);
1565  loop.Run();
1566  EXPECT_EQ(true, loop.high_resolution_timers_enabled());
1567
1568  // Wait for a while so that high-resolution mode elapses.
1569  Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs);
1570
1571  // Post a slow task to disable the high resolution timers.
1572  loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs);
1573  loop.Run();
1574  EXPECT_EQ(false, loop.high_resolution_timers_enabled());
1575}
1576
1577#endif  // defined(OS_WIN)
1578
1579#if defined(OS_POSIX) && !defined(OS_NACL)
1580
1581namespace {
1582
1583class QuitDelegate : public base::MessagePumpLibevent::Watcher {
1584 public:
1585  virtual void OnFileCanWriteWithoutBlocking(int fd) {
1586    MessageLoop::current()->Quit();
1587  }
1588  virtual void OnFileCanReadWithoutBlocking(int fd) {
1589    MessageLoop::current()->Quit();
1590  }
1591};
1592
1593TEST(MessageLoopTest, FileDescriptorWatcherOutlivesMessageLoop) {
1594  // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
1595  // This could happen when people use the Singleton pattern or atexit.
1596
1597  // Create a file descriptor.  Doesn't need to be readable or writable,
1598  // as we don't need to actually get any notifications.
1599  // pipe() is just the easiest way to do it.
1600  int pipefds[2];
1601  int err = pipe(pipefds);
1602  ASSERT_EQ(0, err);
1603  int fd = pipefds[1];
1604  {
1605    // Arrange for controller to live longer than message loop.
1606    base::MessagePumpLibevent::FileDescriptorWatcher controller;
1607    {
1608      MessageLoopForIO message_loop;
1609
1610      QuitDelegate delegate;
1611      message_loop.WatchFileDescriptor(fd,
1612          true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
1613      // and don't run the message loop, just destroy it.
1614    }
1615  }
1616  if (HANDLE_EINTR(close(pipefds[0])) < 0)
1617    PLOG(ERROR) << "close";
1618  if (HANDLE_EINTR(close(pipefds[1])) < 0)
1619    PLOG(ERROR) << "close";
1620}
1621
1622TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) {
1623  // Verify that it's ok to call StopWatchingFileDescriptor().
1624  // (Errors only showed up in valgrind.)
1625  int pipefds[2];
1626  int err = pipe(pipefds);
1627  ASSERT_EQ(0, err);
1628  int fd = pipefds[1];
1629  {
1630    // Arrange for message loop to live longer than controller.
1631    MessageLoopForIO message_loop;
1632    {
1633      base::MessagePumpLibevent::FileDescriptorWatcher controller;
1634
1635      QuitDelegate delegate;
1636      message_loop.WatchFileDescriptor(fd,
1637          true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
1638      controller.StopWatchingFileDescriptor();
1639    }
1640  }
1641  if (HANDLE_EINTR(close(pipefds[0])) < 0)
1642    PLOG(ERROR) << "close";
1643  if (HANDLE_EINTR(close(pipefds[1])) < 0)
1644    PLOG(ERROR) << "close";
1645}
1646
1647}  // namespace
1648
1649#endif  // defined(OS_POSIX) && !defined(OS_NACL)
1650
1651namespace {
1652class RunAtDestructionTask : public Task {
1653 public:
1654  RunAtDestructionTask(bool* task_destroyed, bool* destruction_observer_called)
1655      : task_destroyed_(task_destroyed),
1656        destruction_observer_called_(destruction_observer_called) {
1657  }
1658  ~RunAtDestructionTask() {
1659    EXPECT_FALSE(*destruction_observer_called_);
1660    *task_destroyed_ = true;
1661  }
1662  virtual void Run() {
1663    // This task should never run.
1664    ADD_FAILURE();
1665  }
1666 private:
1667  bool* task_destroyed_;
1668  bool* destruction_observer_called_;
1669};
1670
1671class MLDestructionObserver : public MessageLoop::DestructionObserver {
1672 public:
1673  MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
1674      : task_destroyed_(task_destroyed),
1675        destruction_observer_called_(destruction_observer_called),
1676        task_destroyed_before_message_loop_(false) {
1677  }
1678  virtual void WillDestroyCurrentMessageLoop() {
1679    task_destroyed_before_message_loop_ = *task_destroyed_;
1680    *destruction_observer_called_ = true;
1681  }
1682  bool task_destroyed_before_message_loop() const {
1683    return task_destroyed_before_message_loop_;
1684  }
1685 private:
1686  bool* task_destroyed_;
1687  bool* destruction_observer_called_;
1688  bool task_destroyed_before_message_loop_;
1689};
1690
1691}  // namespace
1692
1693TEST(MessageLoopTest, DestructionObserverTest) {
1694  // Verify that the destruction observer gets called at the very end (after
1695  // all the pending tasks have been destroyed).
1696  MessageLoop* loop = new MessageLoop;
1697  const int kDelayMS = 100;
1698
1699  bool task_destroyed = false;
1700  bool destruction_observer_called = false;
1701
1702  MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
1703  loop->AddDestructionObserver(&observer);
1704  loop->PostDelayedTask(
1705      FROM_HERE,
1706      new RunAtDestructionTask(&task_destroyed, &destruction_observer_called),
1707      kDelayMS);
1708  delete loop;
1709  EXPECT_TRUE(observer.task_destroyed_before_message_loop());
1710  // The task should have been destroyed when we deleted the loop.
1711  EXPECT_TRUE(task_destroyed);
1712  EXPECT_TRUE(destruction_observer_called);
1713}
1714