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