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
19namespace base {
20namespace test {
21
22namespace {
23
24class Foo : public RefCounted<Foo> {
25 public:
26  Foo() : test_count_(0) {
27  }
28
29  void Test0() {
30    ++test_count_;
31  }
32
33  void Test1ConstRef(const std::string& a) {
34    ++test_count_;
35    result_.append(a);
36  }
37
38  void Test1Ptr(std::string* a) {
39    ++test_count_;
40    result_.append(*a);
41  }
42
43  void Test1Int(int a) {
44    test_count_ += a;
45  }
46
47  void Test2Ptr(std::string* a, std::string* b) {
48    ++test_count_;
49    result_.append(*a);
50    result_.append(*b);
51  }
52
53  void Test2Mixed(const std::string& a, std::string* b) {
54    ++test_count_;
55    result_.append(a);
56    result_.append(*b);
57  }
58
59  int test_count() const { return test_count_; }
60  const std::string& result() const { return result_; }
61
62 private:
63  friend class RefCounted<Foo>;
64
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.
74void 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?
83void 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
94void 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
124void 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
146void 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
169void 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
197void 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
223void 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
251void 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.
292class 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      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
313void 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
332void 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
351void 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
363void 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.
376class 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
392void ExpectOneBeginNestedLoop(TestNestingObserver* observer) {
393  EXPECT_EQ(1, observer->begin_nested_loop_count());
394}
395
396// Starts a nested message loop.
397void 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.
419void 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
436enum TaskType {
437  MESSAGEBOX,
438  ENDDIALOG,
439  RECURSIVE,
440  TIMEDMESSAGELOOP,
441  QUITMESSAGELOOP,
442  ORDERED,
443  PUMPS,
444  SLEEP,
445  RUNS,
446};
447
448struct TaskItem {
449  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
459  bool operator == (const TaskItem& other) const {
460    return type == other.type && cookie == other.cookie && start == other.start;
461  }
462};
463
464std::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
482std::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
489class TaskList {
490 public:
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
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
503  size_t Size() {
504    return task_list_.size();
505  }
506
507  TaskItem Get(int n)  {
508    return task_list_[n];
509  }
510
511 private:
512  std::vector<TaskItem> task_list_;
513};
514
515void 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
528void QuitFunc(TaskList* order, int cookie) {
529  order->RecordStart(QUITMESSAGELOOP, cookie);
530  MessageLoop::current()->QuitWhenIdle();
531  order->RecordEnd(QUITMESSAGELOOP, cookie);
532}
533void 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
566void 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
572void OrderedFunc(TaskList* order, int cookie) {
573  order->RecordStart(ORDERED, cookie);
574  order->RecordEnd(ORDERED, cookie);
575}
576
577void 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
614void 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.
647void 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
673void 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
682void 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.
689void 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
732void 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
741void FuncThatQuitsNow() {
742  MessageLoop::current()->QuitNow();
743}
744// Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
745void 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.
780void 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.
810void 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.
840void 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.
873void 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.
942void 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.
963void 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.
990void 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
1029void 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.
1046void 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