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 <stddef.h> 6 7 #include "base/macros.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/test/test_simple_task_runner.h" 11 #include "base/timer/timer.h" 12 #include "build/build_config.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 using base::TimeDelta; 16 using base::SingleThreadTaskRunner; 17 18 namespace { 19 20 // The message loops on which each timer should be tested. 21 const base::MessageLoop::Type testing_message_loops[] = { 22 base::MessageLoop::TYPE_DEFAULT, 23 base::MessageLoop::TYPE_IO, 24 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop. 25 base::MessageLoop::TYPE_UI, 26 #endif 27 }; 28 29 const int kNumTestingMessageLoops = arraysize(testing_message_loops); 30 31 class OneShotTimerTester { 32 public: 33 explicit OneShotTimerTester(bool* did_run, unsigned milliseconds = 10) 34 : did_run_(did_run), 35 delay_ms_(milliseconds), 36 quit_message_loop_(true) { 37 } 38 39 void Start() { 40 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(delay_ms_), this, 41 &OneShotTimerTester::Run); 42 } 43 44 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) { 45 quit_message_loop_ = false; 46 timer_.SetTaskRunner(task_runner); 47 } 48 49 private: 50 void Run() { 51 *did_run_ = true; 52 if (quit_message_loop_) { 53 base::MessageLoop::current()->QuitWhenIdle(); 54 } 55 } 56 57 bool* did_run_; 58 base::OneShotTimer timer_; 59 const unsigned delay_ms_; 60 bool quit_message_loop_; 61 }; 62 63 class OneShotSelfDeletingTimerTester { 64 public: 65 explicit OneShotSelfDeletingTimerTester(bool* did_run) 66 : did_run_(did_run), timer_(new base::OneShotTimer()) {} 67 68 void Start() { 69 timer_->Start(FROM_HERE, TimeDelta::FromMilliseconds(10), this, 70 &OneShotSelfDeletingTimerTester::Run); 71 } 72 73 private: 74 void Run() { 75 *did_run_ = true; 76 timer_.reset(); 77 base::MessageLoop::current()->QuitWhenIdle(); 78 } 79 80 bool* did_run_; 81 scoped_ptr<base::OneShotTimer> timer_; 82 }; 83 84 class RepeatingTimerTester { 85 public: 86 explicit RepeatingTimerTester(bool* did_run, const TimeDelta& delay) 87 : did_run_(did_run), counter_(10), delay_(delay) { 88 } 89 90 void Start() { 91 timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run); 92 } 93 94 private: 95 void Run() { 96 if (--counter_ == 0) { 97 *did_run_ = true; 98 timer_.Stop(); 99 base::MessageLoop::current()->QuitWhenIdle(); 100 } 101 } 102 103 bool* did_run_; 104 int counter_; 105 TimeDelta delay_; 106 base::RepeatingTimer timer_; 107 }; 108 109 void RunTest_OneShotTimer(base::MessageLoop::Type message_loop_type) { 110 base::MessageLoop loop(message_loop_type); 111 112 bool did_run = false; 113 OneShotTimerTester f(&did_run); 114 f.Start(); 115 116 base::MessageLoop::current()->Run(); 117 118 EXPECT_TRUE(did_run); 119 } 120 121 void RunTest_OneShotTimer_Cancel(base::MessageLoop::Type message_loop_type) { 122 base::MessageLoop loop(message_loop_type); 123 124 bool did_run_a = false; 125 OneShotTimerTester* a = new OneShotTimerTester(&did_run_a); 126 127 // This should run before the timer expires. 128 base::MessageLoop::current()->DeleteSoon(FROM_HERE, a); 129 130 // Now start the timer. 131 a->Start(); 132 133 bool did_run_b = false; 134 OneShotTimerTester b(&did_run_b); 135 b.Start(); 136 137 base::MessageLoop::current()->Run(); 138 139 EXPECT_FALSE(did_run_a); 140 EXPECT_TRUE(did_run_b); 141 } 142 143 void RunTest_OneShotSelfDeletingTimer( 144 base::MessageLoop::Type message_loop_type) { 145 base::MessageLoop loop(message_loop_type); 146 147 bool did_run = false; 148 OneShotSelfDeletingTimerTester f(&did_run); 149 f.Start(); 150 151 base::MessageLoop::current()->Run(); 152 153 EXPECT_TRUE(did_run); 154 } 155 156 void RunTest_RepeatingTimer(base::MessageLoop::Type message_loop_type, 157 const TimeDelta& delay) { 158 base::MessageLoop loop(message_loop_type); 159 160 bool did_run = false; 161 RepeatingTimerTester f(&did_run, delay); 162 f.Start(); 163 164 base::MessageLoop::current()->Run(); 165 166 EXPECT_TRUE(did_run); 167 } 168 169 void RunTest_RepeatingTimer_Cancel(base::MessageLoop::Type message_loop_type, 170 const TimeDelta& delay) { 171 base::MessageLoop loop(message_loop_type); 172 173 bool did_run_a = false; 174 RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a, delay); 175 176 // This should run before the timer expires. 177 base::MessageLoop::current()->DeleteSoon(FROM_HERE, a); 178 179 // Now start the timer. 180 a->Start(); 181 182 bool did_run_b = false; 183 RepeatingTimerTester b(&did_run_b, delay); 184 b.Start(); 185 186 base::MessageLoop::current()->Run(); 187 188 EXPECT_FALSE(did_run_a); 189 EXPECT_TRUE(did_run_b); 190 } 191 192 class DelayTimerTarget { 193 public: 194 bool signaled() const { return signaled_; } 195 196 void Signal() { 197 ASSERT_FALSE(signaled_); 198 signaled_ = true; 199 } 200 201 private: 202 bool signaled_ = false; 203 }; 204 205 void RunTest_DelayTimer_NoCall(base::MessageLoop::Type message_loop_type) { 206 base::MessageLoop loop(message_loop_type); 207 208 // If Delay is never called, the timer shouldn't go off. 209 DelayTimerTarget target; 210 base::DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target, 211 &DelayTimerTarget::Signal); 212 213 bool did_run = false; 214 OneShotTimerTester tester(&did_run); 215 tester.Start(); 216 base::MessageLoop::current()->Run(); 217 218 ASSERT_FALSE(target.signaled()); 219 } 220 221 void RunTest_DelayTimer_OneCall(base::MessageLoop::Type message_loop_type) { 222 base::MessageLoop loop(message_loop_type); 223 224 DelayTimerTarget target; 225 base::DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target, 226 &DelayTimerTarget::Signal); 227 timer.Reset(); 228 229 bool did_run = false; 230 OneShotTimerTester tester(&did_run, 100 /* milliseconds */); 231 tester.Start(); 232 base::MessageLoop::current()->Run(); 233 234 ASSERT_TRUE(target.signaled()); 235 } 236 237 struct ResetHelper { 238 ResetHelper(base::DelayTimer* timer, DelayTimerTarget* target) 239 : timer_(timer), target_(target) {} 240 241 void Reset() { 242 ASSERT_FALSE(target_->signaled()); 243 timer_->Reset(); 244 } 245 246 private: 247 base::DelayTimer* const timer_; 248 DelayTimerTarget* const target_; 249 }; 250 251 void RunTest_DelayTimer_Reset(base::MessageLoop::Type message_loop_type) { 252 base::MessageLoop loop(message_loop_type); 253 254 // If Delay is never called, the timer shouldn't go off. 255 DelayTimerTarget target; 256 base::DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target, 257 &DelayTimerTarget::Signal); 258 timer.Reset(); 259 260 ResetHelper reset_helper(&timer, &target); 261 262 base::OneShotTimer timers[20]; 263 for (size_t i = 0; i < arraysize(timers); ++i) { 264 timers[i].Start(FROM_HERE, TimeDelta::FromMilliseconds(i * 10), 265 &reset_helper, &ResetHelper::Reset); 266 } 267 268 bool did_run = false; 269 OneShotTimerTester tester(&did_run, 300); 270 tester.Start(); 271 base::MessageLoop::current()->Run(); 272 273 ASSERT_TRUE(target.signaled()); 274 } 275 276 class DelayTimerFatalTarget { 277 public: 278 void Signal() { 279 ASSERT_TRUE(false); 280 } 281 }; 282 283 284 void RunTest_DelayTimer_Deleted(base::MessageLoop::Type message_loop_type) { 285 base::MessageLoop loop(message_loop_type); 286 287 DelayTimerFatalTarget target; 288 289 { 290 base::DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target, 291 &DelayTimerFatalTarget::Signal); 292 timer.Reset(); 293 } 294 295 // When the timer is deleted, the DelayTimerFatalTarget should never be 296 // called. 297 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); 298 } 299 300 } // namespace 301 302 //----------------------------------------------------------------------------- 303 // Each test is run against each type of MessageLoop. That way we are sure 304 // that timers work properly in all configurations. 305 306 TEST(TimerTest, OneShotTimer) { 307 for (int i = 0; i < kNumTestingMessageLoops; i++) { 308 RunTest_OneShotTimer(testing_message_loops[i]); 309 } 310 } 311 312 TEST(TimerTest, OneShotTimer_Cancel) { 313 for (int i = 0; i < kNumTestingMessageLoops; i++) { 314 RunTest_OneShotTimer_Cancel(testing_message_loops[i]); 315 } 316 } 317 318 // If underline timer does not handle properly, we will crash or fail 319 // in full page heap environment. 320 TEST(TimerTest, OneShotSelfDeletingTimer) { 321 for (int i = 0; i < kNumTestingMessageLoops; i++) { 322 RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]); 323 } 324 } 325 326 TEST(TimerTest, OneShotTimer_CustomTaskRunner) { 327 scoped_refptr<base::TestSimpleTaskRunner> task_runner = 328 new base::TestSimpleTaskRunner(); 329 330 bool did_run = false; 331 OneShotTimerTester f(&did_run); 332 f.SetTaskRunner(task_runner); 333 f.Start(); 334 335 EXPECT_FALSE(did_run); 336 task_runner->RunUntilIdle(); 337 EXPECT_TRUE(did_run); 338 } 339 340 TEST(TimerTest, RepeatingTimer) { 341 for (int i = 0; i < kNumTestingMessageLoops; i++) { 342 RunTest_RepeatingTimer(testing_message_loops[i], 343 TimeDelta::FromMilliseconds(10)); 344 } 345 } 346 347 TEST(TimerTest, RepeatingTimer_Cancel) { 348 for (int i = 0; i < kNumTestingMessageLoops; i++) { 349 RunTest_RepeatingTimer_Cancel(testing_message_loops[i], 350 TimeDelta::FromMilliseconds(10)); 351 } 352 } 353 354 TEST(TimerTest, RepeatingTimerZeroDelay) { 355 for (int i = 0; i < kNumTestingMessageLoops; i++) { 356 RunTest_RepeatingTimer(testing_message_loops[i], 357 TimeDelta::FromMilliseconds(0)); 358 } 359 } 360 361 TEST(TimerTest, RepeatingTimerZeroDelay_Cancel) { 362 for (int i = 0; i < kNumTestingMessageLoops; i++) { 363 RunTest_RepeatingTimer_Cancel(testing_message_loops[i], 364 TimeDelta::FromMilliseconds(0)); 365 } 366 } 367 368 TEST(TimerTest, DelayTimer_NoCall) { 369 for (int i = 0; i < kNumTestingMessageLoops; i++) { 370 RunTest_DelayTimer_NoCall(testing_message_loops[i]); 371 } 372 } 373 374 TEST(TimerTest, DelayTimer_OneCall) { 375 for (int i = 0; i < kNumTestingMessageLoops; i++) { 376 RunTest_DelayTimer_OneCall(testing_message_loops[i]); 377 } 378 } 379 380 // It's flaky on the buildbot, http://crbug.com/25038. 381 TEST(TimerTest, DISABLED_DelayTimer_Reset) { 382 for (int i = 0; i < kNumTestingMessageLoops; i++) { 383 RunTest_DelayTimer_Reset(testing_message_loops[i]); 384 } 385 } 386 387 TEST(TimerTest, DelayTimer_Deleted) { 388 for (int i = 0; i < kNumTestingMessageLoops; i++) { 389 RunTest_DelayTimer_Deleted(testing_message_loops[i]); 390 } 391 } 392 393 TEST(TimerTest, MessageLoopShutdown) { 394 // This test is designed to verify that shutdown of the 395 // message loop does not cause crashes if there were pending 396 // timers not yet fired. It may only trigger exceptions 397 // if debug heap checking is enabled. 398 bool did_run = false; 399 { 400 OneShotTimerTester a(&did_run); 401 OneShotTimerTester b(&did_run); 402 OneShotTimerTester c(&did_run); 403 OneShotTimerTester d(&did_run); 404 { 405 base::MessageLoop loop; 406 a.Start(); 407 b.Start(); 408 } // MessageLoop destructs by falling out of scope. 409 } // OneShotTimers destruct. SHOULD NOT CRASH, of course. 410 411 EXPECT_FALSE(did_run); 412 } 413 414 void TimerTestCallback() { 415 } 416 417 TEST(TimerTest, NonRepeatIsRunning) { 418 { 419 base::MessageLoop loop; 420 base::Timer timer(false, false); 421 EXPECT_FALSE(timer.IsRunning()); 422 timer.Start(FROM_HERE, TimeDelta::FromDays(1), 423 base::Bind(&TimerTestCallback)); 424 EXPECT_TRUE(timer.IsRunning()); 425 timer.Stop(); 426 EXPECT_FALSE(timer.IsRunning()); 427 EXPECT_TRUE(timer.user_task().is_null()); 428 } 429 430 { 431 base::Timer timer(true, false); 432 base::MessageLoop loop; 433 EXPECT_FALSE(timer.IsRunning()); 434 timer.Start(FROM_HERE, TimeDelta::FromDays(1), 435 base::Bind(&TimerTestCallback)); 436 EXPECT_TRUE(timer.IsRunning()); 437 timer.Stop(); 438 EXPECT_FALSE(timer.IsRunning()); 439 ASSERT_FALSE(timer.user_task().is_null()); 440 timer.Reset(); 441 EXPECT_TRUE(timer.IsRunning()); 442 } 443 } 444 445 TEST(TimerTest, NonRepeatMessageLoopDeath) { 446 base::Timer timer(false, false); 447 { 448 base::MessageLoop loop; 449 EXPECT_FALSE(timer.IsRunning()); 450 timer.Start(FROM_HERE, TimeDelta::FromDays(1), 451 base::Bind(&TimerTestCallback)); 452 EXPECT_TRUE(timer.IsRunning()); 453 } 454 EXPECT_FALSE(timer.IsRunning()); 455 EXPECT_TRUE(timer.user_task().is_null()); 456 } 457 458 TEST(TimerTest, RetainRepeatIsRunning) { 459 base::MessageLoop loop; 460 base::Timer timer(FROM_HERE, TimeDelta::FromDays(1), 461 base::Bind(&TimerTestCallback), true); 462 EXPECT_FALSE(timer.IsRunning()); 463 timer.Reset(); 464 EXPECT_TRUE(timer.IsRunning()); 465 timer.Stop(); 466 EXPECT_FALSE(timer.IsRunning()); 467 timer.Reset(); 468 EXPECT_TRUE(timer.IsRunning()); 469 } 470 471 TEST(TimerTest, RetainNonRepeatIsRunning) { 472 base::MessageLoop loop; 473 base::Timer timer(FROM_HERE, TimeDelta::FromDays(1), 474 base::Bind(&TimerTestCallback), false); 475 EXPECT_FALSE(timer.IsRunning()); 476 timer.Reset(); 477 EXPECT_TRUE(timer.IsRunning()); 478 timer.Stop(); 479 EXPECT_FALSE(timer.IsRunning()); 480 timer.Reset(); 481 EXPECT_TRUE(timer.IsRunning()); 482 } 483 484 namespace { 485 486 bool g_callback_happened1 = false; 487 bool g_callback_happened2 = false; 488 489 void ClearAllCallbackHappened() { 490 g_callback_happened1 = false; 491 g_callback_happened2 = false; 492 } 493 494 void SetCallbackHappened1() { 495 g_callback_happened1 = true; 496 base::MessageLoop::current()->QuitWhenIdle(); 497 } 498 499 void SetCallbackHappened2() { 500 g_callback_happened2 = true; 501 base::MessageLoop::current()->QuitWhenIdle(); 502 } 503 504 TEST(TimerTest, ContinuationStopStart) { 505 { 506 ClearAllCallbackHappened(); 507 base::MessageLoop loop; 508 base::Timer timer(false, false); 509 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), 510 base::Bind(&SetCallbackHappened1)); 511 timer.Stop(); 512 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40), 513 base::Bind(&SetCallbackHappened2)); 514 base::MessageLoop::current()->Run(); 515 EXPECT_FALSE(g_callback_happened1); 516 EXPECT_TRUE(g_callback_happened2); 517 } 518 } 519 520 TEST(TimerTest, ContinuationReset) { 521 { 522 ClearAllCallbackHappened(); 523 base::MessageLoop loop; 524 base::Timer timer(false, false); 525 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), 526 base::Bind(&SetCallbackHappened1)); 527 timer.Reset(); 528 // Since Reset happened before task ran, the user_task must not be cleared: 529 ASSERT_FALSE(timer.user_task().is_null()); 530 base::MessageLoop::current()->Run(); 531 EXPECT_TRUE(g_callback_happened1); 532 } 533 } 534 535 } // namespace 536