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