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/timer/timer.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/callback.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/run_loop.h"
19 #include "base/sequenced_task_runner.h"
20 #include "base/single_thread_task_runner.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/test/sequenced_worker_pool_owner.h"
23 #include "base/test/test_mock_time_task_runner.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/threading/sequenced_task_runner_handle.h"
26 #include "base/threading/thread.h"
27 #include "base/threading/thread_task_runner_handle.h"
28 #include "base/time/tick_clock.h"
29 #include "base/time/time.h"
30 #include "build/build_config.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace base {
34
35 namespace {
36
37 // The message loops on which each timer should be tested.
38 const MessageLoop::Type testing_message_loops[] = {
39 MessageLoop::TYPE_DEFAULT, MessageLoop::TYPE_IO,
40 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
41 MessageLoop::TYPE_UI,
42 #endif
43 };
44
45 const int kNumTestingMessageLoops = arraysize(testing_message_loops);
46
47 class Receiver {
48 public:
Receiver()49 Receiver() : count_(0) {}
OnCalled()50 void OnCalled() { count_++; }
WasCalled()51 bool WasCalled() { return count_ > 0; }
TimesCalled()52 int TimesCalled() { return count_; }
53
54 private:
55 int count_;
56 };
57
58 // A basic helper class that can start a one-shot timer and signal a
59 // WaitableEvent when this timer fires.
60 class OneShotTimerTesterBase {
61 public:
62 // |did_run|, if provided, will be signaled when Run() fires.
OneShotTimerTesterBase(WaitableEvent * did_run=nullptr,const TimeDelta & delay=TimeDelta::FromMilliseconds (10))63 explicit OneShotTimerTesterBase(
64 WaitableEvent* did_run = nullptr,
65 const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
66 : did_run_(did_run), delay_(delay) {}
67
68 virtual ~OneShotTimerTesterBase() = default;
69
Start()70 void Start() {
71 started_time_ = TimeTicks::Now();
72 timer_->Start(FROM_HERE, delay_, this, &OneShotTimerTesterBase::Run);
73 }
74
IsRunning()75 bool IsRunning() { return timer_->IsRunning(); }
76
started_time() const77 TimeTicks started_time() const { return started_time_; }
delay() const78 TimeDelta delay() const { return delay_; }
79
80 protected:
Run()81 virtual void Run() {
82 if (did_run_) {
83 EXPECT_FALSE(did_run_->IsSignaled());
84 did_run_->Signal();
85 }
86 }
87
88 std::unique_ptr<OneShotTimer> timer_ = MakeUnique<OneShotTimer>();
89
90 private:
91 WaitableEvent* const did_run_;
92 const TimeDelta delay_;
93 TimeTicks started_time_;
94
95 DISALLOW_COPY_AND_ASSIGN(OneShotTimerTesterBase);
96 };
97
98 // Extends functionality of OneShotTimerTesterBase with the abilities to wait
99 // until the timer fires and to change task runner for the timer.
100 class OneShotTimerTester : public OneShotTimerTesterBase {
101 public:
102 // |did_run|, if provided, will be signaled when Run() fires.
OneShotTimerTester(WaitableEvent * did_run=nullptr,const TimeDelta & delay=TimeDelta::FromMilliseconds (10))103 explicit OneShotTimerTester(
104 WaitableEvent* did_run = nullptr,
105 const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
106 : OneShotTimerTesterBase(did_run, delay),
107 quit_closure_(run_loop_.QuitClosure()) {}
108
109 ~OneShotTimerTester() override = default;
110
SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner)111 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) {
112 timer_->SetTaskRunner(std::move(task_runner));
113
114 // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure
115 // needs to run on this thread (where the MessageLoop lives).
116 quit_closure_ =
117 Bind(IgnoreResult(&SingleThreadTaskRunner::PostTask),
118 ThreadTaskRunnerHandle::Get(), FROM_HERE, run_loop_.QuitClosure());
119 }
120
121 // Blocks until Run() executes and confirms that Run() didn't fire before
122 // |delay_| expired.
WaitAndConfirmTimerFiredAfterDelay()123 void WaitAndConfirmTimerFiredAfterDelay() {
124 run_loop_.Run();
125
126 EXPECT_NE(TimeTicks(), started_time());
127 EXPECT_GE(TimeTicks::Now() - started_time(), delay());
128 }
129
130 protected:
131 // Overridable method to do things on Run() before signaling events/closures
132 // managed by this helper.
OnRun()133 virtual void OnRun() {}
134
135 private:
Run()136 void Run() override {
137 OnRun();
138 OneShotTimerTesterBase::Run();
139 quit_closure_.Run();
140 }
141
142 RunLoop run_loop_;
143 Closure quit_closure_;
144
145 DISALLOW_COPY_AND_ASSIGN(OneShotTimerTester);
146 };
147
148 class OneShotSelfDeletingTimerTester : public OneShotTimerTester {
149 protected:
OnRun()150 void OnRun() override { timer_.reset(); }
151 };
152
153 constexpr int kNumRepeats = 10;
154
155 class RepeatingTimerTester {
156 public:
RepeatingTimerTester(WaitableEvent * did_run,const TimeDelta & delay)157 explicit RepeatingTimerTester(WaitableEvent* did_run, const TimeDelta& delay)
158 : counter_(kNumRepeats),
159 quit_closure_(run_loop_.QuitClosure()),
160 did_run_(did_run),
161 delay_(delay) {}
162
Start()163 void Start() {
164 started_time_ = TimeTicks::Now();
165 timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run);
166 }
167
WaitAndConfirmTimerFiredRepeatedlyAfterDelay()168 void WaitAndConfirmTimerFiredRepeatedlyAfterDelay() {
169 run_loop_.Run();
170
171 EXPECT_NE(TimeTicks(), started_time_);
172 EXPECT_GE(TimeTicks::Now() - started_time_, kNumRepeats * delay_);
173 }
174
175 private:
Run()176 void Run() {
177 if (--counter_ == 0) {
178 if (did_run_) {
179 EXPECT_FALSE(did_run_->IsSignaled());
180 did_run_->Signal();
181 }
182 timer_.Stop();
183 quit_closure_.Run();
184 }
185 }
186
187 RepeatingTimer timer_;
188 int counter_;
189
190 RunLoop run_loop_;
191 Closure quit_closure_;
192 WaitableEvent* const did_run_;
193
194 const TimeDelta delay_;
195 TimeTicks started_time_;
196
197 DISALLOW_COPY_AND_ASSIGN(RepeatingTimerTester);
198 };
199
200 // Basic test with same setup as RunTest_OneShotTimers_Cancel below to confirm
201 // that |did_run_a| would be signaled in that test if it wasn't for the
202 // deletion.
RunTest_OneShotTimers(MessageLoop::Type message_loop_type)203 void RunTest_OneShotTimers(MessageLoop::Type message_loop_type) {
204 MessageLoop loop(message_loop_type);
205
206 WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
207 WaitableEvent::InitialState::NOT_SIGNALED);
208 OneShotTimerTester a(&did_run_a);
209 a.Start();
210
211 OneShotTimerTester b;
212 b.Start();
213
214 b.WaitAndConfirmTimerFiredAfterDelay();
215
216 EXPECT_TRUE(did_run_a.IsSignaled());
217 }
218
RunTest_OneShotTimers_Cancel(MessageLoop::Type message_loop_type)219 void RunTest_OneShotTimers_Cancel(MessageLoop::Type message_loop_type) {
220 MessageLoop loop(message_loop_type);
221
222 WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
223 WaitableEvent::InitialState::NOT_SIGNALED);
224 OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
225
226 // This should run before the timer expires.
227 SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
228
229 // Now start the timer.
230 a->Start();
231
232 OneShotTimerTester b;
233 b.Start();
234
235 b.WaitAndConfirmTimerFiredAfterDelay();
236
237 EXPECT_FALSE(did_run_a.IsSignaled());
238 }
239
RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type)240 void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
241 MessageLoop loop(message_loop_type);
242
243 OneShotSelfDeletingTimerTester f;
244 f.Start();
245 f.WaitAndConfirmTimerFiredAfterDelay();
246 }
247
RunTest_RepeatingTimer(MessageLoop::Type message_loop_type,const TimeDelta & delay)248 void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type,
249 const TimeDelta& delay) {
250 MessageLoop loop(message_loop_type);
251
252 RepeatingTimerTester f(nullptr, delay);
253 f.Start();
254 f.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
255 }
256
RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type,const TimeDelta & delay)257 void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type,
258 const TimeDelta& delay) {
259 MessageLoop loop(message_loop_type);
260
261 WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
262 WaitableEvent::InitialState::NOT_SIGNALED);
263 RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a, delay);
264
265 // This should run before the timer expires.
266 SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
267
268 // Now start the timer.
269 a->Start();
270
271 RepeatingTimerTester b(nullptr, delay);
272 b.Start();
273
274 b.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
275
276 // |a| should not have fired despite |b| starting after it on the same
277 // sequence and being complete by now.
278 EXPECT_FALSE(did_run_a.IsSignaled());
279 }
280
281 class DelayTimerTarget {
282 public:
signaled() const283 bool signaled() const { return signaled_; }
284
Signal()285 void Signal() {
286 ASSERT_FALSE(signaled_);
287 signaled_ = true;
288 }
289
290 private:
291 bool signaled_ = false;
292 };
293
RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type)294 void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
295 MessageLoop loop(message_loop_type);
296
297 // If Delay is never called, the timer shouldn't go off.
298 DelayTimerTarget target;
299 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
300 &DelayTimerTarget::Signal);
301
302 OneShotTimerTester tester;
303 tester.Start();
304 tester.WaitAndConfirmTimerFiredAfterDelay();
305
306 ASSERT_FALSE(target.signaled());
307 }
308
RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type)309 void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
310 MessageLoop loop(message_loop_type);
311
312 DelayTimerTarget target;
313 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
314 &DelayTimerTarget::Signal);
315 timer.Reset();
316
317 OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(100));
318 tester.Start();
319 tester.WaitAndConfirmTimerFiredAfterDelay();
320
321 ASSERT_TRUE(target.signaled());
322 }
323
324 struct ResetHelper {
ResetHelperbase::__anon38a4be600111::ResetHelper325 ResetHelper(DelayTimer* timer, DelayTimerTarget* target)
326 : timer_(timer), target_(target) {}
327
Resetbase::__anon38a4be600111::ResetHelper328 void Reset() {
329 ASSERT_FALSE(target_->signaled());
330 timer_->Reset();
331 }
332
333 private:
334 DelayTimer* const timer_;
335 DelayTimerTarget* const target_;
336 };
337
RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type)338 void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
339 MessageLoop loop(message_loop_type);
340
341 // If Delay is never called, the timer shouldn't go off.
342 DelayTimerTarget target;
343 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
344 &DelayTimerTarget::Signal);
345 timer.Reset();
346
347 ResetHelper reset_helper(&timer, &target);
348
349 OneShotTimer timers[20];
350 for (size_t i = 0; i < arraysize(timers); ++i) {
351 timers[i].Start(FROM_HERE, TimeDelta::FromMilliseconds(i * 10),
352 &reset_helper, &ResetHelper::Reset);
353 }
354
355 OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(300));
356 tester.Start();
357 tester.WaitAndConfirmTimerFiredAfterDelay();
358
359 ASSERT_TRUE(target.signaled());
360 }
361
362 class DelayTimerFatalTarget {
363 public:
Signal()364 void Signal() {
365 ASSERT_TRUE(false);
366 }
367 };
368
RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type)369 void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
370 MessageLoop loop(message_loop_type);
371
372 DelayTimerFatalTarget target;
373
374 {
375 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
376 &DelayTimerFatalTarget::Signal);
377 timer.Reset();
378 }
379
380 // When the timer is deleted, the DelayTimerFatalTarget should never be
381 // called.
382 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
383 }
384
385 } // namespace
386
387 //-----------------------------------------------------------------------------
388 // Each test is run against each type of MessageLoop. That way we are sure
389 // that timers work properly in all configurations.
390
TEST(TimerTest,OneShotTimers)391 TEST(TimerTest, OneShotTimers) {
392 for (int i = 0; i < kNumTestingMessageLoops; i++) {
393 RunTest_OneShotTimers(testing_message_loops[i]);
394 }
395 }
396
TEST(TimerTest,OneShotTimers_Cancel)397 TEST(TimerTest, OneShotTimers_Cancel) {
398 for (int i = 0; i < kNumTestingMessageLoops; i++) {
399 RunTest_OneShotTimers_Cancel(testing_message_loops[i]);
400 }
401 }
402
403 // If underline timer does not handle properly, we will crash or fail
404 // in full page heap environment.
TEST(TimerTest,OneShotSelfDeletingTimer)405 TEST(TimerTest, OneShotSelfDeletingTimer) {
406 for (int i = 0; i < kNumTestingMessageLoops; i++) {
407 RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]);
408 }
409 }
410
TEST(TimerTest,OneShotTimer_CustomTaskRunner)411 TEST(TimerTest, OneShotTimer_CustomTaskRunner) {
412 // A MessageLoop is required for the timer events on the other thread to
413 // communicate back to the Timer under test.
414 MessageLoop loop;
415
416 Thread other_thread("OneShotTimer_CustomTaskRunner");
417 other_thread.Start();
418
419 WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
420 WaitableEvent::InitialState::NOT_SIGNALED);
421 OneShotTimerTester f(&did_run);
422 f.SetTaskRunner(other_thread.task_runner());
423 f.Start();
424 EXPECT_TRUE(f.IsRunning());
425
426 f.WaitAndConfirmTimerFiredAfterDelay();
427 EXPECT_TRUE(did_run.IsSignaled());
428
429 // |f| should already have communicated back to this |loop| before invoking
430 // Run() and as such this thread should already be aware that |f| is no longer
431 // running.
432 EXPECT_TRUE(loop.IsIdleForTesting());
433 EXPECT_FALSE(f.IsRunning());
434 }
435
TEST(TimerTest,OneShotTimerWithTickClock)436 TEST(TimerTest, OneShotTimerWithTickClock) {
437 scoped_refptr<TestMockTimeTaskRunner> task_runner(
438 new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
439 std::unique_ptr<TickClock> tick_clock(task_runner->GetMockTickClock());
440 MessageLoop message_loop;
441 message_loop.SetTaskRunner(task_runner);
442 Receiver receiver;
443 OneShotTimer timer(tick_clock.get());
444 timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
445 Bind(&Receiver::OnCalled, Unretained(&receiver)));
446 task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
447 EXPECT_TRUE(receiver.WasCalled());
448 }
449
TEST(TimerTest,RepeatingTimer)450 TEST(TimerTest, RepeatingTimer) {
451 for (int i = 0; i < kNumTestingMessageLoops; i++) {
452 RunTest_RepeatingTimer(testing_message_loops[i],
453 TimeDelta::FromMilliseconds(10));
454 }
455 }
456
TEST(TimerTest,RepeatingTimer_Cancel)457 TEST(TimerTest, RepeatingTimer_Cancel) {
458 for (int i = 0; i < kNumTestingMessageLoops; i++) {
459 RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
460 TimeDelta::FromMilliseconds(10));
461 }
462 }
463
TEST(TimerTest,RepeatingTimerZeroDelay)464 TEST(TimerTest, RepeatingTimerZeroDelay) {
465 for (int i = 0; i < kNumTestingMessageLoops; i++) {
466 RunTest_RepeatingTimer(testing_message_loops[i],
467 TimeDelta::FromMilliseconds(0));
468 }
469 }
470
TEST(TimerTest,RepeatingTimerZeroDelay_Cancel)471 TEST(TimerTest, RepeatingTimerZeroDelay_Cancel) {
472 for (int i = 0; i < kNumTestingMessageLoops; i++) {
473 RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
474 TimeDelta::FromMilliseconds(0));
475 }
476 }
477
TEST(TimerTest,RepeatingTimerWithTickClock)478 TEST(TimerTest, RepeatingTimerWithTickClock) {
479 scoped_refptr<TestMockTimeTaskRunner> task_runner(
480 new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
481 std::unique_ptr<TickClock> tick_clock(task_runner->GetMockTickClock());
482 MessageLoop message_loop;
483 message_loop.SetTaskRunner(task_runner);
484 Receiver receiver;
485 const int expected_times_called = 10;
486 RepeatingTimer timer(tick_clock.get());
487 timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
488 Bind(&Receiver::OnCalled, Unretained(&receiver)));
489 task_runner->FastForwardBy(TimeDelta::FromSeconds(expected_times_called));
490 timer.Stop();
491 EXPECT_EQ(expected_times_called, receiver.TimesCalled());
492 }
493
TEST(TimerTest,DelayTimer_NoCall)494 TEST(TimerTest, DelayTimer_NoCall) {
495 for (int i = 0; i < kNumTestingMessageLoops; i++) {
496 RunTest_DelayTimer_NoCall(testing_message_loops[i]);
497 }
498 }
499
TEST(TimerTest,DelayTimer_OneCall)500 TEST(TimerTest, DelayTimer_OneCall) {
501 for (int i = 0; i < kNumTestingMessageLoops; i++) {
502 RunTest_DelayTimer_OneCall(testing_message_loops[i]);
503 }
504 }
505
506 // It's flaky on the buildbot, http://crbug.com/25038.
TEST(TimerTest,DISABLED_DelayTimer_Reset)507 TEST(TimerTest, DISABLED_DelayTimer_Reset) {
508 for (int i = 0; i < kNumTestingMessageLoops; i++) {
509 RunTest_DelayTimer_Reset(testing_message_loops[i]);
510 }
511 }
512
TEST(TimerTest,DelayTimer_Deleted)513 TEST(TimerTest, DelayTimer_Deleted) {
514 for (int i = 0; i < kNumTestingMessageLoops; i++) {
515 RunTest_DelayTimer_Deleted(testing_message_loops[i]);
516 }
517 }
518
TEST(TimerTest,DelayTimerWithTickClock)519 TEST(TimerTest, DelayTimerWithTickClock) {
520 scoped_refptr<TestMockTimeTaskRunner> task_runner(
521 new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
522 std::unique_ptr<TickClock> tick_clock(task_runner->GetMockTickClock());
523 MessageLoop message_loop;
524 message_loop.SetTaskRunner(task_runner);
525 Receiver receiver;
526 DelayTimer timer(FROM_HERE, TimeDelta::FromSeconds(1), &receiver,
527 &Receiver::OnCalled, tick_clock.get());
528 task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
529 EXPECT_FALSE(receiver.WasCalled());
530 timer.Reset();
531 task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
532 EXPECT_FALSE(receiver.WasCalled());
533 timer.Reset();
534 task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
535 EXPECT_TRUE(receiver.WasCalled());
536 }
537
TEST(TimerTest,MessageLoopShutdown)538 TEST(TimerTest, MessageLoopShutdown) {
539 // This test is designed to verify that shutdown of the
540 // message loop does not cause crashes if there were pending
541 // timers not yet fired. It may only trigger exceptions
542 // if debug heap checking is enabled.
543 WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
544 WaitableEvent::InitialState::NOT_SIGNALED);
545 {
546 OneShotTimerTesterBase a(&did_run);
547 OneShotTimerTesterBase b(&did_run);
548 OneShotTimerTesterBase c(&did_run);
549 OneShotTimerTesterBase d(&did_run);
550 {
551 MessageLoop loop;
552 a.Start();
553 b.Start();
554 } // MessageLoop destructs by falling out of scope.
555 } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
556
557 EXPECT_FALSE(did_run.IsSignaled());
558 }
559
560 // Ref counted class which owns a Timer. The class passes a reference to itself
561 // via the |user_task| parameter in Timer::Start(). |Timer::user_task_| might
562 // end up holding the last reference to the class.
563 class OneShotSelfOwningTimerTester
564 : public RefCounted<OneShotSelfOwningTimerTester> {
565 public:
566 OneShotSelfOwningTimerTester() = default;
567
StartTimer()568 void StartTimer() {
569 // Start timer with long delay in order to test the timer getting destroyed
570 // while a timer task is still pending.
571 timer_.Start(FROM_HERE, TimeDelta::FromDays(1),
572 base::Bind(&OneShotSelfOwningTimerTester::Run, this));
573 }
574
575 private:
576 friend class RefCounted<OneShotSelfOwningTimerTester>;
577 ~OneShotSelfOwningTimerTester() = default;
578
Run()579 void Run() {
580 ADD_FAILURE() << "Timer unexpectedly fired.";
581 }
582
583 OneShotTimer timer_;
584
585 DISALLOW_COPY_AND_ASSIGN(OneShotSelfOwningTimerTester);
586 };
587
TEST(TimerTest,MessageLoopShutdownSelfOwningTimer)588 TEST(TimerTest, MessageLoopShutdownSelfOwningTimer) {
589 // This test verifies that shutdown of the message loop does not cause crashes
590 // if there is a pending timer not yet fired and |Timer::user_task_| owns the
591 // timer. The test may only trigger exceptions if debug heap checking is
592 // enabled.
593
594 MessageLoop loop;
595 scoped_refptr<OneShotSelfOwningTimerTester> tester =
596 new OneShotSelfOwningTimerTester();
597
598 std::move(tester)->StartTimer();
599 // |Timer::user_task_| owns sole reference to |tester|.
600
601 // MessageLoop destructs by falling out of scope. SHOULD NOT CRASH.
602 }
603
TimerTestCallback()604 void TimerTestCallback() {
605 }
606
TEST(TimerTest,NonRepeatIsRunning)607 TEST(TimerTest, NonRepeatIsRunning) {
608 {
609 MessageLoop loop;
610 Timer timer(false, false);
611 EXPECT_FALSE(timer.IsRunning());
612 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
613 EXPECT_TRUE(timer.IsRunning());
614 timer.Stop();
615 EXPECT_FALSE(timer.IsRunning());
616 EXPECT_TRUE(timer.user_task().is_null());
617 }
618
619 {
620 Timer timer(true, false);
621 MessageLoop loop;
622 EXPECT_FALSE(timer.IsRunning());
623 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
624 EXPECT_TRUE(timer.IsRunning());
625 timer.Stop();
626 EXPECT_FALSE(timer.IsRunning());
627 ASSERT_FALSE(timer.user_task().is_null());
628 timer.Reset();
629 EXPECT_TRUE(timer.IsRunning());
630 }
631 }
632
TEST(TimerTest,NonRepeatMessageLoopDeath)633 TEST(TimerTest, NonRepeatMessageLoopDeath) {
634 Timer timer(false, false);
635 {
636 MessageLoop loop;
637 EXPECT_FALSE(timer.IsRunning());
638 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
639 EXPECT_TRUE(timer.IsRunning());
640 }
641 EXPECT_FALSE(timer.IsRunning());
642 EXPECT_TRUE(timer.user_task().is_null());
643 }
644
TEST(TimerTest,RetainRepeatIsRunning)645 TEST(TimerTest, RetainRepeatIsRunning) {
646 MessageLoop loop;
647 Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
648 true);
649 EXPECT_FALSE(timer.IsRunning());
650 timer.Reset();
651 EXPECT_TRUE(timer.IsRunning());
652 timer.Stop();
653 EXPECT_FALSE(timer.IsRunning());
654 timer.Reset();
655 EXPECT_TRUE(timer.IsRunning());
656 }
657
TEST(TimerTest,RetainNonRepeatIsRunning)658 TEST(TimerTest, RetainNonRepeatIsRunning) {
659 MessageLoop loop;
660 Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
661 false);
662 EXPECT_FALSE(timer.IsRunning());
663 timer.Reset();
664 EXPECT_TRUE(timer.IsRunning());
665 timer.Stop();
666 EXPECT_FALSE(timer.IsRunning());
667 timer.Reset();
668 EXPECT_TRUE(timer.IsRunning());
669 }
670
671 namespace {
672
673 bool g_callback_happened1 = false;
674 bool g_callback_happened2 = false;
675
ClearAllCallbackHappened()676 void ClearAllCallbackHappened() {
677 g_callback_happened1 = false;
678 g_callback_happened2 = false;
679 }
680
SetCallbackHappened1()681 void SetCallbackHappened1() {
682 g_callback_happened1 = true;
683 MessageLoop::current()->QuitWhenIdle();
684 }
685
SetCallbackHappened2()686 void SetCallbackHappened2() {
687 g_callback_happened2 = true;
688 MessageLoop::current()->QuitWhenIdle();
689 }
690
691 } // namespace
692
TEST(TimerTest,ContinuationStopStart)693 TEST(TimerTest, ContinuationStopStart) {
694 {
695 ClearAllCallbackHappened();
696 MessageLoop loop;
697 Timer timer(false, false);
698 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
699 Bind(&SetCallbackHappened1));
700 timer.Stop();
701 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40),
702 Bind(&SetCallbackHappened2));
703 RunLoop().Run();
704 EXPECT_FALSE(g_callback_happened1);
705 EXPECT_TRUE(g_callback_happened2);
706 }
707 }
708
TEST(TimerTest,ContinuationReset)709 TEST(TimerTest, ContinuationReset) {
710 {
711 ClearAllCallbackHappened();
712 MessageLoop loop;
713 Timer timer(false, false);
714 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
715 Bind(&SetCallbackHappened1));
716 timer.Reset();
717 // Since Reset happened before task ran, the user_task must not be cleared:
718 ASSERT_FALSE(timer.user_task().is_null());
719 RunLoop().Run();
720 EXPECT_TRUE(g_callback_happened1);
721 }
722 }
723
724 } // namespace base
725