• 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/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