1 // Copyright (c) 2011 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.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 base::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_FALSE(did_run); 355 } 356