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

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

Powered by Google App Engine
This is Rietveld 408576698