• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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