Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(538)

Side by Side Diff: base/message_loop_unittest.cc

Issue 6463013: Add support for base::Closure in the MessageLoop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: rebased Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/message_loop.cc ('k') | chrome/browser/jankometer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h"
7 #include "base/eintr_wrapper.h" 10 #include "base/eintr_wrapper.h"
8 #include "base/logging.h" 11 #include "base/logging.h"
9 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
10 #include "base/message_loop.h" 13 #include "base/message_loop.h"
11 #include "base/task.h" 14 #include "base/task.h"
12 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
13 #include "base/threading/thread.h" 16 #include "base/threading/thread.h"
14 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
15 18
16 #if defined(OS_WIN) 19 #if defined(OS_WIN)
17 #include "base/message_pump_win.h" 20 #include "base/message_pump_win.h"
18 #include "base/win/scoped_handle.h" 21 #include "base/win/scoped_handle.h"
19 #endif 22 #endif
20 #if defined(OS_POSIX) 23 #if defined(OS_POSIX)
21 #include "base/message_pump_libevent.h" 24 #include "base/message_pump_libevent.h"
22 #endif 25 #endif
23 26
24 using base::PlatformThread; 27 using base::PlatformThread;
25 using base::Thread; 28 using base::Thread;
26 using base::Time; 29 using base::Time;
27 using base::TimeDelta; 30 using base::TimeDelta;
31 using base::TimeTicks;
28 32
29 // TODO(darin): Platform-specific MessageLoop tests should be grouped together 33 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
30 // to avoid chopping this file up with so many #ifdefs. 34 // to avoid chopping this file up with so many #ifdefs.
31 35
32 namespace { 36 namespace {
33 37
34 class MessageLoopTest : public testing::Test {}; 38 class MessageLoopTest : public testing::Test {};
35 39
36 class Foo : public base::RefCounted<Foo> { 40 class Foo : public base::RefCounted<Foo> {
37 public: 41 public:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 77
74 private: 78 private:
75 friend class base::RefCounted<Foo>; 79 friend class base::RefCounted<Foo>;
76 80
77 ~Foo() {} 81 ~Foo() {}
78 82
79 int test_count_; 83 int test_count_;
80 std::string result_; 84 std::string result_;
81 }; 85 };
82 86
83 class QuitMsgLoop : public base::RefCounted<QuitMsgLoop> { 87 // TODO(ajwong): Remove this once we've finished getting rid of the PostTask()
84 public: 88 // compatibility methods.
85 void QuitNow() { 89 void RunTest_PostLegacyTask(MessageLoop::Type message_loop_type) {
86 MessageLoop::current()->Quit();
87 }
88
89 private:
90 friend class base::RefCounted<QuitMsgLoop>;
91
92 ~QuitMsgLoop() {}
93 };
94
95 void RunTest_PostTask(MessageLoop::Type message_loop_type) {
96 MessageLoop loop(message_loop_type); 90 MessageLoop loop(message_loop_type);
97 91
98 // Add tests to message loop 92 // Add tests to message loop
99 scoped_refptr<Foo> foo(new Foo()); 93 scoped_refptr<Foo> foo(new Foo());
100 std::string a("a"), b("b"), c("c"), d("d"); 94 std::string a("a"), b("b"), c("c"), d("d");
101 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 95 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
102 foo.get(), &Foo::Test0)); 96 foo.get(), &Foo::Test0));
103 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 97 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
104 foo.get(), &Foo::Test1ConstRef, a)); 98 foo.get(), &Foo::Test1ConstRef, a));
105 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 99 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
106 foo.get(), &Foo::Test1Ptr, &b)); 100 foo.get(), &Foo::Test1Ptr, &b));
107 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 101 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
108 foo.get(), &Foo::Test1Int, 100)); 102 foo.get(), &Foo::Test1Int, 100));
109 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 103 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
110 foo.get(), &Foo::Test2Ptr, &a, &c)); 104 foo.get(), &Foo::Test2Ptr, &a, &c));
111 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 105 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
112 foo.get(), &Foo::Test2Mixed, a, &d)); 106 foo.get(), &Foo::Test2Mixed, a, &d));
113 107
114 // After all tests, post a message that will shut down the message loop 108 // After all tests, post a message that will shut down the message loop
115 scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop()); 109 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
116 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 110 &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
117 quit.get(), &QuitMsgLoop::QuitNow));
118 111
119 // Now kick things off 112 // Now kick things off
120 MessageLoop::current()->Run(); 113 MessageLoop::current()->Run();
114
115 EXPECT_EQ(foo->test_count(), 105);
116 EXPECT_EQ(foo->result(), "abacad");
117 }
118
119 void RunTest_PostTask(MessageLoop::Type message_loop_type) {
120 MessageLoop loop(message_loop_type);
121
122 // Add tests to message loop
123 scoped_refptr<Foo> foo(new Foo());
124 std::string a("a"), b("b"), c("c"), d("d");
125 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
126 &Foo::Test0, foo.get()));
127 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
128 &Foo::Test1ConstRef, foo.get(), a));
129 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
130 &Foo::Test1Ptr, foo.get(), &b));
131 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
132 &Foo::Test1Int, foo.get(), 100));
133 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
134 &Foo::Test2Ptr, foo.get(), &a, &c));
135 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
136 &Foo::Test2Mixed, foo.get(), a, &d));
137
138 // After all tests, post a message that will shut down the message loop
139 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
140 &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
141
142 // Now kick things off
143 MessageLoop::current()->Run();
121 144
122 EXPECT_EQ(foo->test_count(), 105); 145 EXPECT_EQ(foo->test_count(), 105);
123 EXPECT_EQ(foo->result(), "abacad"); 146 EXPECT_EQ(foo->result(), "abacad");
124 } 147 }
125 148
126 void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type) { 149 void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type) {
127 MessageLoop loop(message_loop_type); 150 MessageLoop loop(message_loop_type);
128 151
129 // Add tests to message loop 152 // Add tests to message loop
130 scoped_refptr<Foo> foo(new Foo()); 153 scoped_refptr<Foo> foo(new Foo());
131 std::string a("a"), b("b"), c("c"), d("d"); 154 std::string a("a"), b("b"), c("c"), d("d");
132 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 155 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
133 foo.get(), &Foo::Test0)); 156 &Foo::Test0, foo.get()));
134 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 157 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
135 foo.get(), &Foo::Test1ConstRef, a)); 158 &Foo::Test1ConstRef, foo.get(), a));
136 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 159 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
137 foo.get(), &Foo::Test1Ptr, &b)); 160 &Foo::Test1Ptr, foo.get(), &b));
138 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 161 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
139 foo.get(), &Foo::Test1Int, 100)); 162 &Foo::Test1Int, foo.get(), 100));
140 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 163 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
141 foo.get(), &Foo::Test2Ptr, &a, &c)); 164 &Foo::Test2Ptr, foo.get(), &a, &c));
142 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 165 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
143 foo.get(), &Foo::Test2Mixed, a, &d)); 166 &Foo::Test2Mixed, foo.get(), a, &d));
144 167
145 // After all tests, post a message that will shut down the message loop 168 // After all tests, post a message that will shut down the message loop
146 scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop()); 169 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
147 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 170 &MessageLoop::Quit, base::Unretained(MessageLoop::current())));
148 quit.get(), &QuitMsgLoop::QuitNow));
149 171
150 // Now kick things off with the SEH block active. 172 // Now kick things off with the SEH block active.
151 MessageLoop::current()->set_exception_restoration(true); 173 MessageLoop::current()->set_exception_restoration(true);
152 MessageLoop::current()->Run(); 174 MessageLoop::current()->Run();
153 MessageLoop::current()->set_exception_restoration(false); 175 MessageLoop::current()->set_exception_restoration(false);
154 176
155 EXPECT_EQ(foo->test_count(), 105); 177 EXPECT_EQ(foo->test_count(), 105);
156 EXPECT_EQ(foo->result(), "abacad"); 178 EXPECT_EQ(foo->result(), "abacad");
157 } 179 }
158 180
159 // This class runs slowly to simulate a large amount of work being done. 181 // This function runs slowly to simulate a large amount of work being done.
160 class SlowTask : public Task { 182 static void SlowFunc(int pause_ms, int* quit_counter) {
161 public: 183 PlatformThread::Sleep(pause_ms);
162 SlowTask(int pause_ms, int* quit_counter) 184 if (--(*quit_counter) == 0)
163 : pause_ms_(pause_ms), quit_counter_(quit_counter) {
164 }
165 virtual void Run() {
166 PlatformThread::Sleep(pause_ms_);
167 if (--(*quit_counter_) == 0)
168 MessageLoop::current()->Quit(); 185 MessageLoop::current()->Quit();
169 } 186 }
170 private:
171 int pause_ms_;
172 int* quit_counter_;
173 };
174 187
175 // This class records the time when Run was called in a Time object, which is 188 // This function records the time when Run was called in a Time object, which is
176 // useful for building a variety of MessageLoop tests. 189 // useful for building a variety of MessageLoop tests.
177 class RecordRunTimeTask : public SlowTask { 190 static void RecordRunTimeFunc(Time* run_time, int* quit_counter) {
178 public: 191 *run_time = Time::Now();
179 RecordRunTimeTask(Time* run_time, int* quit_counter) 192
180 : SlowTask(10, quit_counter), run_time_(run_time) {
181 }
182 virtual void Run() {
183 *run_time_ = Time::Now();
184 // Cause our Run function to take some time to execute. As a result we can 193 // Cause our Run function to take some time to execute. As a result we can
185 // count on subsequent RecordRunTimeTask objects running at a future time, 194 // count on subsequent RecordRunTimeFunc()s running at a future time,
186 // without worry about the resolution of our system clock being an issue. 195 // without worry about the resolution of our system clock being an issue.
187 SlowTask::Run(); 196 SlowFunc(10, quit_counter);
188 } 197 }
189 private:
190 Time* run_time_;
191 };
192 198
193 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) { 199 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) {
194 MessageLoop loop(message_loop_type); 200 MessageLoop loop(message_loop_type);
195 201
196 // Test that PostDelayedTask results in a delayed task. 202 // Test that PostDelayedTask results in a delayed task.
197 203
198 const int kDelayMS = 100; 204 const int kDelayMS = 100;
199 205
200 int num_tasks = 1; 206 int num_tasks = 1;
201 Time run_time; 207 Time run_time;
202 208
203 loop.PostDelayedTask( 209 loop.PostDelayedTask(
204 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), kDelayMS); 210 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
211 kDelayMS);
205 212
206 Time time_before_run = Time::Now(); 213 Time time_before_run = Time::Now();
207 loop.Run(); 214 loop.Run();
208 Time time_after_run = Time::Now(); 215 Time time_after_run = Time::Now();
209 216
210 EXPECT_EQ(0, num_tasks); 217 EXPECT_EQ(0, num_tasks);
211 EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds()); 218 EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds());
212 } 219 }
213 220
214 void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type) { 221 void RunTest_PostDelayedTask_InDelayOrder(
222 MessageLoop::Type message_loop_type) {
215 MessageLoop loop(message_loop_type); 223 MessageLoop loop(message_loop_type);
216 224
217 // Test that two tasks with different delays run in the right order. 225 // Test that two tasks with different delays run in the right order.
218
219 int num_tasks = 2; 226 int num_tasks = 2;
220 Time run_time1, run_time2; 227 Time run_time1, run_time2;
221 228
222 loop.PostDelayedTask( 229 loop.PostDelayedTask(
223 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 200); 230 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), 200);
224 // If we get a large pause in execution (due to a context switch) here, this 231 // If we get a large pause in execution (due to a context switch) here, this
225 // test could fail. 232 // test could fail.
226 loop.PostDelayedTask( 233 loop.PostDelayedTask(
227 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10); 234 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 10);
228 235
229 loop.Run(); 236 loop.Run();
230 EXPECT_EQ(0, num_tasks); 237 EXPECT_EQ(0, num_tasks);
231 238
232 EXPECT_TRUE(run_time2 < run_time1); 239 EXPECT_TRUE(run_time2 < run_time1);
233 } 240 }
234 241
235 void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type) { 242 void RunTest_PostDelayedTask_InPostOrder(
243 MessageLoop::Type message_loop_type) {
236 MessageLoop loop(message_loop_type); 244 MessageLoop loop(message_loop_type);
237 245
238 // Test that two tasks with the same delay run in the order in which they 246 // Test that two tasks with the same delay run in the order in which they
239 // were posted. 247 // were posted.
240 // 248 //
241 // NOTE: This is actually an approximate test since the API only takes a 249 // NOTE: This is actually an approximate test since the API only takes a
242 // "delay" parameter, so we are not exactly simulating two tasks that get 250 // "delay" parameter, so we are not exactly simulating two tasks that get
243 // posted at the exact same time. It would be nice if the API allowed us to 251 // posted at the exact same time. It would be nice if the API allowed us to
244 // specify the desired run time. 252 // specify the desired run time.
245 253
246 const int kDelayMS = 100; 254 const int kDelayMS = 100;
247 255
248 int num_tasks = 2; 256 int num_tasks = 2;
249 Time run_time1, run_time2; 257 Time run_time1, run_time2;
250 258
251 loop.PostDelayedTask( 259 loop.PostDelayedTask(
252 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), kDelayMS); 260 FROM_HERE,
261 base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), kDelayMS);
253 loop.PostDelayedTask( 262 loop.PostDelayedTask(
254 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), kDelayMS); 263 FROM_HERE,
264 base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), kDelayMS);
255 265
256 loop.Run(); 266 loop.Run();
257 EXPECT_EQ(0, num_tasks); 267 EXPECT_EQ(0, num_tasks);
258 268
259 EXPECT_TRUE(run_time1 < run_time2); 269 EXPECT_TRUE(run_time1 < run_time2);
260 } 270 }
261 271
262 void RunTest_PostDelayedTask_InPostOrder_2( 272 void RunTest_PostDelayedTask_InPostOrder_2(
263 MessageLoop::Type message_loop_type) { 273 MessageLoop::Type message_loop_type) {
264 MessageLoop loop(message_loop_type); 274 MessageLoop loop(message_loop_type);
265 275
266 // Test that a delayed task still runs after a normal tasks even if the 276 // Test that a delayed task still runs after a normal tasks even if the
267 // normal tasks take a long time to run. 277 // normal tasks take a long time to run.
268 278
269 const int kPauseMS = 50; 279 const int kPauseMS = 50;
270 280
271 int num_tasks = 2; 281 int num_tasks = 2;
272 Time run_time; 282 Time run_time;
273 283
274 loop.PostTask( 284 loop.PostTask(FROM_HERE, base::Bind(&SlowFunc, kPauseMS, &num_tasks));
275 FROM_HERE, new SlowTask(kPauseMS, &num_tasks));
276 loop.PostDelayedTask( 285 loop.PostDelayedTask(
277 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 10); 286 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks), 10);
278 287
279 Time time_before_run = Time::Now(); 288 Time time_before_run = Time::Now();
280 loop.Run(); 289 loop.Run();
281 Time time_after_run = Time::Now(); 290 Time time_after_run = Time::Now();
282 291
283 EXPECT_EQ(0, num_tasks); 292 EXPECT_EQ(0, num_tasks);
284 293
285 EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds()); 294 EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds());
286 } 295 }
287 296
288 void RunTest_PostDelayedTask_InPostOrder_3( 297 void RunTest_PostDelayedTask_InPostOrder_3(
289 MessageLoop::Type message_loop_type) { 298 MessageLoop::Type message_loop_type) {
290 MessageLoop loop(message_loop_type); 299 MessageLoop loop(message_loop_type);
291 300
292 // Test that a delayed task still runs after a pile of normal tasks. The key 301 // Test that a delayed task still runs after a pile of normal tasks. The key
293 // difference between this test and the previous one is that here we return 302 // difference between this test and the previous one is that here we return
294 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities 303 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities
295 // to maybe run the delayed task. It should know not to do so until the 304 // to maybe run the delayed task. It should know not to do so until the
296 // delayed task's delay has passed. 305 // delayed task's delay has passed.
297 306
298 int num_tasks = 11; 307 int num_tasks = 11;
299 Time run_time1, run_time2; 308 Time run_time1, run_time2;
300 309
301 // Clutter the ML with tasks. 310 // Clutter the ML with tasks.
302 for (int i = 1; i < num_tasks; ++i) 311 for (int i = 1; i < num_tasks; ++i)
303 loop.PostTask(FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks)); 312 loop.PostTask(FROM_HERE,
313 base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks));
304 314
305 loop.PostDelayedTask( 315 loop.PostDelayedTask(
306 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 1); 316 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 1);
307 317
308 loop.Run(); 318 loop.Run();
309 EXPECT_EQ(0, num_tasks); 319 EXPECT_EQ(0, num_tasks);
310 320
311 EXPECT_TRUE(run_time2 > run_time1); 321 EXPECT_TRUE(run_time2 > run_time1);
312 } 322 }
313 323
314 void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type) { 324 void RunTest_PostDelayedTask_SharedTimer(
325 MessageLoop::Type message_loop_type) {
315 MessageLoop loop(message_loop_type); 326 MessageLoop loop(message_loop_type);
316 327
317 // Test that the interval of the timer, used to run the next delayed task, is 328 // Test that the interval of the timer, used to run the next delayed task, is
318 // set to a value corresponding to when the next delayed task should run. 329 // set to a value corresponding to when the next delayed task should run.
319 330
320 // By setting num_tasks to 1, we ensure that the first task to run causes the 331 // By setting num_tasks to 1, we ensure that the first task to run causes the
321 // run loop to exit. 332 // run loop to exit.
322 int num_tasks = 1; 333 int num_tasks = 1;
323 Time run_time1, run_time2; 334 Time run_time1, run_time2;
324 335
325 loop.PostDelayedTask( 336 loop.PostDelayedTask(
326 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 1000000); 337 FROM_HERE,
338 base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks),
339 1000000);
327 loop.PostDelayedTask( 340 loop.PostDelayedTask(
328 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10); 341 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 10);
329 342
330 Time start_time = Time::Now(); 343 Time start_time = Time::Now();
331 344
332 loop.Run(); 345 loop.Run();
333 EXPECT_EQ(0, num_tasks); 346 EXPECT_EQ(0, num_tasks);
334 347
335 // Ensure that we ran in far less time than the slower timer. 348 // Ensure that we ran in far less time than the slower timer.
336 TimeDelta total_time = Time::Now() - start_time; 349 TimeDelta total_time = Time::Now() - start_time;
337 EXPECT_GT(5000, total_time.InMilliseconds()); 350 EXPECT_GT(5000, total_time.InMilliseconds());
338 351
339 // In case both timers somehow run at nearly the same time, sleep a little 352 // In case both timers somehow run at nearly the same time, sleep a little
340 // and then run all pending to force them both to have run. This is just 353 // and then run all pending to force them both to have run. This is just
341 // encouraging flakiness if there is any. 354 // encouraging flakiness if there is any.
342 PlatformThread::Sleep(100); 355 PlatformThread::Sleep(100);
343 loop.RunAllPending(); 356 loop.RunAllPending();
344 357
345 EXPECT_TRUE(run_time1.is_null()); 358 EXPECT_TRUE(run_time1.is_null());
346 EXPECT_FALSE(run_time2.is_null()); 359 EXPECT_FALSE(run_time2.is_null());
347 } 360 }
348 361
349 #if defined(OS_WIN) 362 #if defined(OS_WIN)
350 363
351 class SubPumpTask : public Task { 364 void SubPumpFunc() {
352 public: 365 MessageLoop::current()->SetNestableTasksAllowed(true);
353 virtual void Run() { 366 MSG msg;
354 MessageLoop::current()->SetNestableTasksAllowed(true); 367 while (GetMessage(&msg, NULL, 0, 0)) {
355 MSG msg; 368 TranslateMessage(&msg);
356 while (GetMessage(&msg, NULL, 0, 0)) { 369 DispatchMessage(&msg);
357 TranslateMessage(&msg);
358 DispatchMessage(&msg);
359 }
360 MessageLoop::current()->Quit();
361 } 370 }
362 }; 371 MessageLoop::current()->Quit();
363 372 }
364 class SubPumpQuitTask : public Task {
365 public:
366 SubPumpQuitTask() {
367 }
368 virtual void Run() {
369 PostQuitMessage(0);
370 }
371 };
372 373
373 void RunTest_PostDelayedTask_SharedTimer_SubPump() { 374 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
374 MessageLoop loop(MessageLoop::TYPE_UI); 375 MessageLoop loop(MessageLoop::TYPE_UI);
375 376
376 // Test that the interval of the timer, used to run the next delayed task, is 377 // Test that the interval of the timer, used to run the next delayed task, is
377 // set to a value corresponding to when the next delayed task should run. 378 // set to a value corresponding to when the next delayed task should run.
378 379
379 // By setting num_tasks to 1, we ensure that the first task to run causes the 380 // By setting num_tasks to 1, we ensure that the first task to run causes the
380 // run loop to exit. 381 // run loop to exit.
381 int num_tasks = 1; 382 int num_tasks = 1;
382 Time run_time; 383 Time run_time;
383 384
384 loop.PostTask(FROM_HERE, new SubPumpTask()); 385 loop.PostTask(FROM_HERE, base::Bind(&SubPumpFunc));
385 386
386 // This very delayed task should never run. 387 // This very delayed task should never run.
387 loop.PostDelayedTask( 388 loop.PostDelayedTask(
388 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 1000000); 389 FROM_HERE,
390 base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks),
391 1000000);
389 392
390 // This slightly delayed task should run from within SubPumpTask::Run(). 393 // This slightly delayed task should run from within SubPumpFunc).
391 loop.PostDelayedTask( 394 loop.PostDelayedTask(FROM_HERE, base::Bind(&PostQuitMessage, 0), 10);
392 FROM_HERE, new SubPumpQuitTask(), 10);
393 395
394 Time start_time = Time::Now(); 396 Time start_time = Time::Now();
395 397
396 loop.Run(); 398 loop.Run();
397 EXPECT_EQ(1, num_tasks); 399 EXPECT_EQ(1, num_tasks);
398 400
399 // Ensure that we ran in far less time than the slower timer. 401 // Ensure that we ran in far less time than the slower timer.
400 TimeDelta total_time = Time::Now() - start_time; 402 TimeDelta total_time = Time::Now() - start_time;
401 EXPECT_GT(5000, total_time.InMilliseconds()); 403 EXPECT_GT(5000, total_time.InMilliseconds());
402 404
403 // In case both timers somehow run at nearly the same time, sleep a little 405 // In case both timers somehow run at nearly the same time, sleep a little
404 // and then run all pending to force them both to have run. This is just 406 // and then run all pending to force them both to have run. This is just
405 // encouraging flakiness if there is any. 407 // encouraging flakiness if there is any.
406 PlatformThread::Sleep(100); 408 PlatformThread::Sleep(100);
407 loop.RunAllPending(); 409 loop.RunAllPending();
408 410
409 EXPECT_TRUE(run_time.is_null()); 411 EXPECT_TRUE(run_time.is_null());
410 } 412 }
411 413
412 #endif // defined(OS_WIN) 414 #endif // defined(OS_WIN)
413 415
414 class RecordDeletionTask : public Task { 416 // This is used to inject a test point for recording the destructor calls for
417 // Closure objects send to MessageLoop::PostTask(). It is awkward usage since we
418 // are trying to hook the actual destruction, which is not a common operation.
419 class RecordDeletionProbe : public base::RefCounted<RecordDeletionProbe> {
415 public: 420 public:
416 RecordDeletionTask(Task* post_on_delete, bool* was_deleted) 421 RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
417 : post_on_delete_(post_on_delete), was_deleted_(was_deleted) { 422 : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {
418 } 423 }
419 ~RecordDeletionTask() { 424 ~RecordDeletionProbe() {
420 *was_deleted_ = true; 425 *was_deleted_ = true;
421 if (post_on_delete_) 426 if (post_on_delete_)
422 MessageLoop::current()->PostTask(FROM_HERE, post_on_delete_); 427 MessageLoop::current()->PostTask(
428 FROM_HERE,
429 base::Bind(&RecordDeletionProbe::Run, post_on_delete_.get()));
423 } 430 }
424 virtual void Run() {} 431 virtual void Run() {}
425 private: 432 private:
426 Task* post_on_delete_; 433 scoped_refptr<RecordDeletionProbe> post_on_delete_;
427 bool* was_deleted_; 434 bool* was_deleted_;
428 }; 435 };
429 436
430 void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type) { 437 void RunTest_EnsureDeletion(MessageLoop::Type message_loop_type) {
431 bool a_was_deleted = false; 438 bool a_was_deleted = false;
432 bool b_was_deleted = false; 439 bool b_was_deleted = false;
433 { 440 {
434 MessageLoop loop(message_loop_type); 441 MessageLoop loop(message_loop_type);
435 loop.PostTask( 442 loop.PostTask(
436 FROM_HERE, new RecordDeletionTask(NULL, &a_was_deleted)); 443 FROM_HERE, base::Bind(&RecordDeletionProbe::Run,
444 new RecordDeletionProbe(NULL, &a_was_deleted)));
437 loop.PostDelayedTask( 445 loop.PostDelayedTask(
438 FROM_HERE, new RecordDeletionTask(NULL, &b_was_deleted), 1000); 446 FROM_HERE, base::Bind(&RecordDeletionProbe::Run,
447 new RecordDeletionProbe(NULL, &b_was_deleted)),
448 1000); // TODO(ajwong): Do we really need 1000ms here?
439 } 449 }
440 EXPECT_TRUE(a_was_deleted); 450 EXPECT_TRUE(a_was_deleted);
441 EXPECT_TRUE(b_was_deleted); 451 EXPECT_TRUE(b_was_deleted);
442 } 452 }
443 453
444 void RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type) { 454 void RunTest_EnsureDeletion_Chain(MessageLoop::Type message_loop_type) {
445 bool a_was_deleted = false; 455 bool a_was_deleted = false;
446 bool b_was_deleted = false; 456 bool b_was_deleted = false;
447 bool c_was_deleted = false; 457 bool c_was_deleted = false;
448 { 458 {
449 MessageLoop loop(message_loop_type); 459 MessageLoop loop(message_loop_type);
450 RecordDeletionTask* a = new RecordDeletionTask(NULL, &a_was_deleted); 460 // The scoped_refptr for each of the below is held either by the chained
451 RecordDeletionTask* b = new RecordDeletionTask(a, &b_was_deleted); 461 // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback.
452 RecordDeletionTask* c = new RecordDeletionTask(b, &c_was_deleted); 462 RecordDeletionProbe* a = new RecordDeletionProbe(NULL, &a_was_deleted);
453 loop.PostTask(FROM_HERE, c); 463 RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted);
464 RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted);
465 loop.PostTask(FROM_HERE, base::Bind(&RecordDeletionProbe::Run, c));
454 } 466 }
455 EXPECT_TRUE(a_was_deleted); 467 EXPECT_TRUE(a_was_deleted);
456 EXPECT_TRUE(b_was_deleted); 468 EXPECT_TRUE(b_was_deleted);
457 EXPECT_TRUE(c_was_deleted); 469 EXPECT_TRUE(c_was_deleted);
458 } 470 }
459 471
460 class NestingTest : public Task { 472 void NestingFunc(int* depth) {
461 public: 473 if (*depth > 0) {
462 explicit NestingTest(int* depth) : depth_(depth) { 474 *depth -= 1;
475 MessageLoop::current()->PostTask(FROM_HERE,
476 base::Bind(&NestingFunc, depth));
477
478 MessageLoop::current()->SetNestableTasksAllowed(true);
479 MessageLoop::current()->Run();
463 } 480 }
464 void Run() { 481 MessageLoop::current()->Quit();
465 if (*depth_ > 0) { 482 }
466 *depth_ -= 1;
467 MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(depth_));
468
469 MessageLoop::current()->SetNestableTasksAllowed(true);
470 MessageLoop::current()->Run();
471 }
472 MessageLoop::current()->Quit();
473 }
474 private:
475 int* depth_;
476 };
477 483
478 #if defined(OS_WIN) 484 #if defined(OS_WIN)
479 485
480 LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) { 486 LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) {
481 ADD_FAILURE() << "bad exception handler"; 487 ADD_FAILURE() << "bad exception handler";
482 ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode); 488 ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode);
483 return EXCEPTION_EXECUTE_HANDLER; 489 return EXCEPTION_EXECUTE_HANDLER;
484 } 490 }
485 491
486 // This task throws an SEH exception: initially write to an invalid address. 492 // This task throws an SEH exception: initially write to an invalid address.
487 // If the right SEH filter is installed, it will fix the error. 493 // If the right SEH filter is installed, it will fix the error.
488 class CrasherTask : public Task { 494 class Crasher : public base::RefCounted<Crasher> {
489 public: 495 public:
490 // Ctor. If trash_SEH_handler is true, the task will override the unhandled 496 // Ctor. If trash_SEH_handler is true, the task will override the unhandled
491 // exception handler with one sure to crash this test. 497 // exception handler with one sure to crash this test.
492 explicit CrasherTask(bool trash_SEH_handler) 498 explicit Crasher(bool trash_SEH_handler)
493 : trash_SEH_handler_(trash_SEH_handler) { 499 : trash_SEH_handler_(trash_SEH_handler) {
494 } 500 }
501
495 void Run() { 502 void Run() {
496 PlatformThread::Sleep(1); 503 PlatformThread::Sleep(1);
497 if (trash_SEH_handler_) 504 if (trash_SEH_handler_)
498 ::SetUnhandledExceptionFilter(&BadExceptionHandler); 505 ::SetUnhandledExceptionFilter(&BadExceptionHandler);
499 // Generate a SEH fault. We do it in asm to make sure we know how to undo 506 // Generate a SEH fault. We do it in asm to make sure we know how to undo
500 // the damage. 507 // the damage.
501 508
502 #if defined(_M_IX86) 509 #if defined(_M_IX86)
503 510
504 __asm { 511 __asm {
505 mov eax, dword ptr [CrasherTask::bad_array_] 512 mov eax, dword ptr [Crasher::bad_array_]
506 mov byte ptr [eax], 66 513 mov byte ptr [eax], 66
507 } 514 }
508 515
509 #elif defined(_M_X64) 516 #elif defined(_M_X64)
510 517
511 bad_array_[0] = 66; 518 bad_array_[0] = 66;
512 519
513 #else 520 #else
514 #error "needs architecture support" 521 #error "needs architecture support"
515 #endif 522 #endif
516 523
517 MessageLoop::current()->Quit(); 524 MessageLoop::current()->Quit();
518 } 525 }
519 // Points the bad array to a valid memory location. 526 // Points the bad array to a valid memory location.
520 static void FixError() { 527 static void FixError() {
521 bad_array_ = &valid_store_; 528 bad_array_ = &valid_store_;
522 } 529 }
523 530
524 private: 531 private:
525 bool trash_SEH_handler_; 532 bool trash_SEH_handler_;
526 static volatile char* bad_array_; 533 static volatile char* bad_array_;
527 static char valid_store_; 534 static char valid_store_;
528 }; 535 };
529 536
530 volatile char* CrasherTask::bad_array_ = 0; 537 volatile char* Crasher::bad_array_ = 0;
531 char CrasherTask::valid_store_ = 0; 538 char Crasher::valid_store_ = 0;
532 539
533 // This SEH filter fixes the problem and retries execution. Fixing requires 540 // This SEH filter fixes the problem and retries execution. Fixing requires
534 // that the last instruction: mov eax, [CrasherTask::bad_array_] to be retried 541 // that the last instruction: mov eax, [Crasher::bad_array_] to be retried
535 // so we move the instruction pointer 5 bytes back. 542 // so we move the instruction pointer 5 bytes back.
536 LONG WINAPI HandleCrasherTaskException(EXCEPTION_POINTERS *ex_info) { 543 LONG WINAPI HandleCrasherException(EXCEPTION_POINTERS *ex_info) {
537 if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) 544 if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
538 return EXCEPTION_EXECUTE_HANDLER; 545 return EXCEPTION_EXECUTE_HANDLER;
539 546
540 CrasherTask::FixError(); 547 Crasher::FixError();
541 548
542 #if defined(_M_IX86) 549 #if defined(_M_IX86)
543 550
544 ex_info->ContextRecord->Eip -= 5; 551 ex_info->ContextRecord->Eip -= 5;
545 552
546 #elif defined(_M_X64) 553 #elif defined(_M_X64)
547 554
548 ex_info->ContextRecord->Rip -= 5; 555 ex_info->ContextRecord->Rip -= 5;
549 556
550 #endif 557 #endif
551 558
552 return EXCEPTION_CONTINUE_EXECUTION; 559 return EXCEPTION_CONTINUE_EXECUTION;
553 } 560 }
554 561
555 void RunTest_Crasher(MessageLoop::Type message_loop_type) { 562 void RunTest_Crasher(MessageLoop::Type message_loop_type) {
556 MessageLoop loop(message_loop_type); 563 MessageLoop loop(message_loop_type);
557 564
558 if (::IsDebuggerPresent()) 565 if (::IsDebuggerPresent())
559 return; 566 return;
560 567
561 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = 568 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
562 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException); 569 ::SetUnhandledExceptionFilter(&HandleCrasherException);
563 570
564 MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(false)); 571 MessageLoop::current()->PostTask(
572 FROM_HERE,
573 base::Bind(&Crasher::Run, new Crasher(false)));
565 MessageLoop::current()->set_exception_restoration(true); 574 MessageLoop::current()->set_exception_restoration(true);
566 MessageLoop::current()->Run(); 575 MessageLoop::current()->Run();
567 MessageLoop::current()->set_exception_restoration(false); 576 MessageLoop::current()->set_exception_restoration(false);
568 577
569 ::SetUnhandledExceptionFilter(old_SEH_filter); 578 ::SetUnhandledExceptionFilter(old_SEH_filter);
570 } 579 }
571 580
572 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) { 581 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) {
573 MessageLoop loop(message_loop_type); 582 MessageLoop loop(message_loop_type);
574 583
575 if (::IsDebuggerPresent()) 584 if (::IsDebuggerPresent())
576 return; 585 return;
577 586
578 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = 587 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter =
579 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException); 588 ::SetUnhandledExceptionFilter(&HandleCrasherException);
580 589
581 MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(true)); 590 MessageLoop::current()->PostTask(
591 FROM_HERE,
592 base::Bind(&Crasher::Run, new Crasher(true)));
582 MessageLoop::current()->set_exception_restoration(true); 593 MessageLoop::current()->set_exception_restoration(true);
583 MessageLoop::current()->Run(); 594 MessageLoop::current()->Run();
584 MessageLoop::current()->set_exception_restoration(false); 595 MessageLoop::current()->set_exception_restoration(false);
585 596
586 ::SetUnhandledExceptionFilter(old_SEH_filter); 597 ::SetUnhandledExceptionFilter(old_SEH_filter);
587 } 598 }
588 599
589 #endif // defined(OS_WIN) 600 #endif // defined(OS_WIN)
590 601
591 void RunTest_Nesting(MessageLoop::Type message_loop_type) { 602 void RunTest_Nesting(MessageLoop::Type message_loop_type) {
592 MessageLoop loop(message_loop_type); 603 MessageLoop loop(message_loop_type);
593 604
594 int depth = 100; 605 int depth = 100;
595 MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(&depth)); 606 MessageLoop::current()->PostTask(FROM_HERE,
607 base::Bind(&NestingFunc, &depth));
596 MessageLoop::current()->Run(); 608 MessageLoop::current()->Run();
597 EXPECT_EQ(depth, 0); 609 EXPECT_EQ(depth, 0);
598 } 610 }
599 611
600 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; 612 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test";
601 613
602 enum TaskType { 614 enum TaskType {
603 MESSAGEBOX, 615 MESSAGEBOX,
604 ENDDIALOG, 616 ENDDIALOG,
605 RECURSIVE, 617 RECURSIVE,
(...skipping 14 matching lines...) Expand all
620 632
621 TaskType type; 633 TaskType type;
622 int cookie; 634 int cookie;
623 bool start; 635 bool start;
624 636
625 bool operator == (const TaskItem& other) const { 637 bool operator == (const TaskItem& other) const {
626 return type == other.type && cookie == other.cookie && start == other.start; 638 return type == other.type && cookie == other.cookie && start == other.start;
627 } 639 }
628 }; 640 };
629 641
630 typedef std::vector<TaskItem> TaskList;
631
632 std::ostream& operator <<(std::ostream& os, TaskType type) { 642 std::ostream& operator <<(std::ostream& os, TaskType type) {
633 switch (type) { 643 switch (type) {
634 case MESSAGEBOX: os << "MESSAGEBOX"; break; 644 case MESSAGEBOX: os << "MESSAGEBOX"; break;
635 case ENDDIALOG: os << "ENDDIALOG"; break; 645 case ENDDIALOG: os << "ENDDIALOG"; break;
636 case RECURSIVE: os << "RECURSIVE"; break; 646 case RECURSIVE: os << "RECURSIVE"; break;
637 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; 647 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break;
638 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; 648 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break;
639 case ORDERERD: os << "ORDERERD"; break; 649 case ORDERERD: os << "ORDERERD"; break;
640 case PUMPS: os << "PUMPS"; break; 650 case PUMPS: os << "PUMPS"; break;
641 case SLEEP: os << "SLEEP"; break; 651 case SLEEP: os << "SLEEP"; break;
642 default: 652 default:
643 NOTREACHED(); 653 NOTREACHED();
644 os << "Unknown TaskType"; 654 os << "Unknown TaskType";
645 break; 655 break;
646 } 656 }
647 return os; 657 return os;
648 } 658 }
649 659
650 std::ostream& operator <<(std::ostream& os, const TaskItem& item) { 660 std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
651 if (item.start) 661 if (item.start)
652 return os << item.type << " " << item.cookie << " starts"; 662 return os << item.type << " " << item.cookie << " starts";
653 else 663 else
654 return os << item.type << " " << item.cookie << " ends"; 664 return os << item.type << " " << item.cookie << " ends";
655 } 665 }
656 666
657 // Saves the order the tasks ran. 667 class TaskList {
658 class OrderedTasks : public Task {
659 public: 668 public:
660 OrderedTasks(TaskList* order, int cookie) 669 void RecordStart(TaskType type, int cookie) {
661 : order_(order), 670 TaskItem item(type, cookie, true);
662 type_(ORDERERD), 671 DVLOG(1) << item;
663 cookie_(cookie) { 672 task_list_.push_back(item);
664 }
665 OrderedTasks(TaskList* order, TaskType type, int cookie)
666 : order_(order),
667 type_(type),
668 cookie_(cookie) {
669 } 673 }
670 674
671 void RunStart() { 675 void RecordEnd(TaskType type, int cookie) {
672 TaskItem item(type_, cookie_, true); 676 TaskItem item(type, cookie, false);
673 DVLOG(1) << item; 677 DVLOG(1) << item;
674 order_->push_back(item); 678 task_list_.push_back(item);
675 }
676 void RunEnd() {
677 TaskItem item(type_, cookie_, false);
678 DVLOG(1) << item;
679 order_->push_back(item);
680 } 679 }
681 680
682 virtual void Run() { 681 size_t Size() {
683 RunStart(); 682 return task_list_.size();
684 RunEnd();
685 } 683 }
686 684
687 protected: 685 TaskItem Get(int n) {
688 TaskList* order() const { 686 return task_list_[n];
689 return order_;
690 }
691
692 int cookie() const {
693 return cookie_;
694 } 687 }
695 688
696 private: 689 private:
697 TaskList* order_; 690 std::vector<TaskItem> task_list_;
698 TaskType type_;
699 int cookie_;
700 }; 691 };
701 692
693 // Saves the order the tasks ran.
694 void OrderedFunc(TaskList* order, int cookie) {
695 order->RecordStart(ORDERERD, cookie);
696 order->RecordEnd(ORDERERD, cookie);
697 }
698
702 #if defined(OS_WIN) 699 #if defined(OS_WIN)
703 700
704 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes, 701 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
705 // common controls (like OpenFile) and StartDoc printing function can cause 702 // common controls (like OpenFile) and StartDoc printing function can cause
706 // implicit message loops. 703 // implicit message loops.
707 class MessageBoxTask : public OrderedTasks { 704 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
708 public: 705 order->RecordStart(MESSAGEBOX, cookie);
709 MessageBoxTask(TaskList* order, int cookie, bool is_reentrant) 706 if (is_reentrant)
710 : OrderedTasks(order, MESSAGEBOX, cookie), 707 MessageLoop::current()->SetNestableTasksAllowed(true);
711 is_reentrant_(is_reentrant) { 708 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
712 } 709 order->RecordEnd(MESSAGEBOX, cookie);
713 710 }
714 virtual void Run() {
715 RunStart();
716 if (is_reentrant_)
717 MessageLoop::current()->SetNestableTasksAllowed(true);
718 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
719 RunEnd();
720 }
721
722 private:
723 bool is_reentrant_;
724 };
725 711
726 // Will end the MessageBox. 712 // Will end the MessageBox.
727 class EndDialogTask : public OrderedTasks { 713 void EndDialogFunc(TaskList* order, int cookie) {
728 public: 714 order->RecordStart(ENDDIALOG, cookie);
729 EndDialogTask(TaskList* order, int cookie) 715 HWND window = GetActiveWindow();
730 : OrderedTasks(order, ENDDIALOG, cookie) { 716 if (window != NULL) {
717 EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
718 // Cheap way to signal that the window wasn't found if RunEnd() isn't
719 // called.
720 order->RecordEnd(ENDDIALOG, cookie);
731 } 721 }
732 722 }
733 virtual void Run() {
734 RunStart();
735 HWND window = GetActiveWindow();
736 if (window != NULL) {
737 EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
738 // Cheap way to signal that the window wasn't found if RunEnd() isn't
739 // called.
740 RunEnd();
741 }
742 }
743 };
744 723
745 #endif // defined(OS_WIN) 724 #endif // defined(OS_WIN)
746 725
747 class RecursiveTask : public OrderedTasks { 726 void RecursiveFunc(TaskList* order, int cookie, int depth,
748 public: 727 bool is_reentrant) {
749 RecursiveTask(int depth, TaskList* order, int cookie, bool is_reentrant) 728 order->RecordStart(RECURSIVE, cookie);
750 : OrderedTasks(order, RECURSIVE, cookie), 729 if (depth > 0) {
751 depth_(depth), 730 if (is_reentrant)
752 is_reentrant_(is_reentrant) { 731 MessageLoop::current()->SetNestableTasksAllowed(true);
732 MessageLoop::current()->PostTask(
733 FROM_HERE,
734 base::Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
753 } 735 }
736 order->RecordEnd(RECURSIVE, cookie);
737 }
754 738
755 virtual void Run() { 739 void RecursiveSlowFunc(TaskList* order, int cookie, int depth,
756 RunStart(); 740 bool is_reentrant) {
757 if (depth_ > 0) { 741 RecursiveFunc(order, cookie, depth, is_reentrant);
758 if (is_reentrant_) 742 PlatformThread::Sleep(10); // milliseconds
759 MessageLoop::current()->SetNestableTasksAllowed(true); 743 }
760 MessageLoop::current()->PostTask(FROM_HERE,
761 new RecursiveTask(depth_ - 1, order(), cookie(), is_reentrant_));
762 }
763 RunEnd();
764 }
765 744
766 private: 745 void QuitFunc(TaskList* order, int cookie) {
767 int depth_; 746 order->RecordStart(QUITMESSAGELOOP, cookie);
768 bool is_reentrant_; 747 MessageLoop::current()->Quit();
769 }; 748 order->RecordEnd(QUITMESSAGELOOP, cookie);
749 }
770 750
771 class RecursiveSlowTask : public RecursiveTask { 751 void SleepFunc(TaskList* order, int cookie, int ms) {
772 public: 752 order->RecordStart(SLEEP, cookie);
773 RecursiveSlowTask(int depth, TaskList* order, int cookie, bool is_reentrant) 753 PlatformThread::Sleep(ms);
774 : RecursiveTask(depth, order, cookie, is_reentrant) { 754 order->RecordEnd(SLEEP, cookie);
775 } 755 }
776
777 virtual void Run() {
778 RecursiveTask::Run();
779 PlatformThread::Sleep(10); // milliseconds
780 }
781 };
782
783 class QuitTask : public OrderedTasks {
784 public:
785 QuitTask(TaskList* order, int cookie)
786 : OrderedTasks(order, QUITMESSAGELOOP, cookie) {
787 }
788
789 virtual void Run() {
790 RunStart();
791 MessageLoop::current()->Quit();
792 RunEnd();
793 }
794 };
795
796 class SleepTask : public OrderedTasks {
797 public:
798 SleepTask(TaskList* order, int cookie, int ms)
799 : OrderedTasks(order, SLEEP, cookie), ms_(ms) {
800 }
801
802 virtual void Run() {
803 RunStart();
804 PlatformThread::Sleep(ms_);
805 RunEnd();
806 }
807
808 private:
809 int ms_;
810 };
811 756
812 #if defined(OS_WIN) 757 #if defined(OS_WIN)
758 void RecursiveFuncWin(MessageLoop* target,
759 HANDLE event,
760 bool expect_window,
761 TaskList* order,
762 bool is_reentrant) {
763 target->PostTask(FROM_HERE,
764 base::Bind(&RecursiveFunc, order, 1, 2, is_reentrant));
765 target->PostTask(FROM_HERE,
766 base::Bind(&MessageBoxFunc, order, 2, is_reentrant));
767 target->PostTask(FROM_HERE,
768 base::Bind(&RecursiveFunc, order, 3, 2, is_reentrant));
769 // The trick here is that for recursive task processing, this task will be
770 // ran _inside_ the MessageBox message loop, dismissing the MessageBox
771 // without a chance.
772 // For non-recursive task processing, this will be executed _after_ the
773 // MessageBox will have been dismissed by the code below, where
774 // expect_window_ is true.
775 target->PostTask(FROM_HERE,
776 base::Bind(&EndDialogFunc, order, 4));
777 target->PostTask(FROM_HERE,
778 base::Bind(&QuitFunc, order, 5));
813 779
814 class Recursive2Tasks : public Task { 780 // Enforce that every tasks are sent before starting to run the main thread
815 public: 781 // message loop.
816 Recursive2Tasks(MessageLoop* target, 782 ASSERT_TRUE(SetEvent(event));
817 HANDLE event,
818 bool expect_window,
819 TaskList* order,
820 bool is_reentrant)
821 : target_(target),
822 event_(event),
823 expect_window_(expect_window),
824 order_(order),
825 is_reentrant_(is_reentrant) {
826 }
827 783
828 virtual void Run() { 784 // Poll for the MessageBox. Don't do this at home! At the speed we do it,
829 target_->PostTask(FROM_HERE, 785 // you will never realize one MessageBox was shown.
830 new RecursiveTask(2, order_, 1, is_reentrant_)); 786 for (; expect_window;) {
831 target_->PostTask(FROM_HERE, 787 HWND window = FindWindow(L"#32770", kMessageBoxTitle);
832 new MessageBoxTask(order_, 2, is_reentrant_)); 788 if (window) {
833 target_->PostTask(FROM_HERE, 789 // Dismiss it.
834 new RecursiveTask(2, order_, 3, is_reentrant_)); 790 for (;;) {
835 // The trick here is that for recursive task processing, this task will be 791 HWND button = FindWindowEx(window, NULL, L"Button", NULL);
836 // ran _inside_ the MessageBox message loop, dismissing the MessageBox 792 if (button != NULL) {
837 // without a chance. 793 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
838 // For non-recursive task processing, this will be executed _after_ the 794 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
839 // MessageBox will have been dismissed by the code below, where 795 break;
840 // expect_window_ is true.
841 target_->PostTask(FROM_HERE, new EndDialogTask(order_, 4));
842 target_->PostTask(FROM_HERE, new QuitTask(order_, 5));
843
844 // Enforce that every tasks are sent before starting to run the main thread
845 // message loop.
846 ASSERT_TRUE(SetEvent(event_));
847
848 // Poll for the MessageBox. Don't do this at home! At the speed we do it,
849 // you will never realize one MessageBox was shown.
850 for (; expect_window_;) {
851 HWND window = FindWindow(L"#32770", kMessageBoxTitle);
852 if (window) {
853 // Dismiss it.
854 for (;;) {
855 HWND button = FindWindowEx(window, NULL, L"Button", NULL);
856 if (button != NULL) {
857 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
858 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
859 break;
860 }
861 } 796 }
862 break;
863 } 797 }
798 break;
864 } 799 }
865 } 800 }
866 801 }
867 private:
868 MessageLoop* target_;
869 HANDLE event_;
870 TaskList* order_;
871 bool expect_window_;
872 bool is_reentrant_;
873 };
874 802
875 #endif // defined(OS_WIN) 803 #endif // defined(OS_WIN)
876 804
877 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) { 805 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) {
878 MessageLoop loop(message_loop_type); 806 MessageLoop loop(message_loop_type);
879 807
880 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); 808 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
881 TaskList order; 809 TaskList order;
882 MessageLoop::current()->PostTask(FROM_HERE, 810 MessageLoop::current()->PostTask(
883 new RecursiveTask(2, &order, 1, false)); 811 FROM_HERE,
884 MessageLoop::current()->PostTask(FROM_HERE, 812 base::Bind(&RecursiveFunc, &order, 1, 2, false));
885 new RecursiveTask(2, &order, 2, false)); 813 MessageLoop::current()->PostTask(
886 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); 814 FROM_HERE,
815 base::Bind(&RecursiveFunc, &order, 2, 2, false));
816 MessageLoop::current()->PostTask(
817 FROM_HERE,
818 base::Bind(&QuitFunc, &order, 3));
887 819
888 MessageLoop::current()->Run(); 820 MessageLoop::current()->Run();
889 821
890 // FIFO order. 822 // FIFO order.
891 ASSERT_EQ(14U, order.size()); 823 ASSERT_EQ(14U, order.Size());
892 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 824 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
893 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 825 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
894 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 826 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
895 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 827 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
896 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 828 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
897 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 829 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
898 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); 830 EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
899 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); 831 EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
900 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 832 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
901 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 833 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
902 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 834 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
903 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 835 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
904 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); 836 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
905 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); 837 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
906 } 838 }
907 839
908 void RunTest_RecursiveDenial3(MessageLoop::Type message_loop_type) { 840 void RunTest_RecursiveDenial3(MessageLoop::Type message_loop_type) {
909 MessageLoop loop(message_loop_type); 841 MessageLoop loop(message_loop_type);
910 842
911 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); 843 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed());
912 TaskList order; 844 TaskList order;
913 MessageLoop::current()->PostTask(FROM_HERE, 845 MessageLoop::current()->PostTask(
914 new RecursiveSlowTask(2, &order, 1, false)); 846 FROM_HERE, base::Bind(&RecursiveSlowFunc, &order, 1, 2, false));
915 MessageLoop::current()->PostTask(FROM_HERE, 847 MessageLoop::current()->PostTask(
916 new RecursiveSlowTask(2, &order, 2, false)); 848 FROM_HERE, base::Bind(&RecursiveSlowFunc, &order, 2, 2, false));
917 MessageLoop::current()->PostDelayedTask(FROM_HERE, 849 MessageLoop::current()->PostDelayedTask(
918 new OrderedTasks(&order, 3), 5); 850 FROM_HERE, base::Bind(&OrderedFunc, &order, 3), 5);
919 MessageLoop::current()->PostDelayedTask(FROM_HERE, 851 MessageLoop::current()->PostDelayedTask(
920 new QuitTask(&order, 4), 5); 852 FROM_HERE, base::Bind(&QuitFunc, &order, 4), 5);
921 853
922 MessageLoop::current()->Run(); 854 MessageLoop::current()->Run();
923 855
924 // FIFO order. 856 // FIFO order.
925 ASSERT_EQ(16U, order.size()); 857 ASSERT_EQ(16U, order.Size());
926 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 858 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
927 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 859 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
928 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 860 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
929 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 861 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
930 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 1, true)); 862 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true));
931 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 1, false)); 863 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false));
932 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 3, true)); 864 EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 3, true));
933 EXPECT_EQ(order[ 7], TaskItem(ORDERERD, 3, false)); 865 EXPECT_EQ(order.Get(7), TaskItem(ORDERERD, 3, false));
934 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 866 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
935 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 867 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
936 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 4, true)); 868 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true));
937 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 4, false)); 869 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false));
938 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 1, true)); 870 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true));
939 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, false)); 871 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false));
940 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 2, true)); 872 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true));
941 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 2, false)); 873 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false));
942 } 874 }
943 875
944 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) { 876 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) {
945 MessageLoop loop(message_loop_type); 877 MessageLoop loop(message_loop_type);
946 878
947 TaskList order; 879 TaskList order;
948 MessageLoop::current()->PostTask(FROM_HERE, 880 MessageLoop::current()->PostTask(
949 new RecursiveTask(2, &order, 1, true)); 881 FROM_HERE, base::Bind(&RecursiveFunc, &order, 1, 2, true));
950 MessageLoop::current()->PostTask(FROM_HERE, 882 MessageLoop::current()->PostTask(
951 new RecursiveTask(2, &order, 2, true)); 883 FROM_HERE, base::Bind(&RecursiveFunc, &order, 2, 2, true));
952 MessageLoop::current()->PostTask(FROM_HERE, 884 MessageLoop::current()->PostTask(
953 new QuitTask(&order, 3)); 885 FROM_HERE, base::Bind(&QuitFunc, &order, 3));
954 886
955 MessageLoop::current()->Run(); 887 MessageLoop::current()->Run();
956 888
957 // FIFO order. 889 // FIFO order.
958 ASSERT_EQ(14U, order.size()); 890 ASSERT_EQ(14U, order.Size());
959 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 891 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
960 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 892 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
961 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); 893 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
962 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); 894 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
963 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 895 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
964 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 896 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
965 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); 897 EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
966 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); 898 EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
967 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); 899 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
968 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); 900 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
969 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 901 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
970 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 902 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
971 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); 903 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
972 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); 904 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
973 } 905 }
974 906
975 #if defined(OS_WIN) 907 #if defined(OS_WIN)
976 // TODO(darin): These tests need to be ported since they test critical 908 // TODO(darin): These tests need to be ported since they test critical
977 // message loop functionality. 909 // message loop functionality.
978 910
979 // A side effect of this test is the generation a beep. Sorry. 911 // A side effect of this test is the generation a beep. Sorry.
980 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { 912 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
981 MessageLoop loop(message_loop_type); 913 MessageLoop loop(message_loop_type);
982 914
983 Thread worker("RecursiveDenial2_worker"); 915 Thread worker("RecursiveDenial2_worker");
984 Thread::Options options; 916 Thread::Options options;
985 options.message_loop_type = message_loop_type; 917 options.message_loop_type = message_loop_type;
986 ASSERT_EQ(true, worker.StartWithOptions(options)); 918 ASSERT_EQ(true, worker.StartWithOptions(options));
987 TaskList order; 919 TaskList order;
988 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 920 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
989 worker.message_loop()->PostTask(FROM_HERE, 921 worker.message_loop()->PostTask(FROM_HERE,
990 new Recursive2Tasks(MessageLoop::current(), 922 base::Bind(&RecursiveFuncWin,
991 event, 923 MessageLoop::current(),
992 true, 924 event.Get(),
993 &order, 925 true,
994 false)); 926 &order,
927 false));
995 // Let the other thread execute. 928 // Let the other thread execute.
996 WaitForSingleObject(event, INFINITE); 929 WaitForSingleObject(event, INFINITE);
997 MessageLoop::current()->Run(); 930 MessageLoop::current()->Run();
998 931
999 ASSERT_EQ(order.size(), 17); 932 ASSERT_EQ(order.Size(), 17);
1000 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 933 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1001 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 934 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1002 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); 935 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
1003 EXPECT_EQ(order[ 3], TaskItem(MESSAGEBOX, 2, false)); 936 EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
1004 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, true)); 937 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
1005 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 3, false)); 938 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
1006 // When EndDialogTask is processed, the window is already dismissed, hence no 939 // When EndDialogFunc is processed, the window is already dismissed, hence no
1007 // "end" entry. 940 // "end" entry.
1008 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, true)); 941 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
1009 EXPECT_EQ(order[ 7], TaskItem(QUITMESSAGELOOP, 5, true)); 942 EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
1010 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, false)); 943 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
1011 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 1, true)); 944 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
1012 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, false)); 945 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
1013 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 3, true)); 946 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
1014 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, false)); 947 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
1015 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, true)); 948 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
1016 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, false)); 949 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
1017 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 3, true)); 950 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
1018 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, false)); 951 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
1019 } 952 }
1020 953
1021 // A side effect of this test is the generation a beep. Sorry. This test also 954 // A side effect of this test is the generation a beep. Sorry. This test also
1022 // needs to process windows messages on the current thread. 955 // needs to process windows messages on the current thread.
1023 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { 956 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
1024 MessageLoop loop(message_loop_type); 957 MessageLoop loop(message_loop_type);
1025 958
1026 Thread worker("RecursiveSupport2_worker"); 959 Thread worker("RecursiveSupport2_worker");
1027 Thread::Options options; 960 Thread::Options options;
1028 options.message_loop_type = message_loop_type; 961 options.message_loop_type = message_loop_type;
1029 ASSERT_EQ(true, worker.StartWithOptions(options)); 962 ASSERT_EQ(true, worker.StartWithOptions(options));
1030 TaskList order; 963 TaskList order;
1031 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); 964 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
1032 worker.message_loop()->PostTask(FROM_HERE, 965 worker.message_loop()->PostTask(FROM_HERE,
1033 new Recursive2Tasks(MessageLoop::current(), 966 base::Bind(&RecursiveFuncWin,
1034 event, 967 MessageLoop::current(),
1035 false, 968 event.Get(),
1036 &order, 969 false,
1037 true)); 970 &order,
971 true));
1038 // Let the other thread execute. 972 // Let the other thread execute.
1039 WaitForSingleObject(event, INFINITE); 973 WaitForSingleObject(event, INFINITE);
1040 MessageLoop::current()->Run(); 974 MessageLoop::current()->Run();
1041 975
1042 ASSERT_EQ(order.size(), 18); 976 ASSERT_EQ(order.Size(), 18);
1043 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); 977 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1044 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); 978 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1045 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); 979 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
1046 // Note that this executes in the MessageBox modal loop. 980 // Note that this executes in the MessageBox modal loop.
1047 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 3, true)); 981 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
1048 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, false)); 982 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
1049 EXPECT_EQ(order[ 5], TaskItem(ENDDIALOG, 4, true)); 983 EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
1050 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, false)); 984 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
1051 EXPECT_EQ(order[ 7], TaskItem(MESSAGEBOX, 2, false)); 985 EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
1052 /* The order can subtly change here. The reason is that when RecursiveTask(1) 986 /* The order can subtly change here. The reason is that when RecursiveFunc(1)
1053 is called in the main thread, if it is faster than getting to the 987 is called in the main thread, if it is faster than getting to the
1054 PostTask(FROM_HERE, QuitTask) execution, the order of task execution can 988 PostTask(FROM_HERE, base::Bind(&QuitFunc) execution, the order of task
1055 change. We don't care anyway that the order isn't correct. 989 execution can change. We don't care anyway that the order isn't correct.
1056 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true)); 990 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
1057 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false)); 991 EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
1058 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); 992 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
1059 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); 993 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
1060 */ 994 */
1061 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, true)); 995 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
1062 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 3, false)); 996 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
1063 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, true)); 997 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
1064 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 1, false)); 998 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
1065 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, true)); 999 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
1066 EXPECT_EQ(order[17], TaskItem(RECURSIVE, 3, false)); 1000 EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
1067 } 1001 }
1068 1002
1069 #endif // defined(OS_WIN) 1003 #endif // defined(OS_WIN)
1070 1004
1071 class TaskThatPumps : public OrderedTasks { 1005 void FuncThatPumps(TaskList* order, int cookie) {
1072 public: 1006 order->RecordStart(PUMPS, cookie);
1073 TaskThatPumps(TaskList* order, int cookie) 1007 bool old_state = MessageLoop::current()->NestableTasksAllowed();
1074 : OrderedTasks(order, PUMPS, cookie) { 1008 MessageLoop::current()->SetNestableTasksAllowed(true);
1075 } 1009 MessageLoop::current()->RunAllPending();
1076 1010 MessageLoop::current()->SetNestableTasksAllowed(old_state);
1077 virtual void Run() { 1011 order->RecordEnd(PUMPS, cookie);
1078 RunStart(); 1012 }
1079 bool old_state = MessageLoop::current()->NestableTasksAllowed();
1080 MessageLoop::current()->SetNestableTasksAllowed(true);
1081 MessageLoop::current()->RunAllPending();
1082 MessageLoop::current()->SetNestableTasksAllowed(old_state);
1083 RunEnd();
1084 }
1085 };
1086 1013
1087 // Tests that non nestable tasks run in FIFO if there are no nested loops. 1014 // Tests that non nestable tasks run in FIFO if there are no nested loops.
1088 void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) { 1015 void RunTest_NonNestableWithNoNesting(
1016 MessageLoop::Type message_loop_type) {
1089 MessageLoop loop(message_loop_type); 1017 MessageLoop loop(message_loop_type);
1090 1018
1091 TaskList order; 1019 TaskList order;
1092 1020
1093 Task* task = new OrderedTasks(&order, 1); 1021 MessageLoop::current()->PostNonNestableTask(
1094 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); 1022 FROM_HERE,
1095 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 2)); 1023 base::Bind(&OrderedFunc, &order, 1));
1096 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); 1024 MessageLoop::current()->PostTask(FROM_HERE,
1025 base::Bind(&OrderedFunc, &order, 2));
1026 MessageLoop::current()->PostTask(FROM_HERE,
1027 base::Bind(&QuitFunc, &order, 3));
1097 MessageLoop::current()->Run(); 1028 MessageLoop::current()->Run();
1098 1029
1099 // FIFO order. 1030 // FIFO order.
1100 ASSERT_EQ(6U, order.size()); 1031 ASSERT_EQ(6U, order.Size());
1101 EXPECT_EQ(order[ 0], TaskItem(ORDERERD, 1, true)); 1032 EXPECT_EQ(order.Get(0), TaskItem(ORDERERD, 1, true));
1102 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 1, false)); 1033 EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 1, false));
1103 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 2, true)); 1034 EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 2, true));
1104 EXPECT_EQ(order[ 3], TaskItem(ORDERERD, 2, false)); 1035 EXPECT_EQ(order.Get(3), TaskItem(ORDERERD, 2, false));
1105 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); 1036 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
1106 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); 1037 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
1107 } 1038 }
1108 1039
1109 // Tests that non nestable tasks don't run when there's code in the call stack. 1040 // Tests that non nestable tasks don't run when there's code in the call stack.
1110 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, 1041 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type,
1111 bool use_delayed) { 1042 bool use_delayed) {
1112 MessageLoop loop(message_loop_type); 1043 MessageLoop loop(message_loop_type);
1113 1044
1114 TaskList order; 1045 TaskList order;
1115 1046
1047 MessageLoop::current()->PostTask(
1048 FROM_HERE,
1049 base::Bind(&FuncThatPumps, &order, 1));
1050 if (use_delayed) {
1051 MessageLoop::current()->PostNonNestableDelayedTask(
1052 FROM_HERE,
1053 base::Bind(&OrderedFunc, &order, 2),
1054 1);
1055 } else {
1056 MessageLoop::current()->PostNonNestableTask(
1057 FROM_HERE,
1058 base::Bind(&OrderedFunc, &order, 2));
1059 }
1116 MessageLoop::current()->PostTask(FROM_HERE, 1060 MessageLoop::current()->PostTask(FROM_HERE,
1117 new TaskThatPumps(&order, 1)); 1061 base::Bind(&OrderedFunc, &order, 3));
1118 Task* task = new OrderedTasks(&order, 2); 1062 MessageLoop::current()->PostTask(FROM_HERE,
1063 base::Bind(&SleepFunc, &order, 4, 50));
1064 MessageLoop::current()->PostTask(FROM_HERE,
1065 base::Bind(&OrderedFunc, &order, 5));
1119 if (use_delayed) { 1066 if (use_delayed) {
1120 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1); 1067 MessageLoop::current()->PostNonNestableDelayedTask(
1068 FROM_HERE,
1069 base::Bind(&QuitFunc, &order, 6),
1070 2);
1121 } else { 1071 } else {
1122 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); 1072 MessageLoop::current()->PostNonNestableTask(
1123 } 1073 FROM_HERE,
1124 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 3)); 1074 base::Bind(&QuitFunc, &order, 6));
1125 MessageLoop::current()->PostTask(FROM_HERE, new SleepTask(&order, 4, 50));
1126 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 5));
1127 Task* non_nestable_quit = new QuitTask(&order, 6);
1128 if (use_delayed) {
1129 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE,
1130 non_nestable_quit,
1131 2);
1132 } else {
1133 MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit);
1134 } 1075 }
1135 1076
1136 MessageLoop::current()->Run(); 1077 MessageLoop::current()->Run();
1137 1078
1138 // FIFO order. 1079 // FIFO order.
1139 ASSERT_EQ(12U, order.size()); 1080 ASSERT_EQ(12U, order.Size());
1140 EXPECT_EQ(order[ 0], TaskItem(PUMPS, 1, true)); 1081 EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
1141 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 3, true)); 1082 EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 3, true));
1142 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 3, false)); 1083 EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 3, false));
1143 EXPECT_EQ(order[ 3], TaskItem(SLEEP, 4, true)); 1084 EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
1144 EXPECT_EQ(order[ 4], TaskItem(SLEEP, 4, false)); 1085 EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
1145 EXPECT_EQ(order[ 5], TaskItem(ORDERERD, 5, true)); 1086 EXPECT_EQ(order.Get(5), TaskItem(ORDERERD, 5, true));
1146 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 5, false)); 1087 EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 5, false));
1147 EXPECT_EQ(order[ 7], TaskItem(PUMPS, 1, false)); 1088 EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
1148 EXPECT_EQ(order[ 8], TaskItem(ORDERERD, 2, true)); 1089 EXPECT_EQ(order.Get(8), TaskItem(ORDERERD, 2, true));
1149 EXPECT_EQ(order[ 9], TaskItem(ORDERERD, 2, false)); 1090 EXPECT_EQ(order.Get(9), TaskItem(ORDERERD, 2, false));
1150 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 6, true)); 1091 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
1151 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 6, false)); 1092 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
1152 } 1093 }
1153 1094
1154 #if defined(OS_WIN) 1095 #if defined(OS_WIN)
1155 1096
1156 class DispatcherImpl : public MessageLoopForUI::Dispatcher { 1097 class DispatcherImpl : public MessageLoopForUI::Dispatcher {
1157 public: 1098 public:
1158 DispatcherImpl() : dispatch_count_(0) {} 1099 DispatcherImpl() : dispatch_count_(0) {}
1159 1100
1160 virtual bool Dispatch(const MSG& msg) { 1101 virtual bool Dispatch(const MSG& msg) {
1161 ::TranslateMessage(&msg); 1102 ::TranslateMessage(&msg);
1162 ::DispatchMessage(&msg); 1103 ::DispatchMessage(&msg);
1163 // Do not count WM_TIMER since it is not what we post and it will cause 1104 // Do not count WM_TIMER since it is not what we post and it will cause
1164 // flakiness. 1105 // flakiness.
1165 if (msg.message != WM_TIMER) 1106 if (msg.message != WM_TIMER)
1166 ++dispatch_count_; 1107 ++dispatch_count_;
1167 // We treat WM_LBUTTONUP as the last message. 1108 // We treat WM_LBUTTONUP as the last message.
1168 return msg.message != WM_LBUTTONUP; 1109 return msg.message != WM_LBUTTONUP;
1169 } 1110 }
1170 1111
1171 int dispatch_count_; 1112 int dispatch_count_;
1172 }; 1113 };
1173 1114
1115 void MouseDownUp() {
1116 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1117 PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1118 }
1119
1174 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { 1120 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
1175 MessageLoop loop(message_loop_type); 1121 MessageLoop loop(message_loop_type);
1176 1122
1177 class MyTask : public Task { 1123 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1178 public: 1124 base::Bind(&MouseDownUp), 100);
1179 virtual void Run() {
1180 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1181 PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1182 }
1183 };
1184 Task* task = new MyTask();
1185 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
1186 DispatcherImpl dispatcher; 1125 DispatcherImpl dispatcher;
1187 MessageLoopForUI::current()->Run(&dispatcher); 1126 MessageLoopForUI::current()->Run(&dispatcher);
1188 ASSERT_EQ(2, dispatcher.dispatch_count_); 1127 ASSERT_EQ(2, dispatcher.dispatch_count_);
1189 } 1128 }
1190 1129
1191 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { 1130 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) {
1192 if (code == base::MessagePumpForUI::kMessageFilterCode) { 1131 if (code == base::MessagePumpForUI::kMessageFilterCode) {
1193 MSG* msg = reinterpret_cast<MSG*>(lparam); 1132 MSG* msg = reinterpret_cast<MSG*>(lparam);
1194 if (msg->message == WM_LBUTTONDOWN) 1133 if (msg->message == WM_LBUTTONDOWN)
1195 return TRUE; 1134 return TRUE;
1196 } 1135 }
1197 return FALSE; 1136 return FALSE;
1198 } 1137 }
1199 1138
1200 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { 1139 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
1201 MessageLoop loop(message_loop_type); 1140 MessageLoop loop(message_loop_type);
1202 1141
1203 class MyTask : public Task { 1142 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1204 public: 1143 base::Bind(&MouseDownUp), 100);
1205 virtual void Run() {
1206 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
1207 PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
1208 }
1209 };
1210 Task* task = new MyTask();
1211 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
1212 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, 1144 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
1213 MsgFilterProc, 1145 MsgFilterProc,
1214 NULL, 1146 NULL,
1215 GetCurrentThreadId()); 1147 GetCurrentThreadId());
1216 DispatcherImpl dispatcher; 1148 DispatcherImpl dispatcher;
1217 MessageLoopForUI::current()->Run(&dispatcher); 1149 MessageLoopForUI::current()->Run(&dispatcher);
1218 ASSERT_EQ(1, dispatcher.dispatch_count_); 1150 ASSERT_EQ(1, dispatcher.dispatch_count_);
1219 UnhookWindowsHookEx(msg_hook); 1151 UnhookWindowsHookEx(msg_hook);
1220 } 1152 }
1221 1153
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 DWORD bytes_transfered, DWORD error) { 1196 DWORD bytes_transfered, DWORD error) {
1265 ASSERT_TRUE(context == &context_); 1197 ASSERT_TRUE(context == &context_);
1266 ASSERT_TRUE(SetEvent(signal_)); 1198 ASSERT_TRUE(SetEvent(signal_));
1267 } 1199 }
1268 1200
1269 void TestIOHandler::WaitForIO() { 1201 void TestIOHandler::WaitForIO() {
1270 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this)); 1202 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
1271 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this)); 1203 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
1272 } 1204 }
1273 1205
1274 class IOHandlerTask : public Task {
1275 public:
1276 explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {}
1277 virtual void Run() {
1278 handler_->Init();
1279 }
1280
1281 private:
1282 TestIOHandler* handler_;
1283 };
1284
1285 void RunTest_IOHandler() { 1206 void RunTest_IOHandler() {
1286 base::win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 1207 base::win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1287 ASSERT_TRUE(callback_called.IsValid()); 1208 ASSERT_TRUE(callback_called.IsValid());
1288 1209
1289 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; 1210 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
1290 base::win::ScopedHandle server( 1211 base::win::ScopedHandle server(
1291 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); 1212 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
1292 ASSERT_TRUE(server.IsValid()); 1213 ASSERT_TRUE(server.IsValid());
1293 1214
1294 Thread thread("IOHandler test"); 1215 Thread thread("IOHandler test");
1295 Thread::Options options; 1216 Thread::Options options;
1296 options.message_loop_type = MessageLoop::TYPE_IO; 1217 options.message_loop_type = MessageLoop::TYPE_IO;
1297 ASSERT_TRUE(thread.StartWithOptions(options)); 1218 ASSERT_TRUE(thread.StartWithOptions(options));
1298 1219
1299 MessageLoop* thread_loop = thread.message_loop(); 1220 MessageLoop* thread_loop = thread.message_loop();
1300 ASSERT_TRUE(NULL != thread_loop); 1221 ASSERT_TRUE(NULL != thread_loop);
1301 1222
1302 TestIOHandler handler(kPipeName, callback_called, false); 1223 TestIOHandler handler(kPipeName, callback_called, false);
1303 IOHandlerTask* task = new IOHandlerTask(&handler); 1224 thread_loop->PostTask(FROM_HERE, base::Bind(&TestIOHandler::Init,
1304 thread_loop->PostTask(FROM_HERE, task); 1225 base::Unretained(&handler)));
1305 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1226 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1306 1227
1307 const char buffer[] = "Hello there!"; 1228 const char buffer[] = "Hello there!";
1308 DWORD written; 1229 DWORD written;
1309 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); 1230 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL));
1310 1231
1311 DWORD result = WaitForSingleObject(callback_called, 1000); 1232 DWORD result = WaitForSingleObject(callback_called, 1000);
1312 EXPECT_EQ(WAIT_OBJECT_0, result); 1233 EXPECT_EQ(WAIT_OBJECT_0, result);
1313 1234
1314 thread.Stop(); 1235 thread.Stop();
(...skipping 19 matching lines...) Expand all
1334 Thread thread("IOHandler test"); 1255 Thread thread("IOHandler test");
1335 Thread::Options options; 1256 Thread::Options options;
1336 options.message_loop_type = MessageLoop::TYPE_IO; 1257 options.message_loop_type = MessageLoop::TYPE_IO;
1337 ASSERT_TRUE(thread.StartWithOptions(options)); 1258 ASSERT_TRUE(thread.StartWithOptions(options));
1338 1259
1339 MessageLoop* thread_loop = thread.message_loop(); 1260 MessageLoop* thread_loop = thread.message_loop();
1340 ASSERT_TRUE(NULL != thread_loop); 1261 ASSERT_TRUE(NULL != thread_loop);
1341 1262
1342 TestIOHandler handler1(kPipeName1, callback1_called, false); 1263 TestIOHandler handler1(kPipeName1, callback1_called, false);
1343 TestIOHandler handler2(kPipeName2, callback2_called, true); 1264 TestIOHandler handler2(kPipeName2, callback2_called, true);
1344 IOHandlerTask* task1 = new IOHandlerTask(&handler1); 1265 thread_loop->PostTask(FROM_HERE, base::Bind(&TestIOHandler::Init,
1345 IOHandlerTask* task2 = new IOHandlerTask(&handler2); 1266 base::Unretained(&handler1)));
1346 thread_loop->PostTask(FROM_HERE, task1); 1267 // TODO(ajwong): Do we really need such long Sleeps in ths function?
1347 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1268 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1348 thread_loop->PostTask(FROM_HERE, task2); 1269 thread_loop->PostTask(FROM_HERE, base::Bind(&TestIOHandler::Init,
1270 base::Unretained(&handler2)));
1349 Sleep(100); 1271 Sleep(100);
1350 1272
1351 // At this time handler1 is waiting to be called, and the thread is waiting 1273 // At this time handler1 is waiting to be called, and the thread is waiting
1352 // on the Init method of handler2, filtering only handler2 callbacks. 1274 // on the Init method of handler2, filtering only handler2 callbacks.
1353 1275
1354 const char buffer[] = "Hello there!"; 1276 const char buffer[] = "Hello there!";
1355 DWORD written; 1277 DWORD written;
1356 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); 1278 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL));
1357 Sleep(200); 1279 Sleep(200);
1358 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << 1280 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) <<
(...skipping 10 matching lines...) Expand all
1369 1291
1370 #endif // defined(OS_WIN) 1292 #endif // defined(OS_WIN)
1371 1293
1372 } // namespace 1294 } // namespace
1373 1295
1374 //----------------------------------------------------------------------------- 1296 //-----------------------------------------------------------------------------
1375 // Each test is run against each type of MessageLoop. That way we are sure 1297 // Each test is run against each type of MessageLoop. That way we are sure
1376 // that message loops work properly in all configurations. Of course, in some 1298 // that message loops work properly in all configurations. Of course, in some
1377 // cases, a unit test may only be for a particular type of loop. 1299 // cases, a unit test may only be for a particular type of loop.
1378 1300
1301 TEST(MessageLoopTest, PostLegacyTask) {
1302 RunTest_PostLegacyTask(MessageLoop::TYPE_DEFAULT);
1303 RunTest_PostLegacyTask(MessageLoop::TYPE_UI);
1304 RunTest_PostLegacyTask(MessageLoop::TYPE_IO);
1305 }
1306
1379 TEST(MessageLoopTest, PostTask) { 1307 TEST(MessageLoopTest, PostTask) {
1380 RunTest_PostTask(MessageLoop::TYPE_DEFAULT); 1308 RunTest_PostTask(MessageLoop::TYPE_DEFAULT);
1381 RunTest_PostTask(MessageLoop::TYPE_UI); 1309 RunTest_PostTask(MessageLoop::TYPE_UI);
1382 RunTest_PostTask(MessageLoop::TYPE_IO); 1310 RunTest_PostTask(MessageLoop::TYPE_IO);
1383 } 1311 }
1384 1312
1385 TEST(MessageLoopTest, PostTask_SEH) { 1313 TEST(MessageLoopTest, PostTask_SEH) {
1386 RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT); 1314 RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT);
1387 RunTest_PostTask_SEH(MessageLoop::TYPE_UI); 1315 RunTest_PostTask_SEH(MessageLoop::TYPE_UI);
1388 RunTest_PostTask_SEH(MessageLoop::TYPE_IO); 1316 RunTest_PostTask_SEH(MessageLoop::TYPE_IO);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1426 1354
1427 #if defined(OS_WIN) 1355 #if defined(OS_WIN)
1428 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) { 1356 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
1429 RunTest_PostDelayedTask_SharedTimer_SubPump(); 1357 RunTest_PostDelayedTask_SharedTimer_SubPump();
1430 } 1358 }
1431 #endif 1359 #endif
1432 1360
1433 // TODO(darin): MessageLoop does not support deleting all tasks in the 1361 // TODO(darin): MessageLoop does not support deleting all tasks in the
1434 // destructor. 1362 // destructor.
1435 // Fails, http://crbug.com/50272. 1363 // Fails, http://crbug.com/50272.
1436 TEST(MessageLoopTest, FAILS_EnsureTaskDeletion) { 1364 TEST(MessageLoopTest, FAILS_EnsureDeletion) {
1437 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT); 1365 RunTest_EnsureDeletion(MessageLoop::TYPE_DEFAULT);
1438 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI); 1366 RunTest_EnsureDeletion(MessageLoop::TYPE_UI);
1439 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO); 1367 RunTest_EnsureDeletion(MessageLoop::TYPE_IO);
1440 } 1368 }
1441 1369
1442 // TODO(darin): MessageLoop does not support deleting all tasks in the 1370 // TODO(darin): MessageLoop does not support deleting all tasks in the
1443 // destructor. 1371 // destructor.
1444 // Fails, http://crbug.com/50272. 1372 // Fails, http://crbug.com/50272.
1445 TEST(MessageLoopTest, FAILS_EnsureTaskDeletion_Chain) { 1373 TEST(MessageLoopTest, FAILS_EnsureDeletion_Chain) {
1446 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT); 1374 RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_DEFAULT);
1447 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI); 1375 RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_UI);
1448 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO); 1376 RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_IO);
1449 } 1377 }
1450 1378
1451 #if defined(OS_WIN) 1379 #if defined(OS_WIN)
1452 TEST(MessageLoopTest, Crasher) { 1380 TEST(MessageLoopTest, Crasher) {
1453 RunTest_Crasher(MessageLoop::TYPE_DEFAULT); 1381 RunTest_Crasher(MessageLoop::TYPE_DEFAULT);
1454 RunTest_Crasher(MessageLoop::TYPE_UI); 1382 RunTest_Crasher(MessageLoop::TYPE_UI);
1455 RunTest_Crasher(MessageLoop::TYPE_IO); 1383 RunTest_Crasher(MessageLoop::TYPE_IO);
1456 } 1384 }
1457 1385
1458 TEST(MessageLoopTest, CrasherNasty) { 1386 TEST(MessageLoopTest, CrasherNasty) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); 1439 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false);
1512 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); 1440 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false);
1513 } 1441 }
1514 1442
1515 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { 1443 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) {
1516 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); 1444 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true);
1517 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); 1445 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true);
1518 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); 1446 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true);
1519 } 1447 }
1520 1448
1521 class DummyTask : public Task { 1449 void PostNTasksThenQuit(int posts_remaining) {
1522 public: 1450 if (posts_remaining > 1) {
1523 explicit DummyTask(int num_tasks) : num_tasks_(num_tasks) {} 1451 MessageLoop::current()->PostTask(
1524 1452 FROM_HERE,
1525 virtual void Run() { 1453 base::Bind(&PostNTasksThenQuit, posts_remaining - 1));
1526 if (num_tasks_ > 1) { 1454 } else {
1527 MessageLoop::current()->PostTask( 1455 MessageLoop::current()->Quit();
1528 FROM_HERE,
1529 new DummyTask(num_tasks_ - 1));
1530 } else {
1531 MessageLoop::current()->Quit();
1532 }
1533 } 1456 }
1534 1457 }
1535 private:
1536 const int num_tasks_;
1537 };
1538 1458
1539 class DummyTaskObserver : public MessageLoop::TaskObserver { 1459 class DummyTaskObserver : public MessageLoop::TaskObserver {
1540 public: 1460 public:
1541 explicit DummyTaskObserver(int num_tasks) 1461 explicit DummyTaskObserver(int num_tasks)
1542 : num_tasks_started_(0), 1462 : num_tasks_started_(0),
1543 num_tasks_processed_(0), 1463 num_tasks_processed_(0),
1544 num_tasks_(num_tasks) {} 1464 num_tasks_(num_tasks) {}
1545 1465
1546 virtual ~DummyTaskObserver() {} 1466 virtual ~DummyTaskObserver() {}
1547 1467
1548 virtual void WillProcessTask(const Task* task) { 1468 virtual void WillProcessTask(TimeTicks time_posted) OVERRIDE {
1549 num_tasks_started_++; 1469 num_tasks_started_++;
1550 EXPECT_TRUE(task != NULL); 1470 EXPECT_TRUE(time_posted != TimeTicks());
1551 EXPECT_LE(num_tasks_started_, num_tasks_); 1471 EXPECT_LE(num_tasks_started_, num_tasks_);
1552 EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1); 1472 EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
1553 } 1473 }
1554 1474
1555 virtual void DidProcessTask(const Task* task) { 1475 virtual void DidProcessTask(TimeTicks time_posted) OVERRIDE {
1556 num_tasks_processed_++; 1476 num_tasks_processed_++;
1557 EXPECT_TRUE(task != NULL); 1477 EXPECT_TRUE(time_posted != TimeTicks());
1558 EXPECT_LE(num_tasks_started_, num_tasks_); 1478 EXPECT_LE(num_tasks_started_, num_tasks_);
1559 EXPECT_EQ(num_tasks_started_, num_tasks_processed_); 1479 EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
1560 } 1480 }
1561 1481
1562 int num_tasks_started() const { return num_tasks_started_; } 1482 int num_tasks_started() const { return num_tasks_started_; }
1563 int num_tasks_processed() const { return num_tasks_processed_; } 1483 int num_tasks_processed() const { return num_tasks_processed_; }
1564 1484
1565 private: 1485 private:
1566 int num_tasks_started_; 1486 int num_tasks_started_;
1567 int num_tasks_processed_; 1487 int num_tasks_processed_;
1568 const int num_tasks_; 1488 const int num_tasks_;
1569 1489
1570 DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver); 1490 DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver);
1571 }; 1491 };
1572 1492
1573 TEST(MessageLoopTest, TaskObserver) { 1493 TEST(MessageLoopTest, TaskObserver) {
1574 const int kNumTasks = 6; 1494 const int kNumPosts = 6;
1575 DummyTaskObserver observer(kNumTasks); 1495 DummyTaskObserver observer(kNumPosts);
1576 1496
1577 MessageLoop loop; 1497 MessageLoop loop;
1578 loop.AddTaskObserver(&observer); 1498 loop.AddTaskObserver(&observer);
1579 loop.PostTask(FROM_HERE, new DummyTask(kNumTasks)); 1499 loop.PostTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, kNumPosts));
1580 loop.Run(); 1500 loop.Run();
1581 loop.RemoveTaskObserver(&observer); 1501 loop.RemoveTaskObserver(&observer);
1582 1502
1583 EXPECT_EQ(kNumTasks, observer.num_tasks_started()); 1503 EXPECT_EQ(kNumPosts, observer.num_tasks_started());
1584 EXPECT_EQ(kNumTasks, observer.num_tasks_processed()); 1504 EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
1585 } 1505 }
1586 1506
1587 #if defined(OS_WIN) 1507 #if defined(OS_WIN)
1588 TEST(MessageLoopTest, Dispatcher) { 1508 TEST(MessageLoopTest, Dispatcher) {
1589 // This test requires a UI loop 1509 // This test requires a UI loop
1590 RunTest_Dispatcher(MessageLoop::TYPE_UI); 1510 RunTest_Dispatcher(MessageLoop::TYPE_UI);
1591 } 1511 }
1592 1512
1593 TEST(MessageLoopTest, DispatcherWithMessageHook) { 1513 TEST(MessageLoopTest, DispatcherWithMessageHook) {
1594 // This test requires a UI loop 1514 // This test requires a UI loop
(...skipping 10 matching lines...) Expand all
1605 1525
1606 TEST(MessageLoopTest, HighResolutionTimer) { 1526 TEST(MessageLoopTest, HighResolutionTimer) {
1607 MessageLoop loop; 1527 MessageLoop loop;
1608 1528
1609 const int kFastTimerMs = 5; 1529 const int kFastTimerMs = 5;
1610 const int kSlowTimerMs = 100; 1530 const int kSlowTimerMs = 100;
1611 1531
1612 EXPECT_FALSE(loop.high_resolution_timers_enabled()); 1532 EXPECT_FALSE(loop.high_resolution_timers_enabled());
1613 1533
1614 // Post a fast task to enable the high resolution timers. 1534 // Post a fast task to enable the high resolution timers.
1615 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kFastTimerMs); 1535 loop.PostDelayedTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, 1),
1536 kFastTimerMs);
1616 loop.Run(); 1537 loop.Run();
1617 EXPECT_TRUE(loop.high_resolution_timers_enabled()); 1538 EXPECT_TRUE(loop.high_resolution_timers_enabled());
1618 1539
1619 // Post a slow task and verify high resolution timers 1540 // Post a slow task and verify high resolution timers
1620 // are still enabled. 1541 // are still enabled.
1621 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs); 1542 loop.PostDelayedTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, 1),
1543 kSlowTimerMs);
1622 loop.Run(); 1544 loop.Run();
1623 EXPECT_TRUE(loop.high_resolution_timers_enabled()); 1545 EXPECT_TRUE(loop.high_resolution_timers_enabled());
1624 1546
1625 // Wait for a while so that high-resolution mode elapses. 1547 // Wait for a while so that high-resolution mode elapses.
1626 Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs); 1548 Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs);
1627 1549
1628 // Post a slow task to disable the high resolution timers. 1550 // Post a slow task to disable the high resolution timers.
1629 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs); 1551 loop.PostDelayedTask(FROM_HERE, base::Bind(&PostNTasksThenQuit, 1),
1552 kSlowTimerMs);
1630 loop.Run(); 1553 loop.Run();
1631 EXPECT_FALSE(loop.high_resolution_timers_enabled()); 1554 EXPECT_FALSE(loop.high_resolution_timers_enabled());
1632 } 1555 }
1633 1556
1634 #endif // defined(OS_WIN) 1557 #endif // defined(OS_WIN)
1635 1558
1636 #if defined(OS_POSIX) && !defined(OS_NACL) 1559 #if defined(OS_POSIX) && !defined(OS_NACL)
1637 1560
1638 namespace { 1561 namespace {
1639 1562
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 PLOG(ERROR) << "close"; 1622 PLOG(ERROR) << "close";
1700 if (HANDLE_EINTR(close(pipefds[1])) < 0) 1623 if (HANDLE_EINTR(close(pipefds[1])) < 0)
1701 PLOG(ERROR) << "close"; 1624 PLOG(ERROR) << "close";
1702 } 1625 }
1703 1626
1704 } // namespace 1627 } // namespace
1705 1628
1706 #endif // defined(OS_POSIX) && !defined(OS_NACL) 1629 #endif // defined(OS_POSIX) && !defined(OS_NACL)
1707 1630
1708 namespace { 1631 namespace {
1709 class RunAtDestructionTask : public Task { 1632 // Inject a test point for recording the destructor calls for Closure objects
1633 // send to MessageLoop::PostTask(). It is awkward usage since we are trying to
1634 // hook the actual destruction, which is not a common operation.
1635 class DestructionObserverProbe :
1636 public base::RefCounted<DestructionObserverProbe> {
1710 public: 1637 public:
1711 RunAtDestructionTask(bool* task_destroyed, bool* destruction_observer_called) 1638 DestructionObserverProbe(bool* task_destroyed,
1639 bool* destruction_observer_called)
1712 : task_destroyed_(task_destroyed), 1640 : task_destroyed_(task_destroyed),
1713 destruction_observer_called_(destruction_observer_called) { 1641 destruction_observer_called_(destruction_observer_called) {
1714 } 1642 }
1715 ~RunAtDestructionTask() { 1643 virtual ~DestructionObserverProbe() {
1716 EXPECT_FALSE(*destruction_observer_called_); 1644 EXPECT_FALSE(*destruction_observer_called_);
1717 *task_destroyed_ = true; 1645 *task_destroyed_ = true;
1718 } 1646 }
1719 virtual void Run() { 1647 virtual void Run() {
1720 // This task should never run. 1648 // This task should never run.
1721 ADD_FAILURE(); 1649 ADD_FAILURE();
1722 } 1650 }
1723 private: 1651 private:
1724 bool* task_destroyed_; 1652 bool* task_destroyed_;
1725 bool* destruction_observer_called_; 1653 bool* destruction_observer_called_;
(...skipping 27 matching lines...) Expand all
1753 MessageLoop* loop = new MessageLoop; 1681 MessageLoop* loop = new MessageLoop;
1754 const int kDelayMS = 100; 1682 const int kDelayMS = 100;
1755 1683
1756 bool task_destroyed = false; 1684 bool task_destroyed = false;
1757 bool destruction_observer_called = false; 1685 bool destruction_observer_called = false;
1758 1686
1759 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called); 1687 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
1760 loop->AddDestructionObserver(&observer); 1688 loop->AddDestructionObserver(&observer);
1761 loop->PostDelayedTask( 1689 loop->PostDelayedTask(
1762 FROM_HERE, 1690 FROM_HERE,
1763 new RunAtDestructionTask(&task_destroyed, &destruction_observer_called), 1691 base::Bind(&DestructionObserverProbe::Run,
1692 new DestructionObserverProbe(&task_destroyed,
1693 &destruction_observer_called)),
1764 kDelayMS); 1694 kDelayMS);
1765 delete loop; 1695 delete loop;
1766 EXPECT_TRUE(observer.task_destroyed_before_message_loop()); 1696 EXPECT_TRUE(observer.task_destroyed_before_message_loop());
1767 // The task should have been destroyed when we deleted the loop. 1697 // The task should have been destroyed when we deleted the loop.
1768 EXPECT_TRUE(task_destroyed); 1698 EXPECT_TRUE(task_destroyed);
1769 EXPECT_TRUE(destruction_observer_called); 1699 EXPECT_TRUE(destruction_observer_called);
1770 } 1700 }
OLDNEW
« no previous file with comments | « base/message_loop.cc ('k') | chrome/browser/jankometer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698