Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 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/message_loop.h"
      6 #include "base/scoped_ptr.h"
      7 #include "base/task.h"
      8 #include "base/timer.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 using base::TimeDelta;
     12 
     13 namespace {
     14 
     15 class OneShotTimerTester {
     16  public:
     17   OneShotTimerTester(bool* did_run, unsigned milliseconds = 10)
     18       : did_run_(did_run),
     19         delay_ms_(milliseconds) {
     20   }
     21   void Start() {
     22     timer_.Start(TimeDelta::FromMilliseconds(delay_ms_), this,
     23                  &OneShotTimerTester::Run);
     24   }
     25  private:
     26   void Run() {
     27     *did_run_ = true;
     28     MessageLoop::current()->Quit();
     29   }
     30   bool* did_run_;
     31   base::OneShotTimer<OneShotTimerTester> timer_;
     32   const unsigned delay_ms_;
     33 };
     34 
     35 class OneShotSelfDeletingTimerTester {
     36  public:
     37   explicit OneShotSelfDeletingTimerTester(bool* did_run) :
     38       did_run_(did_run),
     39       timer_(new base::OneShotTimer<OneShotSelfDeletingTimerTester>()) {
     40   }
     41   void Start() {
     42     timer_->Start(TimeDelta::FromMilliseconds(10), this,
     43                   &OneShotSelfDeletingTimerTester::Run);
     44   }
     45  private:
     46   void Run() {
     47     *did_run_ = true;
     48     timer_.reset();
     49     MessageLoop::current()->Quit();
     50   }
     51   bool* did_run_;
     52   scoped_ptr<base::OneShotTimer<OneShotSelfDeletingTimerTester> > timer_;
     53 };
     54 
     55 class RepeatingTimerTester {
     56  public:
     57   explicit RepeatingTimerTester(bool* did_run)
     58       : did_run_(did_run), counter_(10) {
     59   }
     60 
     61   void Start() {
     62     timer_.Start(TimeDelta::FromMilliseconds(10), this,
     63                  &RepeatingTimerTester::Run);
     64   }
     65  private:
     66   void Run() {
     67     if (--counter_ == 0) {
     68       *did_run_ = true;
     69       MessageLoop::current()->Quit();
     70     }
     71   }
     72   bool* did_run_;
     73   int counter_;
     74   base::RepeatingTimer<RepeatingTimerTester> timer_;
     75 };
     76 
     77 void RunTest_OneShotTimer(MessageLoop::Type message_loop_type) {
     78   MessageLoop loop(message_loop_type);
     79 
     80   bool did_run = false;
     81   OneShotTimerTester f(&did_run);
     82   f.Start();
     83 
     84   MessageLoop::current()->Run();
     85 
     86   EXPECT_TRUE(did_run);
     87 }
     88 
     89 void RunTest_OneShotTimer_Cancel(MessageLoop::Type message_loop_type) {
     90   MessageLoop loop(message_loop_type);
     91 
     92   bool did_run_a = false;
     93   OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
     94 
     95   // This should run before the timer expires.
     96   MessageLoop::current()->DeleteSoon(FROM_HERE, a);
     97 
     98   // Now start the timer.
     99   a->Start();
    100 
    101   bool did_run_b = false;
    102   OneShotTimerTester b(&did_run_b);
    103   b.Start();
    104 
    105   MessageLoop::current()->Run();
    106 
    107   EXPECT_FALSE(did_run_a);
    108   EXPECT_TRUE(did_run_b);
    109 }
    110 
    111 void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
    112   MessageLoop loop(message_loop_type);
    113 
    114   bool did_run = false;
    115   OneShotSelfDeletingTimerTester f(&did_run);
    116   f.Start();
    117 
    118   MessageLoop::current()->Run();
    119 
    120   EXPECT_TRUE(did_run);
    121 }
    122 
    123 void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type) {
    124   MessageLoop loop(message_loop_type);
    125 
    126   bool did_run = false;
    127   RepeatingTimerTester f(&did_run);
    128   f.Start();
    129 
    130   MessageLoop::current()->Run();
    131 
    132   EXPECT_TRUE(did_run);
    133 }
    134 
    135 void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type) {
    136   MessageLoop loop(message_loop_type);
    137 
    138   bool did_run_a = false;
    139   RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a);
    140 
    141   // This should run before the timer expires.
    142   MessageLoop::current()->DeleteSoon(FROM_HERE, a);
    143 
    144   // Now start the timer.
    145   a->Start();
    146 
    147   bool did_run_b = false;
    148   RepeatingTimerTester b(&did_run_b);
    149   b.Start();
    150 
    151   MessageLoop::current()->Run();
    152 
    153   EXPECT_FALSE(did_run_a);
    154   EXPECT_TRUE(did_run_b);
    155 }
    156 
    157 class DelayTimerTarget {
    158  public:
    159   DelayTimerTarget()
    160       : signaled_(false) {
    161   }
    162 
    163   bool signaled() const { return signaled_; }
    164 
    165   void Signal() {
    166     ASSERT_FALSE(signaled_);
    167     signaled_ = true;
    168   }
    169 
    170  private:
    171   bool signaled_;
    172 };
    173 
    174 void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
    175   MessageLoop loop(message_loop_type);
    176 
    177   // If Delay is never called, the timer shouldn't go off.
    178   DelayTimerTarget target;
    179   base::DelayTimer<DelayTimerTarget> timer(
    180       TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal);
    181 
    182   bool did_run = false;
    183   OneShotTimerTester tester(&did_run);
    184   tester.Start();
    185   MessageLoop::current()->Run();
    186 
    187   ASSERT_FALSE(target.signaled());
    188 }
    189 
    190 void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
    191   MessageLoop loop(message_loop_type);
    192 
    193   DelayTimerTarget target;
    194   base::DelayTimer<DelayTimerTarget> timer(
    195       TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal);
    196   timer.Reset();
    197 
    198   bool did_run = false;
    199   OneShotTimerTester tester(&did_run, 100 /* milliseconds */);
    200   tester.Start();
    201   MessageLoop::current()->Run();
    202 
    203   ASSERT_TRUE(target.signaled());
    204 }
    205 
    206 struct ResetHelper {
    207   ResetHelper(base::DelayTimer<DelayTimerTarget>* timer,
    208               DelayTimerTarget* target)
    209       : timer_(timer),
    210         target_(target) {
    211   }
    212 
    213   void Reset() {
    214     ASSERT_FALSE(target_->signaled());
    215     timer_->Reset();
    216   }
    217 
    218  private:
    219   base::DelayTimer<DelayTimerTarget> *const timer_;
    220   DelayTimerTarget *const target_;
    221 };
    222 
    223 void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
    224   MessageLoop loop(message_loop_type);
    225 
    226   // If Delay is never called, the timer shouldn't go off.
    227   DelayTimerTarget target;
    228   base::DelayTimer<DelayTimerTarget> timer(
    229       TimeDelta::FromMilliseconds(50), &target, &DelayTimerTarget::Signal);
    230   timer.Reset();
    231 
    232   ResetHelper reset_helper(&timer, &target);
    233 
    234   base::OneShotTimer<ResetHelper> timers[20];
    235   for (size_t i = 0; i < arraysize(timers); ++i) {
    236     timers[i].Start(TimeDelta::FromMilliseconds(i * 10), &reset_helper,
    237                     &ResetHelper::Reset);
    238   }
    239 
    240   bool did_run = false;
    241   OneShotTimerTester tester(&did_run, 300);
    242   tester.Start();
    243   MessageLoop::current()->Run();
    244 
    245   ASSERT_TRUE(target.signaled());
    246 }
    247 
    248 class DelayTimerFatalTarget {
    249  public:
    250   void Signal() {
    251     ASSERT_TRUE(false);
    252   }
    253 };
    254 
    255 
    256 void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
    257   MessageLoop loop(message_loop_type);
    258 
    259   DelayTimerFatalTarget target;
    260 
    261   {
    262     base::DelayTimer<DelayTimerFatalTarget> timer(
    263         TimeDelta::FromMilliseconds(50), &target,
    264         &DelayTimerFatalTarget::Signal);
    265     timer.Reset();
    266   }
    267 
    268   // When the timer is deleted, the DelayTimerFatalTarget should never be
    269   // called.
    270   PlatformThread::Sleep(100);
    271 }
    272 
    273 }  // namespace
    274 
    275 //-----------------------------------------------------------------------------
    276 // Each test is run against each type of MessageLoop.  That way we are sure
    277 // that timers work properly in all configurations.
    278 
    279 TEST(TimerTest, OneShotTimer) {
    280   RunTest_OneShotTimer(MessageLoop::TYPE_DEFAULT);
    281   RunTest_OneShotTimer(MessageLoop::TYPE_UI);
    282   RunTest_OneShotTimer(MessageLoop::TYPE_IO);
    283 }
    284 
    285 TEST(TimerTest, OneShotTimer_Cancel) {
    286   RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_DEFAULT);
    287   RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_UI);
    288   RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_IO);
    289 }
    290 
    291 // If underline timer does not handle properly, we will crash or fail
    292 // in full page heap or purify environment.
    293 TEST(TimerTest, OneShotSelfDeletingTimer) {
    294   RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_DEFAULT);
    295   RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_UI);
    296   RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_IO);
    297 }
    298 
    299 TEST(TimerTest, RepeatingTimer) {
    300   RunTest_RepeatingTimer(MessageLoop::TYPE_DEFAULT);
    301   RunTest_RepeatingTimer(MessageLoop::TYPE_UI);
    302   RunTest_RepeatingTimer(MessageLoop::TYPE_IO);
    303 }
    304 
    305 TEST(TimerTest, RepeatingTimer_Cancel) {
    306   RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_DEFAULT);
    307   RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_UI);
    308   RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_IO);
    309 }
    310 
    311 TEST(TimerTest, DelayTimer_NoCall) {
    312   RunTest_DelayTimer_NoCall(MessageLoop::TYPE_DEFAULT);
    313   RunTest_DelayTimer_NoCall(MessageLoop::TYPE_UI);
    314   RunTest_DelayTimer_NoCall(MessageLoop::TYPE_IO);
    315 }
    316 
    317 TEST(TimerTest, DelayTimer_OneCall) {
    318   RunTest_DelayTimer_OneCall(MessageLoop::TYPE_DEFAULT);
    319   RunTest_DelayTimer_OneCall(MessageLoop::TYPE_UI);
    320   RunTest_DelayTimer_OneCall(MessageLoop::TYPE_IO);
    321 }
    322 
    323 // It's flaky on the buildbot, http://crbug.com/25038.
    324 TEST(TimerTest, FLAKY_DelayTimer_Reset) {
    325   RunTest_DelayTimer_Reset(MessageLoop::TYPE_DEFAULT);
    326   RunTest_DelayTimer_Reset(MessageLoop::TYPE_UI);
    327   RunTest_DelayTimer_Reset(MessageLoop::TYPE_IO);
    328 }
    329 
    330 TEST(TimerTest, DelayTimer_Deleted) {
    331   RunTest_DelayTimer_Deleted(MessageLoop::TYPE_DEFAULT);
    332   RunTest_DelayTimer_Deleted(MessageLoop::TYPE_UI);
    333   RunTest_DelayTimer_Deleted(MessageLoop::TYPE_IO);
    334 }
    335 
    336 TEST(TimerTest, MessageLoopShutdown) {
    337   // This test is designed to verify that shutdown of the
    338   // message loop does not cause crashes if there were pending
    339   // timers not yet fired.  It may only trigger exceptions
    340   // if debug heap checking (or purify) is enabled.
    341   bool did_run = false;
    342   {
    343     OneShotTimerTester a(&did_run);
    344     OneShotTimerTester b(&did_run);
    345     OneShotTimerTester c(&did_run);
    346     OneShotTimerTester d(&did_run);
    347     {
    348       MessageLoop loop(MessageLoop::TYPE_DEFAULT);
    349       a.Start();
    350       b.Start();
    351     }  // MessageLoop destructs by falling out of scope.
    352   }  // OneShotTimers destruct.  SHOULD NOT CRASH, of course.
    353 
    354   EXPECT_EQ(false, did_run);
    355 }
    356