17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_loop.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop_proxy_impl.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop_test.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/pending_task.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/message_loop/message_pump_dispatcher.h"
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_win.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/process/memory.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string16.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace base {
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(darin): Platform-specific MessageLoop tests should be grouped together
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to avoid chopping this file up with so many #ifdefs.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<MessagePump> TypeDefaultMessagePumpFactory() {
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_DEFAULT);
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<MessagePump> TypeIOMessagePumpFactory() {
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_IO);
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<MessagePump> TypeUIMessagePumpFactory() {
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return MessageLoop::CreateMessagePumpForType(MessageLoop::TYPE_UI);
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class Foo : public RefCounted<Foo> {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Foo() : test_count_(0) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Test1ConstRef(const std::string& a) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++test_count_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_.append(a);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int test_count() const { return test_count_; }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& result() const { return result_; }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  friend class RefCounted<Foo>;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Foo() {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int test_count_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_WIN)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function runs slowly to simulate a large amount of work being done.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SlowFunc(TimeDelta pause, int* quit_counter) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformThread::Sleep(pause);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (--(*quit_counter) == 0)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MessageLoop::current()->QuitWhenIdle();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function records the time when Run was called in a Time object, which is
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// useful for building a variety of MessageLoop tests.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RecordRunTimeFunc(Time* run_time, int* quit_counter) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *run_time = Time::Now();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cause our Run function to take some time to execute.  As a result we can
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // count on subsequent RecordRunTimeFunc()s running at a future time,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without worry about the resolution of our system clock being an issue.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SubPumpFunc() {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->SetNestableTasksAllowed(true);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MSG msg;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (GetMessage(&msg, NULL, 0, 0)) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TranslateMessage(&msg);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatchMessage(&msg);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MessageLoop::current()->QuitWhenIdle();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_PostDelayedTask_SharedTimer_SubPump() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop(MessageLoop::TYPE_UI);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that the interval of the timer, used to run the next delayed task, is
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set to a value corresponding to when the next delayed task should run.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By setting num_tasks to 1, we ensure that the first task to run causes the
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // run loop to exit.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_tasks = 1;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time run_time;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostTask(FROM_HERE, Bind(&SubPumpFunc));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This very delayed task should never run.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.PostDelayedTask(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta::FromSeconds(1000));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This slightly delayed task should run from within SubPumpFunc).
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.PostDelayedTask(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&PostQuitMessage, 0),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta::FromMilliseconds(10));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time start_time = Time::Now();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, num_tasks);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that we ran in far less time than the slower timer.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta total_time = Time::Now() - start_time;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(5000, total_time.InMilliseconds());
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case both timers somehow run at nearly the same time, sleep a little
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and then run all pending to force them both to have run.  This is just
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // encouraging flakiness if there is any.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunLoop().RunUntilIdle();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(run_time.is_null());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test";
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum TaskType {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MESSAGEBOX,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ENDDIALOG,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RECURSIVE,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TIMEDMESSAGELOOP,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QUITMESSAGELOOP,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ORDERED,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PUMPS,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SLEEP,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RUNS,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Saves the order in which the tasks executed.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TaskItem {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskItem(TaskType t, int c, bool s)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : type(t),
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cookie(c),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        start(s) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskType type;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cookie;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool start;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator == (const TaskItem& other) const {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return type == other.type && cookie == other.cookie && start == other.start;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator <<(std::ostream& os, TaskType type) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case MESSAGEBOX:        os << "MESSAGEBOX"; break;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENDDIALOG:         os << "ENDDIALOG"; break;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case RECURSIVE:         os << "RECURSIVE"; break;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case TIMEDMESSAGELOOP:  os << "TIMEDMESSAGELOOP"; break;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case QUITMESSAGELOOP:   os << "QUITMESSAGELOOP"; break;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ORDERED:          os << "ORDERED"; break;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case PUMPS:             os << "PUMPS"; break;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case SLEEP:             os << "SLEEP"; break;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << "Unknown TaskType";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (item.start)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return os << item.type << " " << item.cookie << " starts";
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return os << item.type << " " << item.cookie << " ends";
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TaskList {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordStart(TaskType type, int cookie) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TaskItem item(type, cookie, true);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << item;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_list_.push_back(item);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordEnd(TaskType type, int cookie) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TaskItem item(type, cookie, false);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << item;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_list_.push_back(item);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t Size() {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return task_list_.size();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskItem Get(int n)  {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return task_list_[n];
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<TaskItem> task_list_;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// common controls (like OpenFile) and StartDoc printing function can cause
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implicit message loops.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordStart(MESSAGEBOX, cookie);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_reentrant)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->SetNestableTasksAllowed(true);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordEnd(MESSAGEBOX, cookie);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will end the MessageBox.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EndDialogFunc(TaskList* order, int cookie) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordStart(ENDDIALOG, cookie);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HWND window = GetActiveWindow();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window != NULL) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cheap way to signal that the window wasn't found if RunEnd() isn't
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // called.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    order->RecordEnd(ENDDIALOG, cookie);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecursiveFunc(TaskList* order, int cookie, int depth,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   bool is_reentrant) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordStart(RECURSIVE, cookie);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (depth > 0) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_reentrant)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageLoop::current()->SetNestableTasksAllowed(true);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->PostTask(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordEnd(RECURSIVE, cookie);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuitFunc(TaskList* order, int cookie) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordStart(QUITMESSAGELOOP, cookie);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MessageLoop::current()->QuitWhenIdle();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  order->RecordEnd(QUITMESSAGELOOP, cookie);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecursiveFuncWin(MessageLoop* target,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      HANDLE event,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool expect_window,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      TaskList* order,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool is_reentrant) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target->PostTask(FROM_HERE,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   Bind(&RecursiveFunc, order, 1, 2, is_reentrant));
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target->PostTask(FROM_HERE,
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   Bind(&MessageBoxFunc, order, 2, is_reentrant));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target->PostTask(FROM_HERE,
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   Bind(&RecursiveFunc, order, 3, 2, is_reentrant));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The trick here is that for recursive task processing, this task will be
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ran _inside_ the MessageBox message loop, dismissing the MessageBox
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without a chance.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For non-recursive task processing, this will be executed _after_ the
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessageBox will have been dismissed by the code below, where
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expect_window_ is true.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target->PostTask(FROM_HERE,
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   Bind(&EndDialogFunc, order, 4));
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target->PostTask(FROM_HERE,
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   Bind(&QuitFunc, order, 5));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enforce that every tasks are sent before starting to run the main thread
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message loop.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(SetEvent(event));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Poll for the MessageBox. Don't do this at home! At the speed we do it,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // you will never realize one MessageBox was shown.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; expect_window;) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HWND window = FindWindow(L"#32770", kMessageBoxTitle);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Dismiss it.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (;;) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HWND button = FindWindowEx(window, NULL, L"Button", NULL);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (button != NULL) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(darin): These tests need to be ported since they test critical
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message loop functionality.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A side effect of this test is the generation a beep. Sorry.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop(message_loop_type);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread worker("RecursiveDenial2_worker");
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread::Options options;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.message_loop_type = message_loop_type;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(true, worker.StartWithOptions(options));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskList order;
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.message_loop()->PostTask(FROM_HERE,
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  Bind(&RecursiveFuncWin,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             MessageLoop::current(),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             event.Get(),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             true,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             &order,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             false));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let the other thread execute.
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WaitForSingleObject(event.Get(), INFINITE);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->Run();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(order.Size(), 17);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When EndDialogFunc is processed, the window is already dismissed, hence no
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "end" entry.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A side effect of this test is the generation a beep. Sorry.  This test also
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needs to process windows messages on the current thread.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop(message_loop_type);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread worker("RecursiveSupport2_worker");
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread::Options options;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.message_loop_type = message_loop_type;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(true, worker.StartWithOptions(options));
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskList order;
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.message_loop()->PostTask(FROM_HERE,
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  Bind(&RecursiveFuncWin,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             MessageLoop::current(),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             event.Get(),
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             false,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             &order,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             true));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let the other thread execute.
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WaitForSingleObject(event.Get(), INFINITE);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->Run();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(order.Size(), 18);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this executes in the MessageBox modal loop.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The order can subtly change here. The reason is that when RecursiveFunc(1)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     is called in the main thread, if it is faster than getting to the
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     PostTask(FROM_HERE, Bind(&QuitFunc) execution, the order of task
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     execution can change. We don't care anyway that the order isn't correct.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PostNTasksThenQuit(int posts_remaining) {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (posts_remaining > 1) {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageLoop::current()->PostTask(
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        Bind(&PostNTasksThenQuit, posts_remaining - 1));
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageLoop::current()->QuitWhenIdle();
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class DispatcherImpl : public MessagePumpDispatcher {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatcherImpl() : dispatch_count_(0) {}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual uint32_t Dispatch(const NativeEvent& msg) OVERRIDE {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::TranslateMessage(&msg);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::DispatchMessage(&msg);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do not count WM_TIMER since it is not what we post and it will cause
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // flakiness.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (msg.message != WM_TIMER)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++dispatch_count_;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We treat WM_LBUTTONUP as the last message.
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return msg.message == WM_LBUTTONUP ? POST_DISPATCH_QUIT_LOOP
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       : POST_DISPATCH_NONE;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dispatch_count_;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseDownUp() {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop(message_loop_type);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->PostDelayedTask(
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&MouseDownUp),
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta::FromMilliseconds(100));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatcherImpl dispatcher;
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunLoop run_loop(&dispatcher);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2, dispatcher.dispatch_count_);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) {
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (code == MessagePumpForUI::kMessageFilterCode) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MSG* msg = reinterpret_cast<MSG*>(lparam);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (msg->message == WM_LBUTTONDOWN)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TRUE;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FALSE;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop(message_loop_type);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->PostDelayedTask(
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&MouseDownUp),
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta::FromMilliseconds(100));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    MsgFilterProc,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    NULL,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    GetCurrentThreadId());
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatcherImpl dispatcher;
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RunLoop run_loop(&dispatcher);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1, dispatcher.dispatch_count_);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnhookWindowsHookEx(msg_hook);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestIOHandler : public MessageLoopForIO::IOHandler {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             DWORD bytes_transfered, DWORD error);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForIO();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OVERLAPPED* context() { return &context_.overlapped; }
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size() { return sizeof(buffer_); }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer_[48];
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoopForIO::IOContext context_;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE signal_;
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle file_;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : signal_(signal), wait_(wait) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(buffer_, 0, sizeof(buffer_));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&context_, 0, sizeof(context_));
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_.handler = this;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       FILE_FLAG_OVERLAPPED, NULL));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(file_.IsValid());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestIOHandler::Init() {
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MessageLoopForIO::current()->RegisterIOHandler(file_.Get(), this);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD read;
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context()));
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitForIO();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  DWORD bytes_transfered, DWORD error) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(context == &context_);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(SetEvent(signal_));
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestIOHandler::WaitForIO() {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_IOHandler() {
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(callback_called.IsValid());
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle server(
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server.IsValid());
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread thread("IOHandler test");
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread::Options options;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.message_loop_type = MessageLoop::TYPE_IO;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(thread.StartWithOptions(options));
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop* thread_loop = thread.message_loop();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(NULL != thread_loop);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestIOHandler handler(kPipeName, callback_called.Get(), false);
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init,
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              Unretained(&handler)));
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the thread runs and sleeps for lack of work.
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char buffer[] = "Hello there!";
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD written;
5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(WriteFile(server.Get(), buffer, sizeof(buffer), &written, NULL));
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DWORD result = WaitForSingleObject(callback_called.Get(), 1000);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WAIT_OBJECT_0, result);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread.Stop();
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunTest_WaitForIO() {
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle callback1_called(
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateEvent(NULL, TRUE, FALSE, NULL));
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle callback2_called(
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateEvent(NULL, TRUE, FALSE, NULL));
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(callback1_called.IsValid());
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(callback2_called.IsValid());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle server1(
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  win::ScopedHandle server2(
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server1.IsValid());
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(server2.IsValid());
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread thread("IOHandler test");
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread::Options options;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.message_loop_type = MessageLoop::TYPE_IO;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(thread.StartWithOptions(options));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop* thread_loop = thread.message_loop();
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(NULL != thread_loop);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestIOHandler handler1(kPipeName1, callback1_called.Get(), false);
5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestIOHandler handler2(kPipeName2, callback2_called.Get(), true);
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init,
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              Unretained(&handler1)));
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(ajwong): Do we really need such long Sleeps in ths function?
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the thread runs and sleeps for lack of work.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta delay = TimeDelta::FromMilliseconds(100);
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PlatformThread::Sleep(delay);
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init,
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              Unretained(&handler2)));
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PlatformThread::Sleep(delay);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this time handler1 is waiting to be called, and the thread is waiting
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the Init method of handler2, filtering only handler2 callbacks.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char buffer[] = "Hello there!";
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD written;
6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(WriteFile(server1.Get(), buffer, sizeof(buffer), &written, NULL));
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PlatformThread::Sleep(2 * delay);
6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called.Get(), 0)) <<
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "handler1 has not been called";
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(WriteFile(server2.Get(), buffer, sizeof(buffer), &written, NULL));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WAIT_OBJECT_0, result);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread.Stop();
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each test is run against each type of MessageLoop.  That way we are sure
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that message loops work properly in all configurations.  Of course, in some
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cases, a unit test may only be for a particular type of loop.
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RUN_MESSAGE_LOOP_TESTS(Default, &TypeDefaultMessagePumpFactory);
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RUN_MESSAGE_LOOP_TESTS(UI, &TypeUIMessagePumpFactory);
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RUN_MESSAGE_LOOP_TESTS(IO, &TypeIOMessagePumpFactory);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_PostDelayedTask_SharedTimer_SubPump();
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test occasionally hangs http://crbug.com/44567
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, DISABLED_RecursiveDenial2) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, RecursiveSupport2) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test requires a UI loop
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyTaskObserver : public MessageLoop::TaskObserver {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DummyTaskObserver(int num_tasks)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : num_tasks_started_(0),
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_tasks_processed_(0),
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_tasks_(num_tasks) {}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DummyTaskObserver() {}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void WillProcessTask(const PendingTask& pending_task) OVERRIDE {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_tasks_started_++;
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(pending_task.time_posted != TimeTicks());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LE(num_tasks_started_, num_tasks_);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DidProcessTask(const PendingTask& pending_task) OVERRIDE {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_tasks_processed_++;
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(pending_task.time_posted != TimeTicks());
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LE(num_tasks_started_, num_tasks_);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_tasks_started() const { return num_tasks_started_; }
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_tasks_processed() const { return num_tasks_processed_; }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_tasks_started_;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_tasks_processed_;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_tasks_;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, TaskObserver) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kNumPosts = 6;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DummyTaskObserver observer(kNumPosts);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.AddTaskObserver(&observer);
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostTask(FROM_HERE, Bind(&PostNTasksThenQuit, kNumPosts));
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.RemoveTaskObserver(&observer);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNumPosts, observer.num_tasks_started());
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, Dispatcher) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test requires a UI loop
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_Dispatcher(MessageLoop::TYPE_UI);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, DispatcherWithMessageHook) {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test requires a UI loop
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, IOHandler) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_IOHandler();
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, WaitForIO) {
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest_WaitForIO();
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, HighResolutionTimer) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop;
7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Time::EnableHighResolutionTimer(true);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(loop.HasHighResolutionTasks());
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a fast task to enable the high resolution timers.
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1),
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       kFastTimer);
7381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(loop.HasHighResolutionTasks());
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(loop.HasHighResolutionTasks());
7411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Check that a slow task does not trigger the high resolution logic.
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1),
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       kSlowTimer);
7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(loop.HasHighResolutionTasks());
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(loop.HasHighResolutionTasks());
7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Time::EnableHighResolutionTimer(false);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_NACL)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class QuitDelegate : public MessageLoopForIO::Watcher {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageLoop::current()->QuitWhenIdle();
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageLoop::current()->QuitWhenIdle();
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, FileDescriptorWatcherOutlivesMessageLoop) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This could happen when people use the Singleton pattern or atexit.
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a file descriptor.  Doesn't need to be readable or writable,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as we don't need to actually get any notifications.
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pipe() is just the easiest way to do it.
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pipefds[2];
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = pipe(pipefds);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, err);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = pipefds[1];
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Arrange for controller to live longer than message loop.
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoopForIO::FileDescriptorWatcher controller;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageLoopForIO message_loop;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      QuitDelegate delegate;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_loop.WatchFileDescriptor(fd,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and don't run the message loop, just destroy it.
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IGNORE_EINTR(close(pipefds[0])) < 0)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(ERROR) << "close";
792a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IGNORE_EINTR(close(pipefds[1])) < 0)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(ERROR) << "close";
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, FileDescriptorWatcherDoubleStop) {
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that it's ok to call StopWatchingFileDescriptor().
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (Errors only showed up in valgrind.)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pipefds[2];
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = pipe(pipefds);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, err);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = pipefds[1];
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Arrange for message loop to live longer than controller.
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoopForIO message_loop;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageLoopForIO::FileDescriptorWatcher controller;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      QuitDelegate delegate;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_loop.WatchFileDescriptor(fd,
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          true, MessageLoopForIO::WATCH_WRITE, &controller, &delegate);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller.StopWatchingFileDescriptor();
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IGNORE_EINTR(close(pipefds[0])) < 0)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(ERROR) << "close";
817a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IGNORE_EINTR(close(pipefds[1])) < 0)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(ERROR) << "close";
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_POSIX) && !defined(OS_NACL)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Inject a test point for recording the destructor calls for Closure objects
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// send to MessageLoop::PostTask(). It is awkward usage since we are trying to
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hook the actual destruction, which is not a common operation.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DestructionObserverProbe :
830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  public RefCounted<DestructionObserverProbe> {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DestructionObserverProbe(bool* task_destroyed,
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bool* destruction_observer_called)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : task_destroyed_(task_destroyed),
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        destruction_observer_called_(destruction_observer_called) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This task should never run.
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
842c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  friend class RefCounted<DestructionObserverProbe>;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DestructionObserverProbe() {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(*destruction_observer_called_);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *task_destroyed_ = true;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool* task_destroyed_;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool* destruction_observer_called_;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MLDestructionObserver : public MessageLoop::DestructionObserver {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : task_destroyed_(task_destroyed),
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        destruction_observer_called_(destruction_observer_called),
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        task_destroyed_before_message_loop_(false) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_destroyed_before_message_loop_ = *task_destroyed_;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *destruction_observer_called_ = true;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool task_destroyed_before_message_loop() const {
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return task_destroyed_before_message_loop_;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool* task_destroyed_;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool* destruction_observer_called_;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool task_destroyed_before_message_loop_;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, DestructionObserverTest) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the destruction observer gets called at the very end (after
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all the pending tasks have been destroyed).
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop* loop = new MessageLoop;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool task_destroyed = false;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool destruction_observer_called = false;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop->AddDestructionObserver(&observer);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop->PostDelayedTask(
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&DestructionObserverProbe::Run,
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 new DestructionObserverProbe(&task_destroyed,
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              &destruction_observer_called)),
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kDelay);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete loop;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(observer.task_destroyed_before_message_loop());
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The task should have been destroyed when we deleted the loop.
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(task_destroyed);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(destruction_observer_called);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that MessageLoop sets ThreadMainTaskRunner::current() and it
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// posts tasks on that message loop.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, ThreadMainTaskRunner) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Foo> foo(new Foo());
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string a("a");
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Foo::Test1ConstRef, foo.get(), a));
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post quit task;
911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MessageLoop::current()->PostTask(FROM_HERE, Bind(
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &MessageLoop::Quit, Unretained(MessageLoop::current())));
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now kick things off
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->Run();
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(foo->test_count(), 1);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(foo->result(), "a");
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(MessageLoopTest, IsType) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop loop(MessageLoop::TYPE_UI);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(loop.IsType(MessageLoop::TYPE_UI));
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_IO));
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT));
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
928f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_WIN)
929f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EmptyFunction() {}
930f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
931f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PostMultipleTasks() {
932f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
933f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
936f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static const int kSignalMsg = WM_USER + 2;
937f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
938f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PostWindowsMessage(HWND message_hwnd) {
939f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PostMessage(message_hwnd, kSignalMsg, 0, 2);
940f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
941f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
942f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EndTest(bool* did_run, HWND hwnd) {
943f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *did_run = true;
944f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PostMessage(hwnd, WM_CLOSE, 0, 0);
945f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
946f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
947f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int kMyMessageFilterCode = 0x5002;
948f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
949f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
950f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  WPARAM wparam, LPARAM lparam) {
951f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (message == WM_CLOSE)
952f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_TRUE(DestroyWindow(hwnd));
953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (message != kSignalMsg)
954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return DefWindowProc(hwnd, message, wparam, lparam);
955f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
956f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (lparam) {
957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  case 1:
958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // First, we post a task that will post multiple no-op tasks to make sure
959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // that the pump's incoming task queue does not become empty during the
960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // test.
961f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&PostMultipleTasks));
962f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Next, we post a task that posts a windows message to trigger the second
963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // stage of the test.
964f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MessageLoop::current()->PostTask(FROM_HERE,
965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     base::Bind(&PostWindowsMessage, hwnd));
966f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    break;
967f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  case 2:
968f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Since we're about to enter a modal loop, tell the message loop that we
969f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // intend to nest tasks.
970f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MessageLoop::current()->SetNestableTasksAllowed(true);
971f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool did_run = false;
972f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MessageLoop::current()->PostTask(FROM_HERE,
973f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     base::Bind(&EndTest, &did_run, hwnd));
974f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Run a nested windows-style message loop and verify that our task runs. If
975f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // it doesn't, then we'll loop here until the test times out.
976f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MSG msg;
977f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    while (GetMessage(&msg, 0, 0, 0)) {
978f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!CallMsgFilter(&msg, kMyMessageFilterCode))
979f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        DispatchMessage(&msg);
980f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting
981f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats
982f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // WM_QUIT messages even when running inside a modal loop.
983f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (msg.message == WM_CLOSE)
984f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
985f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
986f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_TRUE(did_run);
987f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MessageLoop::current()->Quit();
988f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    break;
989f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
990f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0;
991f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
992f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
993f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) {
994f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MessageLoop loop(MessageLoop::TYPE_UI);
995f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HINSTANCE instance = GetModuleFromAddress(&TestWndProcThunk);
996f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WNDCLASSEX wc = {0};
997f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  wc.cbSize = sizeof(wc);
998f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  wc.lpfnWndProc = TestWndProcThunk;
999f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  wc.hInstance = instance;
1000f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  wc.lpszClassName = L"MessageLoopTest_HWND";
1001f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ATOM atom = RegisterClassEx(&wc);
1002f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(atom);
1003f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1004f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
1005f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   HWND_MESSAGE, 0, instance, 0);
1006f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(message_hwnd) << GetLastError();
1007f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1008f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
1009f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1010f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  loop.Run();
1011f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1012f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1014f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // defined(OS_WIN)
1015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace base
1017