blob: a868441c07640e80352d41dab562b3a22ac71895 [file] [log] [blame]
evan@chromium.org3c0bc352012-02-14 09:29:14 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
dchengcc8e4d82016-04-05 06:25:51 +09005#include "base/timer/timer.h"
6
avia6a6a682015-12-27 07:15:14 +09007#include <stddef.h>
8
dchengcc8e4d82016-04-05 06:25:51 +09009#include <memory>
10
jameswest9f1f3a02016-11-15 14:19:54 +090011#include "base/bind.h"
12#include "base/bind_helpers.h"
gabccd5b952016-11-29 08:01:33 +090013#include "base/callback.h"
avia6a6a682015-12-27 07:15:14 +090014#include "base/macros.h"
gabccd5b952016-11-29 08:01:33 +090015#include "base/memory/ptr_util.h"
pkotwicz55d7a1e2017-01-18 05:45:26 +090016#include "base/memory/ref_counted.h"
avi@chromium.orga043a862013-07-18 17:12:40 +090017#include "base/message_loop/message_loop.h"
fdoray85919bb2016-07-01 03:17:39 +090018#include "base/run_loop.h"
gabccd5b952016-11-29 08:01:33 +090019#include "base/sequenced_task_runner.h"
gabccd5b952016-11-29 08:01:33 +090020#include "base/synchronization/waitable_event.h"
Francois Doray18516722018-01-28 10:32:18 +090021#include "base/task_scheduler/post_task.h"
22#include "base/test/scoped_task_environment.h"
jameswest9f1f3a02016-11-15 14:19:54 +090023#include "base/test/test_mock_time_task_runner.h"
gabccd5b952016-11-29 08:01:33 +090024#include "base/threading/platform_thread.h"
25#include "base/threading/sequenced_task_runner_handle.h"
26#include "base/threading/thread.h"
jameswest9f1f3a02016-11-15 14:19:54 +090027#include "base/time/tick_clock.h"
gabccd5b952016-11-29 08:01:33 +090028#include "base/time/time.h"
avia6a6a682015-12-27 07:15:14 +090029#include "build/build_config.h"
initial.commit3f4a7322008-07-27 06:49:38 +090030#include "testing/gtest/include/gtest/gtest.h"
31
gabccd5b952016-11-29 08:01:33 +090032namespace base {
dsh@google.com0f8dd262008-10-28 05:43:33 +090033
darin@google.com0b8a30c2008-08-29 05:50:12 +090034namespace {
35
leng@chromium.org44fe4d72012-07-17 20:22:59 +090036// The message loops on which each timer should be tested.
gabccd5b952016-11-29 08:01:33 +090037const MessageLoop::Type testing_message_loops[] = {
38 MessageLoop::TYPE_DEFAULT, MessageLoop::TYPE_IO,
leng@chromium.org44fe4d72012-07-17 20:22:59 +090039#if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
gabccd5b952016-11-29 08:01:33 +090040 MessageLoop::TYPE_UI,
leng@chromium.org44fe4d72012-07-17 20:22:59 +090041#endif
42};
43
44const int kNumTestingMessageLoops = arraysize(testing_message_loops);
45
jameswest9f1f3a02016-11-15 14:19:54 +090046class Receiver {
47 public:
48 Receiver() : count_(0) {}
49 void OnCalled() { count_++; }
50 bool WasCalled() { return count_ > 0; }
51 int TimesCalled() { return count_; }
52
53 private:
54 int count_;
55};
56
ahest9a63aa22016-12-13 20:34:38 +090057// A basic helper class that can start a one-shot timer and signal a
58// WaitableEvent when this timer fires.
59class OneShotTimerTesterBase {
60 public:
61 // |did_run|, if provided, will be signaled when Run() fires.
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
69 void Start() {
70 started_time_ = TimeTicks::Now();
71 timer_->Start(FROM_HERE, delay_, this, &OneShotTimerTesterBase::Run);
72 }
73
74 bool IsRunning() { return timer_->IsRunning(); }
75
76 TimeTicks started_time() const { return started_time_; }
77 TimeDelta delay() const { return delay_; }
78
79 protected:
80 virtual void Run() {
81 if (did_run_) {
82 EXPECT_FALSE(did_run_->IsSignaled());
83 did_run_->Signal();
84 }
85 }
86
Jeremy Romancd0c4672017-08-17 08:27:24 +090087 std::unique_ptr<OneShotTimer> timer_ = std::make_unique<OneShotTimer>();
ahest9a63aa22016-12-13 20:34:38 +090088
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.
99class OneShotTimerTester : public OneShotTimerTesterBase {
darin@google.com0b8a30c2008-08-29 05:50:12 +0900100 public:
gabccd5b952016-11-29 08:01:33 +0900101 // |did_run|, if provided, will be signaled when Run() fires.
102 explicit OneShotTimerTester(
103 WaitableEvent* did_run = nullptr,
104 const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
ahest9a63aa22016-12-13 20:34:38 +0900105 : OneShotTimerTesterBase(did_run, delay),
106 quit_closure_(run_loop_.QuitClosure()) {}
petrcermak4dec79e2014-11-06 11:17:57 +0900107
ahest9a63aa22016-12-13 20:34:38 +0900108 ~OneShotTimerTester() override = default;
petrcermak4dec79e2014-11-06 11:17:57 +0900109
gabb4a7cd42017-06-02 01:23:36 +0900110 void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
gabccd5b952016-11-29 08:01:33 +0900111 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).
gabb4a7cd42017-06-02 01:23:36 +0900115 quit_closure_ = Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
116 SequencedTaskRunnerHandle::Get(), FROM_HERE,
117 run_loop_.QuitClosure());
petrcermak4dec79e2014-11-06 11:17:57 +0900118 }
119
gabccd5b952016-11-29 08:01:33 +0900120 // Blocks until Run() executes and confirms that Run() didn't fire before
121 // |delay_| expired.
122 void WaitAndConfirmTimerFiredAfterDelay() {
123 run_loop_.Run();
124
ahest9a63aa22016-12-13 20:34:38 +0900125 EXPECT_NE(TimeTicks(), started_time());
126 EXPECT_GE(TimeTicks::Now() - started_time(), delay());
gabccd5b952016-11-29 08:01:33 +0900127 }
128
gabccd5b952016-11-29 08:01:33 +0900129 protected:
130 // Overridable method to do things on Run() before signaling events/closures
131 // managed by this helper.
132 virtual void OnRun() {}
133
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900134 private:
ahest9a63aa22016-12-13 20:34:38 +0900135 void Run() override {
gabccd5b952016-11-29 08:01:33 +0900136 OnRun();
ahest9a63aa22016-12-13 20:34:38 +0900137 OneShotTimerTesterBase::Run();
gabccd5b952016-11-29 08:01:33 +0900138 quit_closure_.Run();
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900139 }
petrcermak4dec79e2014-11-06 11:17:57 +0900140
gabccd5b952016-11-29 08:01:33 +0900141 RunLoop run_loop_;
142 Closure quit_closure_;
gabccd5b952016-11-29 08:01:33 +0900143
144 DISALLOW_COPY_AND_ASSIGN(OneShotTimerTester);
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900145};
146
gabccd5b952016-11-29 08:01:33 +0900147class OneShotSelfDeletingTimerTester : public OneShotTimerTester {
148 protected:
149 void OnRun() override { timer_.reset(); }
150};
151
152constexpr int kNumRepeats = 10;
153
darin@google.com0b8a30c2008-08-29 05:50:12 +0900154class RepeatingTimerTester {
155 public:
gabccd5b952016-11-29 08:01:33 +0900156 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) {}
erg@google.combf6ce9f2010-01-27 08:08:02 +0900161
darin@google.com0b8a30c2008-08-29 05:50:12 +0900162 void Start() {
gabccd5b952016-11-29 08:01:33 +0900163 started_time_ = TimeTicks::Now();
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900164 timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900165 }
petrcermak4dec79e2014-11-06 11:17:57 +0900166
gabccd5b952016-11-29 08:01:33 +0900167 void WaitAndConfirmTimerFiredRepeatedlyAfterDelay() {
168 run_loop_.Run();
169
170 EXPECT_NE(TimeTicks(), started_time_);
171 EXPECT_GE(TimeTicks::Now() - started_time_, kNumRepeats * delay_);
172 }
173
darin@google.com0b8a30c2008-08-29 05:50:12 +0900174 private:
175 void Run() {
176 if (--counter_ == 0) {
gabccd5b952016-11-29 08:01:33 +0900177 if (did_run_) {
178 EXPECT_FALSE(did_run_->IsSignaled());
179 did_run_->Signal();
180 }
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900181 timer_.Stop();
gabccd5b952016-11-29 08:01:33 +0900182 quit_closure_.Run();
darin@google.com0b8a30c2008-08-29 05:50:12 +0900183 }
184 }
petrcermak4dec79e2014-11-06 11:17:57 +0900185
gabccd5b952016-11-29 08:01:33 +0900186 RepeatingTimer timer_;
darin@google.com0b8a30c2008-08-29 05:50:12 +0900187 int counter_;
gabccd5b952016-11-29 08:01:33 +0900188
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);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900197};
198
gabccd5b952016-11-29 08:01:33 +0900199// 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.
202void RunTest_OneShotTimers(MessageLoop::Type message_loop_type) {
203 MessageLoop loop(message_loop_type);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900204
gabccd5b952016-11-29 08:01:33 +0900205 WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
206 WaitableEvent::InitialState::NOT_SIGNALED);
207 OneShotTimerTester a(&did_run_a);
208 a.Start();
darin@google.com0b8a30c2008-08-29 05:50:12 +0900209
gabccd5b952016-11-29 08:01:33 +0900210 OneShotTimerTester b;
211 b.Start();
darin@google.com0b8a30c2008-08-29 05:50:12 +0900212
gabccd5b952016-11-29 08:01:33 +0900213 b.WaitAndConfirmTimerFiredAfterDelay();
214
215 EXPECT_TRUE(did_run_a.IsSignaled());
darin@google.com0b8a30c2008-08-29 05:50:12 +0900216}
217
gabccd5b952016-11-29 08:01:33 +0900218void RunTest_OneShotTimers_Cancel(MessageLoop::Type message_loop_type) {
219 MessageLoop loop(message_loop_type);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900220
gabccd5b952016-11-29 08:01:33 +0900221 WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
222 WaitableEvent::InitialState::NOT_SIGNALED);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900223 OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
224
225 // This should run before the timer expires.
gabccd5b952016-11-29 08:01:33 +0900226 SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900227
228 // Now start the timer.
229 a->Start();
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +0900230
gabccd5b952016-11-29 08:01:33 +0900231 OneShotTimerTester b;
darin@google.com0b8a30c2008-08-29 05:50:12 +0900232 b.Start();
233
gabccd5b952016-11-29 08:01:33 +0900234 b.WaitAndConfirmTimerFiredAfterDelay();
darin@google.com0b8a30c2008-08-29 05:50:12 +0900235
gabccd5b952016-11-29 08:01:33 +0900236 EXPECT_FALSE(did_run_a.IsSignaled());
darin@google.com0b8a30c2008-08-29 05:50:12 +0900237}
238
gabccd5b952016-11-29 08:01:33 +0900239void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
240 MessageLoop loop(message_loop_type);
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900241
gabccd5b952016-11-29 08:01:33 +0900242 OneShotSelfDeletingTimerTester f;
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900243 f.Start();
gabccd5b952016-11-29 08:01:33 +0900244 f.WaitAndConfirmTimerFiredAfterDelay();
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900245}
246
gabccd5b952016-11-29 08:01:33 +0900247void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type,
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900248 const TimeDelta& delay) {
gabccd5b952016-11-29 08:01:33 +0900249 MessageLoop loop(message_loop_type);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900250
gabccd5b952016-11-29 08:01:33 +0900251 RepeatingTimerTester f(nullptr, delay);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900252 f.Start();
gabccd5b952016-11-29 08:01:33 +0900253 f.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
darin@google.com0b8a30c2008-08-29 05:50:12 +0900254}
255
gabccd5b952016-11-29 08:01:33 +0900256void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type,
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900257 const TimeDelta& delay) {
gabccd5b952016-11-29 08:01:33 +0900258 MessageLoop loop(message_loop_type);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900259
gabccd5b952016-11-29 08:01:33 +0900260 WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
261 WaitableEvent::InitialState::NOT_SIGNALED);
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900262 RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a, delay);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900263
264 // This should run before the timer expires.
gabccd5b952016-11-29 08:01:33 +0900265 SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900266
267 // Now start the timer.
268 a->Start();
agl@chromium.org31de02e2009-02-20 11:00:04 +0900269
gabccd5b952016-11-29 08:01:33 +0900270 RepeatingTimerTester b(nullptr, delay);
darin@google.com0b8a30c2008-08-29 05:50:12 +0900271 b.Start();
272
gabccd5b952016-11-29 08:01:33 +0900273 b.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
darin@google.com0b8a30c2008-08-29 05:50:12 +0900274
gabccd5b952016-11-29 08:01:33 +0900275 // |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());
darin@google.com0b8a30c2008-08-29 05:50:12 +0900278}
279
agl@chromium.org31de02e2009-02-20 11:00:04 +0900280class DelayTimerTarget {
281 public:
agl@chromium.org31de02e2009-02-20 11:00:04 +0900282 bool signaled() const { return signaled_; }
283
284 void Signal() {
285 ASSERT_FALSE(signaled_);
286 signaled_ = true;
287 }
288
289 private:
hashimoto9c170992015-01-23 00:21:41 +0900290 bool signaled_ = false;
agl@chromium.org31de02e2009-02-20 11:00:04 +0900291};
292
gabccd5b952016-11-29 08:01:33 +0900293void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
294 MessageLoop loop(message_loop_type);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900295
296 // If Delay is never called, the timer shouldn't go off.
297 DelayTimerTarget target;
gabccd5b952016-11-29 08:01:33 +0900298 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
299 &DelayTimerTarget::Signal);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900300
gabccd5b952016-11-29 08:01:33 +0900301 OneShotTimerTester tester;
agl@chromium.org31de02e2009-02-20 11:00:04 +0900302 tester.Start();
gabccd5b952016-11-29 08:01:33 +0900303 tester.WaitAndConfirmTimerFiredAfterDelay();
agl@chromium.org31de02e2009-02-20 11:00:04 +0900304
305 ASSERT_FALSE(target.signaled());
306}
307
gabccd5b952016-11-29 08:01:33 +0900308void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
309 MessageLoop loop(message_loop_type);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900310
311 DelayTimerTarget target;
gabccd5b952016-11-29 08:01:33 +0900312 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
313 &DelayTimerTarget::Signal);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900314 timer.Reset();
315
gabccd5b952016-11-29 08:01:33 +0900316 OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(100));
agl@chromium.org31de02e2009-02-20 11:00:04 +0900317 tester.Start();
gabccd5b952016-11-29 08:01:33 +0900318 tester.WaitAndConfirmTimerFiredAfterDelay();
agl@chromium.org31de02e2009-02-20 11:00:04 +0900319
320 ASSERT_TRUE(target.signaled());
321}
322
323struct ResetHelper {
gabccd5b952016-11-29 08:01:33 +0900324 ResetHelper(DelayTimer* timer, DelayTimerTarget* target)
danakj85d43f42015-09-24 16:53:00 +0900325 : timer_(timer), target_(target) {}
agl@chromium.org31de02e2009-02-20 11:00:04 +0900326
327 void Reset() {
328 ASSERT_FALSE(target_->signaled());
329 timer_->Reset();
330 }
331
332 private:
gabccd5b952016-11-29 08:01:33 +0900333 DelayTimer* const timer_;
danakj85d43f42015-09-24 16:53:00 +0900334 DelayTimerTarget* const target_;
agl@chromium.org31de02e2009-02-20 11:00:04 +0900335};
336
gabccd5b952016-11-29 08:01:33 +0900337void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
338 MessageLoop loop(message_loop_type);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900339
340 // If Delay is never called, the timer shouldn't go off.
341 DelayTimerTarget target;
gabccd5b952016-11-29 08:01:33 +0900342 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
343 &DelayTimerTarget::Signal);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900344 timer.Reset();
345
346 ResetHelper reset_helper(&timer, &target);
347
gabccd5b952016-11-29 08:01:33 +0900348 OneShotTimer timers[20];
agl@chromium.org31de02e2009-02-20 11:00:04 +0900349 for (size_t i = 0; i < arraysize(timers); ++i) {
jbates@chromium.orgad6a3452011-09-03 03:23:02 +0900350 timers[i].Start(FROM_HERE, TimeDelta::FromMilliseconds(i * 10),
351 &reset_helper, &ResetHelper::Reset);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900352 }
353
gabccd5b952016-11-29 08:01:33 +0900354 OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(300));
agl@chromium.org31de02e2009-02-20 11:00:04 +0900355 tester.Start();
gabccd5b952016-11-29 08:01:33 +0900356 tester.WaitAndConfirmTimerFiredAfterDelay();
agl@chromium.org31de02e2009-02-20 11:00:04 +0900357
358 ASSERT_TRUE(target.signaled());
359}
360
agl@chromium.orgf5890862009-02-27 08:17:56 +0900361class DelayTimerFatalTarget {
362 public:
363 void Signal() {
364 ASSERT_TRUE(false);
365 }
366};
367
gabccd5b952016-11-29 08:01:33 +0900368void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
369 MessageLoop loop(message_loop_type);
agl@chromium.orgf5890862009-02-27 08:17:56 +0900370
371 DelayTimerFatalTarget target;
372
373 {
gabccd5b952016-11-29 08:01:33 +0900374 DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
375 &DelayTimerFatalTarget::Signal);
agl@chromium.orgf5890862009-02-27 08:17:56 +0900376 timer.Reset();
377 }
378
379 // When the timer is deleted, the DelayTimerFatalTarget should never be
380 // called.
gabccd5b952016-11-29 08:01:33 +0900381 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
agl@chromium.orgf5890862009-02-27 08:17:56 +0900382}
383
darin@google.comd936b5b2008-08-26 14:53:57 +0900384} // 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
gabccd5b952016-11-29 08:01:33 +0900390TEST(TimerTest, OneShotTimers) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900391 for (int i = 0; i < kNumTestingMessageLoops; i++) {
gabccd5b952016-11-29 08:01:33 +0900392 RunTest_OneShotTimers(testing_message_loops[i]);
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900393 }
darin@google.com0b8a30c2008-08-29 05:50:12 +0900394}
395
gabccd5b952016-11-29 08:01:33 +0900396TEST(TimerTest, OneShotTimers_Cancel) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900397 for (int i = 0; i < kNumTestingMessageLoops; i++) {
gabccd5b952016-11-29 08:01:33 +0900398 RunTest_OneShotTimers_Cancel(testing_message_loops[i]);
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900399 }
darin@google.com0b8a30c2008-08-29 05:50:12 +0900400}
401
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900402// If underline timer does not handle properly, we will crash or fail
jeanluc@chromium.org5fcf7872011-08-18 02:41:02 +0900403// in full page heap environment.
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900404TEST(TimerTest, OneShotSelfDeletingTimer) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900405 for (int i = 0; i < kNumTestingMessageLoops; i++) {
406 RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]);
407 }
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900408}
409
petrcermak4dec79e2014-11-06 11:17:57 +0900410TEST(TimerTest, OneShotTimer_CustomTaskRunner) {
gabccd5b952016-11-29 08:01:33 +0900411 // A MessageLoop is required for the timer events on the other thread to
412 // communicate back to the Timer under test.
413 MessageLoop loop;
petrcermak4dec79e2014-11-06 11:17:57 +0900414
gabccd5b952016-11-29 08:01:33 +0900415 Thread other_thread("OneShotTimer_CustomTaskRunner");
416 other_thread.Start();
417
418 WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
419 WaitableEvent::InitialState::NOT_SIGNALED);
petrcermak4dec79e2014-11-06 11:17:57 +0900420 OneShotTimerTester f(&did_run);
gabccd5b952016-11-29 08:01:33 +0900421 f.SetTaskRunner(other_thread.task_runner());
petrcermak4dec79e2014-11-06 11:17:57 +0900422 f.Start();
Scott Graham0be6f742017-07-26 06:25:32 +0900423 EXPECT_TRUE(f.IsRunning() || did_run.IsSignaled());
petrcermak4dec79e2014-11-06 11:17:57 +0900424
gabccd5b952016-11-29 08:01:33 +0900425 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());
petrcermak4dec79e2014-11-06 11:17:57 +0900433}
434
jameswest9f1f3a02016-11-15 14:19:54 +0900435TEST(TimerTest, OneShotTimerWithTickClock) {
gabccd5b952016-11-29 08:01:33 +0900436 scoped_refptr<TestMockTimeTaskRunner> task_runner(
437 new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
438 std::unique_ptr<TickClock> tick_clock(task_runner->GetMockTickClock());
439 MessageLoop message_loop;
jameswest9f1f3a02016-11-15 14:19:54 +0900440 message_loop.SetTaskRunner(task_runner);
441 Receiver receiver;
gabccd5b952016-11-29 08:01:33 +0900442 OneShotTimer timer(tick_clock.get());
443 timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
444 Bind(&Receiver::OnCalled, Unretained(&receiver)));
445 task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
jameswest9f1f3a02016-11-15 14:19:54 +0900446 EXPECT_TRUE(receiver.WasCalled());
447}
448
darin@google.com0b8a30c2008-08-29 05:50:12 +0900449TEST(TimerTest, RepeatingTimer) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900450 for (int i = 0; i < kNumTestingMessageLoops; i++) {
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900451 RunTest_RepeatingTimer(testing_message_loops[i],
452 TimeDelta::FromMilliseconds(10));
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900453 }
darin@google.com0b8a30c2008-08-29 05:50:12 +0900454}
455
456TEST(TimerTest, RepeatingTimer_Cancel) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900457 for (int i = 0; i < kNumTestingMessageLoops; i++) {
qsr@chromium.org38b986c2013-12-07 00:22:35 +0900458 RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
459 TimeDelta::FromMilliseconds(10));
460 }
461}
462
463TEST(TimerTest, RepeatingTimerZeroDelay) {
464 for (int i = 0; i < kNumTestingMessageLoops; i++) {
465 RunTest_RepeatingTimer(testing_message_loops[i],
466 TimeDelta::FromMilliseconds(0));
467 }
468}
469
470TEST(TimerTest, RepeatingTimerZeroDelay_Cancel) {
471 for (int i = 0; i < kNumTestingMessageLoops; i++) {
472 RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
473 TimeDelta::FromMilliseconds(0));
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900474 }
darin@google.com0b8a30c2008-08-29 05:50:12 +0900475}
mbelshe@google.come0efec82008-12-03 08:16:55 +0900476
jameswest9f1f3a02016-11-15 14:19:54 +0900477TEST(TimerTest, RepeatingTimerWithTickClock) {
gabccd5b952016-11-29 08:01:33 +0900478 scoped_refptr<TestMockTimeTaskRunner> task_runner(
479 new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
480 std::unique_ptr<TickClock> tick_clock(task_runner->GetMockTickClock());
481 MessageLoop message_loop;
jameswest9f1f3a02016-11-15 14:19:54 +0900482 message_loop.SetTaskRunner(task_runner);
483 Receiver receiver;
484 const int expected_times_called = 10;
gabccd5b952016-11-29 08:01:33 +0900485 RepeatingTimer timer(tick_clock.get());
486 timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
487 Bind(&Receiver::OnCalled, Unretained(&receiver)));
488 task_runner->FastForwardBy(TimeDelta::FromSeconds(expected_times_called));
jameswest9f1f3a02016-11-15 14:19:54 +0900489 timer.Stop();
490 EXPECT_EQ(expected_times_called, receiver.TimesCalled());
491}
492
agl@chromium.org31de02e2009-02-20 11:00:04 +0900493TEST(TimerTest, DelayTimer_NoCall) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900494 for (int i = 0; i < kNumTestingMessageLoops; i++) {
495 RunTest_DelayTimer_NoCall(testing_message_loops[i]);
496 }
agl@chromium.org31de02e2009-02-20 11:00:04 +0900497}
498
499TEST(TimerTest, DelayTimer_OneCall) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900500 for (int i = 0; i < kNumTestingMessageLoops; i++) {
501 RunTest_DelayTimer_OneCall(testing_message_loops[i]);
502 }
agl@chromium.org31de02e2009-02-20 11:00:04 +0900503}
504
phajdan.jr@chromium.org0cafffe2009-10-17 00:26:16 +0900505// It's flaky on the buildbot, http://crbug.com/25038.
evan@chromium.org3c0bc352012-02-14 09:29:14 +0900506TEST(TimerTest, DISABLED_DelayTimer_Reset) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900507 for (int i = 0; i < kNumTestingMessageLoops; i++) {
508 RunTest_DelayTimer_Reset(testing_message_loops[i]);
509 }
agl@chromium.org31de02e2009-02-20 11:00:04 +0900510}
511
agl@chromium.orgf5890862009-02-27 08:17:56 +0900512TEST(TimerTest, DelayTimer_Deleted) {
leng@chromium.org44fe4d72012-07-17 20:22:59 +0900513 for (int i = 0; i < kNumTestingMessageLoops; i++) {
514 RunTest_DelayTimer_Deleted(testing_message_loops[i]);
515 }
agl@chromium.orgf5890862009-02-27 08:17:56 +0900516}
517
jameswest9f1f3a02016-11-15 14:19:54 +0900518TEST(TimerTest, DelayTimerWithTickClock) {
gabccd5b952016-11-29 08:01:33 +0900519 scoped_refptr<TestMockTimeTaskRunner> task_runner(
520 new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
521 std::unique_ptr<TickClock> tick_clock(task_runner->GetMockTickClock());
522 MessageLoop message_loop;
jameswest9f1f3a02016-11-15 14:19:54 +0900523 message_loop.SetTaskRunner(task_runner);
524 Receiver receiver;
gabccd5b952016-11-29 08:01:33 +0900525 DelayTimer timer(FROM_HERE, TimeDelta::FromSeconds(1), &receiver,
526 &Receiver::OnCalled, tick_clock.get());
527 task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
jameswest9f1f3a02016-11-15 14:19:54 +0900528 EXPECT_FALSE(receiver.WasCalled());
529 timer.Reset();
gabccd5b952016-11-29 08:01:33 +0900530 task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
jameswest9f1f3a02016-11-15 14:19:54 +0900531 EXPECT_FALSE(receiver.WasCalled());
532 timer.Reset();
gabccd5b952016-11-29 08:01:33 +0900533 task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
jameswest9f1f3a02016-11-15 14:19:54 +0900534 EXPECT_TRUE(receiver.WasCalled());
535}
536
mbelshe@google.come0efec82008-12-03 08:16:55 +0900537TEST(TimerTest, MessageLoopShutdown) {
538 // This test is designed to verify that shutdown of the
539 // message loop does not cause crashes if there were pending
540 // timers not yet fired. It may only trigger exceptions
jeanluc@chromium.org5fcf7872011-08-18 02:41:02 +0900541 // if debug heap checking is enabled.
gabccd5b952016-11-29 08:01:33 +0900542 WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
543 WaitableEvent::InitialState::NOT_SIGNALED);
mbelshe@google.come0efec82008-12-03 08:16:55 +0900544 {
ahest9a63aa22016-12-13 20:34:38 +0900545 OneShotTimerTesterBase a(&did_run);
546 OneShotTimerTesterBase b(&did_run);
547 OneShotTimerTesterBase c(&did_run);
548 OneShotTimerTesterBase d(&did_run);
mbelshe@google.come0efec82008-12-03 08:16:55 +0900549 {
gabccd5b952016-11-29 08:01:33 +0900550 MessageLoop loop;
mbelshe@google.come0efec82008-12-03 08:16:55 +0900551 a.Start();
552 b.Start();
553 } // MessageLoop destructs by falling out of scope.
554 } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
555
gabccd5b952016-11-29 08:01:33 +0900556 EXPECT_FALSE(did_run.IsSignaled());
mbelshe@google.come0efec82008-12-03 08:16:55 +0900557}
jbates@chromium.org18001832012-03-27 09:18:57 +0900558
pkotwicz55d7a1e2017-01-18 05:45:26 +0900559// Ref counted class which owns a Timer. The class passes a reference to itself
560// via the |user_task| parameter in Timer::Start(). |Timer::user_task_| might
561// end up holding the last reference to the class.
562class OneShotSelfOwningTimerTester
563 : public RefCounted<OneShotSelfOwningTimerTester> {
564 public:
565 OneShotSelfOwningTimerTester() = default;
566
567 void StartTimer() {
568 // Start timer with long delay in order to test the timer getting destroyed
569 // while a timer task is still pending.
570 timer_.Start(FROM_HERE, TimeDelta::FromDays(1),
571 base::Bind(&OneShotSelfOwningTimerTester::Run, this));
572 }
573
574 private:
575 friend class RefCounted<OneShotSelfOwningTimerTester>;
576 ~OneShotSelfOwningTimerTester() = default;
577
578 void Run() {
579 ADD_FAILURE() << "Timer unexpectedly fired.";
580 }
581
582 OneShotTimer timer_;
583
584 DISALLOW_COPY_AND_ASSIGN(OneShotSelfOwningTimerTester);
585};
586
587TEST(TimerTest, MessageLoopShutdownSelfOwningTimer) {
588 // This test verifies that shutdown of the message loop does not cause crashes
589 // if there is a pending timer not yet fired and |Timer::user_task_| owns the
590 // timer. The test may only trigger exceptions if debug heap checking is
591 // enabled.
592
593 MessageLoop loop;
594 scoped_refptr<OneShotSelfOwningTimerTester> tester =
595 new OneShotSelfOwningTimerTester();
596
597 std::move(tester)->StartTimer();
598 // |Timer::user_task_| owns sole reference to |tester|.
599
600 // MessageLoop destructs by falling out of scope. SHOULD NOT CRASH.
601}
602
jbates@chromium.org18001832012-03-27 09:18:57 +0900603void TimerTestCallback() {
604}
605
606TEST(TimerTest, NonRepeatIsRunning) {
607 {
gabccd5b952016-11-29 08:01:33 +0900608 MessageLoop loop;
609 Timer timer(false, false);
jbates@chromium.org18001832012-03-27 09:18:57 +0900610 EXPECT_FALSE(timer.IsRunning());
gabccd5b952016-11-29 08:01:33 +0900611 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
jbates@chromium.org18001832012-03-27 09:18:57 +0900612 EXPECT_TRUE(timer.IsRunning());
613 timer.Stop();
614 EXPECT_FALSE(timer.IsRunning());
615 EXPECT_TRUE(timer.user_task().is_null());
616 }
617
618 {
gabccd5b952016-11-29 08:01:33 +0900619 Timer timer(true, false);
620 MessageLoop loop;
jbates@chromium.org18001832012-03-27 09:18:57 +0900621 EXPECT_FALSE(timer.IsRunning());
gabccd5b952016-11-29 08:01:33 +0900622 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
jbates@chromium.org18001832012-03-27 09:18:57 +0900623 EXPECT_TRUE(timer.IsRunning());
624 timer.Stop();
625 EXPECT_FALSE(timer.IsRunning());
626 ASSERT_FALSE(timer.user_task().is_null());
627 timer.Reset();
628 EXPECT_TRUE(timer.IsRunning());
629 }
630}
631
632TEST(TimerTest, NonRepeatMessageLoopDeath) {
gabccd5b952016-11-29 08:01:33 +0900633 Timer timer(false, false);
jbates@chromium.org18001832012-03-27 09:18:57 +0900634 {
gabccd5b952016-11-29 08:01:33 +0900635 MessageLoop loop;
jbates@chromium.org18001832012-03-27 09:18:57 +0900636 EXPECT_FALSE(timer.IsRunning());
gabccd5b952016-11-29 08:01:33 +0900637 timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
jbates@chromium.org18001832012-03-27 09:18:57 +0900638 EXPECT_TRUE(timer.IsRunning());
639 }
640 EXPECT_FALSE(timer.IsRunning());
641 EXPECT_TRUE(timer.user_task().is_null());
642}
643
644TEST(TimerTest, RetainRepeatIsRunning) {
gabccd5b952016-11-29 08:01:33 +0900645 MessageLoop loop;
646 Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
647 true);
jbates@chromium.org18001832012-03-27 09:18:57 +0900648 EXPECT_FALSE(timer.IsRunning());
649 timer.Reset();
650 EXPECT_TRUE(timer.IsRunning());
651 timer.Stop();
652 EXPECT_FALSE(timer.IsRunning());
653 timer.Reset();
654 EXPECT_TRUE(timer.IsRunning());
655}
656
657TEST(TimerTest, RetainNonRepeatIsRunning) {
gabccd5b952016-11-29 08:01:33 +0900658 MessageLoop loop;
659 Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
660 false);
jbates@chromium.org18001832012-03-27 09:18:57 +0900661 EXPECT_FALSE(timer.IsRunning());
662 timer.Reset();
663 EXPECT_TRUE(timer.IsRunning());
664 timer.Stop();
665 EXPECT_FALSE(timer.IsRunning());
666 timer.Reset();
667 EXPECT_TRUE(timer.IsRunning());
668}
669
gabb4a7cd42017-06-02 01:23:36 +0900670//-----------------------------------------------------------------------------
671
jbates@chromium.org18001832012-03-27 09:18:57 +0900672namespace {
673
674bool g_callback_happened1 = false;
675bool g_callback_happened2 = false;
676
677void ClearAllCallbackHappened() {
678 g_callback_happened1 = false;
679 g_callback_happened2 = false;
680}
681
682void SetCallbackHappened1() {
683 g_callback_happened1 = true;
Gabriel Charette274bec82017-07-26 21:36:23 +0900684 RunLoop::QuitCurrentWhenIdleDeprecated();
jbates@chromium.org18001832012-03-27 09:18:57 +0900685}
686
687void SetCallbackHappened2() {
688 g_callback_happened2 = true;
Gabriel Charette274bec82017-07-26 21:36:23 +0900689 RunLoop::QuitCurrentWhenIdleDeprecated();
jbates@chromium.org18001832012-03-27 09:18:57 +0900690}
691
gabccd5b952016-11-29 08:01:33 +0900692} // namespace
693
jbates@chromium.org18001832012-03-27 09:18:57 +0900694TEST(TimerTest, ContinuationStopStart) {
695 {
696 ClearAllCallbackHappened();
gabccd5b952016-11-29 08:01:33 +0900697 MessageLoop loop;
698 Timer timer(false, false);
jbates@chromium.org18001832012-03-27 09:18:57 +0900699 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
gabccd5b952016-11-29 08:01:33 +0900700 Bind(&SetCallbackHappened1));
jbates@chromium.org18001832012-03-27 09:18:57 +0900701 timer.Stop();
702 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40),
gabccd5b952016-11-29 08:01:33 +0900703 Bind(&SetCallbackHappened2));
704 RunLoop().Run();
jbates@chromium.org18001832012-03-27 09:18:57 +0900705 EXPECT_FALSE(g_callback_happened1);
706 EXPECT_TRUE(g_callback_happened2);
707 }
708}
709
710TEST(TimerTest, ContinuationReset) {
711 {
712 ClearAllCallbackHappened();
gabccd5b952016-11-29 08:01:33 +0900713 MessageLoop loop;
714 Timer timer(false, false);
jbates@chromium.org18001832012-03-27 09:18:57 +0900715 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
gabccd5b952016-11-29 08:01:33 +0900716 Bind(&SetCallbackHappened1));
jbates@chromium.org18001832012-03-27 09:18:57 +0900717 timer.Reset();
718 // Since Reset happened before task ran, the user_task must not be cleared:
719 ASSERT_FALSE(timer.user_task().is_null());
gabccd5b952016-11-29 08:01:33 +0900720 RunLoop().Run();
jbates@chromium.org18001832012-03-27 09:18:57 +0900721 EXPECT_TRUE(g_callback_happened1);
722 }
723}
724
gabb4a7cd42017-06-02 01:23:36 +0900725namespace {
726
Francois Doray18516722018-01-28 10:32:18 +0900727// Fixture for tests requiring ScopedTaskEnvironment. Includes a WaitableEvent
728// so that cases may Wait() on one thread and Signal() (explicitly, or
729// implicitly via helper methods) on another.
gabb4a7cd42017-06-02 01:23:36 +0900730class TimerSequenceTest : public testing::Test {
731 public:
732 TimerSequenceTest()
733 : event_(WaitableEvent::ResetPolicy::AUTOMATIC,
734 WaitableEvent::InitialState::NOT_SIGNALED) {}
735
gabb4a7cd42017-06-02 01:23:36 +0900736 // Block until Signal() is called on another thread.
737 void Wait() { event_.Wait(); }
738
739 void Signal() { event_.Signal(); }
740
741 // Helper to augment a task with a subsequent call to Signal().
742 Closure TaskWithSignal(const Closure& task) {
743 return Bind(&TimerSequenceTest::RunTaskAndSignal, Unretained(this), task);
744 }
745
746 // Create the timer.
747 void CreateTimer() { timer_.reset(new OneShotTimer); }
748
749 // Schedule an event on the timer.
750 void StartTimer(TimeDelta delay, const Closure& task) {
751 timer_->Start(FROM_HERE, delay, task);
752 }
753
754 void SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner) {
755 timer_->SetTaskRunner(std::move(task_runner));
756 }
757
758 // Tell the timer to abandon the task.
759 void AbandonTask() {
760 EXPECT_TRUE(timer_->IsRunning());
761 // Reset() to call Timer::AbandonScheduledTask()
762 timer_->Reset();
763 EXPECT_TRUE(timer_->IsRunning());
764 timer_->Stop();
765 EXPECT_FALSE(timer_->IsRunning());
766 }
767
768 static void VerifyAffinity(const SequencedTaskRunner* task_runner) {
Yeol0d4f3eb2017-07-26 02:09:10 +0900769 EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
gabb4a7cd42017-06-02 01:23:36 +0900770 }
771
772 // Delete the timer.
773 void DeleteTimer() { timer_.reset(); }
774
gabb4a7cd42017-06-02 01:23:36 +0900775 private:
776 void RunTaskAndSignal(const Closure& task) {
777 task.Run();
778 Signal();
779 }
780
Francois Doray18516722018-01-28 10:32:18 +0900781 base::test::ScopedTaskEnvironment scoped_task_environment_;
gabb4a7cd42017-06-02 01:23:36 +0900782 WaitableEvent event_;
gabb4a7cd42017-06-02 01:23:36 +0900783 std::unique_ptr<OneShotTimer> timer_;
784
785 DISALLOW_COPY_AND_ASSIGN(TimerSequenceTest);
786};
787
788} // namespace
789
Francois Doray18516722018-01-28 10:32:18 +0900790TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolSequence) {
gabb4a7cd42017-06-02 01:23:36 +0900791 scoped_refptr<SequencedTaskRunner> task_runner =
Francois Doray18516722018-01-28 10:32:18 +0900792 base::CreateSequencedTaskRunnerWithTraits({});
gabb4a7cd42017-06-02 01:23:36 +0900793
794 base::RunLoop run_loop_;
795
796 // Timer is created on this thread.
797 CreateTimer();
798
799 // Task will execute on a pool thread.
800 SetTaskRunnerForTimer(task_runner);
801 StartTimer(TimeDelta::FromMilliseconds(1),
802 Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
803 SequencedTaskRunnerHandle::Get(), FROM_HERE,
804 run_loop_.QuitClosure()));
805
806 // Spin the loop so that the delayed task fires on it, which will forward it
807 // to |task_runner|. And since the Timer's task is one that posts back to this
808 // MessageLoop to quit, we finally unblock.
809 run_loop_.Run();
810
811 // Timer will be destroyed on this thread.
812 DeleteTimer();
813}
814
Francois Doray18516722018-01-28 10:32:18 +0900815TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolSequence) {
gabb4a7cd42017-06-02 01:23:36 +0900816 scoped_refptr<SequencedTaskRunner> task_runner =
Francois Doray18516722018-01-28 10:32:18 +0900817 base::CreateSequencedTaskRunnerWithTraits({});
gabb4a7cd42017-06-02 01:23:36 +0900818
819 // Timer is created on this thread.
820 CreateTimer();
821
822 // Task will be scheduled from a pool thread.
823 task_runner->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900824 FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
825 TimeDelta::FromMilliseconds(1),
826 Bind(&TimerSequenceTest::Signal, Unretained(this))));
gabb4a7cd42017-06-02 01:23:36 +0900827 Wait();
828
829 // Timer must be destroyed on pool thread, too.
830 task_runner->PostTask(
831 FROM_HERE,
832 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
833 Wait();
834}
835
Francois Doray18516722018-01-28 10:32:18 +0900836TEST_F(TimerSequenceTest, OneShotTimerTwoSequencesAbandonTask) {
gabb4a7cd42017-06-02 01:23:36 +0900837 scoped_refptr<SequencedTaskRunner> task_runner1 =
Francois Doray18516722018-01-28 10:32:18 +0900838 base::CreateSequencedTaskRunnerWithTraits({});
gabb4a7cd42017-06-02 01:23:36 +0900839 scoped_refptr<SequencedTaskRunner> task_runner2 =
Francois Doray18516722018-01-28 10:32:18 +0900840 base::CreateSequencedTaskRunnerWithTraits({});
gabb4a7cd42017-06-02 01:23:36 +0900841
Francois Doray18516722018-01-28 10:32:18 +0900842 // Create timer on sequence #1.
gabb4a7cd42017-06-02 01:23:36 +0900843 task_runner1->PostTask(
844 FROM_HERE,
845 TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
846 Wait();
847
Francois Doray18516722018-01-28 10:32:18 +0900848 // And tell it to execute on a different sequence (#2).
gabb4a7cd42017-06-02 01:23:36 +0900849 task_runner1->PostTask(
850 FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
851 Unretained(this), task_runner2)));
852 Wait();
853
Francois Doray18516722018-01-28 10:32:18 +0900854 // Task will be scheduled from sequence #1.
tzik330d83f2017-06-26 15:13:17 +0900855 task_runner1->PostTask(
856 FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
Peter Kasting24efe5e2018-02-24 09:03:01 +0900857 TimeDelta::FromHours(1), DoNothing()));
gabb4a7cd42017-06-02 01:23:36 +0900858
Francois Doray18516722018-01-28 10:32:18 +0900859 // Abandon task - must be called from scheduling sequence (#1).
gabb4a7cd42017-06-02 01:23:36 +0900860 task_runner1->PostTask(
861 FROM_HERE,
862 TaskWithSignal(Bind(&TimerSequenceTest::AbandonTask, Unretained(this))));
863 Wait();
864
Francois Doray18516722018-01-28 10:32:18 +0900865 // Timer must be destroyed on the sequence it was scheduled from (#1).
gabb4a7cd42017-06-02 01:23:36 +0900866 task_runner1->PostTask(
867 FROM_HERE,
868 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
869 Wait();
870}
871
Francois Doray18516722018-01-28 10:32:18 +0900872TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentSequences) {
gabb4a7cd42017-06-02 01:23:36 +0900873 scoped_refptr<SequencedTaskRunner> task_runner1 =
Francois Doray18516722018-01-28 10:32:18 +0900874 base::CreateSequencedTaskRunnerWithTraits({});
gabb4a7cd42017-06-02 01:23:36 +0900875 scoped_refptr<SequencedTaskRunner> task_runner2 =
Francois Doray18516722018-01-28 10:32:18 +0900876 base::CreateSequencedTaskRunnerWithTraits({});
gabb4a7cd42017-06-02 01:23:36 +0900877
Francois Doray18516722018-01-28 10:32:18 +0900878 // Create timer on sequence #1.
gabb4a7cd42017-06-02 01:23:36 +0900879 task_runner1->PostTask(
880 FROM_HERE,
881 TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
882 Wait();
883
Francois Doray18516722018-01-28 10:32:18 +0900884 // And tell it to execute on a different sequence (#2).
gabb4a7cd42017-06-02 01:23:36 +0900885 task_runner1->PostTask(
886 FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
887 Unretained(this), task_runner2)));
888 Wait();
889
Francois Doray18516722018-01-28 10:32:18 +0900890 // Task will be scheduled from sequence #1.
gabb4a7cd42017-06-02 01:23:36 +0900891 task_runner1->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900892 FROM_HERE,
893 BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
894 TimeDelta::FromMilliseconds(1),
895 TaskWithSignal(Bind(&TimerSequenceTest::VerifyAffinity,
896 Unretained(task_runner2.get())))));
gabb4a7cd42017-06-02 01:23:36 +0900897
898 Wait();
899
Francois Doray18516722018-01-28 10:32:18 +0900900 // Timer must be destroyed on the sequence it was scheduled from (#1).
gabb4a7cd42017-06-02 01:23:36 +0900901 task_runner1->PostTask(
902 FROM_HERE,
903 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
904 Wait();
905}
906
gabccd5b952016-11-29 08:01:33 +0900907} // namespace base