1 // Copyright 2012 The Chromium Authors
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/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/run_loop.h"
16 #include "base/task/sequenced_task_runner.h"
17 #include "base/test/bind.h"
18 #include "base/test/mock_callback.h"
19 #include "base/test/task_environment.h"
20 #include "base/test/test_simple_task_runner.h"
21 #include "base/time/tick_clock.h"
22 #include "base/time/time.h"
23 #include "build/build_config.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace base {
27
28 namespace {
29
30 constexpr TimeDelta kTestDelay = Seconds(10);
31 constexpr TimeDelta kLongTestDelay = Minutes(10);
32
33 // The main thread types on which each timer should be tested.
34 const test::TaskEnvironment::MainThreadType testing_main_threads[] = {
35 test::TaskEnvironment::MainThreadType::DEFAULT,
36 test::TaskEnvironment::MainThreadType::IO,
37 #if !BUILDFLAG(IS_IOS) // iOS does not allow direct running of the UI loop.
38 test::TaskEnvironment::MainThreadType::UI,
39 #endif
40 };
41
42 class Receiver {
43 public:
Receiver()44 Receiver() : count_(0) {}
OnCalled()45 void OnCalled() { count_++; }
WasCalled()46 bool WasCalled() { return count_ > 0; }
TimesCalled()47 int TimesCalled() { return count_; }
48
49 private:
50 int count_;
51 };
52
53 // Basic test with same setup as RunTest_OneShotTimers_Cancel below to confirm
54 // that |timer| would be fired in that test if it wasn't for the deletion.
RunTest_OneShotTimers(test::TaskEnvironment::MainThreadType main_thread_type)55 void RunTest_OneShotTimers(
56 test::TaskEnvironment::MainThreadType main_thread_type) {
57 test::TaskEnvironment task_environment(
58 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
59
60 Receiver receiver;
61 OneShotTimer timer;
62 timer.Start(FROM_HERE, kTestDelay,
63 BindOnce(&Receiver::OnCalled, Unretained(&receiver)));
64
65 task_environment.FastForwardBy(kTestDelay);
66 EXPECT_TRUE(receiver.WasCalled());
67 EXPECT_FALSE(timer.IsRunning());
68 }
69
RunTest_OneShotTimers_Cancel(test::TaskEnvironment::MainThreadType main_thread_type)70 void RunTest_OneShotTimers_Cancel(
71 test::TaskEnvironment::MainThreadType main_thread_type) {
72 test::TaskEnvironment task_environment(
73 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
74
75 Receiver receiver;
76 auto timer = std::make_unique<OneShotTimer>();
77 auto* timer_ptr = timer.get();
78
79 // This should run before the timer expires.
80 SequencedTaskRunner::GetCurrentDefault()->DeleteSoon(FROM_HERE,
81 std::move(timer));
82
83 timer_ptr->Start(FROM_HERE, kTestDelay,
84 BindOnce(&Receiver::OnCalled, Unretained(&receiver)));
85
86 task_environment.FastForwardBy(kTestDelay);
87 EXPECT_FALSE(receiver.WasCalled());
88 }
89
RunTest_OneShotSelfDeletingTimer(test::TaskEnvironment::MainThreadType main_thread_type)90 void RunTest_OneShotSelfDeletingTimer(
91 test::TaskEnvironment::MainThreadType main_thread_type) {
92 test::TaskEnvironment task_environment(
93 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
94
95 Receiver receiver;
96 auto timer = std::make_unique<OneShotTimer>();
97 auto* timer_ptr = timer.get();
98
99 timer_ptr->Start(
100 FROM_HERE, kTestDelay,
101 BindLambdaForTesting([&receiver, timer = std::move(timer)]() mutable {
102 receiver.OnCalled();
103 EXPECT_FALSE(timer->IsRunning());
104 timer.reset();
105 }));
106
107 task_environment.FastForwardBy(kTestDelay);
108 EXPECT_TRUE(receiver.WasCalled());
109 }
110
RunTest_RepeatingTimer(test::TaskEnvironment::MainThreadType main_thread_type,const TimeDelta & delay)111 void RunTest_RepeatingTimer(
112 test::TaskEnvironment::MainThreadType main_thread_type,
113 const TimeDelta& delay) {
114 test::TaskEnvironment task_environment(
115 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
116
117 Receiver receiver;
118 RepeatingTimer timer;
119 timer.Start(FROM_HERE, kTestDelay,
120 BindRepeating(&Receiver::OnCalled, Unretained(&receiver)));
121
122 task_environment.FastForwardBy(20 * kTestDelay);
123 EXPECT_EQ(receiver.TimesCalled(), 20);
124 EXPECT_TRUE(timer.IsRunning());
125 }
126
RunTest_RepeatingTimer_Cancel(test::TaskEnvironment::MainThreadType main_thread_type,const TimeDelta & delay)127 void RunTest_RepeatingTimer_Cancel(
128 test::TaskEnvironment::MainThreadType main_thread_type,
129 const TimeDelta& delay) {
130 test::TaskEnvironment task_environment(
131 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
132
133 Receiver receiver;
134 auto timer = std::make_unique<RepeatingTimer>();
135 auto* timer_ptr = timer.get();
136
137 // This should run before the timer expires.
138 SequencedTaskRunner::GetCurrentDefault()->DeleteSoon(FROM_HERE,
139 std::move(timer));
140
141 timer_ptr->Start(FROM_HERE, delay,
142 BindRepeating(&Receiver::OnCalled, Unretained(&receiver)));
143
144 task_environment.FastForwardBy(delay);
145 EXPECT_FALSE(receiver.WasCalled());
146 }
147
RunTest_DelayTimer_NoCall(test::TaskEnvironment::MainThreadType main_thread_type)148 void RunTest_DelayTimer_NoCall(
149 test::TaskEnvironment::MainThreadType main_thread_type) {
150 test::TaskEnvironment task_environment(
151 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
152
153 Receiver receiver;
154 DelayTimer timer(FROM_HERE, kTestDelay, &receiver, &Receiver::OnCalled);
155
156 task_environment.FastForwardBy(kTestDelay);
157 EXPECT_FALSE(receiver.WasCalled());
158 }
159
RunTest_DelayTimer_OneCall(test::TaskEnvironment::MainThreadType main_thread_type)160 void RunTest_DelayTimer_OneCall(
161 test::TaskEnvironment::MainThreadType main_thread_type) {
162 test::TaskEnvironment task_environment(
163 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
164
165 Receiver receiver;
166 DelayTimer timer(FROM_HERE, kTestDelay, &receiver, &Receiver::OnCalled);
167 timer.Reset();
168
169 task_environment.FastForwardBy(kTestDelay);
170 EXPECT_TRUE(receiver.WasCalled());
171 }
172
RunTest_DelayTimer_Reset(test::TaskEnvironment::MainThreadType main_thread_type)173 void RunTest_DelayTimer_Reset(
174 test::TaskEnvironment::MainThreadType main_thread_type) {
175 test::TaskEnvironment task_environment(
176 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
177
178 Receiver receiver;
179 DelayTimer timer(FROM_HERE, kTestDelay, &receiver, &Receiver::OnCalled);
180 timer.Reset();
181
182 // Fast-forward by a delay smaller than the timer delay. The timer will not
183 // fire.
184 task_environment.FastForwardBy(kTestDelay / 2);
185 EXPECT_FALSE(receiver.WasCalled());
186
187 // Postpone the fire time.
188 timer.Reset();
189
190 // Verify that the timer does not fire at its original fire time.
191 task_environment.FastForwardBy(kTestDelay / 2);
192 EXPECT_FALSE(receiver.WasCalled());
193
194 // Fast-forward by the timer delay. The timer will fire.
195 task_environment.FastForwardBy(kTestDelay / 2);
196 EXPECT_TRUE(receiver.WasCalled());
197 }
198
RunTest_DelayTimer_Deleted(test::TaskEnvironment::MainThreadType main_thread_type)199 void RunTest_DelayTimer_Deleted(
200 test::TaskEnvironment::MainThreadType main_thread_type) {
201 test::TaskEnvironment task_environment(
202 test::TaskEnvironment::TimeSource::MOCK_TIME, main_thread_type);
203
204 Receiver receiver;
205
206 {
207 DelayTimer timer(FROM_HERE, kTestDelay, &receiver, &Receiver::OnCalled);
208 timer.Reset();
209 }
210
211 // Because the timer was deleted, it will never fire.
212 task_environment.FastForwardBy(kTestDelay);
213 EXPECT_FALSE(receiver.WasCalled());
214 }
215
216 } // namespace
217
218 //-----------------------------------------------------------------------------
219 // Each test is run against each type of main thread. That way we are sure
220 // that timers work properly in all configurations.
221
222 class TimerTestWithThreadType
223 : public testing::TestWithParam<test::TaskEnvironment::MainThreadType> {};
224
TEST_P(TimerTestWithThreadType,OneShotTimers)225 TEST_P(TimerTestWithThreadType, OneShotTimers) {
226 RunTest_OneShotTimers(GetParam());
227 }
228
TEST_P(TimerTestWithThreadType,OneShotTimers_Cancel)229 TEST_P(TimerTestWithThreadType, OneShotTimers_Cancel) {
230 RunTest_OneShotTimers_Cancel(GetParam());
231 }
232
233 // If underline timer does not handle properly, we will crash or fail
234 // in full page heap environment.
TEST_P(TimerTestWithThreadType,OneShotSelfDeletingTimer)235 TEST_P(TimerTestWithThreadType, OneShotSelfDeletingTimer) {
236 RunTest_OneShotSelfDeletingTimer(GetParam());
237 }
238
TEST(TimerTest,OneShotTimer_CustomTaskRunner)239 TEST(TimerTest, OneShotTimer_CustomTaskRunner) {
240 auto task_runner = base::MakeRefCounted<TestSimpleTaskRunner>();
241
242 OneShotTimer timer;
243
244 bool task_ran = false;
245
246 // The timer will use the TestSimpleTaskRunner to schedule its delays.
247 timer.SetTaskRunner(task_runner);
248 timer.Start(FROM_HERE, Days(1),
249 BindLambdaForTesting([&]() { task_ran = true; }));
250
251 EXPECT_FALSE(task_ran);
252 EXPECT_TRUE(task_runner->HasPendingTask());
253
254 task_runner->RunPendingTasks();
255
256 EXPECT_TRUE(task_ran);
257 }
258
TEST(TimerTest,OneShotTimerWithTickClock)259 TEST(TimerTest, OneShotTimerWithTickClock) {
260 test::TaskEnvironment task_environment(
261 test::TaskEnvironment::TimeSource::MOCK_TIME);
262 Receiver receiver;
263 OneShotTimer timer(task_environment.GetMockTickClock());
264 timer.Start(FROM_HERE, kTestDelay,
265 BindOnce(&Receiver::OnCalled, Unretained(&receiver)));
266 task_environment.FastForwardBy(kTestDelay);
267 EXPECT_TRUE(receiver.WasCalled());
268 EXPECT_FALSE(timer.IsRunning());
269 }
270
TEST_P(TimerTestWithThreadType,RepeatingTimer)271 TEST_P(TimerTestWithThreadType, RepeatingTimer) {
272 RunTest_RepeatingTimer(GetParam(), kTestDelay);
273 }
274
TEST_P(TimerTestWithThreadType,RepeatingTimer_Cancel)275 TEST_P(TimerTestWithThreadType, RepeatingTimer_Cancel) {
276 RunTest_RepeatingTimer_Cancel(GetParam(), kTestDelay);
277 }
278
TEST_P(TimerTestWithThreadType,RepeatingTimerZeroDelay)279 TEST_P(TimerTestWithThreadType, RepeatingTimerZeroDelay) {
280 RunTest_RepeatingTimer(GetParam(), Seconds(0));
281 }
282
TEST_P(TimerTestWithThreadType,RepeatingTimerZeroDelay_Cancel)283 TEST_P(TimerTestWithThreadType, RepeatingTimerZeroDelay_Cancel) {
284 RunTest_RepeatingTimer_Cancel(GetParam(), Seconds(0));
285 }
286
TEST(TimerTest,RepeatingTimerWithTickClock)287 TEST(TimerTest, RepeatingTimerWithTickClock) {
288 test::TaskEnvironment task_environment(
289 test::TaskEnvironment::TimeSource::MOCK_TIME);
290 Receiver receiver;
291 const int expected_times_called = 10;
292 RepeatingTimer timer(task_environment.GetMockTickClock());
293 timer.Start(FROM_HERE, kTestDelay,
294 BindRepeating(&Receiver::OnCalled, Unretained(&receiver)));
295 task_environment.FastForwardBy(expected_times_called * kTestDelay);
296 timer.Stop();
297 EXPECT_EQ(expected_times_called, receiver.TimesCalled());
298 }
299
TEST_P(TimerTestWithThreadType,DelayTimer_NoCall)300 TEST_P(TimerTestWithThreadType, DelayTimer_NoCall) {
301 RunTest_DelayTimer_NoCall(GetParam());
302 }
303
TEST_P(TimerTestWithThreadType,DelayTimer_OneCall)304 TEST_P(TimerTestWithThreadType, DelayTimer_OneCall) {
305 RunTest_DelayTimer_OneCall(GetParam());
306 }
307
TEST_P(TimerTestWithThreadType,DelayTimer_Reset)308 TEST_P(TimerTestWithThreadType, DelayTimer_Reset) {
309 RunTest_DelayTimer_Reset(GetParam());
310 }
311
TEST_P(TimerTestWithThreadType,DelayTimer_Deleted)312 TEST_P(TimerTestWithThreadType, DelayTimer_Deleted) {
313 RunTest_DelayTimer_Deleted(GetParam());
314 }
315
TEST(TimerTest,DelayTimerWithTickClock)316 TEST(TimerTest, DelayTimerWithTickClock) {
317 test::TaskEnvironment task_environment(
318 test::TaskEnvironment::TimeSource::MOCK_TIME);
319 Receiver receiver;
320 DelayTimer timer(FROM_HERE, kTestDelay, &receiver, &Receiver::OnCalled,
321 task_environment.GetMockTickClock());
322 task_environment.FastForwardBy(kTestDelay - Microseconds(1));
323 EXPECT_FALSE(receiver.WasCalled());
324 timer.Reset();
325 task_environment.FastForwardBy(kTestDelay - Microseconds(1));
326 EXPECT_FALSE(receiver.WasCalled());
327 timer.Reset();
328 task_environment.FastForwardBy(kTestDelay);
329 EXPECT_TRUE(receiver.WasCalled());
330 }
331
TEST(TimerTest,TaskEnvironmentShutdown)332 TEST(TimerTest, TaskEnvironmentShutdown) {
333 // This test is designed to verify that shutdown of the
334 // message loop does not cause crashes if there were pending
335 // timers not yet fired. It may only trigger exceptions
336 // if debug heap checking is enabled.
337 Receiver receiver;
338 OneShotTimer timer;
339
340 {
341 test::TaskEnvironment task_environment;
342 timer.Start(FROM_HERE, kTestDelay,
343 BindOnce(&Receiver::OnCalled, Unretained(&receiver)));
344 } // Task environment destructs by falling out of scope.
345
346 EXPECT_FALSE(receiver.WasCalled());
347 // Timer destruct. SHOULD NOT CRASH, of course.
348 }
349
TEST(TimerTest,TaskEnvironmentSelfOwningTimer)350 TEST(TimerTest, TaskEnvironmentSelfOwningTimer) {
351 // This test verifies that a timer does not cause crashes if
352 // |Timer::user_task_| owns the timer. The test may only trigger exceptions if
353 // debug heap checking is enabled.
354
355 auto timer = std::make_unique<OneShotTimer>();
356 auto* timer_ptr = timer.get();
357
358 test::TaskEnvironment task_environment(
359 test::TaskEnvironment::TimeSource::MOCK_TIME);
360
361 timer_ptr->Start(FROM_HERE, kTestDelay,
362 BindLambdaForTesting([timer = std::move(timer)]() {}));
363 // |Timer::user_task_| owns sole reference to |timer|. Both will be destroyed
364 // once the task ran. SHOULD NOT CRASH.
365 task_environment.FastForwardUntilNoTasksRemain();
366 }
367
TEST(TimerTest,TaskEnvironmentSelfOwningTimerStopped)368 TEST(TimerTest, TaskEnvironmentSelfOwningTimerStopped) {
369 // This test verifies that a timer does not cause crashes when stopped if
370 // |Timer::user_task_| owns the timer. The test may only trigger exceptions if
371 // debug heap checking is enabled.
372
373 auto timer = std::make_unique<OneShotTimer>();
374 auto* timer_ptr = timer.get();
375
376 test::TaskEnvironment task_environment(
377 test::TaskEnvironment::TimeSource::MOCK_TIME);
378
379 timer_ptr->Start(FROM_HERE, kTestDelay,
380 BindLambdaForTesting([timer = std::move(timer)]() {
381 // Stop destroys |Timer::user_task_| which owns sole
382 // reference to |timer|. SHOULD NOT CRASH.
383 timer->Stop();
384 }));
385 task_environment.FastForwardUntilNoTasksRemain();
386 }
387
TEST(TimerTest,NonRepeatIsRunning)388 TEST(TimerTest, NonRepeatIsRunning) {
389 {
390 test::TaskEnvironment task_environment;
391 OneShotTimer timer;
392 EXPECT_FALSE(timer.IsRunning());
393 timer.Start(FROM_HERE, kTestDelay, DoNothing());
394 EXPECT_TRUE(timer.IsRunning());
395 timer.Stop();
396 EXPECT_FALSE(timer.IsRunning());
397 }
398
399 {
400 RetainingOneShotTimer timer;
401 test::TaskEnvironment task_environment;
402 EXPECT_FALSE(timer.IsRunning());
403 timer.Start(FROM_HERE, kTestDelay, DoNothing());
404 EXPECT_TRUE(timer.IsRunning());
405 timer.Stop();
406 EXPECT_FALSE(timer.IsRunning());
407 ASSERT_FALSE(timer.user_task().is_null());
408 timer.Reset();
409 EXPECT_TRUE(timer.IsRunning());
410 }
411 }
412
TEST(TimerTest,NonRepeatTaskEnvironmentDeath)413 TEST(TimerTest, NonRepeatTaskEnvironmentDeath) {
414 OneShotTimer timer;
415 {
416 test::TaskEnvironment task_environment;
417 EXPECT_FALSE(timer.IsRunning());
418 timer.Start(FROM_HERE, kTestDelay, DoNothing());
419 EXPECT_TRUE(timer.IsRunning());
420 }
421 EXPECT_FALSE(timer.IsRunning());
422 }
423
TEST(TimerTest,RetainRepeatIsRunning)424 TEST(TimerTest, RetainRepeatIsRunning) {
425 test::TaskEnvironment task_environment;
426 RepeatingTimer timer(FROM_HERE, kTestDelay, DoNothing());
427 EXPECT_FALSE(timer.IsRunning());
428 timer.Reset();
429 EXPECT_TRUE(timer.IsRunning());
430 timer.Stop();
431 EXPECT_FALSE(timer.IsRunning());
432 timer.Reset();
433 EXPECT_TRUE(timer.IsRunning());
434 }
435
TEST(TimerTest,RetainNonRepeatIsRunning)436 TEST(TimerTest, RetainNonRepeatIsRunning) {
437 test::TaskEnvironment task_environment;
438 RetainingOneShotTimer timer(FROM_HERE, kTestDelay, DoNothing());
439 EXPECT_FALSE(timer.IsRunning());
440 timer.Reset();
441 EXPECT_TRUE(timer.IsRunning());
442 timer.Stop();
443 EXPECT_FALSE(timer.IsRunning());
444 timer.Reset();
445 EXPECT_TRUE(timer.IsRunning());
446 }
447
448 //-----------------------------------------------------------------------------
449
TEST(TimerTest,ContinuationStopStart)450 TEST(TimerTest, ContinuationStopStart) {
451 test::TaskEnvironment task_environment(
452 test::TaskEnvironment::TimeSource::MOCK_TIME);
453
454 Receiver receiver1;
455 Receiver receiver2;
456 OneShotTimer timer;
457 timer.Start(FROM_HERE, kTestDelay,
458 BindOnce(&Receiver::OnCalled, Unretained(&receiver1)));
459 timer.Stop();
460 timer.Start(FROM_HERE, kLongTestDelay,
461 BindOnce(&Receiver::OnCalled, Unretained(&receiver2)));
462 task_environment.FastForwardBy(kLongTestDelay);
463 EXPECT_FALSE(receiver1.WasCalled());
464 EXPECT_TRUE(receiver2.WasCalled());
465 }
466
TEST(TimerTest,ContinuationReset)467 TEST(TimerTest, ContinuationReset) {
468 test::TaskEnvironment task_environment(
469 test::TaskEnvironment::TimeSource::MOCK_TIME);
470
471 Receiver receiver;
472 OneShotTimer timer;
473 timer.Start(FROM_HERE, kTestDelay,
474 BindOnce(&Receiver::OnCalled, Unretained(&receiver)));
475 timer.Reset();
476 // // Since Reset happened before task ran, the user_task must not be
477 // cleared: ASSERT_FALSE(timer.user_task().is_null());
478 task_environment.FastForwardBy(kTestDelay);
479 EXPECT_TRUE(receiver.WasCalled());
480 }
481
TEST(TimerTest,AbandonedTaskIsCancelled)482 TEST(TimerTest, AbandonedTaskIsCancelled) {
483 test::TaskEnvironment task_environment(
484 test::TaskEnvironment::TimeSource::MOCK_TIME);
485 OneShotTimer timer;
486
487 // Start a timer. There will be a pending task on the current sequence.
488 timer.Start(FROM_HERE, kTestDelay, base::DoNothing());
489 EXPECT_EQ(1u, task_environment.GetPendingMainThreadTaskCount());
490
491 // After AbandonAndStop(), the task is correctly treated as cancelled.
492 timer.AbandonAndStop();
493 EXPECT_EQ(0u, task_environment.GetPendingMainThreadTaskCount());
494 EXPECT_FALSE(timer.IsRunning());
495 }
496
TEST(TimerTest,DeadlineTimer)497 TEST(TimerTest, DeadlineTimer) {
498 test::TaskEnvironment task_environment(
499 test::TaskEnvironment::TimeSource::MOCK_TIME);
500 RunLoop run_loop;
501 DeadlineTimer timer;
502 TimeTicks start = TimeTicks::Now();
503
504 timer.Start(FROM_HERE, start + Seconds(5), run_loop.QuitClosure());
505 run_loop.Run();
506 EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
507 }
508
TEST(TimerTest,DeadlineTimerCancel)509 TEST(TimerTest, DeadlineTimerCancel) {
510 test::TaskEnvironment task_environment(
511 test::TaskEnvironment::TimeSource::MOCK_TIME);
512 RunLoop run_loop;
513 DeadlineTimer timer;
514 TimeTicks start = TimeTicks::Now();
515
516 MockRepeatingCallback<void()> callback;
517 timer.Start(FROM_HERE, start + Seconds(5), callback.Get());
518
519 EXPECT_CALL(callback, Run()).Times(0);
520 timer.Stop();
521 task_environment.FastForwardBy(Seconds(5));
522 EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
523 }
524
TEST(TimerTest,DeadlineTimerTaskDestructed)525 TEST(TimerTest, DeadlineTimerTaskDestructed) {
526 test::TaskEnvironment task_environment(
527 test::TaskEnvironment::TimeSource::MOCK_TIME);
528 RunLoop run_loop;
529 DeadlineTimer timer;
530 TimeTicks start = TimeTicks::Now();
531
532 MockRepeatingCallback<void()> destructed;
533 ScopedClosureRunner scoped_closure(destructed.Get());
534 timer.Start(FROM_HERE, start + Seconds(5),
535 BindOnce([](ScopedClosureRunner) {}, std::move(scoped_closure)));
536
537 EXPECT_CALL(destructed, Run());
538 timer.Stop();
539 testing::Mock::VerifyAndClearExpectations(&destructed);
540 }
541
TEST(TimerTest,DeadlineTimerStartTwice)542 TEST(TimerTest, DeadlineTimerStartTwice) {
543 test::TaskEnvironment task_environment(
544 test::TaskEnvironment::TimeSource::MOCK_TIME);
545 DeadlineTimer timer;
546 TimeTicks start = TimeTicks::Now();
547
548 RunLoop run_loop;
549 timer.Start(FROM_HERE, start + Seconds(5), run_loop.QuitClosure());
550 timer.Start(FROM_HERE, start + Seconds(10), run_loop.QuitClosure());
551 run_loop.Run();
552 EXPECT_EQ(start + Seconds(10), TimeTicks::Now());
553 }
554
TEST(TimerTest,MetronomeTimer)555 TEST(TimerTest, MetronomeTimer) {
556 test::TaskEnvironment task_environment(
557 test::TaskEnvironment::TimeSource::MOCK_TIME);
558 MetronomeTimer timer;
559 TimeTicks start = TimeTicks::Now();
560
561 // Ensure the run_loop.Run() below doesn't straddle over multiple ticks.
562 task_environment.AdvanceClock(
563 start.SnappedToNextTick(TimeTicks(), Seconds(5)) - start);
564 start = TimeTicks::Now();
565
566 RunLoop run_loop;
567 timer.Start(FROM_HERE, Seconds(5), run_loop.QuitClosure());
568 run_loop.Run();
569 EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
570 }
571
TEST(TimerTest,MetronomeTimerCustomPhase)572 TEST(TimerTest, MetronomeTimerCustomPhase) {
573 test::TaskEnvironment task_environment(
574 test::TaskEnvironment::TimeSource::MOCK_TIME);
575 RunLoop run_loop;
576 MetronomeTimer timer;
577 TimeTicks start = TimeTicks::Now();
578
579 timer.Start(FROM_HERE, Seconds(5), run_loop.QuitClosure(), start);
580 run_loop.Run();
581 EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
582 }
583
TEST(TimerTest,MetronomeTimerReset)584 TEST(TimerTest, MetronomeTimerReset) {
585 test::TaskEnvironment task_environment(
586 test::TaskEnvironment::TimeSource::MOCK_TIME);
587 RunLoop run_loop;
588 TimeTicks start = TimeTicks::Now();
589 MetronomeTimer timer(FROM_HERE, Seconds(5), run_loop.QuitClosure(), start);
590
591 timer.Reset();
592 run_loop.Run();
593 EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
594 }
595
TEST(TimerTest,MetronomeTimerStartTwice)596 TEST(TimerTest, MetronomeTimerStartTwice) {
597 test::TaskEnvironment task_environment(
598 test::TaskEnvironment::TimeSource::MOCK_TIME);
599 MetronomeTimer timer;
600 TimeTicks start = TimeTicks::Now();
601
602 {
603 RunLoop run_loop;
604 timer.Start(FROM_HERE, Seconds(4), run_loop.QuitClosure(), start);
605 run_loop.Run();
606 }
607 EXPECT_EQ(start + Seconds(4), TimeTicks::Now());
608
609 {
610 RunLoop run_loop;
611 timer.Start(FROM_HERE, Seconds(2), run_loop.QuitClosure(), start);
612 run_loop.Run();
613 }
614 EXPECT_EQ(start + Seconds(6), TimeTicks::Now());
615 }
616
TEST(TimerTest,MetronomeTimerMultiple)617 TEST(TimerTest, MetronomeTimerMultiple) {
618 test::TaskEnvironment task_environment(
619 test::TaskEnvironment::TimeSource::MOCK_TIME);
620 MetronomeTimer timer;
621 TimeTicks start = TimeTicks::Now();
622
623 // Ensure the subsequent FastForwardBy() don't straddle over multiple ticks.
624 task_environment.AdvanceClock(
625 start.SnappedToNextTick(TimeTicks(), Seconds(5)) - start);
626
627 MockRepeatingCallback<void()> callback;
628 timer.Start(FROM_HERE, Seconds(5), callback.Get());
629
630 // The first tick is skipped because it is too close. Ticks at 5s and 10s.
631 EXPECT_CALL(callback, Run()).Times(2);
632 task_environment.FastForwardBy(Seconds(10));
633
634 EXPECT_CALL(callback, Run()).Times(2);
635 // Ticks at 15s and 25s, while 20s is missed.
636 task_environment.AdvanceClock(Seconds(12));
637 task_environment.FastForwardBy(Seconds(3));
638 }
639
TEST(TimerTest,MetronomeTimerCancel)640 TEST(TimerTest, MetronomeTimerCancel) {
641 test::TaskEnvironment task_environment(
642 test::TaskEnvironment::TimeSource::MOCK_TIME);
643 RunLoop run_loop;
644 MetronomeTimer timer;
645 TimeTicks start = TimeTicks::Now();
646
647 MockRepeatingCallback<void()> callback;
648 timer.Start(FROM_HERE, Seconds(5), callback.Get());
649
650 EXPECT_CALL(callback, Run()).Times(0);
651 timer.Stop();
652 task_environment.FastForwardBy(Seconds(5));
653 EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
654 }
655
656 INSTANTIATE_TEST_SUITE_P(All,
657 TimerTestWithThreadType,
658 testing::ValuesIn(testing_main_threads));
659
660 } // namespace base
661