OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/memory/scoped_ptr.h" | |
6 #include "base/message_loop.h" | |
7 #include "base/timer.h" | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 | |
10 using base::TimeDelta; | |
11 | |
12 namespace { | |
13 | |
14 // The message loops on which each timer should be tested. | |
15 const base::MessageLoop::Type testing_message_loops[] = { | |
16 base::MessageLoop::TYPE_DEFAULT, | |
17 base::MessageLoop::TYPE_IO, | |
18 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop. | |
19 base::MessageLoop::TYPE_UI, | |
20 #endif | |
21 }; | |
22 | |
23 const int kNumTestingMessageLoops = arraysize(testing_message_loops); | |
24 | |
25 class OneShotTimerTester { | |
26 public: | |
27 explicit OneShotTimerTester(bool* did_run, unsigned milliseconds = 10) | |
28 : did_run_(did_run), | |
29 delay_ms_(milliseconds) { | |
30 } | |
31 void Start() { | |
32 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(delay_ms_), this, | |
33 &OneShotTimerTester::Run); | |
34 } | |
35 private: | |
36 void Run() { | |
37 *did_run_ = true; | |
38 base::MessageLoop::current()->QuitWhenIdle(); | |
39 } | |
40 bool* did_run_; | |
41 base::OneShotTimer<OneShotTimerTester> timer_; | |
42 const unsigned delay_ms_; | |
43 }; | |
44 | |
45 class OneShotSelfDeletingTimerTester { | |
46 public: | |
47 explicit OneShotSelfDeletingTimerTester(bool* did_run) : | |
48 did_run_(did_run), | |
49 timer_(new base::OneShotTimer<OneShotSelfDeletingTimerTester>()) { | |
50 } | |
51 void Start() { | |
52 timer_->Start(FROM_HERE, TimeDelta::FromMilliseconds(10), this, | |
53 &OneShotSelfDeletingTimerTester::Run); | |
54 } | |
55 private: | |
56 void Run() { | |
57 *did_run_ = true; | |
58 timer_.reset(); | |
59 base::MessageLoop::current()->QuitWhenIdle(); | |
60 } | |
61 bool* did_run_; | |
62 scoped_ptr<base::OneShotTimer<OneShotSelfDeletingTimerTester> > timer_; | |
63 }; | |
64 | |
65 class RepeatingTimerTester { | |
66 public: | |
67 explicit RepeatingTimerTester(bool* did_run) | |
68 : did_run_(did_run), counter_(10) { | |
69 } | |
70 | |
71 void Start() { | |
72 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), this, | |
73 &RepeatingTimerTester::Run); | |
74 } | |
75 private: | |
76 void Run() { | |
77 if (--counter_ == 0) { | |
78 *did_run_ = true; | |
79 base::MessageLoop::current()->QuitWhenIdle(); | |
80 } | |
81 } | |
82 bool* did_run_; | |
83 int counter_; | |
84 base::RepeatingTimer<RepeatingTimerTester> timer_; | |
85 }; | |
86 | |
87 void RunTest_OneShotTimer(base::MessageLoop::Type message_loop_type) { | |
88 base::MessageLoop loop(message_loop_type); | |
89 | |
90 bool did_run = false; | |
91 OneShotTimerTester f(&did_run); | |
92 f.Start(); | |
93 | |
94 base::MessageLoop::current()->Run(); | |
95 | |
96 EXPECT_TRUE(did_run); | |
97 } | |
98 | |
99 void RunTest_OneShotTimer_Cancel(base::MessageLoop::Type message_loop_type) { | |
100 base::MessageLoop loop(message_loop_type); | |
101 | |
102 bool did_run_a = false; | |
103 OneShotTimerTester* a = new OneShotTimerTester(&did_run_a); | |
104 | |
105 // This should run before the timer expires. | |
106 base::MessageLoop::current()->DeleteSoon(FROM_HERE, a); | |
107 | |
108 // Now start the timer. | |
109 a->Start(); | |
110 | |
111 bool did_run_b = false; | |
112 OneShotTimerTester b(&did_run_b); | |
113 b.Start(); | |
114 | |
115 base::MessageLoop::current()->Run(); | |
116 | |
117 EXPECT_FALSE(did_run_a); | |
118 EXPECT_TRUE(did_run_b); | |
119 } | |
120 | |
121 void RunTest_OneShotSelfDeletingTimer( | |
122 base::MessageLoop::Type message_loop_type) { | |
123 base::MessageLoop loop(message_loop_type); | |
124 | |
125 bool did_run = false; | |
126 OneShotSelfDeletingTimerTester f(&did_run); | |
127 f.Start(); | |
128 | |
129 base::MessageLoop::current()->Run(); | |
130 | |
131 EXPECT_TRUE(did_run); | |
132 } | |
133 | |
134 void RunTest_RepeatingTimer(base::MessageLoop::Type message_loop_type) { | |
135 base::MessageLoop loop(message_loop_type); | |
136 | |
137 bool did_run = false; | |
138 RepeatingTimerTester f(&did_run); | |
139 f.Start(); | |
140 | |
141 base::MessageLoop::current()->Run(); | |
142 | |
143 EXPECT_TRUE(did_run); | |
144 } | |
145 | |
146 void RunTest_RepeatingTimer_Cancel(base::MessageLoop::Type message_loop_type) { | |
147 base::MessageLoop loop(message_loop_type); | |
148 | |
149 bool did_run_a = false; | |
150 RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a); | |
151 | |
152 // This should run before the timer expires. | |
153 base::MessageLoop::current()->DeleteSoon(FROM_HERE, a); | |
154 | |
155 // Now start the timer. | |
156 a->Start(); | |
157 | |
158 bool did_run_b = false; | |
159 RepeatingTimerTester b(&did_run_b); | |
160 b.Start(); | |
161 | |
162 base::MessageLoop::current()->Run(); | |
163 | |
164 EXPECT_FALSE(did_run_a); | |
165 EXPECT_TRUE(did_run_b); | |
166 } | |
167 | |
168 class DelayTimerTarget { | |
169 public: | |
170 DelayTimerTarget() | |
171 : signaled_(false) { | |
172 } | |
173 | |
174 bool signaled() const { return signaled_; } | |
175 | |
176 void Signal() { | |
177 ASSERT_FALSE(signaled_); | |
178 signaled_ = true; | |
179 } | |
180 | |
181 private: | |
182 bool signaled_; | |
183 }; | |
184 | |
185 void RunTest_DelayTimer_NoCall(base::MessageLoop::Type message_loop_type) { | |
186 base::MessageLoop loop(message_loop_type); | |
187 | |
188 // If Delay is never called, the timer shouldn't go off. | |
189 DelayTimerTarget target; | |
190 base::DelayTimer<DelayTimerTarget> timer(FROM_HERE, | |
191 TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal); | |
192 | |
193 bool did_run = false; | |
194 OneShotTimerTester tester(&did_run); | |
195 tester.Start(); | |
196 base::MessageLoop::current()->Run(); | |
197 | |
198 ASSERT_FALSE(target.signaled()); | |
199 } | |
200 | |
201 void RunTest_DelayTimer_OneCall(base::MessageLoop::Type message_loop_type) { | |
202 base::MessageLoop loop(message_loop_type); | |
203 | |
204 DelayTimerTarget target; | |
205 base::DelayTimer<DelayTimerTarget> timer(FROM_HERE, | |
206 TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal); | |
207 timer.Reset(); | |
208 | |
209 bool did_run = false; | |
210 OneShotTimerTester tester(&did_run, 100 /* milliseconds */); | |
211 tester.Start(); | |
212 base::MessageLoop::current()->Run(); | |
213 | |
214 ASSERT_TRUE(target.signaled()); | |
215 } | |
216 | |
217 struct ResetHelper { | |
218 ResetHelper(base::DelayTimer<DelayTimerTarget>* timer, | |
219 DelayTimerTarget* target) | |
220 : timer_(timer), | |
221 target_(target) { | |
222 } | |
223 | |
224 void Reset() { | |
225 ASSERT_FALSE(target_->signaled()); | |
226 timer_->Reset(); | |
227 } | |
228 | |
229 private: | |
230 base::DelayTimer<DelayTimerTarget> *const timer_; | |
231 DelayTimerTarget *const target_; | |
232 }; | |
233 | |
234 void RunTest_DelayTimer_Reset(base::MessageLoop::Type message_loop_type) { | |
235 base::MessageLoop loop(message_loop_type); | |
236 | |
237 // If Delay is never called, the timer shouldn't go off. | |
238 DelayTimerTarget target; | |
239 base::DelayTimer<DelayTimerTarget> timer(FROM_HERE, | |
240 TimeDelta::FromMilliseconds(50), &target, &DelayTimerTarget::Signal); | |
241 timer.Reset(); | |
242 | |
243 ResetHelper reset_helper(&timer, &target); | |
244 | |
245 base::OneShotTimer<ResetHelper> timers[20]; | |
246 for (size_t i = 0; i < arraysize(timers); ++i) { | |
247 timers[i].Start(FROM_HERE, TimeDelta::FromMilliseconds(i * 10), | |
248 &reset_helper, &ResetHelper::Reset); | |
249 } | |
250 | |
251 bool did_run = false; | |
252 OneShotTimerTester tester(&did_run, 300); | |
253 tester.Start(); | |
254 base::MessageLoop::current()->Run(); | |
255 | |
256 ASSERT_TRUE(target.signaled()); | |
257 } | |
258 | |
259 class DelayTimerFatalTarget { | |
260 public: | |
261 void Signal() { | |
262 ASSERT_TRUE(false); | |
263 } | |
264 }; | |
265 | |
266 | |
267 void RunTest_DelayTimer_Deleted(base::MessageLoop::Type message_loop_type) { | |
268 base::MessageLoop loop(message_loop_type); | |
269 | |
270 DelayTimerFatalTarget target; | |
271 | |
272 { | |
273 base::DelayTimer<DelayTimerFatalTarget> timer( | |
274 FROM_HERE, TimeDelta::FromMilliseconds(50), &target, | |
275 &DelayTimerFatalTarget::Signal); | |
276 timer.Reset(); | |
277 } | |
278 | |
279 // When the timer is deleted, the DelayTimerFatalTarget should never be | |
280 // called. | |
281 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | |
282 } | |
283 | |
284 } // namespace | |
285 | |
286 //----------------------------------------------------------------------------- | |
287 // Each test is run against each type of MessageLoop. That way we are sure | |
288 // that timers work properly in all configurations. | |
289 | |
290 TEST(TimerTest, OneShotTimer) { | |
291 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
292 RunTest_OneShotTimer(testing_message_loops[i]); | |
293 } | |
294 } | |
295 | |
296 TEST(TimerTest, OneShotTimer_Cancel) { | |
297 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
298 RunTest_OneShotTimer_Cancel(testing_message_loops[i]); | |
299 } | |
300 } | |
301 | |
302 // If underline timer does not handle properly, we will crash or fail | |
303 // in full page heap environment. | |
304 TEST(TimerTest, OneShotSelfDeletingTimer) { | |
305 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
306 RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]); | |
307 } | |
308 } | |
309 | |
310 TEST(TimerTest, RepeatingTimer) { | |
311 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
312 RunTest_RepeatingTimer(testing_message_loops[i]); | |
313 } | |
314 } | |
315 | |
316 TEST(TimerTest, RepeatingTimer_Cancel) { | |
317 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
318 RunTest_RepeatingTimer_Cancel(testing_message_loops[i]); | |
319 } | |
320 } | |
321 | |
322 TEST(TimerTest, DelayTimer_NoCall) { | |
323 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
324 RunTest_DelayTimer_NoCall(testing_message_loops[i]); | |
325 } | |
326 } | |
327 | |
328 TEST(TimerTest, DelayTimer_OneCall) { | |
329 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
330 RunTest_DelayTimer_OneCall(testing_message_loops[i]); | |
331 } | |
332 } | |
333 | |
334 // It's flaky on the buildbot, http://crbug.com/25038. | |
335 TEST(TimerTest, DISABLED_DelayTimer_Reset) { | |
336 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
337 RunTest_DelayTimer_Reset(testing_message_loops[i]); | |
338 } | |
339 } | |
340 | |
341 TEST(TimerTest, DelayTimer_Deleted) { | |
342 for (int i = 0; i < kNumTestingMessageLoops; i++) { | |
343 RunTest_DelayTimer_Deleted(testing_message_loops[i]); | |
344 } | |
345 } | |
346 | |
347 TEST(TimerTest, MessageLoopShutdown) { | |
348 // This test is designed to verify that shutdown of the | |
349 // message loop does not cause crashes if there were pending | |
350 // timers not yet fired. It may only trigger exceptions | |
351 // if debug heap checking is enabled. | |
352 bool did_run = false; | |
353 { | |
354 OneShotTimerTester a(&did_run); | |
355 OneShotTimerTester b(&did_run); | |
356 OneShotTimerTester c(&did_run); | |
357 OneShotTimerTester d(&did_run); | |
358 { | |
359 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
360 a.Start(); | |
361 b.Start(); | |
362 } // MessageLoop destructs by falling out of scope. | |
363 } // OneShotTimers destruct. SHOULD NOT CRASH, of course. | |
364 | |
365 EXPECT_FALSE(did_run); | |
366 } | |
367 | |
368 void TimerTestCallback() { | |
369 } | |
370 | |
371 TEST(TimerTest, NonRepeatIsRunning) { | |
372 { | |
373 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
374 base::Timer timer(false, false); | |
375 EXPECT_FALSE(timer.IsRunning()); | |
376 timer.Start(FROM_HERE, TimeDelta::FromDays(1), | |
377 base::Bind(&TimerTestCallback)); | |
378 EXPECT_TRUE(timer.IsRunning()); | |
379 timer.Stop(); | |
380 EXPECT_FALSE(timer.IsRunning()); | |
381 EXPECT_TRUE(timer.user_task().is_null()); | |
382 } | |
383 | |
384 { | |
385 base::Timer timer(true, false); | |
386 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
387 EXPECT_FALSE(timer.IsRunning()); | |
388 timer.Start(FROM_HERE, TimeDelta::FromDays(1), | |
389 base::Bind(&TimerTestCallback)); | |
390 EXPECT_TRUE(timer.IsRunning()); | |
391 timer.Stop(); | |
392 EXPECT_FALSE(timer.IsRunning()); | |
393 ASSERT_FALSE(timer.user_task().is_null()); | |
394 timer.Reset(); | |
395 EXPECT_TRUE(timer.IsRunning()); | |
396 } | |
397 } | |
398 | |
399 TEST(TimerTest, NonRepeatMessageLoopDeath) { | |
400 base::Timer timer(false, false); | |
401 { | |
402 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
403 EXPECT_FALSE(timer.IsRunning()); | |
404 timer.Start(FROM_HERE, TimeDelta::FromDays(1), | |
405 base::Bind(&TimerTestCallback)); | |
406 EXPECT_TRUE(timer.IsRunning()); | |
407 } | |
408 EXPECT_FALSE(timer.IsRunning()); | |
409 EXPECT_TRUE(timer.user_task().is_null()); | |
410 } | |
411 | |
412 TEST(TimerTest, RetainRepeatIsRunning) { | |
413 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
414 base::Timer timer(FROM_HERE, TimeDelta::FromDays(1), | |
415 base::Bind(&TimerTestCallback), true); | |
416 EXPECT_FALSE(timer.IsRunning()); | |
417 timer.Reset(); | |
418 EXPECT_TRUE(timer.IsRunning()); | |
419 timer.Stop(); | |
420 EXPECT_FALSE(timer.IsRunning()); | |
421 timer.Reset(); | |
422 EXPECT_TRUE(timer.IsRunning()); | |
423 } | |
424 | |
425 TEST(TimerTest, RetainNonRepeatIsRunning) { | |
426 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
427 base::Timer timer(FROM_HERE, TimeDelta::FromDays(1), | |
428 base::Bind(&TimerTestCallback), false); | |
429 EXPECT_FALSE(timer.IsRunning()); | |
430 timer.Reset(); | |
431 EXPECT_TRUE(timer.IsRunning()); | |
432 timer.Stop(); | |
433 EXPECT_FALSE(timer.IsRunning()); | |
434 timer.Reset(); | |
435 EXPECT_TRUE(timer.IsRunning()); | |
436 } | |
437 | |
438 namespace { | |
439 | |
440 bool g_callback_happened1 = false; | |
441 bool g_callback_happened2 = false; | |
442 | |
443 void ClearAllCallbackHappened() { | |
444 g_callback_happened1 = false; | |
445 g_callback_happened2 = false; | |
446 } | |
447 | |
448 void SetCallbackHappened1() { | |
449 g_callback_happened1 = true; | |
450 base::MessageLoop::current()->QuitWhenIdle(); | |
451 } | |
452 | |
453 void SetCallbackHappened2() { | |
454 g_callback_happened2 = true; | |
455 base::MessageLoop::current()->QuitWhenIdle(); | |
456 } | |
457 | |
458 TEST(TimerTest, ContinuationStopStart) { | |
459 { | |
460 ClearAllCallbackHappened(); | |
461 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
462 base::Timer timer(false, false); | |
463 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), | |
464 base::Bind(&SetCallbackHappened1)); | |
465 timer.Stop(); | |
466 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40), | |
467 base::Bind(&SetCallbackHappened2)); | |
468 base::MessageLoop::current()->Run(); | |
469 EXPECT_FALSE(g_callback_happened1); | |
470 EXPECT_TRUE(g_callback_happened2); | |
471 } | |
472 } | |
473 | |
474 TEST(TimerTest, ContinuationReset) { | |
475 { | |
476 ClearAllCallbackHappened(); | |
477 base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); | |
478 base::Timer timer(false, false); | |
479 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), | |
480 base::Bind(&SetCallbackHappened1)); | |
481 timer.Reset(); | |
482 // Since Reset happened before task ran, the user_task must not be cleared: | |
483 ASSERT_FALSE(timer.user_task().is_null()); | |
484 base::MessageLoop::current()->Run(); | |
485 EXPECT_TRUE(g_callback_happened1); | |
486 } | |
487 } | |
488 | |
489 } // namespace | |
OLD | NEW |