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 10using base::TimeDelta; 11 12namespace { 13 14// The message loops on which each timer should be tested. 15const 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 23const int kNumTestingMessageLoops = arraysize(testing_message_loops); 24 25class 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 45class 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 65class 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 88void 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 100void 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 122void 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 135void 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 148void 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 171class 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 188void 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 204void 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 220struct 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 237void 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 262class DelayTimerFatalTarget { 263 public: 264 void Signal() { 265 ASSERT_TRUE(false); 266 } 267}; 268 269 270void 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 293TEST(TimerTest, OneShotTimer) { 294 for (int i = 0; i < kNumTestingMessageLoops; i++) { 295 RunTest_OneShotTimer(testing_message_loops[i]); 296 } 297} 298 299TEST(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. 307TEST(TimerTest, OneShotSelfDeletingTimer) { 308 for (int i = 0; i < kNumTestingMessageLoops; i++) { 309 RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]); 310 } 311} 312 313TEST(TimerTest, RepeatingTimer) { 314 for (int i = 0; i < kNumTestingMessageLoops; i++) { 315 RunTest_RepeatingTimer(testing_message_loops[i], 316 TimeDelta::FromMilliseconds(10)); 317 } 318} 319 320TEST(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 327TEST(TimerTest, RepeatingTimerZeroDelay) { 328 for (int i = 0; i < kNumTestingMessageLoops; i++) { 329 RunTest_RepeatingTimer(testing_message_loops[i], 330 TimeDelta::FromMilliseconds(0)); 331 } 332} 333 334TEST(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 341TEST(TimerTest, DelayTimer_NoCall) { 342 for (int i = 0; i < kNumTestingMessageLoops; i++) { 343 RunTest_DelayTimer_NoCall(testing_message_loops[i]); 344 } 345} 346 347TEST(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. 354TEST(TimerTest, DISABLED_DelayTimer_Reset) { 355 for (int i = 0; i < kNumTestingMessageLoops; i++) { 356 RunTest_DelayTimer_Reset(testing_message_loops[i]); 357 } 358} 359 360TEST(TimerTest, DelayTimer_Deleted) { 361 for (int i = 0; i < kNumTestingMessageLoops; i++) { 362 RunTest_DelayTimer_Deleted(testing_message_loops[i]); 363 } 364} 365 366TEST(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 387void TimerTestCallback() { 388} 389 390TEST(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 418TEST(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 431TEST(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 444TEST(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 457namespace { 458 459bool g_callback_happened1 = false; 460bool g_callback_happened2 = false; 461 462void ClearAllCallbackHappened() { 463 g_callback_happened1 = false; 464 g_callback_happened2 = false; 465} 466 467void SetCallbackHappened1() { 468 g_callback_happened1 = true; 469 base::MessageLoop::current()->QuitWhenIdle(); 470} 471 472void SetCallbackHappened2() { 473 g_callback_happened2 = true; 474 base::MessageLoop::current()->QuitWhenIdle(); 475} 476 477TEST(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 493TEST(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