Home | History | Annotate | Download | only in timer
      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:
     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, const TimeDelta& delay)
     68       : did_run_(did_run), counter_(10), delay_(delay) {
     69   }
     70 
     71   void Start() {
     72     timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run);
     73   }
     74  private:
     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 
     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 
    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 
    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 
    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 
    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:
    173   DelayTimerTarget()
    174       : signaled_(false) {
    175   }
    176 
    177   bool signaled() const { return signaled_; }
    178 
    179   void Signal() {
    180     ASSERT_FALSE(signaled_);
    181     signaled_ = true;
    182   }
    183 
    184  private:
    185   bool signaled_;
    186 };
    187 
    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 
    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 {
    221   ResetHelper(base::DelayTimer<DelayTimerTarget>* timer,
    222               DelayTimerTarget* target)
    223       : timer_(timer),
    224         target_(target) {
    225   }
    226 
    227   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 
    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:
    264   void Signal() {
    265     ASSERT_TRUE(false);
    266   }
    267 };
    268 
    269 
    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 
    293 TEST(TimerTest, OneShotTimer) {
    294   for (int i = 0; i < kNumTestingMessageLoops; i++) {
    295     RunTest_OneShotTimer(testing_message_loops[i]);
    296   }
    297 }
    298 
    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.
    307 TEST(TimerTest, OneShotSelfDeletingTimer) {
    308   for (int i = 0; i < kNumTestingMessageLoops; i++) {
    309     RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]);
    310   }
    311 }
    312 
    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 
    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 
    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 
    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 
    341 TEST(TimerTest, DelayTimer_NoCall) {
    342   for (int i = 0; i < kNumTestingMessageLoops; i++) {
    343     RunTest_DelayTimer_NoCall(testing_message_loops[i]);
    344   }
    345 }
    346 
    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.
    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 
    360 TEST(TimerTest, DelayTimer_Deleted) {
    361   for (int i = 0; i < kNumTestingMessageLoops; i++) {
    362     RunTest_DelayTimer_Deleted(testing_message_loops[i]);
    363   }
    364 }
    365 
    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;
    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 
    387 void TimerTestCallback() {
    388 }
    389 
    390 TEST(TimerTest, NonRepeatIsRunning) {
    391   {
    392     base::MessageLoop loop;
    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;
    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 
    418 TEST(TimerTest, NonRepeatMessageLoopDeath) {
    419   base::Timer timer(false, false);
    420   {
    421     base::MessageLoop loop;
    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 
    431 TEST(TimerTest, RetainRepeatIsRunning) {
    432   base::MessageLoop loop;
    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 
    444 TEST(TimerTest, RetainNonRepeatIsRunning) {
    445   base::MessageLoop loop;
    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 
    462 void ClearAllCallbackHappened() {
    463   g_callback_happened1 = false;
    464   g_callback_happened2 = false;
    465 }
    466 
    467 void SetCallbackHappened1() {
    468   g_callback_happened1 = true;
    469   base::MessageLoop::current()->QuitWhenIdle();
    470 }
    471 
    472 void SetCallbackHappened2() {
    473   g_callback_happened2 = true;
    474   base::MessageLoop::current()->QuitWhenIdle();
    475 }
    476 
    477 TEST(TimerTest, ContinuationStopStart) {
    478   {
    479     ClearAllCallbackHappened();
    480     base::MessageLoop loop;
    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 
    493 TEST(TimerTest, ContinuationReset) {
    494   {
    495     ClearAllCallbackHappened();
    496     base::MessageLoop loop;
    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