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