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