Home | History | Annotate | Download | only in message_loop
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <vector>
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/logging.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/message_loop/message_loop_proxy_impl.h"
     14 #include "base/message_loop/message_loop_test.h"
     15 #include "base/pending_task.h"
     16 #include "base/posix/eintr_wrapper.h"
     17 #include "base/run_loop.h"
     18 #include "base/synchronization/waitable_event.h"
     19 #include "base/thread_task_runner_handle.h"
     20 #include "base/threading/platform_thread.h"
     21 #include "base/threading/thread.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 #if defined(OS_WIN)
     25 #include "base/message_loop/message_pump_dispatcher.h"
     26 #include "base/message_loop/message_pump_win.h"
     27 #include "base/process/memory.h"
     28 #include "base/strings/string16.h"
     29 #include "base/win/scoped_handle.h"
     30 #endif
     31 
     32 namespace base {
     33 
     34 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
     35 // to avoid chopping this file up with so many #ifdefs.
     36 
     37 namespace {
     38 
     39 scoped_ptr<MessagePump> TypeDefaultMessagePumpFactory() {
     40   return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_DEFAULT);
     41 }
     42 
     43 scoped_ptr<MessagePump> TypeIOMessagePumpFactory() {
     44   return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_IO);
     45 }
     46 
     47 scoped_ptr<MessagePump> TypeUIMessagePumpFactory() {
     48   return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_UI);
     49 }
     50 
     51 class Foo : public RefCounted<Foo> {
     52  public:
     53   Foo() : test_count_(0) {
     54   }
     55 
     56   void Test1ConstRef(const std::string& a) {
     57     ++test_count_;
     58     result_.append(a);
     59   }
     60 
     61   int test_count() const { return test_count_; }
     62   const std::string& result() const { return result_; }
     63 
     64  private:
     65   friend class RefCounted<Foo>;
     66 
     67   ~Foo() {}
     68 
     69   int test_count_;
     70   std::string result_;
     71 };
     72 
     73 #if defined(OS_WIN)
     74 
     75 // This function runs slowly to simulate a large amount of work being done.
     76 static void SlowFunc(TimeDelta pause, int* quit_counter) {
     77     PlatformThread::Sleep(pause);
     78     if (--(*quit_counter) == 0)
     79       MessageLoop::current()->QuitWhenIdle();
     80 }
     81 
     82 // This function records the time when Run was called in a Time object, which is
     83 // useful for building a variety of MessageLoop tests.
     84 static void RecordRunTimeFunc(Time* run_time, int* quit_counter) {
     85   *run_time = Time::Now();
     86 
     87     // Cause our Run function to take some time to execute.  As a result we can
     88     // count on subsequent RecordRunTimeFunc()s running at a future time,
     89     // without worry about the resolution of our system clock being an issue.
     90   SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter);
     91 }
     92 
     93 void SubPumpFunc() {
     94   MessageLoop::current()->SetNestableTasksAllowed(true);
     95   MSG msg;
     96   while (GetMessage(&msg, NULL, 0, 0)) {
     97     TranslateMessage(&msg);
     98     DispatchMessage(&msg);
     99   }
    100   MessageLoop::current()->QuitWhenIdle();
    101 }
    102 
    103 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
    104   MessageLoop loop(MessageLoop::TYPE_UI);
    105 
    106   // Test that the interval of the timer, used to run the next delayed task, is
    107   // set to a value corresponding to when the next delayed task should run.
    108 
    109   // By setting num_tasks to 1, we ensure that the first task to run causes the
    110   // run loop to exit.
    111   int num_tasks = 1;
    112   Time run_time;
    113 
    114   loop.PostTask(FROM_HERE, Bind(&SubPumpFunc));
    115 
    116   // This very delayed task should never run.
    117   loop.PostDelayedTask(
    118       FROM_HERE,
    119       Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
    120       TimeDelta::FromSeconds(1000));
    121 
    122   // This slightly delayed task should run from within SubPumpFunc).
    123   loop.PostDelayedTask(
    124       FROM_HERE,
    125       Bind(&PostQuitMessage, 0),
    126       TimeDelta::FromMilliseconds(10));
    127 
    128   Time start_time = Time::Now();
    129 
    130   loop.Run();
    131   EXPECT_EQ(1, num_tasks);
    132 
    133   // Ensure that we ran in far less time than the slower timer.
    134   TimeDelta total_time = Time::Now() - start_time;
    135   EXPECT_GT(5000, total_time.InMilliseconds());
    136 
    137   // In case both timers somehow run at nearly the same time, sleep a little
    138   // and then run all pending to force them both to have run.  This is just
    139   // encouraging flakiness if there is any.
    140   PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
    141   RunLoop().RunUntilIdle();
    142 
    143   EXPECT_TRUE(run_time.is_null());
    144 }
    145 
    146 const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test";
    147 
    148 enum TaskType {
    149   MESSAGEBOX,
    150   ENDDIALOG,
    151   RECURSIVE,
    152   TIMEDMESSAGELOOP,
    153   QUITMESSAGELOOP,
    154   ORDERED,
    155   PUMPS,
    156   SLEEP,
    157   RUNS,
    158 };
    159 
    160 // Saves the order in which the tasks executed.
    161 struct TaskItem {
    162   TaskItem(TaskType t, int c, bool s)
    163       : type(t),
    164         cookie(c),
    165         start(s) {
    166   }
    167 
    168   TaskType type;
    169   int cookie;
    170   bool start;
    171 
    172   bool operator == (const TaskItem& other) const {
    173     return type == other.type && cookie == other.cookie && start == other.start;
    174   }
    175 };
    176 
    177 std::ostream& operator <<(std::ostream& os, TaskType type) {
    178   switch (type) {
    179   case MESSAGEBOX:        os << "MESSAGEBOX"; break;
    180   case ENDDIALOG:         os << "ENDDIALOG"; break;
    181   case RECURSIVE:         os << "RECURSIVE"; break;
    182   case TIMEDMESSAGELOOP:  os << "TIMEDMESSAGELOOP"; break;
    183   case QUITMESSAGELOOP:   os << "QUITMESSAGELOOP"; break;
    184   case ORDERED:          os << "ORDERED"; break;
    185   case PUMPS:             os << "PUMPS"; break;
    186   case SLEEP:             os << "SLEEP"; break;
    187   default:
    188     NOTREACHED();
    189     os << "Unknown TaskType";
    190     break;
    191   }
    192   return os;
    193 }
    194 
    195 std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
    196   if (item.start)
    197     return os << item.type << " " << item.cookie << " starts";
    198   else
    199     return os << item.type << " " << item.cookie << " ends";
    200 }
    201 
    202 class TaskList {
    203  public:
    204   void RecordStart(TaskType type, int cookie) {
    205     TaskItem item(type, cookie, true);
    206     DVLOG(1) << item;
    207     task_list_.push_back(item);
    208   }
    209 
    210   void RecordEnd(TaskType type, int cookie) {
    211     TaskItem item(type, cookie, false);
    212     DVLOG(1) << item;
    213     task_list_.push_back(item);
    214   }
    215 
    216   size_t Size() {
    217     return task_list_.size();
    218   }
    219 
    220   TaskItem Get(int n)  {
    221     return task_list_[n];
    222   }
    223 
    224  private:
    225   std::vector<TaskItem> task_list_;
    226 };
    227 
    228 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
    229 // common controls (like OpenFile) and StartDoc printing function can cause
    230 // implicit message loops.
    231 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
    232   order->RecordStart(MESSAGEBOX, cookie);
    233   if (is_reentrant)
    234     MessageLoop::current()->SetNestableTasksAllowed(true);
    235   MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
    236   order->RecordEnd(MESSAGEBOX, cookie);
    237 }
    238 
    239 // Will end the MessageBox.
    240 void EndDialogFunc(TaskList* order, int cookie) {
    241   order->RecordStart(ENDDIALOG, cookie);
    242   HWND window = GetActiveWindow();
    243   if (window != NULL) {
    244     EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
    245     // Cheap way to signal that the window wasn't found if RunEnd() isn't
    246     // called.
    247     order->RecordEnd(ENDDIALOG, cookie);
    248   }
    249 }
    250 
    251 void RecursiveFunc(TaskList* order, int cookie, int depth,
    252                    bool is_reentrant) {
    253   order->RecordStart(RECURSIVE, cookie);
    254   if (depth > 0) {
    255     if (is_reentrant)
    256       MessageLoop::current()->SetNestableTasksAllowed(true);
    257     MessageLoop::current()->PostTask(
    258         FROM_HERE,
    259         Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
    260   }
    261   order->RecordEnd(RECURSIVE, cookie);
    262 }
    263 
    264 void QuitFunc(TaskList* order, int cookie) {
    265   order->RecordStart(QUITMESSAGELOOP, cookie);
    266   MessageLoop::current()->QuitWhenIdle();
    267   order->RecordEnd(QUITMESSAGELOOP, cookie);
    268 }
    269 
    270 void RecursiveFuncWin(MessageLoop* target,
    271                       HANDLE event,
    272                       bool expect_window,
    273                       TaskList* order,
    274                       bool is_reentrant) {
    275   target->PostTask(FROM_HERE,
    276                    Bind(&RecursiveFunc, order, 1, 2, is_reentrant));
    277   target->PostTask(FROM_HERE,
    278                    Bind(&MessageBoxFunc, order, 2, is_reentrant));
    279   target->PostTask(FROM_HERE,
    280                    Bind(&RecursiveFunc, order, 3, 2, is_reentrant));
    281   // The trick here is that for recursive task processing, this task will be
    282   // ran _inside_ the MessageBox message loop, dismissing the MessageBox
    283   // without a chance.
    284   // For non-recursive task processing, this will be executed _after_ the
    285   // MessageBox will have been dismissed by the code below, where
    286   // expect_window_ is true.
    287   target->PostTask(FROM_HERE,
    288                    Bind(&EndDialogFunc, order, 4));
    289   target->PostTask(FROM_HERE,
    290                    Bind(&QuitFunc, order, 5));
    291 
    292   // Enforce that every tasks are sent before starting to run the main thread
    293   // message loop.
    294   ASSERT_TRUE(SetEvent(event));
    295 
    296   // Poll for the MessageBox. Don't do this at home! At the speed we do it,
    297   // you will never realize one MessageBox was shown.
    298   for (; expect_window;) {
    299     HWND window = FindWindow(L"#32770", kMessageBoxTitle);
    300     if (window) {
    301       // Dismiss it.
    302       for (;;) {
    303         HWND button = FindWindowEx(window, NULL, L"Button", NULL);
    304         if (button != NULL) {
    305           EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
    306           EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
    307           break;
    308         }
    309       }
    310       break;
    311     }
    312   }
    313 }
    314 
    315 // TODO(darin): These tests need to be ported since they test critical
    316 // message loop functionality.
    317 
    318 // A side effect of this test is the generation a beep. Sorry.
    319 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
    320   MessageLoop loop(message_loop_type);
    321 
    322   Thread worker("RecursiveDenial2_worker");
    323   Thread::Options options;
    324   options.message_loop_type = message_loop_type;
    325   ASSERT_EQ(true, worker.StartWithOptions(options));
    326   TaskList order;
    327   win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
    328   worker.message_loop()->PostTask(FROM_HERE,
    329                                   Bind(&RecursiveFuncWin,
    330                                              MessageLoop::current(),
    331                                              event.Get(),
    332                                              true,
    333                                              &order,
    334                                              false));
    335   // Let the other thread execute.
    336   WaitForSingleObject(event.Get(), INFINITE);
    337   MessageLoop::current()->Run();
    338 
    339   ASSERT_EQ(order.Size(), 17);
    340   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
    341   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
    342   EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
    343   EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
    344   EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
    345   EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
    346   // When EndDialogFunc is processed, the window is already dismissed, hence no
    347   // "end" entry.
    348   EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
    349   EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
    350   EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
    351   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
    352   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
    353   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
    354   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
    355   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
    356   EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
    357   EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
    358   EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
    359 }
    360 
    361 // A side effect of this test is the generation a beep. Sorry.  This test also
    362 // needs to process windows messages on the current thread.
    363 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
    364   MessageLoop loop(message_loop_type);
    365 
    366   Thread worker("RecursiveSupport2_worker");
    367   Thread::Options options;
    368   options.message_loop_type = message_loop_type;
    369   ASSERT_EQ(true, worker.StartWithOptions(options));
    370   TaskList order;
    371   win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
    372   worker.message_loop()->PostTask(FROM_HERE,
    373                                   Bind(&RecursiveFuncWin,
    374                                              MessageLoop::current(),
    375                                              event.Get(),
    376                                              false,
    377                                              &order,
    378                                              true));
    379   // Let the other thread execute.
    380   WaitForSingleObject(event.Get(), INFINITE);
    381   MessageLoop::current()->Run();
    382 
    383   ASSERT_EQ(order.Size(), 18);
    384   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
    385   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
    386   EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
    387   // Note that this executes in the MessageBox modal loop.
    388   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
    389   EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
    390   EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
    391   EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
    392   EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
    393   /* The order can subtly change here. The reason is that when RecursiveFunc(1)
    394      is called in the main thread, if it is faster than getting to the
    395      PostTask(FROM_HERE, Bind(&QuitFunc) execution, the order of task
    396      execution can change. We don't care anyway that the order isn't correct.
    397   EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
    398   EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
    399   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
    400   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
    401   */
    402   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
    403   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
    404   EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
    405   EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
    406   EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
    407   EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
    408 }
    409 
    410 #endif  // defined(OS_WIN)
    411 
    412 void PostNTasksThenQuit(int posts_remaining) {
    413   if (posts_remaining > 1) {
    414     MessageLoop::current()->PostTask(
    415         FROM_HERE,
    416         Bind(&PostNTasksThenQuit, posts_remaining - 1));
    417   } else {
    418     MessageLoop::current()->QuitWhenIdle();
    419   }
    420 }
    421 
    422 #if defined(OS_WIN)
    423 
    424 class DispatcherImpl : public MessagePumpDispatcher {
    425  public:
    426   DispatcherImpl() : dispatch_count_(0) {}
    427 
    428   virtual uint32_t Dispatch(const NativeEvent& msg) OVERRIDE {
    429     ::TranslateMessage(&msg);
    430     ::DispatchMessage(&msg);
    431     // Do not count WM_TIMER since it is not what we post and it will cause
    432     // flakiness.
    433     if (msg.message != WM_TIMER)
    434       ++dispatch_count_;
    435     // We treat WM_LBUTTONUP as the last message.
    436     return msg.message == WM_LBUTTONUP ? POST_DISPATCH_QUIT_LOOP
    437                                        : POST_DISPATCH_NONE;
    438   }
    439 
    440   int dispatch_count_;
    441 };
    442 
    443 void MouseDownUp() {
    444   PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
    445   PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
    446 }
    447 
    448 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
    449   MessageLoop loop(message_loop_type);
    450 
    451   MessageLoop::current()->PostDelayedTask(
    452       FROM_HERE,
    453       Bind(&MouseDownUp),
    454       TimeDelta::FromMilliseconds(100));
    455   DispatcherImpl dispatcher;
    456   RunLoop run_loop(&dispatcher);
    457   run_loop.Run();
    458   ASSERT_EQ(2, dispatcher.dispatch_count_);
    459 }
    460 
    461 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) {
    462   if (code == MessagePumpForUI::kMessageFilterCode) {
    463     MSG* msg = reinterpret_cast<MSG*>(lparam);
    464     if (msg->message == WM_LBUTTONDOWN)
    465       return TRUE;
    466   }
    467   return FALSE;
    468 }
    469 
    470 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
    471   MessageLoop loop(message_loop_type);
    472 
    473   MessageLoop::current()->PostDelayedTask(
    474       FROM_HERE,
    475       Bind(&MouseDownUp),
    476       TimeDelta::FromMilliseconds(100));
    477   HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
    478                                     MsgFilterProc,
    479                                     NULL,
    480                                     GetCurrentThreadId());
    481   DispatcherImpl dispatcher;
    482   RunLoop run_loop(&dispatcher);
    483   run_loop.Run();
    484   ASSERT_EQ(1, dispatcher.dispatch_count_);
    485   UnhookWindowsHookEx(msg_hook);
    486 }
    487 
    488 class TestIOHandler : public MessageLoopForIO::IOHandler {
    489  public:
    490   TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
    491 
    492   virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
    493                              DWORD bytes_transfered, DWORD error);
    494 
    495   void Init();
    496   void WaitForIO();
    497   OVERLAPPED* context() { return &context_.overlapped; }
    498   DWORD size() { return sizeof(buffer_); }
    499 
    500  private:
    501   char buffer_[48];
    502   MessageLoopForIO::IOContext context_;
    503   HANDLE signal_;
    504   win::ScopedHandle file_;
    505   bool wait_;
    506 };
    507 
    508 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
    509     : signal_(signal), wait_(wait) {
    510   memset(buffer_, 0, sizeof(buffer_));
    511   memset(&context_, 0, sizeof(context_));
    512   context_.handler = this;
    513 
    514   file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
    515                        FILE_FLAG_OVERLAPPED, NULL));
    516   EXPECT_TRUE(file_.IsValid());
    517 }
    518 
    519 void TestIOHandler::Init() {
    520   MessageLoopForIO::current()->RegisterIOHandler(file_.Get(), this);
    521 
    522   DWORD read;
    523   EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context()));
    524   EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
    525   if (wait_)
    526     WaitForIO();
    527 }
    528 
    529 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
    530                                   DWORD bytes_transfered, DWORD error) {
    531   ASSERT_TRUE(context == &context_);
    532   ASSERT_TRUE(SetEvent(signal_));
    533 }
    534 
    535 void TestIOHandler::WaitForIO() {
    536   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
    537   EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
    538 }
    539 
    540 void RunTest_IOHandler() {
    541   win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
    542   ASSERT_TRUE(callback_called.IsValid());
    543 
    544   const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
    545   win::ScopedHandle server(
    546       CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
    547   ASSERT_TRUE(server.IsValid());
    548 
    549   Thread thread("IOHandler test");
    550   Thread::Options options;
    551   options.message_loop_type = MessageLoop::TYPE_IO;
    552   ASSERT_TRUE(thread.StartWithOptions(options));
    553 
    554   MessageLoop* thread_loop = thread.message_loop();
    555   ASSERT_TRUE(NULL != thread_loop);
    556 
    557   TestIOHandler handler(kPipeName, callback_called.Get(), false);
    558   thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init,
    559                                               Unretained(&handler)));
    560   // Make sure the thread runs and sleeps for lack of work.
    561   PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
    562 
    563   const char buffer[] = "Hello there!";
    564   DWORD written;
    565   EXPECT_TRUE(WriteFile(server.Get(), buffer, sizeof(buffer), &written, NULL));
    566 
    567   DWORD result = WaitForSingleObject(callback_called.Get(), 1000);
    568   EXPECT_EQ(WAIT_OBJECT_0, result);
    569 
    570   thread.Stop();
    571 }
    572 
    573 void RunTest_WaitForIO() {
    574   win::ScopedHandle callback1_called(
    575       CreateEvent(NULL, TRUE, FALSE, NULL));
    576   win::ScopedHandle callback2_called(
    577       CreateEvent(NULL, TRUE, FALSE, NULL));
    578   ASSERT_TRUE(callback1_called.IsValid());
    579   ASSERT_TRUE(callback2_called.IsValid());
    580 
    581   const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
    582   const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
    583   win::ScopedHandle server1(
    584       CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
    585   win::ScopedHandle server2(
    586       CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
    587   ASSERT_TRUE(server1.IsValid());
    588   ASSERT_TRUE(server2.IsValid());
    589 
    590   Thread thread("IOHandler test");
    591   Thread::Options options;
    592   options.message_loop_type = MessageLoop::TYPE_IO;
    593   ASSERT_TRUE(thread.StartWithOptions(options));
    594 
    595   MessageLoop* thread_loop = thread.message_loop();
    596   ASSERT_TRUE(NULL != thread_loop);
    597 
    598   TestIOHandler handler1(kPipeName1, callback1_called.Get(), false);
    599   TestIOHandler handler2(kPipeName2, callback2_called.Get(), true);
    600   thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init,
    601                                               Unretained(&handler1)));
    602   // TODO(ajwong): Do we really need such long Sleeps in ths function?
    603   // Make sure the thread runs and sleeps for lack of work.
    604   TimeDelta delay = TimeDelta::FromMilliseconds(100);
    605   PlatformThread::Sleep(delay);
    606   thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init,
    607                                               Unretained(&handler2)));
    608   PlatformThread::Sleep(delay);
    609 
    610   // At this time handler1 is waiting to be called, and the thread is waiting
    611   // on the Init method of handler2, filtering only handler2 callbacks.
    612 
    613   const char buffer[] = "Hello there!";
    614   DWORD written;
    615   EXPECT_TRUE(WriteFile(server1.Get(), buffer, sizeof(buffer), &written, NULL));
    616   PlatformThread::Sleep(2 * delay);
    617   EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called.Get(), 0)) <<
    618       "handler1 has not been called";
    619 
    620   EXPECT_TRUE(WriteFile(server2.Get(), buffer, sizeof(buffer), &written, NULL));
    621 
    622   HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
    623   DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
    624   EXPECT_EQ(WAIT_OBJECT_0, result);
    625 
    626   thread.Stop();
    627 }
    628 
    629 #endif  // defined(OS_WIN)
    630 
    631 }  // namespace
    632 
    633 //-----------------------------------------------------------------------------
    634 // Each test is run against each type of MessageLoop.  That way we are sure
    635 // that message loops work properly in all configurations.  Of course, in some
    636 // cases, a unit test may only be for a particular type of loop.
    637 
    638 RUN_MESSAGE_LOOP_TESTS(Default, &TypeDefaultMessagePumpFactory);
    639 RUN_MESSAGE_LOOP_TESTS(UI, &TypeUIMessagePumpFactory);
    640 RUN_MESSAGE_LOOP_TESTS(IO, &TypeIOMessagePumpFactory);
    641 
    642 #if defined(OS_WIN)
    643 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
    644   RunTest_PostDelayedTask_SharedTimer_SubPump();
    645 }
    646 
    647 // This test occasionally hangs http://crbug.com/44567
    648 TEST(MessageLoopTest, DISABLED_RecursiveDenial2) {
    649   RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
    650   RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
    651   RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
    652 }
    653 
    654 TEST(MessageLoopTest, RecursiveSupport2) {
    655   // This test requires a UI loop
    656   RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
    657 }
    658 #endif  // defined(OS_WIN)
    659 
    660 class DummyTaskObserver : public MessageLoop::TaskObserver {
    661  public:
    662   explicit DummyTaskObserver(int num_tasks)
    663       : num_tasks_started_(0),
    664         num_tasks_processed_(0),
    665         num_tasks_(num_tasks) {}
    666 
    667   virtual ~DummyTaskObserver() {}
    668 
    669   virtual void WillProcessTask(const PendingTask& pending_task) OVERRIDE {
    670     num_tasks_started_++;
    671     EXPECT_TRUE(pending_task.time_posted != TimeTicks());
    672     EXPECT_LE(num_tasks_started_, num_tasks_);
    673     EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
    674   }
    675 
    676   virtual void DidProcessTask(const PendingTask& pending_task) OVERRIDE {
    677     num_tasks_processed_++;
    678     EXPECT_TRUE(pending_task.time_posted != TimeTicks());
    679     EXPECT_LE(num_tasks_started_, num_tasks_);
    680     EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
    681   }
    682 
    683   int num_tasks_started() const { return num_tasks_started_; }
    684   int num_tasks_processed() const { return num_tasks_processed_; }
    685 
    686  private:
    687   int num_tasks_started_;
    688   int num_tasks_processed_;
    689   const int num_tasks_;
    690 
    691   DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver);
    692 };
    693 
    694 TEST(MessageLoopTest, TaskObserver) {
    695   const int kNumPosts = 6;
    696   DummyTaskObserver observer(kNumPosts);
    697 
    698   MessageLoop loop;
    699   loop.AddTaskObserver(&observer);
    700   loop.PostTask(FROM_HERE, Bind(&PostNTasksThenQuit, kNumPosts));
    701   loop.Run();
    702   loop.RemoveTaskObserver(&observer);
    703 
    704   EXPECT_EQ(kNumPosts, observer.num_tasks_started());
    705   EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
    706 }
    707 
    708 #if defined(OS_WIN)
    709 TEST(MessageLoopTest, Dispatcher) {
    710   // This test requires a UI loop
    711   RunTest_Dispatcher(MessageLoop::TYPE_UI);
    712 }
    713 
    714 TEST(MessageLoopTest, DispatcherWithMessageHook) {
    715   // This test requires a UI loop
    716   RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI);
    717 }
    718 
    719 TEST(MessageLoopTest, IOHandler) {
    720   RunTest_IOHandler();
    721 }
    722 
    723 TEST(MessageLoopTest, WaitForIO) {
    724   RunTest_WaitForIO();
    725 }
    726 
    727 TEST(MessageLoopTest, HighResolutionTimer) {
    728   MessageLoop loop;
    729   Time::EnableHighResolutionTimer(true);
    730 
    731   const TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5);
    732   const TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100);
    733 
    734   EXPECT_FALSE(loop.HasHighResolutionTasks());
    735   // Post a fast task to enable the high resolution timers.
    736   loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1),
    737                        kFastTimer);
    738   EXPECT_TRUE(loop.HasHighResolutionTasks());
    739   loop.Run();
    740   EXPECT_FALSE(loop.HasHighResolutionTasks());
    741   EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
    742   // Check that a slow task does not trigger the high resolution logic.
    743   loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1),
    744                        kSlowTimer);
    745   EXPECT_FALSE(loop.HasHighResolutionTasks());
    746   loop.Run();
    747   EXPECT_FALSE(loop.HasHighResolutionTasks());
    748   Time::EnableHighResolutionTimer(false);
    749 }
    750 
    751 #endif  // defined(OS_WIN)
    752 
    753 #if defined(OS_POSIX) && !defined(OS_NACL)
    754 
    755 namespace {
    756 
    757 class QuitDelegate : public MessageLoopForIO::Watcher {
    758  public:
    759   virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {
    760     MessageLoop::current()->QuitWhenIdle();
    761   }
    762   virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
    763     MessageLoop::current()->QuitWhenIdle();
    764   }
    765 };
    766 
    767 TEST(MessageLoopTest, FileDescriptorWatcherOutlivesMessageLoop) {
    768   // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
    769   // This could happen when people use the Singleton pattern or atexit.
    770 
    771   // Create a file descriptor.  Doesn't need to be readable or writable,
    772   // as we don't need to actually get any notifications.
    773   // pipe() is just the easiest way to do it.
    774   int pipefds[2];
    775   int err = pipe(pipefds);
    776   ASSERT_EQ(0, err);
    777   int fd = pipefds[1];
    778   {
    779     // Arrange for controller to live longer than message loop.
    780     MessageLoopForIO::FileDescriptorWatcher controller;
    781     {
    782       MessageLoopForIO message_loop;
    783 
    784       QuitDelegate delegate;
    785       message_loop.WatchFileDescriptor(fd,
    786           true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
    787       // and don't run the message loop, just destroy it.
    788     }
    789   }
    790   if (IGNORE_EINTR(close(pipefds[0])) < 0)
    791     PLOG(ERROR) << "close";
    792   if (IGNORE_EINTR(close(pipefds[1])) < 0)
    793     PLOG(ERROR) << "close";
    794 }
    795 
    796 TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) {
    797   // Verify that it's ok to call StopWatchingFileDescriptor().
    798   // (Errors only showed up in valgrind.)
    799   int pipefds[2];
    800   int err = pipe(pipefds);
    801   ASSERT_EQ(0, err);
    802   int fd = pipefds[1];
    803   {
    804     // Arrange for message loop to live longer than controller.
    805     MessageLoopForIO message_loop;
    806     {
    807       MessageLoopForIO::FileDescriptorWatcher controller;
    808 
    809       QuitDelegate delegate;
    810       message_loop.WatchFileDescriptor(fd,
    811           true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
    812       controller.StopWatchingFileDescriptor();
    813     }
    814   }
    815   if (IGNORE_EINTR(close(pipefds[0])) < 0)
    816     PLOG(ERROR) << "close";
    817   if (IGNORE_EINTR(close(pipefds[1])) < 0)
    818     PLOG(ERROR) << "close";
    819 }
    820 
    821 }  // namespace
    822 
    823 #endif  // defined(OS_POSIX) && !defined(OS_NACL)
    824 
    825 namespace {
    826 // Inject a test point for recording the destructor calls for Closure objects
    827 // send to MessageLoop::PostTask(). It is awkward usage since we are trying to
    828 // hook the actual destruction, which is not a common operation.
    829 class DestructionObserverProbe :
    830   public RefCounted<DestructionObserverProbe> {
    831  public:
    832   DestructionObserverProbe(bool* task_destroyed,
    833                            bool* destruction_observer_called)
    834       : task_destroyed_(task_destroyed),
    835         destruction_observer_called_(destruction_observer_called) {
    836   }
    837   virtual void Run() {
    838     // This task should never run.
    839     ADD_FAILURE();
    840   }
    841  private:
    842   friend class RefCounted<DestructionObserverProbe>;
    843 
    844   virtual ~DestructionObserverProbe() {
    845     EXPECT_FALSE(*destruction_observer_called_);
    846     *task_destroyed_ = true;
    847   }
    848 
    849   bool* task_destroyed_;
    850   bool* destruction_observer_called_;
    851 };
    852 
    853 class MLDestructionObserver : public MessageLoop::DestructionObserver {
    854  public:
    855   MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
    856       : task_destroyed_(task_destroyed),
    857         destruction_observer_called_(destruction_observer_called),
    858         task_destroyed_before_message_loop_(false) {
    859   }
    860   virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
    861     task_destroyed_before_message_loop_ = *task_destroyed_;
    862     *destruction_observer_called_ = true;
    863   }
    864   bool task_destroyed_before_message_loop() const {
    865     return task_destroyed_before_message_loop_;
    866   }
    867  private:
    868   bool* task_destroyed_;
    869   bool* destruction_observer_called_;
    870   bool task_destroyed_before_message_loop_;
    871 };
    872 
    873 }  // namespace
    874 
    875 TEST(MessageLoopTest, DestructionObserverTest) {
    876   // Verify that the destruction observer gets called at the very end (after
    877   // all the pending tasks have been destroyed).
    878   MessageLoop* loop = new MessageLoop;
    879   const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
    880 
    881   bool task_destroyed = false;
    882   bool destruction_observer_called = false;
    883 
    884   MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
    885   loop->AddDestructionObserver(&observer);
    886   loop->PostDelayedTask(
    887       FROM_HERE,
    888       Bind(&DestructionObserverProbe::Run,
    889                  new DestructionObserverProbe(&task_destroyed,
    890                                               &destruction_observer_called)),
    891       kDelay);
    892   delete loop;
    893   EXPECT_TRUE(observer.task_destroyed_before_message_loop());
    894   // The task should have been destroyed when we deleted the loop.
    895   EXPECT_TRUE(task_destroyed);
    896   EXPECT_TRUE(destruction_observer_called);
    897 }
    898 
    899 
    900 // Verify that MessageLoop sets ThreadMainTaskRunner::current() and it
    901 // posts tasks on that message loop.
    902 TEST(MessageLoopTest, ThreadMainTaskRunner) {
    903   MessageLoop loop;
    904 
    905   scoped_refptr<Foo> foo(new Foo());
    906   std::string a("a");
    907   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(
    908       &Foo::Test1ConstRef, foo.get(), a));
    909 
    910   // Post quit task;
    911   MessageLoop::current()->PostTask(FROM_HERE, Bind(
    912       &MessageLoop::Quit, Unretained(MessageLoop::current())));
    913 
    914   // Now kick things off
    915   MessageLoop::current()->Run();
    916 
    917   EXPECT_EQ(foo->test_count(), 1);
    918   EXPECT_EQ(foo->result(), "a");
    919 }
    920 
    921 TEST(MessageLoopTest, IsType) {
    922   MessageLoop loop(MessageLoop::TYPE_UI);
    923   EXPECT_TRUE(loop.IsType(MessageLoop::TYPE_UI));
    924   EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_IO));
    925   EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT));
    926 }
    927 
    928 #if defined(OS_WIN)
    929 void EmptyFunction() {}
    930 
    931 void PostMultipleTasks() {
    932   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
    933   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
    934 }
    935 
    936 static const int kSignalMsg = WM_USER + 2;
    937 
    938 void PostWindowsMessage(HWND message_hwnd) {
    939   PostMessage(message_hwnd, kSignalMsg, 0, 2);
    940 }
    941 
    942 void EndTest(bool* did_run, HWND hwnd) {
    943   *did_run = true;
    944   PostMessage(hwnd, WM_CLOSE, 0, 0);
    945 }
    946 
    947 int kMyMessageFilterCode = 0x5002;
    948 
    949 LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
    950                                   WPARAM wparam, LPARAM lparam) {
    951   if (message == WM_CLOSE)
    952     EXPECT_TRUE(DestroyWindow(hwnd));
    953   if (message != kSignalMsg)
    954     return DefWindowProc(hwnd, message, wparam, lparam);
    955 
    956   switch (lparam) {
    957   case 1:
    958     // First, we post a task that will post multiple no-op tasks to make sure
    959     // that the pump's incoming task queue does not become empty during the
    960     // test.
    961     MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&PostMultipleTasks));
    962     // Next, we post a task that posts a windows message to trigger the second
    963     // stage of the test.
    964     MessageLoop::current()->PostTask(FROM_HERE,
    965                                      base::Bind(&PostWindowsMessage, hwnd));
    966     break;
    967   case 2:
    968     // Since we're about to enter a modal loop, tell the message loop that we
    969     // intend to nest tasks.
    970     MessageLoop::current()->SetNestableTasksAllowed(true);
    971     bool did_run = false;
    972     MessageLoop::current()->PostTask(FROM_HERE,
    973                                      base::Bind(&EndTest, &did_run, hwnd));
    974     // Run a nested windows-style message loop and verify that our task runs. If
    975     // it doesn't, then we'll loop here until the test times out.
    976     MSG msg;
    977     while (GetMessage(&msg, 0, 0, 0)) {
    978       if (!CallMsgFilter(&msg, kMyMessageFilterCode))
    979         DispatchMessage(&msg);
    980       // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting
    981       // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats
    982       // WM_QUIT messages even when running inside a modal loop.
    983       if (msg.message == WM_CLOSE)
    984         break;
    985     }
    986     EXPECT_TRUE(did_run);
    987     MessageLoop::current()->Quit();
    988     break;
    989   }
    990   return 0;
    991 }
    992 
    993 TEST(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) {
    994   MessageLoop loop(MessageLoop::TYPE_UI);
    995   HINSTANCE instance = GetModuleFromAddress(&TestWndProcThunk);
    996   WNDCLASSEX wc = {0};
    997   wc.cbSize = sizeof(wc);
    998   wc.lpfnWndProc = TestWndProcThunk;
    999   wc.hInstance = instance;
   1000   wc.lpszClassName = L"MessageLoopTest_HWND";
   1001   ATOM atom = RegisterClassEx(&wc);
   1002   ASSERT_TRUE(atom);
   1003 
   1004   HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
   1005                                    HWND_MESSAGE, 0, instance, 0);
   1006   ASSERT_TRUE(message_hwnd) << GetLastError();
   1007 
   1008   ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
   1009 
   1010   loop.Run();
   1011 
   1012   ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
   1013 }
   1014 #endif  // defined(OS_WIN)
   1015 
   1016 }  // namespace base
   1017