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