xref: /aosp_15_r20/external/libchrome/base/timer/timer_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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/synchronization/waitable_event.h"
21 #include "base/task_scheduler/post_task.h"
22 #include "base/test/scoped_task_environment.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/time/tick_clock.h"
28 #include "base/time/time.h"
29 #include "build/build_config.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 
32 namespace base {
33 
34 namespace {
35 
36 // The message loops on which each timer should be tested.
37 const MessageLoop::Type testing_message_loops[] = {
38     MessageLoop::TYPE_DEFAULT, MessageLoop::TYPE_IO,
39 #if !defined(OS_IOS)  // iOS does not allow direct running of the UI loop.
40     MessageLoop::TYPE_UI,
41 #endif
42 };
43 
44 const int kNumTestingMessageLoops = arraysize(testing_message_loops);
45 
46 class Receiver {
47  public:
Receiver()48   Receiver() : count_(0) {}
OnCalled()49   void OnCalled() { count_++; }
WasCalled()50   bool WasCalled() { return count_ > 0; }
TimesCalled()51   int TimesCalled() { return count_; }
52 
53  private:
54   int count_;
55 };
56 
57 // A basic helper class that can start a one-shot timer and signal a
58 // WaitableEvent when this timer fires.
59 class OneShotTimerTesterBase {
60  public:
61   // |did_run|, if provided, will be signaled when Run() fires.
OneShotTimerTesterBase(WaitableEvent * did_run=nullptr,const TimeDelta & delay=TimeDelta::FromMilliseconds (10))62   explicit OneShotTimerTesterBase(
63       WaitableEvent* did_run = nullptr,
64       const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
65       : did_run_(did_run), delay_(delay) {}
66 
67   virtual ~OneShotTimerTesterBase() = default;
68 
Start()69   void Start() {
70     started_time_ = TimeTicks::Now();
71     timer_->Start(FROM_HERE, delay_, this, &OneShotTimerTesterBase::Run);
72   }
73 
IsRunning()74   bool IsRunning() { return timer_->IsRunning(); }
75 
started_time() const76   TimeTicks started_time() const { return started_time_; }
delay() const77   TimeDelta delay() const { return delay_; }
78 
79  protected:
Run()80   virtual void Run() {
81     if (did_run_) {
82       EXPECT_FALSE(did_run_->IsSignaled());
83       did_run_->Signal();
84     }
85   }
86 
87   std::unique_ptr<OneShotTimer> timer_ = std::make_unique<OneShotTimer>();
88 
89  private:
90   WaitableEvent* const did_run_;
91   const TimeDelta delay_;
92   TimeTicks started_time_;
93 
94   DISALLOW_COPY_AND_ASSIGN(OneShotTimerTesterBase);
95 };
96 
97 // Extends functionality of OneShotTimerTesterBase with the abilities to wait
98 // until the timer fires and to change task runner for the timer.
99 class OneShotTimerTester : public OneShotTimerTesterBase {
100  public:
101   // |did_run|, if provided, will be signaled when Run() fires.
OneShotTimerTester(WaitableEvent * did_run=nullptr,const TimeDelta & delay=TimeDelta::FromMilliseconds (10))102   explicit OneShotTimerTester(
103       WaitableEvent* did_run = nullptr,
104       const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
105       : OneShotTimerTesterBase(did_run, delay),
106         quit_closure_(run_loop_.QuitClosure()) {}
107 
108   ~OneShotTimerTester() override = default;
109 
SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner)110   void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
111     timer_->SetTaskRunner(std::move(task_runner));
112 
113     // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure
114     // needs to run on this thread (where the MessageLoop lives).
115     quit_closure_ = Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
116                          SequencedTaskRunnerHandle::Get(), FROM_HERE,
117                          run_loop_.QuitClosure());
118   }
119 
120   // Blocks until Run() executes and confirms that Run() didn't fire before
121   // |delay_| expired.
WaitAndConfirmTimerFiredAfterDelay()122   void WaitAndConfirmTimerFiredAfterDelay() {
123     run_loop_.Run();
124 
125     EXPECT_NE(TimeTicks(), started_time());
126     EXPECT_GE(TimeTicks::Now() - started_time(), delay());
127   }
128 
129  protected:
130   // Overridable method to do things on Run() before signaling events/closures
131   // managed by this helper.
OnRun()132   virtual void OnRun() {}
133 
134  private:
Run()135   void Run() override {
136     OnRun();
137     OneShotTimerTesterBase::Run();
138     quit_closure_.Run();
139   }
140 
141   RunLoop run_loop_;
142   Closure quit_closure_;
143 
144   DISALLOW_COPY_AND_ASSIGN(OneShotTimerTester);
145 };
146 
147 class OneShotSelfDeletingTimerTester : public OneShotTimerTester {
148  protected:
OnRun()149   void OnRun() override { timer_.reset(); }
150 };
151 
152 constexpr int kNumRepeats = 10;
153 
154 class RepeatingTimerTester {
155  public:
RepeatingTimerTester(WaitableEvent * did_run,const TimeDelta & delay)156   explicit RepeatingTimerTester(WaitableEvent* did_run, const TimeDelta& delay)
157       : counter_(kNumRepeats),
158         quit_closure_(run_loop_.QuitClosure()),
159         did_run_(did_run),
160         delay_(delay) {}
161 
Start()162   void Start() {
163     started_time_ = TimeTicks::Now();
164     timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run);
165   }
166 
WaitAndConfirmTimerFiredRepeatedlyAfterDelay()167   void WaitAndConfirmTimerFiredRepeatedlyAfterDelay() {
168     run_loop_.Run();
169 
170     EXPECT_NE(TimeTicks(), started_time_);
171     EXPECT_GE(TimeTicks::Now() - started_time_, kNumRepeats * delay_);
172   }
173 
174  private:
Run()175   void Run() {
176     if (--counter_ == 0) {
177       if (did_run_) {
178         EXPECT_FALSE(did_run_->IsSignaled());
179         did_run_->Signal();
180       }
181       timer_.Stop();
182       quit_closure_.Run();
183     }
184   }
185 
186   RepeatingTimer timer_;
187   int counter_;
188 
189   RunLoop run_loop_;
190   Closure quit_closure_;
191   WaitableEvent* const did_run_;
192 
193   const TimeDelta delay_;
194   TimeTicks started_time_;
195 
196   DISALLOW_COPY_AND_ASSIGN(RepeatingTimerTester);
197 };
198 
199 // Basic test with same setup as RunTest_OneShotTimers_Cancel below to confirm
200 // that |did_run_a| would be signaled in that test if it wasn't for the
201 // deletion.
RunTest_OneShotTimers(MessageLoop::Type message_loop_type)202 void RunTest_OneShotTimers(MessageLoop::Type message_loop_type) {
203   MessageLoop loop(message_loop_type);
204 
205   WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
206                           WaitableEvent::InitialState::NOT_SIGNALED);
207   OneShotTimerTester a(&did_run_a);
208   a.Start();
209 
210   OneShotTimerTester b;
211   b.Start();
212 
213   b.WaitAndConfirmTimerFiredAfterDelay();
214 
215   EXPECT_TRUE(did_run_a.IsSignaled());
216 }
217 
RunTest_OneShotTimers_Cancel(MessageLoop::Type message_loop_type)218 void RunTest_OneShotTimers_Cancel(MessageLoop::Type message_loop_type) {
219   MessageLoop loop(message_loop_type);
220 
221   WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
222                           WaitableEvent::InitialState::NOT_SIGNALED);
223   OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
224 
225   // This should run before the timer expires.
226   SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
227 
228   // Now start the timer.
229   a->Start();
230 
231   OneShotTimerTester b;
232   b.Start();
233 
234   b.WaitAndConfirmTimerFiredAfterDelay();
235 
236   EXPECT_FALSE(did_run_a.IsSignaled());
237 }
238 
RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type)239 void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
240   MessageLoop loop(message_loop_type);
241 
242   OneShotSelfDeletingTimerTester f;
243   f.Start();
244   f.WaitAndConfirmTimerFiredAfterDelay();
245 }
246 
RunTest_RepeatingTimer(MessageLoop::Type message_loop_type,const TimeDelta & delay)247 void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type,
248                             const TimeDelta& delay) {
249   MessageLoop loop(message_loop_type);
250 
251   RepeatingTimerTester f(nullptr, delay);
252   f.Start();
253   f.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
254 }
255 
RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type,const TimeDelta & delay)256 void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type,
257                                    const TimeDelta& delay) {
258   MessageLoop loop(message_loop_type);
259 
260   WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
261                           WaitableEvent::InitialState::NOT_SIGNALED);
262   RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a, delay);
263 
264   // This should run before the timer expires.
265   SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
266 
267   // Now start the timer.
268   a->Start();
269 
270   RepeatingTimerTester b(nullptr, delay);
271   b.Start();
272 
273   b.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
274 
275   // |a| should not have fired despite |b| starting after it on the same
276   // sequence and being complete by now.
277   EXPECT_FALSE(did_run_a.IsSignaled());
278 }
279 
280 class DelayTimerTarget {
281  public:
signaled() const282   bool signaled() const { return signaled_; }
283 
Signal()284   void Signal() {
285     ASSERT_FALSE(signaled_);
286     signaled_ = true;
287   }
288 
289  private:
290   bool signaled_ = false;
291 };
292 
RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type)293 void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
294   MessageLoop loop(message_loop_type);
295 
296   // If Delay is never called, the timer shouldn't go off.
297   DelayTimerTarget target;
298   DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
299                    &DelayTimerTarget::Signal);
300 
301   OneShotTimerTester tester;
302   tester.Start();
303   tester.WaitAndConfirmTimerFiredAfterDelay();
304 
305   ASSERT_FALSE(target.signaled());
306 }
307 
RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type)308 void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
309   MessageLoop loop(message_loop_type);
310 
311   DelayTimerTarget target;
312   DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
313                    &DelayTimerTarget::Signal);
314   timer.Reset();
315 
316   OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(100));
317   tester.Start();
318   tester.WaitAndConfirmTimerFiredAfterDelay();
319 
320   ASSERT_TRUE(target.signaled());
321 }
322 
323 struct ResetHelper {
ResetHelperbase::__anon4ee860b90111::ResetHelper324   ResetHelper(DelayTimer* timer, DelayTimerTarget* target)
325       : timer_(timer), target_(target) {}
326 
Resetbase::__anon4ee860b90111::ResetHelper327   void Reset() {
328     ASSERT_FALSE(target_->signaled());
329     timer_->Reset();
330   }
331 
332  private:
333   DelayTimer* const timer_;
334   DelayTimerTarget* const target_;
335 };
336 
RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type)337 void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
338   MessageLoop loop(message_loop_type);
339 
340   // If Delay is never called, the timer shouldn't go off.
341   DelayTimerTarget target;
342   DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
343                    &DelayTimerTarget::Signal);
344   timer.Reset();
345 
346   ResetHelper reset_helper(&timer, &target);
347 
348   OneShotTimer timers[20];
349   for (size_t i = 0; i < arraysize(timers); ++i) {
350     timers[i].Start(FROM_HERE, TimeDelta::FromMilliseconds(i * 10),
351                     &reset_helper, &ResetHelper::Reset);
352   }
353 
354   OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(300));
355   tester.Start();
356   tester.WaitAndConfirmTimerFiredAfterDelay();
357 
358   ASSERT_TRUE(target.signaled());
359 }
360 
361 class DelayTimerFatalTarget {
362  public:
Signal()363   void Signal() {
364     ASSERT_TRUE(false);
365   }
366 };
367 
RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type)368 void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
369   MessageLoop loop(message_loop_type);
370 
371   DelayTimerFatalTarget target;
372 
373   {
374     DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
375                      &DelayTimerFatalTarget::Signal);
376     timer.Reset();
377   }
378 
379   // When the timer is deleted, the DelayTimerFatalTarget should never be
380   // called.
381   PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
382 }
383 
384 }  // namespace
385 
386 //-----------------------------------------------------------------------------
387 // Each test is run against each type of MessageLoop.  That way we are sure
388 // that timers work properly in all configurations.
389 
TEST(TimerTest,OneShotTimers)390 TEST(TimerTest, OneShotTimers) {
391   for (int i = 0; i < kNumTestingMessageLoops; i++) {
392     RunTest_OneShotTimers(testing_message_loops[i]);
393   }
394 }
395 
TEST(TimerTest,OneShotTimers_Cancel)396 TEST(TimerTest, OneShotTimers_Cancel) {
397   for (int i = 0; i < kNumTestingMessageLoops; i++) {
398     RunTest_OneShotTimers_Cancel(testing_message_loops[i]);
399   }
400 }
401 
402 // If underline timer does not handle properly, we will crash or fail
403 // in full page heap environment.
TEST(TimerTest,OneShotSelfDeletingTimer)404 TEST(TimerTest, OneShotSelfDeletingTimer) {
405   for (int i = 0; i < kNumTestingMessageLoops; i++) {
406     RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]);
407   }
408 }
409 
TEST(TimerTest,OneShotTimer_CustomTaskRunner)410 TEST(TimerTest, OneShotTimer_CustomTaskRunner) {
411   // A MessageLoop is required for the timer events on the other thread to
412   // communicate back to the Timer under test.
413   MessageLoop loop;
414 
415   Thread other_thread("OneShotTimer_CustomTaskRunner");
416   other_thread.Start();
417 
418   WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
419                         WaitableEvent::InitialState::NOT_SIGNALED);
420   OneShotTimerTester f(&did_run);
421   f.SetTaskRunner(other_thread.task_runner());
422   f.Start();
423   EXPECT_TRUE(f.IsRunning() || did_run.IsSignaled());
424 
425   f.WaitAndConfirmTimerFiredAfterDelay();
426   EXPECT_TRUE(did_run.IsSignaled());
427 
428   // |f| should already have communicated back to this |loop| before invoking
429   // Run() and as such this thread should already be aware that |f| is no longer
430   // running.
431   EXPECT_TRUE(loop.IsIdleForTesting());
432   EXPECT_FALSE(f.IsRunning());
433 }
434 
TEST(TimerTest,OneShotTimerWithTickClock)435 TEST(TimerTest, OneShotTimerWithTickClock) {
436   scoped_refptr<TestMockTimeTaskRunner> task_runner(
437       new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
438   MessageLoop message_loop;
439   message_loop.SetTaskRunner(task_runner);
440   Receiver receiver;
441   OneShotTimer timer(task_runner->GetMockTickClock());
442   timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
443               Bind(&Receiver::OnCalled, Unretained(&receiver)));
444   task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
445   EXPECT_TRUE(receiver.WasCalled());
446 }
447 
TEST(TimerTest,RepeatingTimer)448 TEST(TimerTest, RepeatingTimer) {
449   for (int i = 0; i < kNumTestingMessageLoops; i++) {
450     RunTest_RepeatingTimer(testing_message_loops[i],
451                            TimeDelta::FromMilliseconds(10));
452   }
453 }
454 
TEST(TimerTest,RepeatingTimer_Cancel)455 TEST(TimerTest, RepeatingTimer_Cancel) {
456   for (int i = 0; i < kNumTestingMessageLoops; i++) {
457     RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
458                                   TimeDelta::FromMilliseconds(10));
459   }
460 }
461 
TEST(TimerTest,RepeatingTimerZeroDelay)462 TEST(TimerTest, RepeatingTimerZeroDelay) {
463   for (int i = 0; i < kNumTestingMessageLoops; i++) {
464     RunTest_RepeatingTimer(testing_message_loops[i],
465                            TimeDelta::FromMilliseconds(0));
466   }
467 }
468 
TEST(TimerTest,RepeatingTimerZeroDelay_Cancel)469 TEST(TimerTest, RepeatingTimerZeroDelay_Cancel) {
470   for (int i = 0; i < kNumTestingMessageLoops; i++) {
471     RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
472                                   TimeDelta::FromMilliseconds(0));
473   }
474 }
475 
TEST(TimerTest,RepeatingTimerWithTickClock)476 TEST(TimerTest, RepeatingTimerWithTickClock) {
477   scoped_refptr<TestMockTimeTaskRunner> task_runner(
478       new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
479   MessageLoop message_loop;
480   message_loop.SetTaskRunner(task_runner);
481   Receiver receiver;
482   const int expected_times_called = 10;
483   RepeatingTimer timer(task_runner->GetMockTickClock());
484   timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
485               Bind(&Receiver::OnCalled, Unretained(&receiver)));
486   task_runner->FastForwardBy(TimeDelta::FromSeconds(expected_times_called));
487   timer.Stop();
488   EXPECT_EQ(expected_times_called, receiver.TimesCalled());
489 }
490 
TEST(TimerTest,DelayTimer_NoCall)491 TEST(TimerTest, DelayTimer_NoCall) {
492   for (int i = 0; i < kNumTestingMessageLoops; i++) {
493     RunTest_DelayTimer_NoCall(testing_message_loops[i]);
494   }
495 }
496 
TEST(TimerTest,DelayTimer_OneCall)497 TEST(TimerTest, DelayTimer_OneCall) {
498   for (int i = 0; i < kNumTestingMessageLoops; i++) {
499     RunTest_DelayTimer_OneCall(testing_message_loops[i]);
500   }
501 }
502 
503 // It's flaky on the buildbot, http://crbug.com/25038.
TEST(TimerTest,DISABLED_DelayTimer_Reset)504 TEST(TimerTest, DISABLED_DelayTimer_Reset) {
505   for (int i = 0; i < kNumTestingMessageLoops; i++) {
506     RunTest_DelayTimer_Reset(testing_message_loops[i]);
507   }
508 }
509 
TEST(TimerTest,DelayTimer_Deleted)510 TEST(TimerTest, DelayTimer_Deleted) {
511   for (int i = 0; i < kNumTestingMessageLoops; i++) {
512     RunTest_DelayTimer_Deleted(testing_message_loops[i]);
513   }
514 }
515 
TEST(TimerTest,DelayTimerWithTickClock)516 TEST(TimerTest, DelayTimerWithTickClock) {
517   scoped_refptr<TestMockTimeTaskRunner> task_runner(
518       new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
519   MessageLoop message_loop;
520   message_loop.SetTaskRunner(task_runner);
521   Receiver receiver;
522   DelayTimer timer(FROM_HERE, TimeDelta::FromSeconds(1), &receiver,
523                    &Receiver::OnCalled, task_runner->GetMockTickClock());
524   task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
525   EXPECT_FALSE(receiver.WasCalled());
526   timer.Reset();
527   task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
528   EXPECT_FALSE(receiver.WasCalled());
529   timer.Reset();
530   task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
531   EXPECT_TRUE(receiver.WasCalled());
532 }
533 
TEST(TimerTest,MessageLoopShutdown)534 TEST(TimerTest, MessageLoopShutdown) {
535   // This test is designed to verify that shutdown of the
536   // message loop does not cause crashes if there were pending
537   // timers not yet fired.  It may only trigger exceptions
538   // if debug heap checking is enabled.
539   WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
540                         WaitableEvent::InitialState::NOT_SIGNALED);
541   {
542     OneShotTimerTesterBase a(&did_run);
543     OneShotTimerTesterBase b(&did_run);
544     OneShotTimerTesterBase c(&did_run);
545     OneShotTimerTesterBase d(&did_run);
546     {
547       MessageLoop loop;
548       a.Start();
549       b.Start();
550     }  // MessageLoop destructs by falling out of scope.
551   }  // OneShotTimers destruct.  SHOULD NOT CRASH, of course.
552 
553   EXPECT_FALSE(did_run.IsSignaled());
554 }
555 
556 // Ref counted class which owns a Timer. The class passes a reference to itself
557 // via the |user_task| parameter in Timer::Start(). |Timer::user_task_| might
558 // end up holding the last reference to the class.
559 class OneShotSelfOwningTimerTester
560     : public RefCounted<OneShotSelfOwningTimerTester> {
561  public:
562   OneShotSelfOwningTimerTester() = default;
563 
StartTimer()564   void StartTimer() {
565     // Start timer with long delay in order to test the timer getting destroyed
566     // while a timer task is still pending.
567     timer_.Start(FROM_HERE, TimeDelta::FromDays(1),
568                  base::Bind(&OneShotSelfOwningTimerTester::Run, this));
569   }
570 
571  private:
572   friend class RefCounted<OneShotSelfOwningTimerTester>;
573   ~OneShotSelfOwningTimerTester() = default;
574 
Run()575   void Run() {
576     ADD_FAILURE() << "Timer unexpectedly fired.";
577   }
578 
579   OneShotTimer timer_;
580 
581   DISALLOW_COPY_AND_ASSIGN(OneShotSelfOwningTimerTester);
582 };
583 
TEST(TimerTest,MessageLoopShutdownSelfOwningTimer)584 TEST(TimerTest, MessageLoopShutdownSelfOwningTimer) {
585   // This test verifies that shutdown of the message loop does not cause crashes
586   // if there is a pending timer not yet fired and |Timer::user_task_| owns the
587   // timer. The test may only trigger exceptions if debug heap checking is
588   // enabled.
589 
590   MessageLoop loop;
591   scoped_refptr<OneShotSelfOwningTimerTester> tester =
592       new OneShotSelfOwningTimerTester();
593 
594   std::move(tester)->StartTimer();
595   // |Timer::user_task_| owns sole reference to |tester|.
596 
597   // MessageLoop destructs by falling out of scope. SHOULD NOT CRASH.
598 }
599 
TimerTestCallback()600 void TimerTestCallback() {
601 }
602 
TEST(TimerTest,NonRepeatIsRunning)603 TEST(TimerTest, NonRepeatIsRunning) {
604   {
605     MessageLoop loop;
606     Timer timer(false, false);
607     EXPECT_FALSE(timer.IsRunning());
608     timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
609     EXPECT_TRUE(timer.IsRunning());
610     timer.Stop();
611     EXPECT_FALSE(timer.IsRunning());
612     EXPECT_TRUE(timer.user_task().is_null());
613   }
614 
615   {
616     Timer timer(true, false);
617     MessageLoop loop;
618     EXPECT_FALSE(timer.IsRunning());
619     timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
620     EXPECT_TRUE(timer.IsRunning());
621     timer.Stop();
622     EXPECT_FALSE(timer.IsRunning());
623     ASSERT_FALSE(timer.user_task().is_null());
624     timer.Reset();
625     EXPECT_TRUE(timer.IsRunning());
626   }
627 }
628 
TEST(TimerTest,NonRepeatMessageLoopDeath)629 TEST(TimerTest, NonRepeatMessageLoopDeath) {
630   Timer timer(false, false);
631   {
632     MessageLoop loop;
633     EXPECT_FALSE(timer.IsRunning());
634     timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
635     EXPECT_TRUE(timer.IsRunning());
636   }
637   EXPECT_FALSE(timer.IsRunning());
638   EXPECT_TRUE(timer.user_task().is_null());
639 }
640 
TEST(TimerTest,RetainRepeatIsRunning)641 TEST(TimerTest, RetainRepeatIsRunning) {
642   MessageLoop loop;
643   Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
644               true);
645   EXPECT_FALSE(timer.IsRunning());
646   timer.Reset();
647   EXPECT_TRUE(timer.IsRunning());
648   timer.Stop();
649   EXPECT_FALSE(timer.IsRunning());
650   timer.Reset();
651   EXPECT_TRUE(timer.IsRunning());
652 }
653 
TEST(TimerTest,RetainNonRepeatIsRunning)654 TEST(TimerTest, RetainNonRepeatIsRunning) {
655   MessageLoop loop;
656   Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
657               false);
658   EXPECT_FALSE(timer.IsRunning());
659   timer.Reset();
660   EXPECT_TRUE(timer.IsRunning());
661   timer.Stop();
662   EXPECT_FALSE(timer.IsRunning());
663   timer.Reset();
664   EXPECT_TRUE(timer.IsRunning());
665 }
666 
667 //-----------------------------------------------------------------------------
668 
669 namespace {
670 
671 bool g_callback_happened1 = false;
672 bool g_callback_happened2 = false;
673 
ClearAllCallbackHappened()674 void ClearAllCallbackHappened() {
675   g_callback_happened1 = false;
676   g_callback_happened2 = false;
677 }
678 
SetCallbackHappened1()679 void SetCallbackHappened1() {
680   g_callback_happened1 = true;
681   RunLoop::QuitCurrentWhenIdleDeprecated();
682 }
683 
SetCallbackHappened2()684 void SetCallbackHappened2() {
685   g_callback_happened2 = true;
686   RunLoop::QuitCurrentWhenIdleDeprecated();
687 }
688 
689 }  // namespace
690 
TEST(TimerTest,ContinuationStopStart)691 TEST(TimerTest, ContinuationStopStart) {
692   {
693     ClearAllCallbackHappened();
694     MessageLoop loop;
695     Timer timer(false, false);
696     timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
697                 Bind(&SetCallbackHappened1));
698     timer.Stop();
699     timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40),
700                 Bind(&SetCallbackHappened2));
701     RunLoop().Run();
702     EXPECT_FALSE(g_callback_happened1);
703     EXPECT_TRUE(g_callback_happened2);
704   }
705 }
706 
TEST(TimerTest,ContinuationReset)707 TEST(TimerTest, ContinuationReset) {
708   {
709     ClearAllCallbackHappened();
710     MessageLoop loop;
711     Timer timer(false, false);
712     timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
713                 Bind(&SetCallbackHappened1));
714     timer.Reset();
715     // Since Reset happened before task ran, the user_task must not be cleared:
716     ASSERT_FALSE(timer.user_task().is_null());
717     RunLoop().Run();
718     EXPECT_TRUE(g_callback_happened1);
719   }
720 }
721 
722 namespace {
723 
724 // Fixture for tests requiring ScopedTaskEnvironment. Includes a WaitableEvent
725 // so that cases may Wait() on one thread and Signal() (explicitly, or
726 // implicitly via helper methods) on another.
727 class TimerSequenceTest : public testing::Test {
728  public:
TimerSequenceTest()729   TimerSequenceTest()
730       : event_(WaitableEvent::ResetPolicy::AUTOMATIC,
731                WaitableEvent::InitialState::NOT_SIGNALED) {}
732 
733   // Block until Signal() is called on another thread.
Wait()734   void Wait() { event_.Wait(); }
735 
Signal()736   void Signal() { event_.Signal(); }
737 
738   // Helper to augment a task with a subsequent call to Signal().
TaskWithSignal(const Closure & task)739   Closure TaskWithSignal(const Closure& task) {
740     return Bind(&TimerSequenceTest::RunTaskAndSignal, Unretained(this), task);
741   }
742 
743   // Create the timer.
CreateTimer()744   void CreateTimer() { timer_.reset(new OneShotTimer); }
745 
746   // Schedule an event on the timer.
StartTimer(TimeDelta delay,const Closure & task)747   void StartTimer(TimeDelta delay, const Closure& task) {
748     timer_->Start(FROM_HERE, delay, task);
749   }
750 
SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner)751   void SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner) {
752     timer_->SetTaskRunner(std::move(task_runner));
753   }
754 
755   // Tell the timer to abandon the task.
AbandonTask()756   void AbandonTask() {
757     EXPECT_TRUE(timer_->IsRunning());
758     // Reset() to call Timer::AbandonScheduledTask()
759     timer_->Reset();
760     EXPECT_TRUE(timer_->IsRunning());
761     timer_->Stop();
762     EXPECT_FALSE(timer_->IsRunning());
763   }
764 
VerifyAffinity(const SequencedTaskRunner * task_runner)765   static void VerifyAffinity(const SequencedTaskRunner* task_runner) {
766     EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
767   }
768 
769   // Delete the timer.
DeleteTimer()770   void DeleteTimer() { timer_.reset(); }
771 
772  private:
RunTaskAndSignal(const Closure & task)773   void RunTaskAndSignal(const Closure& task) {
774     task.Run();
775     Signal();
776   }
777 
778   base::test::ScopedTaskEnvironment scoped_task_environment_;
779   WaitableEvent event_;
780   std::unique_ptr<OneShotTimer> timer_;
781 
782   DISALLOW_COPY_AND_ASSIGN(TimerSequenceTest);
783 };
784 
785 }  // namespace
786 
TEST_F(TimerSequenceTest,OneShotTimerTaskOnPoolSequence)787 TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolSequence) {
788   scoped_refptr<SequencedTaskRunner> task_runner =
789       base::CreateSequencedTaskRunnerWithTraits({});
790 
791   base::RunLoop run_loop_;
792 
793   // Timer is created on this thread.
794   CreateTimer();
795 
796   // Task will execute on a pool thread.
797   SetTaskRunnerForTimer(task_runner);
798   StartTimer(TimeDelta::FromMilliseconds(1),
799              Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
800                   SequencedTaskRunnerHandle::Get(), FROM_HERE,
801                   run_loop_.QuitClosure()));
802 
803   // Spin the loop so that the delayed task fires on it, which will forward it
804   // to |task_runner|. And since the Timer's task is one that posts back to this
805   // MessageLoop to quit, we finally unblock.
806   run_loop_.Run();
807 
808   // Timer will be destroyed on this thread.
809   DeleteTimer();
810 }
811 
TEST_F(TimerSequenceTest,OneShotTimerUsedOnPoolSequence)812 TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolSequence) {
813   scoped_refptr<SequencedTaskRunner> task_runner =
814       base::CreateSequencedTaskRunnerWithTraits({});
815 
816   // Timer is created on this thread.
817   CreateTimer();
818 
819   // Task will be scheduled from a pool thread.
820   task_runner->PostTask(
821       FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
822                           TimeDelta::FromMilliseconds(1),
823                           Bind(&TimerSequenceTest::Signal, Unretained(this))));
824   Wait();
825 
826   // Timer must be destroyed on pool thread, too.
827   task_runner->PostTask(
828       FROM_HERE,
829       TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
830   Wait();
831 }
832 
TEST_F(TimerSequenceTest,OneShotTimerTwoSequencesAbandonTask)833 TEST_F(TimerSequenceTest, OneShotTimerTwoSequencesAbandonTask) {
834   scoped_refptr<SequencedTaskRunner> task_runner1 =
835       base::CreateSequencedTaskRunnerWithTraits({});
836   scoped_refptr<SequencedTaskRunner> task_runner2 =
837       base::CreateSequencedTaskRunnerWithTraits({});
838 
839   // Create timer on sequence #1.
840   task_runner1->PostTask(
841       FROM_HERE,
842       TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
843   Wait();
844 
845   // And tell it to execute on a different sequence (#2).
846   task_runner1->PostTask(
847       FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
848                                      Unretained(this), task_runner2)));
849   Wait();
850 
851   // Task will be scheduled from sequence #1.
852   task_runner1->PostTask(
853       FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
854                           TimeDelta::FromHours(1), DoNothing()));
855 
856   // Abandon task - must be called from scheduling sequence (#1).
857   task_runner1->PostTask(
858       FROM_HERE,
859       TaskWithSignal(Bind(&TimerSequenceTest::AbandonTask, Unretained(this))));
860   Wait();
861 
862   // Timer must be destroyed on the sequence it was scheduled from (#1).
863   task_runner1->PostTask(
864       FROM_HERE,
865       TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
866   Wait();
867 }
868 
TEST_F(TimerSequenceTest,OneShotTimerUsedAndTaskedOnDifferentSequences)869 TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentSequences) {
870   scoped_refptr<SequencedTaskRunner> task_runner1 =
871       base::CreateSequencedTaskRunnerWithTraits({});
872   scoped_refptr<SequencedTaskRunner> task_runner2 =
873       base::CreateSequencedTaskRunnerWithTraits({});
874 
875   // Create timer on sequence #1.
876   task_runner1->PostTask(
877       FROM_HERE,
878       TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
879   Wait();
880 
881   // And tell it to execute on a different sequence (#2).
882   task_runner1->PostTask(
883       FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
884                                      Unretained(this), task_runner2)));
885   Wait();
886 
887   // Task will be scheduled from sequence #1.
888   task_runner1->PostTask(
889       FROM_HERE,
890       BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
891                TimeDelta::FromMilliseconds(1),
892                TaskWithSignal(Bind(&TimerSequenceTest::VerifyAffinity,
893                                    Unretained(task_runner2.get())))));
894 
895   Wait();
896 
897   // Timer must be destroyed on the sequence it was scheduled from (#1).
898   task_runner1->PostTask(
899       FROM_HERE,
900       TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
901   Wait();
902 }
903 
904 }  // namespace base
905