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