| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/message_loop.h" | 5 #include "base/message_loop.h" |
| 6 #include "base/task.h" | 6 #include "base/task.h" |
| 7 #include "base/timer.h" | 7 #include "base/timer.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 9 |
| 10 using base::TimerComparison; | |
| 11 | |
| 12 namespace { | |
| 13 | |
| 14 class TimerTest : public testing::Test {}; | |
| 15 | |
| 16 // A base class timer task that sanity-checks timer functionality and counts | |
| 17 // the number of times it has run. Handles all message loop and memory | |
| 18 // management issues. | |
| 19 class TimerTask : public Task { | |
| 20 public: | |
| 21 // Runs all timers to completion. This returns only after all timers have | |
| 22 // finished firing. | |
| 23 static void RunTimers(); | |
| 24 | |
| 25 // Creates a new timer. If |repeating| is true, the timer will repeat 10 | |
| 26 // times before terminating. | |
| 27 // | |
| 28 // All timers are managed on the message loop of the thread that calls this | |
| 29 // function the first time. | |
| 30 TimerTask(int delay, bool repeating); | |
| 31 | |
| 32 virtual ~TimerTask(); | |
| 33 | |
| 34 int iterations() const { return iterations_; } | |
| 35 const Timer* timer() const { return timer_; } | |
| 36 | |
| 37 // Resets the timer, if it exists. | |
| 38 void Reset(); | |
| 39 | |
| 40 // Task | |
| 41 virtual void Run(); | |
| 42 | |
| 43 protected: | |
| 44 // Shuts down the message loop if necessary. | |
| 45 static void QuitMessageLoop(); | |
| 46 | |
| 47 private: | |
| 48 static MessageLoop* message_loop() { | |
| 49 return MessageLoop::current(); | |
| 50 } | |
| 51 | |
| 52 static int timer_count_; | |
| 53 static bool loop_running_; | |
| 54 | |
| 55 bool timer_running_; | |
| 56 int delay_; | |
| 57 TimeTicks start_ticks_; | |
| 58 int iterations_; | |
| 59 Timer* timer_; | |
| 60 }; | |
| 61 | |
| 62 // static | |
| 63 void TimerTask::RunTimers() { | |
| 64 if (timer_count_ && !loop_running_) { | |
| 65 loop_running_ = true; | |
| 66 message_loop()->Run(); | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 TimerTask::TimerTask(int delay, bool repeating) | |
| 71 : timer_running_(false), | |
| 72 delay_(delay), | |
| 73 start_ticks_(TimeTicks::Now()), | |
| 74 iterations_(0), | |
| 75 timer_(NULL) { | |
| 76 Reset(); // This will just set up the variables to indicate we have a | |
| 77 // running timer. | |
| 78 timer_ = message_loop()->timer_manager_deprecated()->StartTimer( | |
| 79 delay, this, repeating); | |
| 80 } | |
| 81 | |
| 82 TimerTask::~TimerTask() { | |
| 83 if (timer_) { | |
| 84 message_loop()->timer_manager_deprecated()->StopTimer(timer_); | |
| 85 delete timer_; | |
| 86 } | |
| 87 if (timer_running_) { | |
| 88 timer_running_ = false; | |
| 89 if (--timer_count_ <= 0) | |
| 90 QuitMessageLoop(); | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 void TimerTask::Reset() { | |
| 95 if (!timer_running_) { | |
| 96 timer_running_ = true; | |
| 97 ++timer_count_; | |
| 98 } | |
| 99 if (timer_) { | |
| 100 start_ticks_ = TimeTicks::Now(); | |
| 101 message_loop()->timer_manager_deprecated()->ResetTimer(timer_); | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 void TimerTask::Run() { | |
| 106 ++iterations_; | |
| 107 | |
| 108 // Test that we fired on or after the delay, not before. | |
| 109 const TimeTicks ticks = TimeTicks::Now(); | |
| 110 EXPECT_LE(delay_, (ticks - start_ticks_).InMilliseconds()); | |
| 111 // Note: Add the delay rather than using the ticks recorded. | |
| 112 // Repeating timers have already started ticking before | |
| 113 // this callback; we pretend they started *now*, then | |
| 114 // it might seem like they fire early, when they do not. | |
| 115 start_ticks_ += TimeDelta::FromMilliseconds(delay_); | |
| 116 | |
| 117 // If we're done running, shut down the message loop. | |
| 118 if (timer_->repeating() && (iterations_ < 10)) | |
| 119 return; // Iterate 10 times before terminating. | |
| 120 message_loop()->timer_manager_deprecated()->StopTimer(timer_); | |
| 121 timer_running_ = false; | |
| 122 if (--timer_count_ <= 0) | |
| 123 QuitMessageLoop(); | |
| 124 } | |
| 125 | |
| 126 // static | |
| 127 void TimerTask::QuitMessageLoop() { | |
| 128 if (loop_running_) { | |
| 129 message_loop()->Quit(); | |
| 130 loop_running_ = false; | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 int TimerTask::timer_count_ = 0; | |
| 135 bool TimerTask::loop_running_ = false; | |
| 136 | |
| 137 // A task that deletes itself when run. | |
| 138 class DeletingTask : public TimerTask { | |
| 139 public: | |
| 140 DeletingTask(int delay, bool repeating) : TimerTask(delay, repeating) { } | |
| 141 | |
| 142 // Task | |
| 143 virtual void Run(); | |
| 144 }; | |
| 145 | |
| 146 void DeletingTask::Run() { | |
| 147 delete this; | |
| 148 | |
| 149 // Can't call TimerTask::Run() here, we've destroyed ourselves. | |
| 150 } | |
| 151 | |
| 152 // A class that resets another TimerTask when run. | |
| 153 class ResettingTask : public TimerTask { | |
| 154 public: | |
| 155 ResettingTask(int delay, bool repeating, TimerTask* task) | |
| 156 : TimerTask(delay, repeating), | |
| 157 task_(task) { | |
| 158 } | |
| 159 | |
| 160 virtual void Run(); | |
| 161 | |
| 162 private: | |
| 163 TimerTask* task_; | |
| 164 }; | |
| 165 | |
| 166 void ResettingTask::Run() { | |
| 167 task_->Reset(); | |
| 168 | |
| 169 TimerTask::Run(); | |
| 170 } | |
| 171 | |
| 172 // A class that quits the message loop when run. | |
| 173 class QuittingTask : public TimerTask { | |
| 174 public: | |
| 175 QuittingTask(int delay, bool repeating) : TimerTask(delay, repeating) { } | |
| 176 | |
| 177 virtual void Run(); | |
| 178 }; | |
| 179 | |
| 180 void QuittingTask::Run() { | |
| 181 QuitMessageLoop(); | |
| 182 | |
| 183 TimerTask::Run(); | |
| 184 } | |
| 185 | |
| 186 void RunTimerTest() { | |
| 187 // Make sure oneshot timers work correctly. | |
| 188 TimerTask task1(100, false); | |
| 189 TimerTask::RunTimers(); | |
| 190 EXPECT_EQ(1, task1.iterations()); | |
| 191 | |
| 192 // Make sure repeating timers work correctly. | |
| 193 TimerTask task2(10, true); | |
| 194 TimerTask task3(100, true); | |
| 195 TimerTask::RunTimers(); | |
| 196 EXPECT_EQ(10, task2.iterations()); | |
| 197 EXPECT_EQ(10, task3.iterations()); | |
| 198 } | |
| 199 | |
| 200 //----------------------------------------------------------------------------- | |
| 201 // The timer test cases: | |
| 202 | |
| 203 void RunTest_TimerComparison(MessageLoop::Type message_loop_type) { | |
| 204 MessageLoop loop(message_loop_type); | |
| 205 | |
| 206 // Make sure TimerComparison sorts correctly. | |
| 207 const TimerTask task1(10, false); | |
| 208 const Timer* timer1 = task1.timer(); | |
| 209 const TimerTask task2(200, false); | |
| 210 const Timer* timer2 = task2.timer(); | |
| 211 TimerComparison comparison; | |
| 212 EXPECT_FALSE(comparison(timer1, timer2)); | |
| 213 EXPECT_TRUE(comparison(timer2, timer1)); | |
| 214 } | |
| 215 | |
| 216 void RunTest_BasicTimer(MessageLoop::Type message_loop_type) { | |
| 217 MessageLoop loop(message_loop_type); | |
| 218 | |
| 219 RunTimerTest(); | |
| 220 } | |
| 221 | |
| 222 void RunTest_BrokenTimer(MessageLoop::Type message_loop_type) { | |
| 223 MessageLoop loop(message_loop_type); | |
| 224 | |
| 225 // Simulate faulty early-firing timers. The tasks in RunTimerTest should | |
| 226 // nevertheless be invoked after their specified delays, regardless of when | |
| 227 // WM_TIMER fires. | |
| 228 TimerManager* manager = MessageLoop::current()->timer_manager_deprecated(); | |
| 229 manager->set_use_broken_delay(true); | |
| 230 RunTimerTest(); | |
| 231 manager->set_use_broken_delay(false); | |
| 232 } | |
| 233 | |
| 234 void RunTest_DeleteFromRun(MessageLoop::Type message_loop_type) { | |
| 235 MessageLoop loop(message_loop_type); | |
| 236 | |
| 237 // Make sure TimerManager correctly handles a Task that deletes itself when | |
| 238 // run. | |
| 239 new DeletingTask(50, true); | |
| 240 TimerTask timer_task(150, false); | |
| 241 new DeletingTask(250, true); | |
| 242 TimerTask::RunTimers(); | |
| 243 EXPECT_EQ(1, timer_task.iterations()); | |
| 244 } | |
| 245 | |
| 246 void RunTest_Reset(MessageLoop::Type message_loop_type) { | |
| 247 MessageLoop loop(message_loop_type); | |
| 248 | |
| 249 // Make sure resetting a timer after it has fired works. | |
| 250 TimerTask timer_task1(250, false); | |
| 251 TimerTask timer_task2(100, true); | |
| 252 ResettingTask resetting_task1(600, false, &timer_task1); | |
| 253 TimerTask::RunTimers(); | |
| 254 EXPECT_EQ(2, timer_task1.iterations()); | |
| 255 EXPECT_EQ(10, timer_task2.iterations()); | |
| 256 | |
| 257 // Make sure resetting a timer before it has fired works. This will reset | |
| 258 // two timers, then stop the message loop between when they should have | |
| 259 // finally fired. | |
| 260 TimerTask timer_task3(100, false); | |
| 261 TimerTask timer_task4(600, false); | |
| 262 ResettingTask resetting_task3(50, false, &timer_task3); | |
| 263 ResettingTask resetting_task4(50, false, &timer_task4); | |
| 264 QuittingTask quitting_task(300, false); | |
| 265 TimerTask::RunTimers(); | |
| 266 EXPECT_EQ(1, timer_task3.iterations()); | |
| 267 EXPECT_EQ(0, timer_task4.iterations()); | |
| 268 } | |
| 269 | |
| 270 void RunTest_FifoOrder(MessageLoop::Type message_loop_type) { | |
| 271 MessageLoop loop(message_loop_type); | |
| 272 | |
| 273 // Creating timers with the same timeout should | |
| 274 // always compare to result in FIFO ordering. | |
| 275 | |
| 276 // Derive from the timer so that we can set it's fire time. | |
| 277 // We have to do this, because otherwise, it's possible for | |
| 278 // two timers, created back to back, to have different times, | |
| 279 // and in that case, we aren't really testing what we want | |
| 280 // to test! | |
| 281 class MockTimer : public Timer { | |
| 282 public: | |
| 283 MockTimer(int delay) : Timer(delay, NULL, false) {} | |
| 284 void set_fire_time(const Time& t) { fire_time_ = t; } | |
| 285 }; | |
| 286 | |
| 287 class MockTimerManager : public TimerManager { | |
| 288 public: | |
| 289 MockTimerManager() : TimerManager(MessageLoop::current()) { | |
| 290 } | |
| 291 | |
| 292 // Pops the most-recent to fire timer and returns its timer id. | |
| 293 // Returns -1 if there are no timers in the list. | |
| 294 int pop() { | |
| 295 int rv = -1; | |
| 296 Timer* top = PeekTopTimer(); | |
| 297 if (top) { | |
| 298 rv = top->id(); | |
| 299 StopTimer(top); | |
| 300 delete top; | |
| 301 } | |
| 302 return rv; | |
| 303 } | |
| 304 }; | |
| 305 | |
| 306 MockTimer t1(0); | |
| 307 MockTimer t2(0); | |
| 308 t2.set_fire_time(t1.fire_time()); | |
| 309 TimerComparison comparison; | |
| 310 EXPECT_TRUE(comparison(&t2, &t1)); | |
| 311 | |
| 312 // Issue a tight loop of timers; most will have the | |
| 313 // same timestamp; some will not. Either way, since | |
| 314 // all are created with delay(0), the second timer | |
| 315 // must always be greater than the first. Then, pop | |
| 316 // all the timers and verify that it's a FIFO list. | |
| 317 MockTimerManager manager; | |
| 318 const int kNumTimers = 1024; | |
| 319 for (int i=0; i < kNumTimers; i++) | |
| 320 manager.StartTimer(0, NULL, false); | |
| 321 | |
| 322 int last_id = -1; | |
| 323 int new_id = 0; | |
| 324 while((new_id = manager.pop()) > 0) | |
| 325 EXPECT_GT(new_id, last_id); | |
| 326 } | |
| 327 | |
| 328 namespace { | 10 namespace { |
| 329 | 11 |
| 330 class OneShotTimerTester { | 12 class OneShotTimerTester { |
| 331 public: | 13 public: |
| 332 OneShotTimerTester(bool* did_run) : did_run_(did_run) { | 14 OneShotTimerTester(bool* did_run) : did_run_(did_run) { |
| 333 } | 15 } |
| 334 void Start() { | 16 void Start() { |
| 335 timer_.Start(TimeDelta::FromMilliseconds(10), this, | 17 timer_.Start(TimeDelta::FromMilliseconds(10), this, |
| 336 &OneShotTimerTester::Run); | 18 &OneShotTimerTester::Run); |
| 337 } | 19 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 357 if (--counter_ == 0) { | 39 if (--counter_ == 0) { |
| 358 *did_run_ = true; | 40 *did_run_ = true; |
| 359 MessageLoop::current()->Quit(); | 41 MessageLoop::current()->Quit(); |
| 360 } | 42 } |
| 361 } | 43 } |
| 362 bool* did_run_; | 44 bool* did_run_; |
| 363 int counter_; | 45 int counter_; |
| 364 base::RepeatingTimer<RepeatingTimerTester> timer_; | 46 base::RepeatingTimer<RepeatingTimerTester> timer_; |
| 365 }; | 47 }; |
| 366 | 48 |
| 367 } // namespace | |
| 368 | |
| 369 void RunTest_OneShotTimer(MessageLoop::Type message_loop_type) { | 49 void RunTest_OneShotTimer(MessageLoop::Type message_loop_type) { |
| 370 MessageLoop loop(message_loop_type); | 50 MessageLoop loop(message_loop_type); |
| 371 | 51 |
| 372 bool did_run = false; | 52 bool did_run = false; |
| 373 OneShotTimerTester f(&did_run); | 53 OneShotTimerTester f(&did_run); |
| 374 f.Start(); | 54 f.Start(); |
| 375 | 55 |
| 376 MessageLoop::current()->Run(); | 56 MessageLoop::current()->Run(); |
| 377 | 57 |
| 378 EXPECT_TRUE(did_run); | 58 EXPECT_TRUE(did_run); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 EXPECT_FALSE(did_run_a); | 113 EXPECT_FALSE(did_run_a); |
| 434 EXPECT_TRUE(did_run_b); | 114 EXPECT_TRUE(did_run_b); |
| 435 } | 115 } |
| 436 | 116 |
| 437 } // namespace | 117 } // namespace |
| 438 | 118 |
| 439 //----------------------------------------------------------------------------- | 119 //----------------------------------------------------------------------------- |
| 440 // Each test is run against each type of MessageLoop. That way we are sure | 120 // Each test is run against each type of MessageLoop. That way we are sure |
| 441 // that timers work properly in all configurations. | 121 // that timers work properly in all configurations. |
| 442 | 122 |
| 443 TEST(TimerTest, TimerComparison) { | |
| 444 RunTest_TimerComparison(MessageLoop::TYPE_DEFAULT); | |
| 445 RunTest_TimerComparison(MessageLoop::TYPE_UI); | |
| 446 RunTest_TimerComparison(MessageLoop::TYPE_IO); | |
| 447 } | |
| 448 | |
| 449 TEST(TimerTest, BasicTimer) { | |
| 450 RunTest_BasicTimer(MessageLoop::TYPE_DEFAULT); | |
| 451 RunTest_BasicTimer(MessageLoop::TYPE_UI); | |
| 452 RunTest_BasicTimer(MessageLoop::TYPE_IO); | |
| 453 } | |
| 454 | |
| 455 TEST(TimerTest, BrokenTimer) { | |
| 456 RunTest_BrokenTimer(MessageLoop::TYPE_DEFAULT); | |
| 457 RunTest_BrokenTimer(MessageLoop::TYPE_UI); | |
| 458 RunTest_BrokenTimer(MessageLoop::TYPE_IO); | |
| 459 } | |
| 460 | |
| 461 TEST(TimerTest, DeleteFromRun) { | |
| 462 RunTest_DeleteFromRun(MessageLoop::TYPE_DEFAULT); | |
| 463 RunTest_DeleteFromRun(MessageLoop::TYPE_UI); | |
| 464 RunTest_DeleteFromRun(MessageLoop::TYPE_IO); | |
| 465 } | |
| 466 | |
| 467 TEST(TimerTest, Reset) { | |
| 468 RunTest_Reset(MessageLoop::TYPE_DEFAULT); | |
| 469 RunTest_Reset(MessageLoop::TYPE_UI); | |
| 470 RunTest_Reset(MessageLoop::TYPE_IO); | |
| 471 } | |
| 472 | |
| 473 TEST(TimerTest, FifoOrder) { | |
| 474 RunTest_FifoOrder(MessageLoop::TYPE_DEFAULT); | |
| 475 RunTest_FifoOrder(MessageLoop::TYPE_UI); | |
| 476 RunTest_FifoOrder(MessageLoop::TYPE_IO); | |
| 477 } | |
| 478 | |
| 479 TEST(TimerTest, OneShotTimer) { | 123 TEST(TimerTest, OneShotTimer) { |
| 480 RunTest_OneShotTimer(MessageLoop::TYPE_DEFAULT); | 124 RunTest_OneShotTimer(MessageLoop::TYPE_DEFAULT); |
| 481 RunTest_OneShotTimer(MessageLoop::TYPE_UI); | 125 RunTest_OneShotTimer(MessageLoop::TYPE_UI); |
| 482 RunTest_OneShotTimer(MessageLoop::TYPE_IO); | 126 RunTest_OneShotTimer(MessageLoop::TYPE_IO); |
| 483 } | 127 } |
| 484 | 128 |
| 485 TEST(TimerTest, OneShotTimer_Cancel) { | 129 TEST(TimerTest, OneShotTimer_Cancel) { |
| 486 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_DEFAULT); | 130 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_DEFAULT); |
| 487 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_UI); | 131 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_UI); |
| 488 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_IO); | 132 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_IO); |
| 489 } | 133 } |
| 490 | 134 |
| 491 TEST(TimerTest, RepeatingTimer) { | 135 TEST(TimerTest, RepeatingTimer) { |
| 492 RunTest_RepeatingTimer(MessageLoop::TYPE_DEFAULT); | 136 RunTest_RepeatingTimer(MessageLoop::TYPE_DEFAULT); |
| 493 RunTest_RepeatingTimer(MessageLoop::TYPE_UI); | 137 RunTest_RepeatingTimer(MessageLoop::TYPE_UI); |
| 494 RunTest_RepeatingTimer(MessageLoop::TYPE_IO); | 138 RunTest_RepeatingTimer(MessageLoop::TYPE_IO); |
| 495 } | 139 } |
| 496 | 140 |
| 497 TEST(TimerTest, RepeatingTimer_Cancel) { | 141 TEST(TimerTest, RepeatingTimer_Cancel) { |
| 498 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_DEFAULT); | 142 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_DEFAULT); |
| 499 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_UI); | 143 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_UI); |
| 500 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_IO); | 144 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_IO); |
| 501 } | 145 } |
| OLD | NEW |