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