blob: 82b92ef395138b1d26865b58f4874a62053914f2 [file] [log] [blame]
Victor Boivie6fa0cfa2021-03-30 22:54:41 +02001/*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#include "net/dcsctp/timer/timer.h"
11
12#include <memory>
13
14#include "absl/types/optional.h"
15#include "net/dcsctp/public/timeout.h"
16#include "net/dcsctp/timer/fake_timeout.h"
17#include "rtc_base/gunit.h"
18#include "test/gmock.h"
19
20namespace dcsctp {
21namespace {
22using ::testing::Return;
23
24class TimerTest : public testing::Test {
25 protected:
26 TimerTest()
27 : timeout_manager_([this]() { return now_; }),
28 manager_([this]() { return timeout_manager_.CreateTimeout(); }) {
29 ON_CALL(on_expired_, Call).WillByDefault(Return(absl::nullopt));
30 }
31
32 void AdvanceTimeAndRunTimers(DurationMs duration) {
Victor Boivie9861f962021-04-13 14:52:53 +020033 now_ = now_ + duration;
Victor Boivie6fa0cfa2021-03-30 22:54:41 +020034
Victor Boivie1d2fa9a2021-05-05 14:00:50 +020035 for (;;) {
36 absl::optional<TimeoutID> timeout_id =
37 timeout_manager_.GetNextExpiredTimeout();
38 if (!timeout_id.has_value()) {
39 break;
40 }
41 manager_.HandleTimeout(*timeout_id);
Victor Boivie6fa0cfa2021-03-30 22:54:41 +020042 }
43 }
44
45 TimeMs now_ = TimeMs(0);
46 FakeTimeoutManager timeout_manager_;
47 TimerManager manager_;
48 testing::MockFunction<absl::optional<DurationMs>()> on_expired_;
49};
50
51TEST_F(TimerTest, TimerIsInitiallyStopped) {
52 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
53 "t1", on_expired_.AsStdFunction(),
54 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
55
56 EXPECT_FALSE(t1->is_running());
57}
58
59TEST_F(TimerTest, TimerExpiresAtGivenTime) {
60 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
61 "t1", on_expired_.AsStdFunction(),
62 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
63
64 EXPECT_CALL(on_expired_, Call).Times(0);
65 t1->Start();
66 EXPECT_TRUE(t1->is_running());
67
68 AdvanceTimeAndRunTimers(DurationMs(4000));
69
70 EXPECT_CALL(on_expired_, Call).Times(1);
71 AdvanceTimeAndRunTimers(DurationMs(1000));
72}
73
74TEST_F(TimerTest, TimerReschedulesAfterExpiredWithFixedBackoff) {
75 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
76 "t1", on_expired_.AsStdFunction(),
77 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
78
79 EXPECT_CALL(on_expired_, Call).Times(0);
80 t1->Start();
81 EXPECT_EQ(t1->expiration_count(), 0);
82
83 AdvanceTimeAndRunTimers(DurationMs(4000));
84
85 // Fire first time
86 EXPECT_CALL(on_expired_, Call).Times(1);
87 AdvanceTimeAndRunTimers(DurationMs(1000));
88 EXPECT_TRUE(t1->is_running());
89 EXPECT_EQ(t1->expiration_count(), 1);
90
91 EXPECT_CALL(on_expired_, Call).Times(0);
92 AdvanceTimeAndRunTimers(DurationMs(4000));
93
94 // Second time
95 EXPECT_CALL(on_expired_, Call).Times(1);
96 AdvanceTimeAndRunTimers(DurationMs(1000));
97 EXPECT_TRUE(t1->is_running());
98 EXPECT_EQ(t1->expiration_count(), 2);
99
100 EXPECT_CALL(on_expired_, Call).Times(0);
101 AdvanceTimeAndRunTimers(DurationMs(4000));
102
103 // Third time
104 EXPECT_CALL(on_expired_, Call).Times(1);
105 AdvanceTimeAndRunTimers(DurationMs(1000));
106 EXPECT_TRUE(t1->is_running());
107 EXPECT_EQ(t1->expiration_count(), 3);
108}
109
110TEST_F(TimerTest, TimerWithNoRestarts) {
111 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
112 "t1", on_expired_.AsStdFunction(),
113 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
114 /*max_restart=*/0));
115
116 EXPECT_CALL(on_expired_, Call).Times(0);
117 t1->Start();
118 AdvanceTimeAndRunTimers(DurationMs(4000));
119
120 // Fire first time
121 EXPECT_CALL(on_expired_, Call).Times(1);
122 AdvanceTimeAndRunTimers(DurationMs(1000));
123
124 EXPECT_FALSE(t1->is_running());
125
126 // Second time - shouldn't fire
127 EXPECT_CALL(on_expired_, Call).Times(0);
128 AdvanceTimeAndRunTimers(DurationMs(5000));
129 EXPECT_FALSE(t1->is_running());
130}
131
132TEST_F(TimerTest, TimerWithOneRestart) {
133 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
134 "t1", on_expired_.AsStdFunction(),
135 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
136 /*max_restart=*/1));
137
138 EXPECT_CALL(on_expired_, Call).Times(0);
139 t1->Start();
140 AdvanceTimeAndRunTimers(DurationMs(4000));
141
142 // Fire first time
143 EXPECT_CALL(on_expired_, Call).Times(1);
144 AdvanceTimeAndRunTimers(DurationMs(1000));
145 EXPECT_TRUE(t1->is_running());
146
147 EXPECT_CALL(on_expired_, Call).Times(0);
148 AdvanceTimeAndRunTimers(DurationMs(4000));
149
150 // Second time - max restart limit reached.
151 EXPECT_CALL(on_expired_, Call).Times(1);
152 AdvanceTimeAndRunTimers(DurationMs(1000));
153 EXPECT_FALSE(t1->is_running());
154
155 // Third time - should not fire.
156 EXPECT_CALL(on_expired_, Call).Times(0);
157 AdvanceTimeAndRunTimers(DurationMs(5000));
158 EXPECT_FALSE(t1->is_running());
159}
160
161TEST_F(TimerTest, TimerWithTwoRestart) {
162 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
163 "t1", on_expired_.AsStdFunction(),
164 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
165 /*max_restart=*/2));
166
167 EXPECT_CALL(on_expired_, Call).Times(0);
168 t1->Start();
169 AdvanceTimeAndRunTimers(DurationMs(4000));
170
171 // Fire first time
172 EXPECT_CALL(on_expired_, Call).Times(1);
173 AdvanceTimeAndRunTimers(DurationMs(1000));
174 EXPECT_TRUE(t1->is_running());
175
176 EXPECT_CALL(on_expired_, Call).Times(0);
177 AdvanceTimeAndRunTimers(DurationMs(4000));
178
179 // Second time
180 EXPECT_CALL(on_expired_, Call).Times(1);
181 AdvanceTimeAndRunTimers(DurationMs(1000));
182 EXPECT_TRUE(t1->is_running());
183
184 EXPECT_CALL(on_expired_, Call).Times(0);
185 AdvanceTimeAndRunTimers(DurationMs(4000));
186
187 // Third time
188 EXPECT_CALL(on_expired_, Call).Times(1);
189 AdvanceTimeAndRunTimers(DurationMs(1000));
190 EXPECT_FALSE(t1->is_running());
191}
192
193TEST_F(TimerTest, TimerWithExponentialBackoff) {
194 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
195 "t1", on_expired_.AsStdFunction(),
196 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
197
198 t1->Start();
199
200 // Fire first time at 5 seconds
201 EXPECT_CALL(on_expired_, Call).Times(1);
202 AdvanceTimeAndRunTimers(DurationMs(5000));
203
204 // Second time at 5*2^1 = 10 seconds later.
205 EXPECT_CALL(on_expired_, Call).Times(0);
206 AdvanceTimeAndRunTimers(DurationMs(9000));
207 EXPECT_CALL(on_expired_, Call).Times(1);
208 AdvanceTimeAndRunTimers(DurationMs(1000));
209
210 // Third time at 5*2^2 = 20 seconds later.
211 EXPECT_CALL(on_expired_, Call).Times(0);
212 AdvanceTimeAndRunTimers(DurationMs(19000));
213 EXPECT_CALL(on_expired_, Call).Times(1);
214 AdvanceTimeAndRunTimers(DurationMs(1000));
215
216 // Fourth time at 5*2^3 = 40 seconds later.
217 EXPECT_CALL(on_expired_, Call).Times(0);
218 AdvanceTimeAndRunTimers(DurationMs(39000));
219 EXPECT_CALL(on_expired_, Call).Times(1);
220 AdvanceTimeAndRunTimers(DurationMs(1000));
221}
222
223TEST_F(TimerTest, StartTimerWillStopAndStart) {
224 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
225 "t1", on_expired_.AsStdFunction(),
226 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
227
228 t1->Start();
229
230 AdvanceTimeAndRunTimers(DurationMs(3000));
231
232 t1->Start();
233
234 EXPECT_CALL(on_expired_, Call).Times(0);
235 AdvanceTimeAndRunTimers(DurationMs(2000));
236
237 EXPECT_CALL(on_expired_, Call).Times(1);
238 AdvanceTimeAndRunTimers(DurationMs(3000));
239}
240
241TEST_F(TimerTest, ExpirationCounterWillResetIfStopped) {
242 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
243 "t1", on_expired_.AsStdFunction(),
244 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
245
246 t1->Start();
247
248 // Fire first time at 5 seconds
249 EXPECT_CALL(on_expired_, Call).Times(1);
250 AdvanceTimeAndRunTimers(DurationMs(5000));
251 EXPECT_EQ(t1->expiration_count(), 1);
252
253 // Second time at 5*2^1 = 10 seconds later.
254 EXPECT_CALL(on_expired_, Call).Times(0);
255 AdvanceTimeAndRunTimers(DurationMs(9000));
256 EXPECT_CALL(on_expired_, Call).Times(1);
257 AdvanceTimeAndRunTimers(DurationMs(1000));
258 EXPECT_EQ(t1->expiration_count(), 2);
259
260 t1->Start();
261 EXPECT_EQ(t1->expiration_count(), 0);
262
263 // Third time at 5*2^0 = 5 seconds later.
264 EXPECT_CALL(on_expired_, Call).Times(0);
265 AdvanceTimeAndRunTimers(DurationMs(4000));
266 EXPECT_CALL(on_expired_, Call).Times(1);
267 AdvanceTimeAndRunTimers(DurationMs(1000));
268 EXPECT_EQ(t1->expiration_count(), 1);
269}
270
271TEST_F(TimerTest, StopTimerWillMakeItNotExpire) {
272 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
273 "t1", on_expired_.AsStdFunction(),
274 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
275
276 t1->Start();
277 EXPECT_TRUE(t1->is_running());
278
279 EXPECT_CALL(on_expired_, Call).Times(0);
280 AdvanceTimeAndRunTimers(DurationMs(4000));
281 t1->Stop();
282 EXPECT_FALSE(t1->is_running());
283
284 EXPECT_CALL(on_expired_, Call).Times(0);
285 AdvanceTimeAndRunTimers(DurationMs(1000));
286}
287
288TEST_F(TimerTest, ReturningNewDurationWhenExpired) {
289 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
290 "t1", on_expired_.AsStdFunction(),
291 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
292
293 EXPECT_CALL(on_expired_, Call).Times(0);
294 t1->Start();
295 EXPECT_EQ(t1->duration(), DurationMs(5000));
296
297 AdvanceTimeAndRunTimers(DurationMs(4000));
298
299 // Fire first time
300 EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(2000)));
301 AdvanceTimeAndRunTimers(DurationMs(1000));
302 EXPECT_EQ(t1->duration(), DurationMs(2000));
303
304 EXPECT_CALL(on_expired_, Call).Times(0);
305 AdvanceTimeAndRunTimers(DurationMs(1000));
306
307 // Second time
308 EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(10000)));
309 AdvanceTimeAndRunTimers(DurationMs(1000));
310 EXPECT_EQ(t1->duration(), DurationMs(10000));
311
312 EXPECT_CALL(on_expired_, Call).Times(0);
313 AdvanceTimeAndRunTimers(DurationMs(9000));
314 EXPECT_CALL(on_expired_, Call).Times(1);
315 AdvanceTimeAndRunTimers(DurationMs(1000));
316}
317
Victor Boivie5d3bda52021-04-12 21:59:19 +0200318TEST_F(TimerTest, TimersHaveMaximumDuration) {
319 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
320 "t1", on_expired_.AsStdFunction(),
321 TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential));
322
323 t1->set_duration(DurationMs(2 * *Timer::kMaxTimerDuration));
324 EXPECT_EQ(t1->duration(), Timer::kMaxTimerDuration);
325}
326
327TEST_F(TimerTest, TimersHaveMaximumBackoffDuration) {
328 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
329 "t1", on_expired_.AsStdFunction(),
330 TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential));
331
332 t1->Start();
333
334 int max_exponent = static_cast<int>(log2(*Timer::kMaxTimerDuration / 1000));
335 for (int i = 0; i < max_exponent; ++i) {
336 EXPECT_CALL(on_expired_, Call).Times(1);
337 AdvanceTimeAndRunTimers(DurationMs(1000 * (1 << i)));
338 }
339
340 // Reached the maximum duration.
341 EXPECT_CALL(on_expired_, Call).Times(1);
342 AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
343
344 EXPECT_CALL(on_expired_, Call).Times(1);
345 AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
346
347 EXPECT_CALL(on_expired_, Call).Times(1);
348 AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
349
350 EXPECT_CALL(on_expired_, Call).Times(1);
351 AdvanceTimeAndRunTimers(Timer::kMaxTimerDuration);
352}
353
Victor Boivie6fa0cfa2021-03-30 22:54:41 +0200354} // namespace
355} // namespace dcsctp