Hook the WebThreadImplForMessageLoop up to post taks through the blink
[chromium-blink-merge.git] / components / timers / alarm_timer_unittest.cc
blobefa88d4229e813c28e5b991b915cc4492836a99a
1 // Copyright 2014 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.
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/macros.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/threading/platform_thread.h"
11 #include "base/time/time.h"
12 #include "components/timers/alarm_timer.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 // Most of these tests have been lifted right out of timer_unittest.cc with only
16 // cosmetic changes (like replacing calls to MessageLoop::current()->Run() with
17 // a RunLoop). We want the AlarmTimer to be a drop-in replacement for the
18 // regular Timer so it should pass the same tests as the Timer class.
20 // The only new tests are the .*ConcurrentResetAndTimerFired tests, which test
21 // that race conditions that can come up in the AlarmTimer::Delegate are
22 // properly handled.
23 namespace timers {
24 namespace {
25 // The message loops on which each timer should be tested.
26 const base::MessageLoop::Type testing_message_loops[] = {
27 base::MessageLoop::TYPE_DEFAULT,
28 base::MessageLoop::TYPE_IO,
29 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
30 base::MessageLoop::TYPE_UI,
31 #endif
34 const int kNumTestingMessageLoops = arraysize(testing_message_loops);
35 const base::TimeDelta kTenMilliseconds = base::TimeDelta::FromMilliseconds(10);
37 class OneShotAlarmTimerTester {
38 public:
39 OneShotAlarmTimerTester(bool* did_run, base::TimeDelta delay)
40 : did_run_(did_run),
41 delay_(delay),
42 timer_(new timers::AlarmTimer(false, false)) {
44 void Start() {
45 timer_->Start(FROM_HERE,
46 delay_,
47 base::Bind(&OneShotAlarmTimerTester::Run,
48 base::Unretained(this)));
51 private:
52 void Run() {
53 *did_run_ = true;
55 base::MessageLoop::current()->PostTask(
56 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
59 bool* did_run_;
60 const base::TimeDelta delay_;
61 scoped_ptr<timers::AlarmTimer> timer_;
63 DISALLOW_COPY_AND_ASSIGN(OneShotAlarmTimerTester);
66 class OneShotSelfDeletingAlarmTimerTester {
67 public:
68 OneShotSelfDeletingAlarmTimerTester(bool* did_run, base::TimeDelta delay)
69 : did_run_(did_run),
70 delay_(delay),
71 timer_(new timers::AlarmTimer(false, false)) {
73 void Start() {
74 timer_->Start(FROM_HERE,
75 delay_,
76 base::Bind(&OneShotSelfDeletingAlarmTimerTester::Run,
77 base::Unretained(this)));
80 private:
81 void Run() {
82 *did_run_ = true;
83 timer_.reset();
85 base::MessageLoop::current()->PostTask(
86 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
89 bool* did_run_;
90 const base::TimeDelta delay_;
91 scoped_ptr<timers::AlarmTimer> timer_;
93 DISALLOW_COPY_AND_ASSIGN(OneShotSelfDeletingAlarmTimerTester);
96 class RepeatingAlarmTimerTester {
97 public:
98 RepeatingAlarmTimerTester(bool* did_run, base::TimeDelta delay)
99 : did_run_(did_run),
100 delay_(delay),
101 counter_(10),
102 timer_(new timers::AlarmTimer(true, true)) {
104 void Start() {
105 timer_->Start(FROM_HERE,
106 delay_,
107 base::Bind(&RepeatingAlarmTimerTester::Run,
108 base::Unretained(this)));
111 private:
112 void Run() {
113 if (--counter_ == 0) {
114 *did_run_ = true;
115 timer_->Stop();
117 base::MessageLoop::current()->PostTask(
118 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
122 bool* did_run_;
123 const base::TimeDelta delay_;
124 int counter_;
125 scoped_ptr<timers::AlarmTimer> timer_;
127 DISALLOW_COPY_AND_ASSIGN(RepeatingAlarmTimerTester);
130 void RunTest_OneShotAlarmTimer(base::MessageLoop::Type message_loop_type) {
131 base::MessageLoop loop(message_loop_type);
133 bool did_run = false;
134 OneShotAlarmTimerTester f(&did_run, kTenMilliseconds);
135 f.Start();
137 base::RunLoop().Run();
139 EXPECT_TRUE(did_run);
142 void RunTest_OneShotAlarmTimer_Cancel(
143 base::MessageLoop::Type message_loop_type) {
144 base::MessageLoop loop(message_loop_type);
146 bool did_run_a = false;
147 OneShotAlarmTimerTester* a = new OneShotAlarmTimerTester(&did_run_a,
148 kTenMilliseconds);
150 // This should run before the timer expires.
151 base::MessageLoop::current()->DeleteSoon(FROM_HERE, a);
153 // Now start the timer.
154 a->Start();
156 bool did_run_b = false;
157 OneShotAlarmTimerTester b(&did_run_b, kTenMilliseconds);
158 b.Start();
160 base::RunLoop().Run();
162 EXPECT_FALSE(did_run_a);
163 EXPECT_TRUE(did_run_b);
166 void RunTest_OneShotSelfDeletingAlarmTimer(
167 base::MessageLoop::Type message_loop_type) {
168 base::MessageLoop loop(message_loop_type);
170 bool did_run = false;
171 OneShotSelfDeletingAlarmTimerTester f(&did_run, kTenMilliseconds);
172 f.Start();
174 base::RunLoop().Run();
176 EXPECT_TRUE(did_run);
179 void RunTest_RepeatingAlarmTimer(base::MessageLoop::Type message_loop_type,
180 const base::TimeDelta& delay) {
181 base::MessageLoop loop(message_loop_type);
183 bool did_run = false;
184 RepeatingAlarmTimerTester f(&did_run, delay);
185 f.Start();
187 base::RunLoop().Run();
189 EXPECT_TRUE(did_run);
192 void RunTest_RepeatingAlarmTimer_Cancel(
193 base::MessageLoop::Type message_loop_type, const base::TimeDelta& delay) {
194 base::MessageLoop loop(message_loop_type);
196 bool did_run_a = false;
197 RepeatingAlarmTimerTester* a = new RepeatingAlarmTimerTester(&did_run_a,
198 delay);
200 // This should run before the timer expires.
201 base::MessageLoop::current()->DeleteSoon(FROM_HERE, a);
203 // Now start the timer.
204 a->Start();
206 bool did_run_b = false;
207 RepeatingAlarmTimerTester b(&did_run_b, delay);
208 b.Start();
210 base::RunLoop().Run();
212 EXPECT_FALSE(did_run_a);
213 EXPECT_TRUE(did_run_b);
216 } // namespace
218 //-----------------------------------------------------------------------------
219 // Each test is run against each type of MessageLoop. That way we are sure
220 // that timers work properly in all configurations.
222 TEST(AlarmTimerTest, OneShotAlarmTimer) {
223 for (int i = 0; i < kNumTestingMessageLoops; i++) {
224 RunTest_OneShotAlarmTimer(testing_message_loops[i]);
228 TEST(AlarmTimerTest, OneShotAlarmTimer_Cancel) {
229 for (int i = 0; i < kNumTestingMessageLoops; i++) {
230 RunTest_OneShotAlarmTimer_Cancel(testing_message_loops[i]);
234 // If underlying timer does not handle this properly, we will crash or fail
235 // in full page heap environment.
236 TEST(AlarmTimerTest, OneShotSelfDeletingAlarmTimer) {
237 for (int i = 0; i < kNumTestingMessageLoops; i++) {
238 RunTest_OneShotSelfDeletingAlarmTimer(testing_message_loops[i]);
242 TEST(AlarmTimerTest, RepeatingAlarmTimer) {
243 for (int i = 0; i < kNumTestingMessageLoops; i++) {
244 RunTest_RepeatingAlarmTimer(testing_message_loops[i],
245 kTenMilliseconds);
249 TEST(AlarmTimerTest, RepeatingAlarmTimer_Cancel) {
250 for (int i = 0; i < kNumTestingMessageLoops; i++) {
251 RunTest_RepeatingAlarmTimer_Cancel(testing_message_loops[i],
252 kTenMilliseconds);
256 TEST(AlarmTimerTest, RepeatingAlarmTimerZeroDelay) {
257 for (int i = 0; i < kNumTestingMessageLoops; i++) {
258 RunTest_RepeatingAlarmTimer(testing_message_loops[i],
259 base::TimeDelta::FromMilliseconds(0));
263 TEST(AlarmTimerTest, RepeatingAlarmTimerZeroDelay_Cancel) {
264 for (int i = 0; i < kNumTestingMessageLoops; i++) {
265 RunTest_RepeatingAlarmTimer_Cancel(testing_message_loops[i],
266 base::TimeDelta::FromMilliseconds(0));
270 TEST(AlarmTimerTest, MessageLoopShutdown) {
271 // This test is designed to verify that shutdown of the
272 // message loop does not cause crashes if there were pending
273 // timers not yet fired. It may only trigger exceptions
274 // if debug heap checking is enabled.
275 bool did_run = false;
277 OneShotAlarmTimerTester a(&did_run, kTenMilliseconds);
278 OneShotAlarmTimerTester b(&did_run, kTenMilliseconds);
279 OneShotAlarmTimerTester c(&did_run, kTenMilliseconds);
280 OneShotAlarmTimerTester d(&did_run, kTenMilliseconds);
282 base::MessageLoop loop;
283 a.Start();
284 b.Start();
285 } // MessageLoop destructs by falling out of scope.
286 } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
288 EXPECT_FALSE(did_run);
291 TEST(AlarmTimerTest, NonRepeatIsRunning) {
293 base::MessageLoop loop;
294 timers::AlarmTimer timer(false, false);
295 EXPECT_FALSE(timer.IsRunning());
296 timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
297 base::Bind(&base::DoNothing));
298 EXPECT_TRUE(timer.IsRunning());
299 timer.Stop();
300 EXPECT_FALSE(timer.IsRunning());
301 EXPECT_TRUE(timer.user_task().is_null());
305 timers::AlarmTimer timer(true, false);
306 base::MessageLoop loop;
307 EXPECT_FALSE(timer.IsRunning());
308 timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
309 base::Bind(&base::DoNothing));
310 EXPECT_TRUE(timer.IsRunning());
311 timer.Stop();
312 EXPECT_FALSE(timer.IsRunning());
313 ASSERT_FALSE(timer.user_task().is_null());
314 timer.Reset();
315 EXPECT_TRUE(timer.IsRunning());
319 TEST(AlarmTimerTest, NonRepeatMessageLoopDeath) {
320 timers::AlarmTimer timer(false, false);
322 base::MessageLoop loop;
323 EXPECT_FALSE(timer.IsRunning());
324 timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
325 base::Bind(&base::DoNothing));
326 EXPECT_TRUE(timer.IsRunning());
328 EXPECT_FALSE(timer.IsRunning());
329 EXPECT_TRUE(timer.user_task().is_null());
332 TEST(AlarmTimerTest, RetainRepeatIsRunning) {
333 base::MessageLoop loop;
334 timers::AlarmTimer timer(FROM_HERE, base::TimeDelta::FromDays(1),
335 base::Bind(&base::DoNothing), true);
336 EXPECT_FALSE(timer.IsRunning());
337 timer.Reset();
338 EXPECT_TRUE(timer.IsRunning());
339 timer.Stop();
340 EXPECT_FALSE(timer.IsRunning());
341 timer.Reset();
342 EXPECT_TRUE(timer.IsRunning());
345 TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
346 base::MessageLoop loop;
347 timers::AlarmTimer timer(FROM_HERE, base::TimeDelta::FromDays(1),
348 base::Bind(&base::DoNothing), false);
349 EXPECT_FALSE(timer.IsRunning());
350 timer.Reset();
351 EXPECT_TRUE(timer.IsRunning());
352 timer.Stop();
353 EXPECT_FALSE(timer.IsRunning());
354 timer.Reset();
355 EXPECT_TRUE(timer.IsRunning());
358 namespace {
360 bool g_callback_happened1 = false;
361 bool g_callback_happened2 = false;
363 void ClearAllCallbackHappened() {
364 g_callback_happened1 = false;
365 g_callback_happened2 = false;
368 void SetCallbackHappened1() {
369 g_callback_happened1 = true;
370 base::MessageLoop::current()->PostTask(
371 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
374 void SetCallbackHappened2() {
375 g_callback_happened2 = true;
376 base::MessageLoop::current()->PostTask(
377 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
380 TEST(AlarmTimerTest, ContinuationStopStart) {
382 ClearAllCallbackHappened();
383 base::MessageLoop loop;
384 timers::AlarmTimer timer(false, false);
385 timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
386 base::Bind(&SetCallbackHappened1));
387 timer.Stop();
388 timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
389 base::Bind(&SetCallbackHappened2));
390 base::RunLoop().Run();
391 EXPECT_FALSE(g_callback_happened1);
392 EXPECT_TRUE(g_callback_happened2);
396 TEST(AlarmTimerTest, ContinuationReset) {
398 ClearAllCallbackHappened();
399 base::MessageLoop loop;
400 timers::AlarmTimer timer(false, false);
401 timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
402 base::Bind(&SetCallbackHappened1));
403 timer.Reset();
404 // Since Reset happened before task ran, the user_task must not be cleared:
405 ASSERT_FALSE(timer.user_task().is_null());
406 base::RunLoop().Run();
407 EXPECT_TRUE(g_callback_happened1);
411 } // namespace
414 namespace {
415 void TimerRanCallback(bool* did_run) {
416 *did_run = true;
418 base::MessageLoop::current()->PostTask(
419 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
422 void RunTest_OneShotTimerConcurrentResetAndTimerFired(
423 base::MessageLoop::Type message_loop_type) {
424 base::MessageLoop loop(message_loop_type);
426 timers::AlarmTimer timer(false, false);
427 bool did_run = false;
429 timer.Start(
430 FROM_HERE, kTenMilliseconds, base::Bind(&TimerRanCallback, &did_run));
432 // Sleep twice as long as the timer to ensure that the timer task gets queued.
433 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
435 // Now reset the timer. This is attempting to simulate the timer firing and
436 // being reset at the same time. The previously queued task should be
437 // removed.
438 timer.Reset();
440 base::RunLoop().RunUntilIdle();
441 EXPECT_FALSE(did_run);
443 // If the previous check failed, running the message loop again will hang the
444 // test so we only do it if the callback has not run yet.
445 if (!did_run) {
446 base::RunLoop().Run();
447 EXPECT_TRUE(did_run);
451 void RunTest_RepeatingTimerConcurrentResetAndTimerFired(
452 base::MessageLoop::Type message_loop_type) {
453 base::MessageLoop loop(message_loop_type);
455 timers::AlarmTimer timer(true, true);
456 bool did_run = false;
458 timer.Start(
459 FROM_HERE, kTenMilliseconds, base::Bind(&TimerRanCallback, &did_run));
461 // Sleep more that three times as long as the timer duration to ensure that
462 // multiple tasks get queued.
463 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(35));
465 // Now reset the timer. This is attempting to simulate a very busy message
466 // loop where multiple tasks get queued but the timer gets reset before any of
467 // them have a chance to run.
468 timer.Reset();
470 base::RunLoop().RunUntilIdle();
471 EXPECT_FALSE(did_run);
473 // If the previous check failed, running the message loop again will hang the
474 // test so we only do it if the callback has not run yet.
475 if (!did_run) {
476 base::RunLoop().Run();
477 EXPECT_TRUE(did_run);
481 TEST(AlarmTimerTest, OneShotTimerConcurrentResetAndTimerFired) {
482 for (int i = 0; i < kNumTestingMessageLoops; i++) {
483 RunTest_OneShotTimerConcurrentResetAndTimerFired(testing_message_loops[i]);
487 TEST(AlarmTimerTest, RepeatingTimerConcurrentResetAndTimerFired) {
488 for (int i = 0; i < kNumTestingMessageLoops; i++) {
489 RunTest_RepeatingTimerConcurrentResetAndTimerFired(
490 testing_message_loops[i]);
494 } // namespace
496 } // namespace timers