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