• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 namespace base {
20 namespace test {
21 
22 namespace {
23 
24 class Foo : public RefCounted<Foo> {
25  public:
Foo()26   Foo() : test_count_(0) {
27   }
28 
Test0()29   void Test0() {
30     ++test_count_;
31   }
32 
Test1ConstRef(const std::string & a)33   void Test1ConstRef(const std::string& a) {
34     ++test_count_;
35     result_.append(a);
36   }
37 
Test1Ptr(std::string * a)38   void Test1Ptr(std::string* a) {
39     ++test_count_;
40     result_.append(*a);
41   }
42 
Test1Int(int a)43   void Test1Int(int a) {
44     test_count_ += a;
45   }
46 
Test2Ptr(std::string * a,std::string * b)47   void Test2Ptr(std::string* a, std::string* b) {
48     ++test_count_;
49     result_.append(*a);
50     result_.append(*b);
51   }
52 
Test2Mixed(const std::string & a,std::string * b)53   void Test2Mixed(const std::string& a, std::string* b) {
54     ++test_count_;
55     result_.append(a);
56     result_.append(*b);
57   }
58 
test_count() const59   int test_count() const { return test_count_; }
result() const60   const std::string& result() const { return result_; }
61 
62  private:
63   friend class RefCounted<Foo>;
64 
~Foo()65   ~Foo() {}
66 
67   int test_count_;
68   std::string result_;
69 
70   DISALLOW_COPY_AND_ASSIGN(Foo);
71 };
72 
73 // This function runs slowly to simulate a large amount of work being done.
SlowFunc(TimeDelta pause,int * quit_counter)74 void SlowFunc(TimeDelta pause, int* quit_counter) {
75     PlatformThread::Sleep(pause);
76     if (--(*quit_counter) == 0)
77       MessageLoop::current()->QuitWhenIdle();
78 }
79 
80 // This function records the time when Run was called in a Time object, which is
81 // useful for building a variety of MessageLoop tests.
82 // TODO(sky): remove?
RecordRunTimeFunc(Time * run_time,int * quit_counter)83 void RecordRunTimeFunc(Time* run_time, int* quit_counter) {
84   *run_time = Time::Now();
85 
86     // Cause our Run function to take some time to execute.  As a result we can
87     // count on subsequent RecordRunTimeFunc()s running at a future time,
88     // without worry about the resolution of our system clock being an issue.
89   SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter);
90 }
91 
92 }  // namespace
93 
RunTest_PostTask(MessagePumpFactory factory)94 void RunTest_PostTask(MessagePumpFactory factory) {
95   std::unique_ptr<MessagePump> pump(factory());
96   MessageLoop loop(std::move(pump));
97   // Add tests to message loop
98   scoped_refptr<Foo> foo(new Foo());
99   std::string a("a"), b("b"), c("c"), d("d");
100   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
101                                                   Bind(&Foo::Test0, foo.get()));
102   MessageLoop::current()->task_runner()->PostTask(
103       FROM_HERE, Bind(&Foo::Test1ConstRef, foo.get(), a));
104   MessageLoop::current()->task_runner()->PostTask(
105       FROM_HERE, Bind(&Foo::Test1Ptr, foo.get(), &b));
106   MessageLoop::current()->task_runner()->PostTask(
107       FROM_HERE, Bind(&Foo::Test1Int, foo.get(), 100));
108   MessageLoop::current()->task_runner()->PostTask(
109       FROM_HERE, Bind(&Foo::Test2Ptr, foo.get(), &a, &c));
110   MessageLoop::current()->task_runner()->PostTask(
111       FROM_HERE, Bind(&Foo::Test2Mixed, foo.get(), a, &d));
112   // After all tests, post a message that will shut down the message loop
113   MessageLoop::current()->task_runner()->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 
RunTest_PostDelayedTask_Basic(MessagePumpFactory factory)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 
RunTest_PostDelayedTask_InDelayOrder(MessagePumpFactory factory)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 
RunTest_PostDelayedTask_InPostOrder(MessagePumpFactory factory)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 
RunTest_PostDelayedTask_InPostOrder_2(MessagePumpFactory factory)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 
RunTest_PostDelayedTask_InPostOrder_3(MessagePumpFactory factory)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 
RunTest_PostDelayedTask_SharedTimer(MessagePumpFactory factory)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:
RecordDeletionProbe(RecordDeletionProbe * post_on_delete,bool * was_deleted)294   RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
295       : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {
296   }
Run()297   void Run() {}
298 
299  private:
300   friend class RefCounted<RecordDeletionProbe>;
301 
~RecordDeletionProbe()302   ~RecordDeletionProbe() {
303     *was_deleted_ = true;
304     if (post_on_delete_.get())
305       MessageLoop::current()->task_runner()->PostTask(
306           FROM_HERE, Bind(&RecordDeletionProbe::Run, post_on_delete_.get()));
307   }
308 
309   scoped_refptr<RecordDeletionProbe> post_on_delete_;
310   bool* was_deleted_;
311 };
312 
RunTest_EnsureDeletion(MessagePumpFactory factory)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 
RunTest_EnsureDeletion_Chain(MessagePumpFactory factory)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 
NestingFunc(int * depth)351 void NestingFunc(int* depth) {
352   if (*depth > 0) {
353     *depth -= 1;
354     MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
355                                                     Bind(&NestingFunc, depth));
356 
357     MessageLoop::current()->SetNestableTasksAllowed(true);
358     RunLoop().Run();
359   }
360   MessageLoop::current()->QuitWhenIdle();
361 }
362 
RunTest_Nesting(MessagePumpFactory factory)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   MessageLoop::current()->task_runner()->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:
TestNestingObserver()378   TestNestingObserver() {}
~TestNestingObserver()379   ~TestNestingObserver() override {}
380 
begin_nested_loop_count() const381   int begin_nested_loop_count() const { return begin_nested_loop_count_; }
382 
383   // MessageLoop::NestingObserver:
OnBeginNestedMessageLoop()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 
ExpectOneBeginNestedLoop(TestNestingObserver * observer)392 void ExpectOneBeginNestedLoop(TestNestingObserver* observer) {
393   EXPECT_EQ(1, observer->begin_nested_loop_count());
394 }
395 
396 // Starts a nested message loop.
RunNestedLoop(TestNestingObserver * observer,const Closure & quit_outer_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   MessageLoop::current()->task_runner()->PostTask(
407       FROM_HERE, Bind(&ExpectOneBeginNestedLoop, observer));
408   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
409                                                   nested_loop.QuitClosure());
410   nested_loop.Run();
411 
412   // Quitting message loops doesn't change the begin count.
413   EXPECT_EQ(1, observer->begin_nested_loop_count());
414 
415   quit_outer_loop.Run();
416 }
417 
418 // Tests that a NestingObserver is notified when a nested message loop begins.
RunTest_NestingObserver(MessagePumpFactory factory)419 void RunTest_NestingObserver(MessagePumpFactory factory) {
420   std::unique_ptr<MessagePump> pump(factory());
421   MessageLoop outer_loop(std::move(pump));
422 
423   // Observe the outer loop for nested message loops beginning.
424   TestNestingObserver nesting_observer;
425   outer_loop.AddNestingObserver(&nesting_observer);
426 
427   // Post a task that runs a nested message loop.
428   outer_loop.task_runner()->PostTask(FROM_HERE,
429                                      Bind(&RunNestedLoop, &nesting_observer,
430                                           outer_loop.QuitWhenIdleClosure()));
431   RunLoop().Run();
432 
433   outer_loop.RemoveNestingObserver(&nesting_observer);
434 }
435 
436 enum TaskType {
437   MESSAGEBOX,
438   ENDDIALOG,
439   RECURSIVE,
440   TIMEDMESSAGELOOP,
441   QUITMESSAGELOOP,
442   ORDERED,
443   PUMPS,
444   SLEEP,
445   RUNS,
446 };
447 
448 struct TaskItem {
TaskItembase::test::TaskItem449   TaskItem(TaskType t, int c, bool s)
450       : type(t),
451         cookie(c),
452         start(s) {
453   }
454 
455   TaskType type;
456   int cookie;
457   bool start;
458 
operator ==base::test::TaskItem459   bool operator == (const TaskItem& other) const {
460     return type == other.type && cookie == other.cookie && start == other.start;
461   }
462 };
463 
operator <<(std::ostream & os,TaskType type)464 std::ostream& operator <<(std::ostream& os, TaskType type) {
465   switch (type) {
466   case MESSAGEBOX:        os << "MESSAGEBOX"; break;
467   case ENDDIALOG:         os << "ENDDIALOG"; break;
468   case RECURSIVE:         os << "RECURSIVE"; break;
469   case TIMEDMESSAGELOOP:  os << "TIMEDMESSAGELOOP"; break;
470   case QUITMESSAGELOOP:   os << "QUITMESSAGELOOP"; break;
471   case ORDERED:          os << "ORDERED"; break;
472   case PUMPS:             os << "PUMPS"; break;
473   case SLEEP:             os << "SLEEP"; break;
474   default:
475     NOTREACHED();
476     os << "Unknown TaskType";
477     break;
478   }
479   return os;
480 }
481 
operator <<(std::ostream & os,const TaskItem & item)482 std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
483   if (item.start)
484     return os << item.type << " " << item.cookie << " starts";
485   else
486     return os << item.type << " " << item.cookie << " ends";
487 }
488 
489 class TaskList {
490  public:
RecordStart(TaskType type,int cookie)491   void RecordStart(TaskType type, int cookie) {
492     TaskItem item(type, cookie, true);
493     DVLOG(1) << item;
494     task_list_.push_back(item);
495   }
496 
RecordEnd(TaskType type,int cookie)497   void RecordEnd(TaskType type, int cookie) {
498     TaskItem item(type, cookie, false);
499     DVLOG(1) << item;
500     task_list_.push_back(item);
501   }
502 
Size()503   size_t Size() {
504     return task_list_.size();
505   }
506 
Get(int n)507   TaskItem Get(int n)  {
508     return task_list_[n];
509   }
510 
511  private:
512   std::vector<TaskItem> task_list_;
513 };
514 
RecursiveFunc(TaskList * order,int cookie,int depth,bool is_reentrant)515 void RecursiveFunc(TaskList* order, int cookie, int depth,
516                    bool is_reentrant) {
517   order->RecordStart(RECURSIVE, cookie);
518   if (depth > 0) {
519     if (is_reentrant)
520       MessageLoop::current()->SetNestableTasksAllowed(true);
521     MessageLoop::current()->task_runner()->PostTask(
522         FROM_HERE,
523         Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
524   }
525   order->RecordEnd(RECURSIVE, cookie);
526 }
527 
QuitFunc(TaskList * order,int cookie)528 void QuitFunc(TaskList* order, int cookie) {
529   order->RecordStart(QUITMESSAGELOOP, cookie);
530   MessageLoop::current()->QuitWhenIdle();
531   order->RecordEnd(QUITMESSAGELOOP, cookie);
532 }
RunTest_RecursiveDenial1(MessagePumpFactory factory)533 void RunTest_RecursiveDenial1(MessagePumpFactory factory) {
534   std::unique_ptr<MessagePump> pump(factory());
535   MessageLoop loop(std::move(pump));
536 
537   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
538   TaskList order;
539   MessageLoop::current()->task_runner()->PostTask(
540       FROM_HERE, Bind(&RecursiveFunc, &order, 1, 2, false));
541   MessageLoop::current()->task_runner()->PostTask(
542       FROM_HERE, Bind(&RecursiveFunc, &order, 2, 2, false));
543   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
544                                                   Bind(&QuitFunc, &order, 3));
545 
546   RunLoop().Run();
547 
548   // FIFO order.
549   ASSERT_EQ(14U, order.Size());
550   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
551   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
552   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
553   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
554   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
555   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
556   EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
557   EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
558   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
559   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
560   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
561   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
562   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
563   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
564 }
565 
RecursiveSlowFunc(TaskList * order,int cookie,int depth,bool is_reentrant)566 void RecursiveSlowFunc(TaskList* order, int cookie, int depth,
567                        bool is_reentrant) {
568   RecursiveFunc(order, cookie, depth, is_reentrant);
569   PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
570 }
571 
OrderedFunc(TaskList * order,int cookie)572 void OrderedFunc(TaskList* order, int cookie) {
573   order->RecordStart(ORDERED, cookie);
574   order->RecordEnd(ORDERED, cookie);
575 }
576 
RunTest_RecursiveDenial3(MessagePumpFactory factory)577 void RunTest_RecursiveDenial3(MessagePumpFactory factory) {
578   std::unique_ptr<MessagePump> pump(factory());
579   MessageLoop loop(std::move(pump));
580 
581   EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
582   TaskList order;
583   MessageLoop::current()->task_runner()->PostTask(
584       FROM_HERE, Bind(&RecursiveSlowFunc, &order, 1, 2, false));
585   MessageLoop::current()->task_runner()->PostTask(
586       FROM_HERE, Bind(&RecursiveSlowFunc, &order, 2, 2, false));
587   MessageLoop::current()->task_runner()->PostDelayedTask(
588       FROM_HERE, Bind(&OrderedFunc, &order, 3), TimeDelta::FromMilliseconds(5));
589   MessageLoop::current()->task_runner()->PostDelayedTask(
590       FROM_HERE, Bind(&QuitFunc, &order, 4), TimeDelta::FromMilliseconds(5));
591 
592   RunLoop().Run();
593 
594   // FIFO order.
595   ASSERT_EQ(16U, order.Size());
596   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
597   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
598   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
599   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
600   EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true));
601   EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false));
602   EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 3, true));
603   EXPECT_EQ(order.Get(7), TaskItem(ORDERED, 3, false));
604   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
605   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
606   EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true));
607   EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false));
608   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true));
609   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false));
610   EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true));
611   EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false));
612 }
613 
RunTest_RecursiveSupport1(MessagePumpFactory factory)614 void RunTest_RecursiveSupport1(MessagePumpFactory factory) {
615   std::unique_ptr<MessagePump> pump(factory());
616   MessageLoop loop(std::move(pump));
617 
618   TaskList order;
619   MessageLoop::current()->task_runner()->PostTask(
620       FROM_HERE, Bind(&RecursiveFunc, &order, 1, 2, true));
621   MessageLoop::current()->task_runner()->PostTask(
622       FROM_HERE, Bind(&RecursiveFunc, &order, 2, 2, true));
623   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
624                                                   Bind(&QuitFunc, &order, 3));
625 
626   RunLoop().Run();
627 
628   // FIFO order.
629   ASSERT_EQ(14U, order.Size());
630   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
631   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
632   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
633   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
634   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
635   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
636   EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
637   EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
638   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
639   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
640   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
641   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
642   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
643   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
644 }
645 
646 // Tests that non nestable tasks run in FIFO if there are no nested loops.
RunTest_NonNestableWithNoNesting(MessagePumpFactory factory)647 void RunTest_NonNestableWithNoNesting(MessagePumpFactory factory) {
648   std::unique_ptr<MessagePump> pump(factory());
649   MessageLoop loop(std::move(pump));
650 
651   TaskList order;
652 
653   MessageLoop::current()->task_runner()->PostNonNestableTask(
654       FROM_HERE,
655       Bind(&OrderedFunc, &order, 1));
656   MessageLoop::current()->task_runner()->PostTask(
657       FROM_HERE,
658       Bind(&OrderedFunc, &order, 2));
659   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
660                                                   Bind(&QuitFunc, &order, 3));
661   RunLoop().Run();
662 
663   // FIFO order.
664   ASSERT_EQ(6U, order.Size());
665   EXPECT_EQ(order.Get(0), TaskItem(ORDERED, 1, true));
666   EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 1, false));
667   EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 2, true));
668   EXPECT_EQ(order.Get(3), TaskItem(ORDERED, 2, false));
669   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
670   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
671 }
672 
FuncThatPumps(TaskList * order,int cookie)673 void FuncThatPumps(TaskList* order, int cookie) {
674   order->RecordStart(PUMPS, cookie);
675   {
676     MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
677     RunLoop().RunUntilIdle();
678   }
679   order->RecordEnd(PUMPS, cookie);
680 }
681 
SleepFunc(TaskList * order,int cookie,TimeDelta delay)682 void SleepFunc(TaskList* order, int cookie, TimeDelta delay) {
683   order->RecordStart(SLEEP, cookie);
684   PlatformThread::Sleep(delay);
685   order->RecordEnd(SLEEP, cookie);
686 }
687 
688 // Tests that non nestable tasks don't run when there's code in the call stack.
RunTest_NonNestableInNestedLoop(MessagePumpFactory factory)689 void RunTest_NonNestableInNestedLoop(MessagePumpFactory factory) {
690   std::unique_ptr<MessagePump> pump(factory());
691   MessageLoop loop(std::move(pump));
692 
693   TaskList order;
694 
695   MessageLoop::current()->task_runner()->PostTask(
696       FROM_HERE,
697       Bind(&FuncThatPumps, &order, 1));
698   MessageLoop::current()->task_runner()->PostNonNestableTask(
699       FROM_HERE,
700       Bind(&OrderedFunc, &order, 2));
701   MessageLoop::current()->task_runner()->PostTask(
702       FROM_HERE,
703       Bind(&OrderedFunc, &order, 3));
704   MessageLoop::current()->task_runner()->PostTask(
705       FROM_HERE,
706       Bind(&SleepFunc, &order, 4, TimeDelta::FromMilliseconds(50)));
707   MessageLoop::current()->task_runner()->PostTask(
708       FROM_HERE,
709       Bind(&OrderedFunc, &order, 5));
710   MessageLoop::current()->task_runner()->PostNonNestableTask(
711       FROM_HERE,
712       Bind(&QuitFunc, &order, 6));
713 
714   RunLoop().Run();
715 
716   // FIFO order.
717   ASSERT_EQ(12U, order.Size());
718   EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
719   EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 3, true));
720   EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 3, false));
721   EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
722   EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
723   EXPECT_EQ(order.Get(5), TaskItem(ORDERED, 5, true));
724   EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 5, false));
725   EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
726   EXPECT_EQ(order.Get(8), TaskItem(ORDERED, 2, true));
727   EXPECT_EQ(order.Get(9), TaskItem(ORDERED, 2, false));
728   EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
729   EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
730 }
731 
FuncThatRuns(TaskList * order,int cookie,RunLoop * run_loop)732 void FuncThatRuns(TaskList* order, int cookie, RunLoop* run_loop) {
733   order->RecordStart(RUNS, cookie);
734   {
735     MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
736     run_loop->Run();
737   }
738   order->RecordEnd(RUNS, cookie);
739 }
740 
FuncThatQuitsNow()741 void FuncThatQuitsNow() {
742   MessageLoop::current()->QuitNow();
743 }
744 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
RunTest_QuitNow(MessagePumpFactory factory)745 void RunTest_QuitNow(MessagePumpFactory factory) {
746   std::unique_ptr<MessagePump> pump(factory());
747   MessageLoop loop(std::move(pump));
748 
749   TaskList order;
750 
751   RunLoop run_loop;
752 
753   MessageLoop::current()->task_runner()->PostTask(
754       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
755   MessageLoop::current()->task_runner()->PostTask(
756       FROM_HERE, Bind(&OrderedFunc, &order, 2));
757   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
758                                                   Bind(&FuncThatQuitsNow));
759   MessageLoop::current()->task_runner()->PostTask(
760       FROM_HERE, Bind(&OrderedFunc, &order, 3));
761   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
762                                                   Bind(&FuncThatQuitsNow));
763   MessageLoop::current()->task_runner()->PostTask(
764       FROM_HERE, Bind(&OrderedFunc, &order, 4));  // never runs
765 
766   RunLoop().Run();
767 
768   ASSERT_EQ(6U, order.Size());
769   int task_index = 0;
770   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
771   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
772   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
773   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
774   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
775   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
776   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
777 }
778 
779 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
RunTest_RunLoopQuitTop(MessagePumpFactory factory)780 void RunTest_RunLoopQuitTop(MessagePumpFactory factory) {
781   std::unique_ptr<MessagePump> pump(factory());
782   MessageLoop loop(std::move(pump));
783 
784   TaskList order;
785 
786   RunLoop outer_run_loop;
787   RunLoop nested_run_loop;
788 
789   MessageLoop::current()->task_runner()->PostTask(
790       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
791   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
792                                                   outer_run_loop.QuitClosure());
793   MessageLoop::current()->task_runner()->PostTask(
794       FROM_HERE, Bind(&OrderedFunc, &order, 2));
795   MessageLoop::current()->task_runner()->PostTask(
796       FROM_HERE, nested_run_loop.QuitClosure());
797 
798   outer_run_loop.Run();
799 
800   ASSERT_EQ(4U, order.Size());
801   int task_index = 0;
802   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
803   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
804   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
805   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
806   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
807 }
808 
809 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
RunTest_RunLoopQuitNested(MessagePumpFactory factory)810 void RunTest_RunLoopQuitNested(MessagePumpFactory factory) {
811   std::unique_ptr<MessagePump> pump(factory());
812   MessageLoop loop(std::move(pump));
813 
814   TaskList order;
815 
816   RunLoop outer_run_loop;
817   RunLoop nested_run_loop;
818 
819   MessageLoop::current()->task_runner()->PostTask(
820       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
821   MessageLoop::current()->task_runner()->PostTask(
822       FROM_HERE, nested_run_loop.QuitClosure());
823   MessageLoop::current()->task_runner()->PostTask(
824       FROM_HERE, Bind(&OrderedFunc, &order, 2));
825   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
826                                                   outer_run_loop.QuitClosure());
827 
828   outer_run_loop.Run();
829 
830   ASSERT_EQ(4U, order.Size());
831   int task_index = 0;
832   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
833   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
834   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
835   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
836   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
837 }
838 
839 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
RunTest_RunLoopQuitBogus(MessagePumpFactory factory)840 void RunTest_RunLoopQuitBogus(MessagePumpFactory factory) {
841   std::unique_ptr<MessagePump> pump(factory());
842   MessageLoop loop(std::move(pump));
843 
844   TaskList order;
845 
846   RunLoop outer_run_loop;
847   RunLoop nested_run_loop;
848   RunLoop bogus_run_loop;
849 
850   MessageLoop::current()->task_runner()->PostTask(
851       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
852   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
853                                                   bogus_run_loop.QuitClosure());
854   MessageLoop::current()->task_runner()->PostTask(
855       FROM_HERE, Bind(&OrderedFunc, &order, 2));
856   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
857                                                   outer_run_loop.QuitClosure());
858   MessageLoop::current()->task_runner()->PostTask(
859       FROM_HERE, nested_run_loop.QuitClosure());
860 
861   outer_run_loop.Run();
862 
863   ASSERT_EQ(4U, order.Size());
864   int task_index = 0;
865   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
866   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
867   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
868   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
869   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
870 }
871 
872 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
RunTest_RunLoopQuitDeep(MessagePumpFactory factory)873 void RunTest_RunLoopQuitDeep(MessagePumpFactory factory) {
874   std::unique_ptr<MessagePump> pump(factory());
875   MessageLoop loop(std::move(pump));
876 
877   TaskList order;
878 
879   RunLoop outer_run_loop;
880   RunLoop nested_loop1;
881   RunLoop nested_loop2;
882   RunLoop nested_loop3;
883   RunLoop nested_loop4;
884 
885   MessageLoop::current()->task_runner()->PostTask(
886       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&nested_loop1)));
887   MessageLoop::current()->task_runner()->PostTask(
888       FROM_HERE, Bind(&FuncThatRuns, &order, 2, Unretained(&nested_loop2)));
889   MessageLoop::current()->task_runner()->PostTask(
890       FROM_HERE, Bind(&FuncThatRuns, &order, 3, Unretained(&nested_loop3)));
891   MessageLoop::current()->task_runner()->PostTask(
892       FROM_HERE, Bind(&FuncThatRuns, &order, 4, Unretained(&nested_loop4)));
893   MessageLoop::current()->task_runner()->PostTask(
894       FROM_HERE, Bind(&OrderedFunc, &order, 5));
895   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
896                                                   outer_run_loop.QuitClosure());
897   MessageLoop::current()->task_runner()->PostTask(
898       FROM_HERE, Bind(&OrderedFunc, &order, 6));
899   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
900                                                   nested_loop1.QuitClosure());
901   MessageLoop::current()->task_runner()->PostTask(
902       FROM_HERE, Bind(&OrderedFunc, &order, 7));
903   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
904                                                   nested_loop2.QuitClosure());
905   MessageLoop::current()->task_runner()->PostTask(
906       FROM_HERE, Bind(&OrderedFunc, &order, 8));
907   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
908                                                   nested_loop3.QuitClosure());
909   MessageLoop::current()->task_runner()->PostTask(
910       FROM_HERE, Bind(&OrderedFunc, &order, 9));
911   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
912                                                   nested_loop4.QuitClosure());
913   MessageLoop::current()->task_runner()->PostTask(
914       FROM_HERE, Bind(&OrderedFunc, &order, 10));
915 
916   outer_run_loop.Run();
917 
918   ASSERT_EQ(18U, order.Size());
919   int task_index = 0;
920   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
921   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, true));
922   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, true));
923   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, true));
924   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, true));
925   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, false));
926   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, true));
927   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, false));
928   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, true));
929   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, false));
930   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, true));
931   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, false));
932   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, true));
933   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, false));
934   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, false));
935   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, false));
936   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, false));
937   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
938   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
939 }
940 
941 // Tests RunLoopQuit works before RunWithID.
RunTest_RunLoopQuitOrderBefore(MessagePumpFactory factory)942 void RunTest_RunLoopQuitOrderBefore(MessagePumpFactory factory) {
943   std::unique_ptr<MessagePump> pump(factory());
944   MessageLoop loop(std::move(pump));
945 
946   TaskList order;
947 
948   RunLoop run_loop;
949 
950   run_loop.Quit();
951 
952   MessageLoop::current()->task_runner()->PostTask(
953       FROM_HERE, Bind(&OrderedFunc, &order, 1));  // never runs
954   MessageLoop::current()->task_runner()->PostTask(
955       FROM_HERE, Bind(&FuncThatQuitsNow));  // never runs
956 
957   run_loop.Run();
958 
959   ASSERT_EQ(0U, order.Size());
960 }
961 
962 // Tests RunLoopQuit works during RunWithID.
RunTest_RunLoopQuitOrderDuring(MessagePumpFactory factory)963 void RunTest_RunLoopQuitOrderDuring(MessagePumpFactory factory) {
964   std::unique_ptr<MessagePump> pump(factory());
965   MessageLoop loop(std::move(pump));
966 
967   TaskList order;
968 
969   RunLoop run_loop;
970 
971   MessageLoop::current()->task_runner()->PostTask(
972       FROM_HERE, Bind(&OrderedFunc, &order, 1));
973   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
974                                                   run_loop.QuitClosure());
975   MessageLoop::current()->task_runner()->PostTask(
976       FROM_HERE, Bind(&OrderedFunc, &order, 2));  // never runs
977   MessageLoop::current()->task_runner()->PostTask(
978       FROM_HERE, Bind(&FuncThatQuitsNow));  // never runs
979 
980   run_loop.Run();
981 
982   ASSERT_EQ(2U, order.Size());
983   int task_index = 0;
984   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, true));
985   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, false));
986   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
987 }
988 
989 // Tests RunLoopQuit works after RunWithID.
RunTest_RunLoopQuitOrderAfter(MessagePumpFactory factory)990 void RunTest_RunLoopQuitOrderAfter(MessagePumpFactory factory) {
991   std::unique_ptr<MessagePump> pump(factory());
992   MessageLoop loop(std::move(pump));
993 
994   TaskList order;
995 
996   RunLoop run_loop;
997 
998   MessageLoop::current()->task_runner()->PostTask(
999       FROM_HERE, Bind(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
1000   MessageLoop::current()->task_runner()->PostTask(
1001       FROM_HERE, Bind(&OrderedFunc, &order, 2));
1002   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
1003                                                   Bind(&FuncThatQuitsNow));
1004   MessageLoop::current()->task_runner()->PostTask(
1005       FROM_HERE, Bind(&OrderedFunc, &order, 3));
1006   MessageLoop::current()->task_runner()->PostTask(
1007       FROM_HERE, run_loop.QuitClosure());  // has no affect
1008   MessageLoop::current()->task_runner()->PostTask(
1009       FROM_HERE, Bind(&OrderedFunc, &order, 4));
1010   MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
1011                                                   Bind(&FuncThatQuitsNow));
1012 
1013   RunLoop outer_run_loop;
1014   outer_run_loop.Run();
1015 
1016   ASSERT_EQ(8U, order.Size());
1017   int task_index = 0;
1018   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1019   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1020   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1021   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1022   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
1023   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
1024   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, true));
1025   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, false));
1026   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1027 }
1028 
PostNTasksThenQuit(int posts_remaining)1029 void PostNTasksThenQuit(int posts_remaining) {
1030   if (posts_remaining > 1) {
1031     MessageLoop::current()->task_runner()->PostTask(
1032         FROM_HERE, Bind(&PostNTasksThenQuit, posts_remaining - 1));
1033   } else {
1034     MessageLoop::current()->QuitWhenIdle();
1035   }
1036 }
1037 
1038 // There was a bug in the MessagePumpGLib where posting tasks recursively
1039 // caused the message loop to hang, due to the buffer of the internal pipe
1040 // becoming full. Test all MessageLoop types to ensure this issue does not
1041 // exist in other MessagePumps.
1042 //
1043 // On Linux, the pipe buffer size is 64KiB by default. The bug caused one
1044 // byte accumulated in the pipe per two posts, so we should repeat 128K
1045 // times to reproduce the bug.
RunTest_RecursivePosts(MessagePumpFactory factory)1046 void RunTest_RecursivePosts(MessagePumpFactory factory) {
1047   const int kNumTimes = 1 << 17;
1048   std::unique_ptr<MessagePump> pump(factory());
1049   MessageLoop loop(std::move(pump));
1050   loop.task_runner()->PostTask(FROM_HERE, Bind(&PostNTasksThenQuit, kNumTimes));
1051   RunLoop().Run();
1052 }
1053 
1054 }  // namespace test
1055 }  // namespace base
1056