Home | History | Annotate | Download | only in message_loop
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/message_loop/message_loop_test.h"
      6 
      7 #include <stddef.h>
      8 
      9 #include <utility>
     10 
     11 #include "base/bind.h"
     12 #include "base/macros.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/run_loop.h"
     15 #include "base/single_thread_task_runner.h"
     16 #include "base/synchronization/waitable_event.h"
     17 #include "base/threading/thread.h"
     18 #include "base/threading/thread_task_runner_handle.h"
     19 
     20 namespace base {
     21 namespace test {
     22 
     23 namespace {
     24 
     25 class Foo : public RefCounted<Foo> {
     26  public:
     27   Foo() : test_count_(0) {
     28   }
     29 
     30   void Test0() {
     31     ++test_count_;
     32   }
     33 
     34   void Test1ConstRef(const std::string& a) {
     35     ++test_count_;
     36     result_.append(a);
     37   }
     38 
     39   void Test1Ptr(std::string* a) {
     40     ++test_count_;
     41     result_.append(*a);
     42   }
     43 
     44   void Test1Int(int a) {
     45     test_count_ += a;
     46   }
     47 
     48   void Test2Ptr(std::string* a, std::string* b) {
     49     ++test_count_;
     50     result_.append(*a);
     51     result_.append(*b);
     52   }
     53 
     54   void Test2Mixed(const std::string& a, std::string* b) {
     55     ++test_count_;
     56     result_.append(a);
     57     result_.append(*b);
     58   }
     59 
     60   int test_count() const { return test_count_; }
     61   const std::string& result() const { return result_; }
     62 
     63  private:
     64   friend class RefCounted<Foo>;
     65 
     66   ~Foo() {}
     67 
     68   int test_count_;
     69   std::string result_;
     70 
     71   DISALLOW_COPY_AND_ASSIGN(Foo);
     72 };
     73 
     74 // This function runs slowly to simulate a large amount of work being done.
     75 void SlowFunc(TimeDelta pause, int* quit_counter) {
     76     PlatformThread::Sleep(pause);
     77     if (--(*quit_counter) == 0)
     78       MessageLoop::current()->QuitWhenIdle();
     79 }
     80 
     81 // This function records the time when Run was called in a Time object, which is
     82 // useful for building a variety of MessageLoop tests.
     83 // TODO(sky): remove?
     84 void RecordRunTimeFunc(Time* run_time, int* quit_counter) {
     85   *run_time = Time::Now();
     86 
     87     // Cause our Run function to take some time to execute.  As a result we can
     88     // count on subsequent RecordRunTimeFunc()s running at a future time,
     89     // without worry about the resolution of our system clock being an issue.
     90   SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter);
     91 }
     92 
     93 }  // namespace
     94 
     95 void RunTest_PostTask(MessagePumpFactory factory) {
     96   std::unique_ptr<MessagePump> pump(factory());
     97   MessageLoop loop(std::move(pump));
     98   // Add tests to message loop
     99   scoped_refptr<Foo> foo(new Foo());
    100   std::string a("a"), b("b"), c("c"), d("d");
    101   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&Foo::Test0, foo));
    102   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    103                                           Bind(&Foo::Test1ConstRef, foo, a));
    104   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    105                                           Bind(&Foo::Test1Ptr, foo, &b));
    106   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    107                                           Bind(&Foo::Test1Int, foo, 100));
    108   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    109                                           Bind(&Foo::Test2Ptr, foo, &a, &c));
    110   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    111                                           Bind(&Foo::Test2Mixed, foo, a, &d));
    112   // After all tests, post a message that will shut down the message loop
    113   ThreadTaskRunnerHandle::Get()->PostTask(
    114       FROM_HERE,
    115       Bind(&MessageLoop::QuitWhenIdle, Unretained(MessageLoop::current())));
    116 
    117   // Now kick things off
    118   RunLoop().Run();
    119 
    120   EXPECT_EQ(foo->test_count(), 105);
    121   EXPECT_EQ(foo->result(), "abacad");
    122 }
    123 
    124 void RunTest_PostDelayedTask_Basic(MessagePumpFactory factory) {
    125   std::unique_ptr<MessagePump> pump(factory());
    126   MessageLoop loop(std::move(pump));
    127 
    128   // Test that PostDelayedTask results in a delayed task.
    129 
    130   const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
    131 
    132   int num_tasks = 1;
    133   Time run_time;
    134 
    135   loop.task_runner()->PostDelayedTask(
    136       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time, &num_tasks), kDelay);
    137 
    138   Time time_before_run = Time::Now();
    139   RunLoop().Run();
    140   Time time_after_run = Time::Now();
    141 
    142   EXPECT_EQ(0, num_tasks);
    143   EXPECT_LT(kDelay, time_after_run - time_before_run);
    144 }
    145 
    146 void RunTest_PostDelayedTask_InDelayOrder(MessagePumpFactory factory) {
    147   std::unique_ptr<MessagePump> pump(factory());
    148   MessageLoop loop(std::move(pump));
    149 
    150   // Test that two tasks with different delays run in the right order.
    151   int num_tasks = 2;
    152   Time run_time1, run_time2;
    153 
    154   loop.task_runner()->PostDelayedTask(
    155       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time1, &num_tasks),
    156       TimeDelta::FromMilliseconds(200));
    157   // If we get a large pause in execution (due to a context switch) here, this
    158   // test could fail.
    159   loop.task_runner()->PostDelayedTask(
    160       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time2, &num_tasks),
    161       TimeDelta::FromMilliseconds(10));
    162 
    163   RunLoop().Run();
    164   EXPECT_EQ(0, num_tasks);
    165 
    166   EXPECT_TRUE(run_time2 < run_time1);
    167 }
    168 
    169 void RunTest_PostDelayedTask_InPostOrder(MessagePumpFactory factory) {
    170   std::unique_ptr<MessagePump> pump(factory());
    171   MessageLoop loop(std::move(pump));
    172 
    173   // Test that two tasks with the same delay run in the order in which they
    174   // were posted.
    175   //
    176   // NOTE: This is actually an approximate test since the API only takes a
    177   // "delay" parameter, so we are not exactly simulating two tasks that get
    178   // posted at the exact same time.  It would be nice if the API allowed us to
    179   // specify the desired run time.
    180 
    181   const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
    182 
    183   int num_tasks = 2;
    184   Time run_time1, run_time2;
    185 
    186   loop.task_runner()->PostDelayedTask(
    187       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), kDelay);
    188   loop.task_runner()->PostDelayedTask(
    189       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), kDelay);
    190 
    191   RunLoop().Run();
    192   EXPECT_EQ(0, num_tasks);
    193 
    194   EXPECT_TRUE(run_time1 < run_time2);
    195 }
    196 
    197 void RunTest_PostDelayedTask_InPostOrder_2(MessagePumpFactory factory) {
    198   std::unique_ptr<MessagePump> pump(factory());
    199   MessageLoop loop(std::move(pump));
    200 
    201   // Test that a delayed task still runs after a normal tasks even if the
    202   // normal tasks take a long time to run.
    203 
    204   const TimeDelta kPause = TimeDelta::FromMilliseconds(50);
    205 
    206   int num_tasks = 2;
    207   Time run_time;
    208 
    209   loop.task_runner()->PostTask(FROM_HERE, Bind(&SlowFunc, kPause, &num_tasks));
    210   loop.task_runner()->PostDelayedTask(
    211       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
    212       TimeDelta::FromMilliseconds(10));
    213 
    214   Time time_before_run = Time::Now();
    215   RunLoop().Run();
    216   Time time_after_run = Time::Now();
    217 
    218   EXPECT_EQ(0, num_tasks);
    219 
    220   EXPECT_LT(kPause, time_after_run - time_before_run);
    221 }
    222 
    223 void RunTest_PostDelayedTask_InPostOrder_3(MessagePumpFactory factory) {
    224   std::unique_ptr<MessagePump> pump(factory());
    225   MessageLoop loop(std::move(pump));
    226 
    227   // Test that a delayed task still runs after a pile of normal tasks.  The key
    228   // difference between this test and the previous one is that here we return
    229   // the MessageLoop a lot so we give the MessageLoop plenty of opportunities
    230   // to maybe run the delayed task.  It should know not to do so until the
    231   // delayed task's delay has passed.
    232 
    233   int num_tasks = 11;
    234   Time run_time1, run_time2;
    235 
    236   // Clutter the ML with tasks.
    237   for (int i = 1; i < num_tasks; ++i)
    238     loop.task_runner()->PostTask(
    239         FROM_HERE, Bind(&RecordRunTimeFunc, &run_time1, &num_tasks));
    240 
    241   loop.task_runner()->PostDelayedTask(
    242       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time2, &num_tasks),
    243       TimeDelta::FromMilliseconds(1));
    244 
    245   RunLoop().Run();
    246   EXPECT_EQ(0, num_tasks);
    247 
    248   EXPECT_TRUE(run_time2 > run_time1);
    249 }
    250 
    251 void RunTest_PostDelayedTask_SharedTimer(MessagePumpFactory factory) {
    252   std::unique_ptr<MessagePump> pump(factory());
    253   MessageLoop loop(std::move(pump));
    254 
    255   // Test that the interval of the timer, used to run the next delayed task, is
    256   // set to a value corresponding to when the next delayed task should run.
    257 
    258   // By setting num_tasks to 1, we ensure that the first task to run causes the
    259   // run loop to exit.
    260   int num_tasks = 1;
    261   Time run_time1, run_time2;
    262 
    263   loop.task_runner()->PostDelayedTask(
    264       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time1, &num_tasks),
    265       TimeDelta::FromSeconds(1000));
    266   loop.task_runner()->PostDelayedTask(
    267       FROM_HERE, Bind(&RecordRunTimeFunc, &run_time2, &num_tasks),
    268       TimeDelta::FromMilliseconds(10));
    269 
    270   Time start_time = Time::Now();
    271 
    272   RunLoop().Run();
    273   EXPECT_EQ(0, num_tasks);
    274 
    275   // Ensure that we ran in far less time than the slower timer.
    276   TimeDelta total_time = Time::Now() - start_time;
    277   EXPECT_GT(5000, total_time.InMilliseconds());
    278 
    279   // In case both timers somehow run at nearly the same time, sleep a little
    280   // and then run all pending to force them both to have run.  This is just
    281   // encouraging flakiness if there is any.
    282   PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
    283   RunLoop().RunUntilIdle();
    284 
    285   EXPECT_TRUE(run_time1.is_null());
    286   EXPECT_FALSE(run_time2.is_null());
    287 }
    288 
    289 // This is used to inject a test point for recording the destructor calls for
    290 // Closure objects send to MessageLoop::PostTask(). It is awkward usage since we
    291 // are trying to hook the actual destruction, which is not a common operation.
    292 class RecordDeletionProbe : public RefCounted<RecordDeletionProbe> {
    293  public:
    294   RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
    295       : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {
    296   }
    297   void Run() {}
    298 
    299  private:
    300   friend class RefCounted<RecordDeletionProbe>;
    301 
    302   ~RecordDeletionProbe() {
    303     *was_deleted_ = true;
    304     if (post_on_delete_.get())
    305       ThreadTaskRunnerHandle::Get()->PostTask(
    306           FROM_HERE, Bind(&RecordDeletionProbe::Run, post_on_delete_));
    307   }
    308 
    309   scoped_refptr<RecordDeletionProbe> post_on_delete_;
    310   bool* was_deleted_;
    311 };
    312 
    313 void RunTest_EnsureDeletion(MessagePumpFactory factory) {
    314   bool a_was_deleted = false;
    315   bool b_was_deleted = false;
    316   {
    317     std::unique_ptr<MessagePump> pump(factory());
    318     MessageLoop loop(std::move(pump));
    319     loop.task_runner()->PostTask(
    320         FROM_HERE, Bind(&RecordDeletionProbe::Run,
    321                         new RecordDeletionProbe(NULL, &a_was_deleted)));
    322     // TODO(ajwong): Do we really need 1000ms here?
    323     loop.task_runner()->PostDelayedTask(
    324         FROM_HERE, Bind(&RecordDeletionProbe::Run,
    325                         new RecordDeletionProbe(NULL, &b_was_deleted)),
    326         TimeDelta::FromMilliseconds(1000));
    327   }
    328   EXPECT_TRUE(a_was_deleted);
    329   EXPECT_TRUE(b_was_deleted);
    330 }
    331 
    332 void RunTest_EnsureDeletion_Chain(MessagePumpFactory factory) {
    333   bool a_was_deleted = false;
    334   bool b_was_deleted = false;
    335   bool c_was_deleted = false;
    336   {
    337     std::unique_ptr<MessagePump> pump(factory());
    338     MessageLoop loop(std::move(pump));
    339     // The scoped_refptr for each of the below is held either by the chained
    340     // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback.
    341     RecordDeletionProbe* a = new RecordDeletionProbe(NULL, &a_was_deleted);
    342     RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted);
    343     RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted);
    344     loop.task_runner()->PostTask(FROM_HERE, Bind(&RecordDeletionProbe::Run, c));
    345   }
    346   EXPECT_TRUE(a_was_deleted);
    347   EXPECT_TRUE(b_was_deleted);
    348   EXPECT_TRUE(c_was_deleted);
    349 }
    350 
    351 void NestingFunc(int* depth) {
    352   if (*depth > 0) {
    353     *depth -= 1;
    354     ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    355                                             Bind(&NestingFunc, depth));
    356 
    357     MessageLoop::current()->SetNestableTasksAllowed(true);
    358     RunLoop().Run();
    359   }
    360   MessageLoop::current()->QuitWhenIdle();
    361 }
    362 
    363 void RunTest_Nesting(MessagePumpFactory factory) {
    364   std::unique_ptr<MessagePump> pump(factory());
    365   MessageLoop loop(std::move(pump));
    366 
    367   int depth = 100;
    368   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    369                                           Bind(&NestingFunc, &depth));
    370   RunLoop().Run();
    371   EXPECT_EQ(depth, 0);
    372 }
    373 
    374 // A NestingObserver that tracks the number of nested message loop starts it
    375 // has seen.
    376 class TestNestingObserver : public MessageLoop::NestingObserver {
    377  public:
    378   TestNestingObserver() {}
    379   ~TestNestingObserver() override {}
    380 
    381   int begin_nested_loop_count() const { return begin_nested_loop_count_; }
    382 
    383   // MessageLoop::NestingObserver:
    384   void OnBeginNestedMessageLoop() override { begin_nested_loop_count_++; }
    385 
    386  private:
    387   int begin_nested_loop_count_ = 0;
    388 
    389   DISALLOW_COPY_AND_ASSIGN(TestNestingObserver);
    390 };
    391 
    392 void ExpectOneBeginNestedLoop(TestNestingObserver* observer) {
    393   EXPECT_EQ(1, observer->begin_nested_loop_count());
    394 }
    395 
    396 // Starts a nested message loop.
    397 void RunNestedLoop(TestNestingObserver* observer,
    398                    const Closure& quit_outer_loop) {
    399   // The nested loop hasn't started yet.
    400   EXPECT_EQ(0, observer->begin_nested_loop_count());
    401 
    402   MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
    403   RunLoop nested_loop;
    404   // Verify that by the time the first task is run the observer has seen the
    405   // message loop begin.
    406   ThreadTaskRunnerHandle::Get()->PostTask(
    407       FROM_HERE, Bind(&ExpectOneBeginNestedLoop, observer));
    408   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, nested_loop.QuitClosure());
    409   nested_loop.Run();
    410 
    411   // Quitting message loops doesn't change the begin count.
    412   EXPECT_EQ(1, observer->begin_nested_loop_count());
    413 
    414   quit_outer_loop.Run();
    415 }
    416 
    417 // Tests that a NestingObserver is notified when a nested message loop begins.
    418 void RunTest_NestingObserver(MessagePumpFactory factory) {
    419   std::unique_ptr<MessagePump> pump(factory());
    420   MessageLoop outer_loop(std::move(pump));
    421 
    422   // Observe the outer loop for nested message loops beginning.
    423   TestNestingObserver nesting_observer;
    424   outer_loop.AddNestingObserver(&nesting_observer);
    425 
    426   // Post a task that runs a nested message loop.
    427   outer_loop.task_runner()->PostTask(FROM_HERE,
    428                                      Bind(&RunNestedLoop, &nesting_observer,
    429                                           outer_loop.QuitWhenIdleClosure()));
    430   RunLoop().Run();
    431 
    432   outer_loop.RemoveNestingObserver(&nesting_observer);
    433 }
    434 
    435 enum TaskType {
    436   MESSAGEBOX,
    437   ENDDIALOG,
    438   RECURSIVE,
    439   TIMEDMESSAGELOOP,
    440   QUITMESSAGELOOP,
    441   ORDERED,
    442   PUMPS,
    443   SLEEP,
    444   RUNS,
    445 };
    446 
    447 struct TaskItem {
    448   TaskItem(TaskType t, int c, bool s)
    449       : type(t),
    450         cookie(c),
    451         start(s) {
    452   }
    453 
    454   TaskType type;
    455   int cookie;
    456   bool start;
    457 
    458   bool operator == (const TaskItem& other) const {
    459     return type == other.type && cookie == other.cookie && start == other.start;
    460   }
    461 };
    462 
    463 std::ostream& operator <<(std::ostream& os, TaskType type) {
    464   switch (type) {
    465   case MESSAGEBOX:        os << "MESSAGEBOX"; break;
    466   case ENDDIALOG:         os << "ENDDIALOG"; break;
    467   case RECURSIVE:         os << "RECURSIVE"; break;
    468   case TIMEDMESSAGELOOP:  os << "TIMEDMESSAGELOOP"; break;
    469   case QUITMESSAGELOOP:   os << "QUITMESSAGELOOP"; break;
    470   case ORDERED:          os << "ORDERED"; break;
    471   case PUMPS:             os << "PUMPS"; break;
    472   case SLEEP:             os << "SLEEP"; break;
    473   default:
    474     NOTREACHED();
    475     os << "Unknown TaskType";
    476     break;
    477   }
    478   return os;
    479 }
    480 
    481 std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
    482   if (item.start)
    483     return os << item.type << " " << item.cookie << " starts";
    484   else
    485     return os << item.type << " " << item.cookie << " ends";
    486 }
    487 
    488 class TaskList {
    489  public:
    490   void RecordStart(TaskType type, int cookie) {
    491     TaskItem item(type, cookie, true);
    492     DVLOG(1) << item;
    493     task_list_.push_back(item);
    494   }
    495 
    496   void RecordEnd(TaskType type, int cookie) {
    497     TaskItem item(type, cookie, false);
    498     DVLOG(1) << item;
    499     task_list_.push_back(item);
    500   }
    501 
    502   size_t Size() {
    503     return task_list_.size();
    504   }
    505 
    506   TaskItem Get(int n)  {
    507     return task_list_[n];
    508   }
    509 
    510  private:
    511   std::vector<TaskItem> task_list_;
    512 };
    513 
    514 void RecursiveFunc(TaskList* order, int cookie, int depth,
    515                    bool is_reentrant) {
    516   order->RecordStart(RECURSIVE, cookie);
    517   if (depth > 0) {
    518     if (is_reentrant)
    519       MessageLoop::current()->SetNestableTasksAllowed(true);
    520     ThreadTaskRunnerHandle::Get()->PostTask(
    521         FROM_HERE,
    522         Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
    523   }
    524   order->RecordEnd(RECURSIVE, cookie);
    525 }
    526 
    527 void QuitFunc(TaskList* order, int cookie) {
    528   order->RecordStart(QUITMESSAGELOOP, cookie);
    529   MessageLoop::current()->QuitWhenIdle();
    530   order->RecordEnd(QUITMESSAGELOOP, cookie);
    531 }
    532 void RunTest_RecursiveDenial1(MessagePumpFactory factory) {
    533   std::unique_ptr<MessagePump> pump(factory());
    534   MessageLoop loop(std::move(pump));
    535 
    536   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
    537   TaskList order;
    538   ThreadTaskRunnerHandle::Get()->PostTask(
    539       FROM_HERE, Bind(&RecursiveFunc, &order, 1, 2, false));
    540   ThreadTaskRunnerHandle::Get()->PostTask(
    541       FROM_HERE, Bind(&RecursiveFunc, &order, 2, 2, false));
    542   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    543                                           Bind(&QuitFunc, &order, 3));
    544 
    545   RunLoop().Run();
    546 
    547   // FIFO order.
    548   ASSERT_EQ(14U, order.Size());
    549   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
    550   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
    551   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
    552   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
    553   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
    554   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
    555   EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
    556   EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
    557   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
    558   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
    559   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
    560   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
    561   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
    562   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
    563 }
    564 
    565 void RecursiveSlowFunc(TaskList* order, int cookie, int depth,
    566                        bool is_reentrant) {
    567   RecursiveFunc(order, cookie, depth, is_reentrant);
    568   PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
    569 }
    570 
    571 void OrderedFunc(TaskList* order, int cookie) {
    572   order->RecordStart(ORDERED, cookie);
    573   order->RecordEnd(ORDERED, cookie);
    574 }
    575 
    576 void RunTest_RecursiveDenial3(MessagePumpFactory factory) {
    577   std::unique_ptr<MessagePump> pump(factory());
    578   MessageLoop loop(std::move(pump));
    579 
    580   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
    581   TaskList order;
    582   ThreadTaskRunnerHandle::Get()->PostTask(
    583       FROM_HERE, Bind(&RecursiveSlowFunc, &order, 1, 2, false));
    584   ThreadTaskRunnerHandle::Get()->PostTask(
    585       FROM_HERE, Bind(&RecursiveSlowFunc, &order, 2, 2, false));
    586   ThreadTaskRunnerHandle::Get()->PostDelayedTask(
    587       FROM_HERE, Bind(&OrderedFunc, &order, 3), TimeDelta::FromMilliseconds(5));
    588   ThreadTaskRunnerHandle::Get()->PostDelayedTask(
    589       FROM_HERE, Bind(&QuitFunc, &order, 4), TimeDelta::FromMilliseconds(5));
    590 
    591   RunLoop().Run();
    592 
    593   // FIFO order.
    594   ASSERT_EQ(16U, order.Size());
    595   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
    596   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
    597   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
    598   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
    599   EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true));
    600   EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false));
    601   EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 3, true));
    602   EXPECT_EQ(order.Get(7), TaskItem(ORDERED, 3, false));
    603   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
    604   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
    605   EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true));
    606   EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false));
    607   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true));
    608   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false));
    609   EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true));
    610   EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false));
    611 }
    612 
    613 void RunTest_RecursiveSupport1(MessagePumpFactory factory) {
    614   std::unique_ptr<MessagePump> pump(factory());
    615   MessageLoop loop(std::move(pump));
    616 
    617   TaskList order;
    618   ThreadTaskRunnerHandle::Get()->PostTask(
    619       FROM_HERE, Bind(&RecursiveFunc, &order, 1, 2, true));
    620   ThreadTaskRunnerHandle::Get()->PostTask(
    621       FROM_HERE, Bind(&RecursiveFunc, &order, 2, 2, true));
    622   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    623                                           Bind(&QuitFunc, &order, 3));
    624 
    625   RunLoop().Run();
    626 
    627   // FIFO order.
    628   ASSERT_EQ(14U, order.Size());
    629   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
    630   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
    631   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
    632   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
    633   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
    634   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
    635   EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
    636   EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
    637   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
    638   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
    639   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
    640   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
    641   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
    642   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
    643 }
    644 
    645 // Tests that non nestable tasks run in FIFO if there are no nested loops.
    646 void RunTest_NonNestableWithNoNesting(MessagePumpFactory factory) {
    647   std::unique_ptr<MessagePump> pump(factory());
    648   MessageLoop loop(std::move(pump));
    649 
    650   TaskList order;
    651 
    652   ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
    653       FROM_HERE, Bind(&OrderedFunc, &order, 1));
    654   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    655                                           Bind(&OrderedFunc, &order, 2));
    656   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    657                                           Bind(&QuitFunc, &order, 3));
    658   RunLoop().Run();
    659 
    660   // FIFO order.
    661   ASSERT_EQ(6U, order.Size());
    662   EXPECT_EQ(order.Get(0), TaskItem(ORDERED, 1, true));
    663   EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 1, false));
    664   EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 2, true));
    665   EXPECT_EQ(order.Get(3), TaskItem(ORDERED, 2, false));
    666   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
    667   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
    668 }
    669 
    670 void FuncThatPumps(TaskList* order, int cookie) {
    671   order->RecordStart(PUMPS, cookie);
    672   {
    673     MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
    674     RunLoop().RunUntilIdle();
    675   }
    676   order->RecordEnd(PUMPS, cookie);
    677 }
    678 
    679 void SleepFunc(TaskList* order, int cookie, TimeDelta delay) {
    680   order->RecordStart(SLEEP, cookie);
    681   PlatformThread::Sleep(delay);
    682   order->RecordEnd(SLEEP, cookie);
    683 }
    684 
    685 // Tests that non nestable tasks don't run when there's code in the call stack.
    686 void RunTest_NonNestableInNestedLoop(MessagePumpFactory factory) {
    687   std::unique_ptr<MessagePump> pump(factory());
    688   MessageLoop loop(std::move(pump));
    689 
    690   TaskList order;
    691 
    692   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    693                                           Bind(&FuncThatPumps, &order, 1));
    694   ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
    695       FROM_HERE, Bind(&OrderedFunc, &order, 2));
    696   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    697                                           Bind(&OrderedFunc, &order, 3));
    698   ThreadTaskRunnerHandle::Get()->PostTask(
    699       FROM_HERE, Bind(&SleepFunc, &order, 4, TimeDelta::FromMilliseconds(50)));
    700   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    701                                           Bind(&OrderedFunc, &order, 5));
    702   ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
    703       FROM_HERE, Bind(&QuitFunc, &order, 6));
    704 
    705   RunLoop().Run();
    706 
    707   // FIFO order.
    708   ASSERT_EQ(12U, order.Size());
    709   EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
    710   EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 3, true));
    711   EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 3, false));
    712   EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
    713   EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
    714   EXPECT_EQ(order.Get(5), TaskItem(ORDERED, 5, true));
    715   EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 5, false));
    716   EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
    717   EXPECT_EQ(order.Get(8), TaskItem(ORDERED, 2, true));
    718   EXPECT_EQ(order.Get(9), TaskItem(ORDERED, 2, false));
    719   EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
    720   EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
    721 }
    722 
    723 void FuncThatRuns(TaskList* order, int cookie, RunLoop* run_loop) {
    724   order->RecordStart(RUNS, cookie);
    725   {
    726     MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
    727     run_loop->Run();
    728   }
    729   order->RecordEnd(RUNS, cookie);
    730 }
    731 
    732 void FuncThatQuitsNow() {
    733   MessageLoop::current()->QuitNow();
    734 }
    735 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
    736 void RunTest_QuitNow(MessagePumpFactory factory) {
    737   std::unique_ptr<MessagePump> pump(factory());
    738   MessageLoop loop(std::move(pump));
    739 
    740   TaskList order;
    741 
    742   RunLoop run_loop;
    743 
    744   ThreadTaskRunnerHandle::Get()->PostTask(
    745       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
    746   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    747                                           Bind(&OrderedFunc, &order, 2));
    748   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&FuncThatQuitsNow));
    749   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    750                                           Bind(&OrderedFunc, &order, 3));
    751   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&FuncThatQuitsNow));
    752   ThreadTaskRunnerHandle::Get()->PostTask(
    753       FROM_HERE, Bind(&OrderedFunc, &order, 4));  // never runs
    754 
    755   RunLoop().Run();
    756 
    757   ASSERT_EQ(6U, order.Size());
    758   int task_index = 0;
    759   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
    760   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
    761   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
    762   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
    763   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
    764   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
    765   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
    766 }
    767 
    768 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
    769 void RunTest_RunLoopQuitTop(MessagePumpFactory factory) {
    770   std::unique_ptr<MessagePump> pump(factory());
    771   MessageLoop loop(std::move(pump));
    772 
    773   TaskList order;
    774 
    775   RunLoop outer_run_loop;
    776   RunLoop nested_run_loop;
    777 
    778   ThreadTaskRunnerHandle::Get()->PostTask(
    779       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
    780   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    781                                           outer_run_loop.QuitClosure());
    782   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    783                                           Bind(&OrderedFunc, &order, 2));
    784   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    785                                           nested_run_loop.QuitClosure());
    786 
    787   outer_run_loop.Run();
    788 
    789   ASSERT_EQ(4U, order.Size());
    790   int task_index = 0;
    791   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
    792   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
    793   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
    794   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
    795   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
    796 }
    797 
    798 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
    799 void RunTest_RunLoopQuitNested(MessagePumpFactory factory) {
    800   std::unique_ptr<MessagePump> pump(factory());
    801   MessageLoop loop(std::move(pump));
    802 
    803   TaskList order;
    804 
    805   RunLoop outer_run_loop;
    806   RunLoop nested_run_loop;
    807 
    808   ThreadTaskRunnerHandle::Get()->PostTask(
    809       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
    810   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    811                                           nested_run_loop.QuitClosure());
    812   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    813                                           Bind(&OrderedFunc, &order, 2));
    814   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    815                                           outer_run_loop.QuitClosure());
    816 
    817   outer_run_loop.Run();
    818 
    819   ASSERT_EQ(4U, order.Size());
    820   int task_index = 0;
    821   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
    822   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
    823   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
    824   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
    825   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
    826 }
    827 
    828 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
    829 void RunTest_RunLoopQuitBogus(MessagePumpFactory factory) {
    830   std::unique_ptr<MessagePump> pump(factory());
    831   MessageLoop loop(std::move(pump));
    832 
    833   TaskList order;
    834 
    835   RunLoop outer_run_loop;
    836   RunLoop nested_run_loop;
    837   RunLoop bogus_run_loop;
    838 
    839   ThreadTaskRunnerHandle::Get()->PostTask(
    840       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
    841   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    842                                           bogus_run_loop.QuitClosure());
    843   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    844                                           Bind(&OrderedFunc, &order, 2));
    845   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    846                                           outer_run_loop.QuitClosure());
    847   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    848                                           nested_run_loop.QuitClosure());
    849 
    850   outer_run_loop.Run();
    851 
    852   ASSERT_EQ(4U, order.Size());
    853   int task_index = 0;
    854   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
    855   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
    856   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
    857   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
    858   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
    859 }
    860 
    861 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
    862 void RunTest_RunLoopQuitDeep(MessagePumpFactory factory) {
    863   std::unique_ptr<MessagePump> pump(factory());
    864   MessageLoop loop(std::move(pump));
    865 
    866   TaskList order;
    867 
    868   RunLoop outer_run_loop;
    869   RunLoop nested_loop1;
    870   RunLoop nested_loop2;
    871   RunLoop nested_loop3;
    872   RunLoop nested_loop4;
    873 
    874   ThreadTaskRunnerHandle::Get()->PostTask(
    875       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_loop1)));
    876   ThreadTaskRunnerHandle::Get()->PostTask(
    877       FROM_HERE, Bind(&FuncThatRuns, &order, 2, Unretained(&nested_loop2)));
    878   ThreadTaskRunnerHandle::Get()->PostTask(
    879       FROM_HERE, Bind(&FuncThatRuns, &order, 3, Unretained(&nested_loop3)));
    880   ThreadTaskRunnerHandle::Get()->PostTask(
    881       FROM_HERE, Bind(&FuncThatRuns, &order, 4, Unretained(&nested_loop4)));
    882   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    883                                           Bind(&OrderedFunc, &order, 5));
    884   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    885                                           outer_run_loop.QuitClosure());
    886   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    887                                           Bind(&OrderedFunc, &order, 6));
    888   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    889                                           nested_loop1.QuitClosure());
    890   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    891                                           Bind(&OrderedFunc, &order, 7));
    892   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    893                                           nested_loop2.QuitClosure());
    894   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    895                                           Bind(&OrderedFunc, &order, 8));
    896   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    897                                           nested_loop3.QuitClosure());
    898   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    899                                           Bind(&OrderedFunc, &order, 9));
    900   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    901                                           nested_loop4.QuitClosure());
    902   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    903                                           Bind(&OrderedFunc, &order, 10));
    904 
    905   outer_run_loop.Run();
    906 
    907   ASSERT_EQ(18U, order.Size());
    908   int task_index = 0;
    909   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
    910   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, true));
    911   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, true));
    912   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, true));
    913   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, true));
    914   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, false));
    915   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, true));
    916   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, false));
    917   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, true));
    918   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, false));
    919   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, true));
    920   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, false));
    921   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, true));
    922   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, false));
    923   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, false));
    924   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, false));
    925   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, false));
    926   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
    927   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
    928 }
    929 
    930 // Tests RunLoopQuit works before RunWithID.
    931 void RunTest_RunLoopQuitOrderBefore(MessagePumpFactory factory) {
    932   std::unique_ptr<MessagePump> pump(factory());
    933   MessageLoop loop(std::move(pump));
    934 
    935   TaskList order;
    936 
    937   RunLoop run_loop;
    938 
    939   run_loop.Quit();
    940 
    941   ThreadTaskRunnerHandle::Get()->PostTask(
    942       FROM_HERE, Bind(&OrderedFunc, &order, 1));  // never runs
    943   ThreadTaskRunnerHandle::Get()->PostTask(
    944       FROM_HERE, Bind(&FuncThatQuitsNow));  // never runs
    945 
    946   run_loop.Run();
    947 
    948   ASSERT_EQ(0U, order.Size());
    949 }
    950 
    951 // Tests RunLoopQuit works during RunWithID.
    952 void RunTest_RunLoopQuitOrderDuring(MessagePumpFactory factory) {
    953   std::unique_ptr<MessagePump> pump(factory());
    954   MessageLoop loop(std::move(pump));
    955 
    956   TaskList order;
    957 
    958   RunLoop run_loop;
    959 
    960   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    961                                           Bind(&OrderedFunc, &order, 1));
    962   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
    963   ThreadTaskRunnerHandle::Get()->PostTask(
    964       FROM_HERE, Bind(&OrderedFunc, &order, 2));  // never runs
    965   ThreadTaskRunnerHandle::Get()->PostTask(
    966       FROM_HERE, Bind(&FuncThatQuitsNow));  // never runs
    967 
    968   run_loop.Run();
    969 
    970   ASSERT_EQ(2U, order.Size());
    971   int task_index = 0;
    972   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, true));
    973   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, false));
    974   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
    975 }
    976 
    977 // Tests RunLoopQuit works after RunWithID.
    978 void RunTest_RunLoopQuitOrderAfter(MessagePumpFactory factory) {
    979   std::unique_ptr<MessagePump> pump(factory());
    980   MessageLoop loop(std::move(pump));
    981 
    982   TaskList order;
    983 
    984   RunLoop run_loop;
    985 
    986   ThreadTaskRunnerHandle::Get()->PostTask(
    987       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
    988   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    989                                           Bind(&OrderedFunc, &order, 2));
    990   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&FuncThatQuitsNow));
    991   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    992                                           Bind(&OrderedFunc, &order, 3));
    993   ThreadTaskRunnerHandle::Get()->PostTask(
    994       FROM_HERE, run_loop.QuitClosure());  // has no affect
    995   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
    996                                           Bind(&OrderedFunc, &order, 4));
    997   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, Bind(&FuncThatQuitsNow));
    998 
    999   RunLoop outer_run_loop;
   1000   outer_run_loop.Run();
   1001 
   1002   ASSERT_EQ(8U, order.Size());
   1003   int task_index = 0;
   1004   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
   1005   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
   1006   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
   1007   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
   1008   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
   1009   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
   1010   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, true));
   1011   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, false));
   1012   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
   1013 }
   1014 
   1015 void PostNTasksThenQuit(int posts_remaining) {
   1016   if (posts_remaining > 1) {
   1017     ThreadTaskRunnerHandle::Get()->PostTask(
   1018         FROM_HERE, Bind(&PostNTasksThenQuit, posts_remaining - 1));
   1019   } else {
   1020     MessageLoop::current()->QuitWhenIdle();
   1021   }
   1022 }
   1023 
   1024 // There was a bug in the MessagePumpGLib where posting tasks recursively
   1025 // caused the message loop to hang, due to the buffer of the internal pipe
   1026 // becoming full. Test all MessageLoop types to ensure this issue does not
   1027 // exist in other MessagePumps.
   1028 //
   1029 // On Linux, the pipe buffer size is 64KiB by default. The bug caused one
   1030 // byte accumulated in the pipe per two posts, so we should repeat 128K
   1031 // times to reproduce the bug.
   1032 void RunTest_RecursivePosts(MessagePumpFactory factory) {
   1033   const int kNumTimes = 1 << 17;
   1034   std::unique_ptr<MessagePump> pump(factory());
   1035   MessageLoop loop(std::move(pump));
   1036   loop.task_runner()->PostTask(FROM_HERE, Bind(&PostNTasksThenQuit, kNumTimes));
   1037   RunLoop().Run();
   1038 }
   1039 
   1040 }  // namespace test
   1041 }  // namespace base
   1042