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