1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/timer/timer.h"
11*d9f75844SAndroid Build Coastguard Worker
12*d9f75844SAndroid Build Coastguard Worker #include <memory>
13*d9f75844SAndroid Build Coastguard Worker
14*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
15*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
16*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/public/timeout.h"
17*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/timer/fake_timeout.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
19*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker namespace dcsctp {
22*d9f75844SAndroid Build Coastguard Worker namespace {
23*d9f75844SAndroid Build Coastguard Worker using ::testing::Return;
24*d9f75844SAndroid Build Coastguard Worker
25*d9f75844SAndroid Build Coastguard Worker class TimerTest : public testing::Test {
26*d9f75844SAndroid Build Coastguard Worker protected:
TimerTest()27*d9f75844SAndroid Build Coastguard Worker TimerTest()
28*d9f75844SAndroid Build Coastguard Worker : timeout_manager_([this]() { return now_; }),
__anon4d5868470302(webrtc::TaskQueueBase::DelayPrecision precision) 29*d9f75844SAndroid Build Coastguard Worker manager_([this](webrtc::TaskQueueBase::DelayPrecision precision) {
30*d9f75844SAndroid Build Coastguard Worker return timeout_manager_.CreateTimeout(precision);
31*d9f75844SAndroid Build Coastguard Worker }) {
32*d9f75844SAndroid Build Coastguard Worker ON_CALL(on_expired_, Call).WillByDefault(Return(absl::nullopt));
33*d9f75844SAndroid Build Coastguard Worker }
34*d9f75844SAndroid Build Coastguard Worker
AdvanceTimeAndRunTimers(DurationMs duration)35*d9f75844SAndroid Build Coastguard Worker void AdvanceTimeAndRunTimers(DurationMs duration) {
36*d9f75844SAndroid Build Coastguard Worker now_ = now_ + duration;
37*d9f75844SAndroid Build Coastguard Worker
38*d9f75844SAndroid Build Coastguard Worker for (;;) {
39*d9f75844SAndroid Build Coastguard Worker absl::optional<TimeoutID> timeout_id =
40*d9f75844SAndroid Build Coastguard Worker timeout_manager_.GetNextExpiredTimeout();
41*d9f75844SAndroid Build Coastguard Worker if (!timeout_id.has_value()) {
42*d9f75844SAndroid Build Coastguard Worker break;
43*d9f75844SAndroid Build Coastguard Worker }
44*d9f75844SAndroid Build Coastguard Worker manager_.HandleTimeout(*timeout_id);
45*d9f75844SAndroid Build Coastguard Worker }
46*d9f75844SAndroid Build Coastguard Worker }
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker TimeMs now_ = TimeMs(0);
49*d9f75844SAndroid Build Coastguard Worker FakeTimeoutManager timeout_manager_;
50*d9f75844SAndroid Build Coastguard Worker TimerManager manager_;
51*d9f75844SAndroid Build Coastguard Worker testing::MockFunction<absl::optional<DurationMs>()> on_expired_;
52*d9f75844SAndroid Build Coastguard Worker };
53*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerIsInitiallyStopped)54*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerIsInitiallyStopped) {
55*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
56*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
57*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
58*d9f75844SAndroid Build Coastguard Worker
59*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
60*d9f75844SAndroid Build Coastguard Worker }
61*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerExpiresAtGivenTime)62*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerExpiresAtGivenTime) {
63*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
64*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
65*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
66*d9f75844SAndroid Build Coastguard Worker
67*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
68*d9f75844SAndroid Build Coastguard Worker t1->Start();
69*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
70*d9f75844SAndroid Build Coastguard Worker
71*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
74*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerReschedulesAfterExpiredWithFixedBackoff)77*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerReschedulesAfterExpiredWithFixedBackoff) {
78*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
79*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
80*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
81*d9f75844SAndroid Build Coastguard Worker
82*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
83*d9f75844SAndroid Build Coastguard Worker t1->Start();
84*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 0);
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
87*d9f75844SAndroid Build Coastguard Worker
88*d9f75844SAndroid Build Coastguard Worker // Fire first time
89*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
90*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
91*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
92*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 1);
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
95*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
96*d9f75844SAndroid Build Coastguard Worker
97*d9f75844SAndroid Build Coastguard Worker // Second time
98*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
99*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
100*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
101*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 2);
102*d9f75844SAndroid Build Coastguard Worker
103*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
104*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker // Third time
107*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
108*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
109*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
110*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 3);
111*d9f75844SAndroid Build Coastguard Worker }
112*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerWithNoRestarts)113*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerWithNoRestarts) {
114*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
115*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
116*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
117*d9f75844SAndroid Build Coastguard Worker /*max_restart=*/0));
118*d9f75844SAndroid Build Coastguard Worker
119*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
120*d9f75844SAndroid Build Coastguard Worker t1->Start();
121*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
122*d9f75844SAndroid Build Coastguard Worker
123*d9f75844SAndroid Build Coastguard Worker // Fire first time
124*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
125*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
126*d9f75844SAndroid Build Coastguard Worker
127*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
128*d9f75844SAndroid Build Coastguard Worker
129*d9f75844SAndroid Build Coastguard Worker // Second time - shouldn't fire
130*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
131*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(5000));
132*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerWithOneRestart)135*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerWithOneRestart) {
136*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
137*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
138*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
139*d9f75844SAndroid Build Coastguard Worker /*max_restart=*/1));
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
142*d9f75844SAndroid Build Coastguard Worker t1->Start();
143*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
144*d9f75844SAndroid Build Coastguard Worker
145*d9f75844SAndroid Build Coastguard Worker // Fire first time
146*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
147*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
148*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
149*d9f75844SAndroid Build Coastguard Worker
150*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
151*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
152*d9f75844SAndroid Build Coastguard Worker
153*d9f75844SAndroid Build Coastguard Worker // Second time - max restart limit reached.
154*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
155*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
156*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
157*d9f75844SAndroid Build Coastguard Worker
158*d9f75844SAndroid Build Coastguard Worker // Third time - should not fire.
159*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
160*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(5000));
161*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
162*d9f75844SAndroid Build Coastguard Worker }
163*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerWithTwoRestart)164*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerWithTwoRestart) {
165*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
166*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
167*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
168*d9f75844SAndroid Build Coastguard Worker /*max_restart=*/2));
169*d9f75844SAndroid Build Coastguard Worker
170*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
171*d9f75844SAndroid Build Coastguard Worker t1->Start();
172*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
173*d9f75844SAndroid Build Coastguard Worker
174*d9f75844SAndroid Build Coastguard Worker // Fire first time
175*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
176*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
177*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
178*d9f75844SAndroid Build Coastguard Worker
179*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
180*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
181*d9f75844SAndroid Build Coastguard Worker
182*d9f75844SAndroid Build Coastguard Worker // Second time
183*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
184*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
185*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
186*d9f75844SAndroid Build Coastguard Worker
187*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
188*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
189*d9f75844SAndroid Build Coastguard Worker
190*d9f75844SAndroid Build Coastguard Worker // Third time
191*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
192*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
193*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerWithExponentialBackoff)196*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerWithExponentialBackoff) {
197*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
198*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
199*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
200*d9f75844SAndroid Build Coastguard Worker
201*d9f75844SAndroid Build Coastguard Worker t1->Start();
202*d9f75844SAndroid Build Coastguard Worker
203*d9f75844SAndroid Build Coastguard Worker // Fire first time at 5 seconds
204*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
205*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(5000));
206*d9f75844SAndroid Build Coastguard Worker
207*d9f75844SAndroid Build Coastguard Worker // Second time at 5*2^1 = 10 seconds later.
208*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
209*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(9000));
210*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
211*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
212*d9f75844SAndroid Build Coastguard Worker
213*d9f75844SAndroid Build Coastguard Worker // Third time at 5*2^2 = 20 seconds later.
214*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
215*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(19000));
216*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
217*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
218*d9f75844SAndroid Build Coastguard Worker
219*d9f75844SAndroid Build Coastguard Worker // Fourth time at 5*2^3 = 40 seconds later.
220*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
221*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(39000));
222*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
223*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
224*d9f75844SAndroid Build Coastguard Worker }
225*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,StartTimerWillStopAndStart)226*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, StartTimerWillStopAndStart) {
227*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
228*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
229*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
230*d9f75844SAndroid Build Coastguard Worker
231*d9f75844SAndroid Build Coastguard Worker t1->Start();
232*d9f75844SAndroid Build Coastguard Worker
233*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(3000));
234*d9f75844SAndroid Build Coastguard Worker
235*d9f75844SAndroid Build Coastguard Worker t1->Start();
236*d9f75844SAndroid Build Coastguard Worker
237*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
238*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(2000));
239*d9f75844SAndroid Build Coastguard Worker
240*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
241*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(3000));
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,ExpirationCounterWillResetIfStopped)244*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, ExpirationCounterWillResetIfStopped) {
245*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
246*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
247*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
248*d9f75844SAndroid Build Coastguard Worker
249*d9f75844SAndroid Build Coastguard Worker t1->Start();
250*d9f75844SAndroid Build Coastguard Worker
251*d9f75844SAndroid Build Coastguard Worker // Fire first time at 5 seconds
252*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
253*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(5000));
254*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 1);
255*d9f75844SAndroid Build Coastguard Worker
256*d9f75844SAndroid Build Coastguard Worker // Second time at 5*2^1 = 10 seconds later.
257*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
258*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(9000));
259*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
260*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
261*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 2);
262*d9f75844SAndroid Build Coastguard Worker
263*d9f75844SAndroid Build Coastguard Worker t1->Start();
264*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 0);
265*d9f75844SAndroid Build Coastguard Worker
266*d9f75844SAndroid Build Coastguard Worker // Third time at 5*2^0 = 5 seconds later.
267*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
268*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
269*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
270*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
271*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->expiration_count(), 1);
272*d9f75844SAndroid Build Coastguard Worker }
273*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,StopTimerWillMakeItNotExpire)274*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, StopTimerWillMakeItNotExpire) {
275*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
276*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
277*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
278*d9f75844SAndroid Build Coastguard Worker
279*d9f75844SAndroid Build Coastguard Worker t1->Start();
280*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
281*d9f75844SAndroid Build Coastguard Worker
282*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
283*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
284*d9f75844SAndroid Build Coastguard Worker t1->Stop();
285*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(t1->is_running());
286*d9f75844SAndroid Build Coastguard Worker
287*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
288*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
289*d9f75844SAndroid Build Coastguard Worker }
290*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,ReturningNewDurationWhenExpired)291*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, ReturningNewDurationWhenExpired) {
292*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
293*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
294*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
295*d9f75844SAndroid Build Coastguard Worker
296*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
297*d9f75844SAndroid Build Coastguard Worker t1->Start();
298*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->duration(), DurationMs(5000));
299*d9f75844SAndroid Build Coastguard Worker
300*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4000));
301*d9f75844SAndroid Build Coastguard Worker
302*d9f75844SAndroid Build Coastguard Worker // Fire first time
303*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(2000)));
304*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
305*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->duration(), DurationMs(2000));
306*d9f75844SAndroid Build Coastguard Worker
307*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
308*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker // Second time
311*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(10000)));
312*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
313*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->duration(), DurationMs(10000));
314*d9f75844SAndroid Build Coastguard Worker
315*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
316*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(9000));
317*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
318*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimersHaveMaximumDuration)321*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimersHaveMaximumDuration) {
322*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
323*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
324*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential));
325*d9f75844SAndroid Build Coastguard Worker
326*d9f75844SAndroid Build Coastguard Worker t1->set_duration(DurationMs(2 * *Timer::kMaxTimerDuration));
327*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(t1->duration(), Timer::kMaxTimerDuration);
328*d9f75844SAndroid Build Coastguard Worker }
329*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimersHaveMaximumBackoffDuration)330*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimersHaveMaximumBackoffDuration) {
331*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
332*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
333*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential));
334*d9f75844SAndroid Build Coastguard Worker
335*d9f75844SAndroid Build Coastguard Worker t1->Start();
336*d9f75844SAndroid Build Coastguard Worker
337*d9f75844SAndroid Build Coastguard Worker int max_exponent = static_cast<int>(log2(*Timer::kMaxTimerDuration / 1000));
338*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < max_exponent; ++i) {
339*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
340*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000 * (1 << i)));
341*d9f75844SAndroid Build Coastguard Worker }
342*d9f75844SAndroid Build Coastguard Worker
343*d9f75844SAndroid Build Coastguard Worker // Reached the maximum duration.
344*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
345*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
346*d9f75844SAndroid Build Coastguard Worker
347*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
348*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
349*d9f75844SAndroid Build Coastguard Worker
350*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
351*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
352*d9f75844SAndroid Build Coastguard Worker
353*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
354*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
355*d9f75844SAndroid Build Coastguard Worker }
356*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,TimerCanBeStartedFromWithinExpirationHandler)357*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, TimerCanBeStartedFromWithinExpirationHandler) {
358*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
359*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
360*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kFixed));
361*d9f75844SAndroid Build Coastguard Worker
362*d9f75844SAndroid Build Coastguard Worker t1->Start();
363*d9f75844SAndroid Build Coastguard Worker
364*d9f75844SAndroid Build Coastguard Worker // Start a timer, but don't return any new duration in callback.
365*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).WillOnce([&]() {
366*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
367*d9f75844SAndroid Build Coastguard Worker t1->set_duration(DurationMs(5000));
368*d9f75844SAndroid Build Coastguard Worker t1->Start();
369*d9f75844SAndroid Build Coastguard Worker return absl::nullopt;
370*d9f75844SAndroid Build Coastguard Worker });
371*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
372*d9f75844SAndroid Build Coastguard Worker
373*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
374*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4999));
375*d9f75844SAndroid Build Coastguard Worker
376*d9f75844SAndroid Build Coastguard Worker // Start a timer, and return any new duration in callback.
377*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).WillOnce([&]() {
378*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(t1->is_running());
379*d9f75844SAndroid Build Coastguard Worker t1->set_duration(DurationMs(5000));
380*d9f75844SAndroid Build Coastguard Worker t1->Start();
381*d9f75844SAndroid Build Coastguard Worker return absl::make_optional(DurationMs(8000));
382*d9f75844SAndroid Build Coastguard Worker });
383*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1));
384*d9f75844SAndroid Build Coastguard Worker
385*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
386*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(7999));
387*d9f75844SAndroid Build Coastguard Worker
388*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
389*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1));
390*d9f75844SAndroid Build Coastguard Worker }
391*d9f75844SAndroid Build Coastguard Worker
TEST_F(TimerTest,DurationStaysWithinMaxTimerBackOffDuration)392*d9f75844SAndroid Build Coastguard Worker TEST_F(TimerTest, DurationStaysWithinMaxTimerBackOffDuration) {
393*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timer> t1 = manager_.CreateTimer(
394*d9f75844SAndroid Build Coastguard Worker "t1", on_expired_.AsStdFunction(),
395*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential,
396*d9f75844SAndroid Build Coastguard Worker /*max_restarts=*/absl::nullopt, DurationMs(5000)));
397*d9f75844SAndroid Build Coastguard Worker
398*d9f75844SAndroid Build Coastguard Worker t1->Start();
399*d9f75844SAndroid Build Coastguard Worker
400*d9f75844SAndroid Build Coastguard Worker // Initial timeout, 1000 ms
401*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
402*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1000));
403*d9f75844SAndroid Build Coastguard Worker
404*d9f75844SAndroid Build Coastguard Worker // Exponential backoff -> 2000 ms
405*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
406*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1999));
407*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
408*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1));
409*d9f75844SAndroid Build Coastguard Worker
410*d9f75844SAndroid Build Coastguard Worker // Exponential backoff -> 4000 ms
411*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
412*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(3999));
413*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
414*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1));
415*d9f75844SAndroid Build Coastguard Worker
416*d9f75844SAndroid Build Coastguard Worker // Limited backoff -> 5000ms
417*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
418*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4999));
419*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
420*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1));
421*d9f75844SAndroid Build Coastguard Worker
422*d9f75844SAndroid Build Coastguard Worker // ... where it plateaus
423*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(0);
424*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(4999));
425*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(on_expired_, Call).Times(1);
426*d9f75844SAndroid Build Coastguard Worker AdvanceTimeAndRunTimers(DurationMs(1));
427*d9f75844SAndroid Build Coastguard Worker }
428*d9f75844SAndroid Build Coastguard Worker
TEST(TimerManagerTest,TimerManagerPassesPrecisionToCreateTimeoutMethod)429*d9f75844SAndroid Build Coastguard Worker TEST(TimerManagerTest, TimerManagerPassesPrecisionToCreateTimeoutMethod) {
430*d9f75844SAndroid Build Coastguard Worker FakeTimeoutManager timeout_manager([&]() { return TimeMs(0); });
431*d9f75844SAndroid Build Coastguard Worker absl::optional<webrtc::TaskQueueBase::DelayPrecision> create_timer_precison;
432*d9f75844SAndroid Build Coastguard Worker TimerManager manager([&](webrtc::TaskQueueBase::DelayPrecision precision) {
433*d9f75844SAndroid Build Coastguard Worker create_timer_precison = precision;
434*d9f75844SAndroid Build Coastguard Worker return timeout_manager.CreateTimeout(precision);
435*d9f75844SAndroid Build Coastguard Worker });
436*d9f75844SAndroid Build Coastguard Worker // Default TimerOptions.
437*d9f75844SAndroid Build Coastguard Worker manager.CreateTimer(
438*d9f75844SAndroid Build Coastguard Worker "test_timer", []() { return absl::optional<DurationMs>(); },
439*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(123)));
440*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(create_timer_precison, webrtc::TaskQueueBase::DelayPrecision::kLow);
441*d9f75844SAndroid Build Coastguard Worker // High precision TimerOptions.
442*d9f75844SAndroid Build Coastguard Worker manager.CreateTimer(
443*d9f75844SAndroid Build Coastguard Worker "test_timer", []() { return absl::optional<DurationMs>(); },
444*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(123), TimerBackoffAlgorithm::kExponential,
445*d9f75844SAndroid Build Coastguard Worker absl::nullopt, absl::nullopt,
446*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase::DelayPrecision::kHigh));
447*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(create_timer_precison,
448*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase::DelayPrecision::kHigh);
449*d9f75844SAndroid Build Coastguard Worker // Low precision TimerOptions.
450*d9f75844SAndroid Build Coastguard Worker manager.CreateTimer(
451*d9f75844SAndroid Build Coastguard Worker "test_timer", []() { return absl::optional<DurationMs>(); },
452*d9f75844SAndroid Build Coastguard Worker TimerOptions(DurationMs(123), TimerBackoffAlgorithm::kExponential,
453*d9f75844SAndroid Build Coastguard Worker absl::nullopt, absl::nullopt,
454*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase::DelayPrecision::kLow));
455*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(create_timer_precison, webrtc::TaskQueueBase::DelayPrecision::kLow);
456*d9f75844SAndroid Build Coastguard Worker }
457*d9f75844SAndroid Build Coastguard Worker
458*d9f75844SAndroid Build Coastguard Worker } // namespace
459*d9f75844SAndroid Build Coastguard Worker } // namespace dcsctp
460