blob: 263f535dab30b1d41a54e618a64ee10e4e5cd8bb [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) {
33 now_ = TimeMs(*now_ + *duration);
34
35 for (TimeoutID timeout_id : timeout_manager_.RunTimers()) {
36 manager_.HandleTimeout(timeout_id);
37 }
38 }
39
40 TimeMs now_ = TimeMs(0);
41 FakeTimeoutManager timeout_manager_;
42 TimerManager manager_;
43 testing::MockFunction<absl::optional<DurationMs>()> on_expired_;
44};
45
46TEST_F(TimerTest, TimerIsInitiallyStopped) {
47 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
48 "t1", on_expired_.AsStdFunction(),
49 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
50
51 EXPECT_FALSE(t1->is_running());
52}
53
54TEST_F(TimerTest, TimerExpiresAtGivenTime) {
55 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
56 "t1", on_expired_.AsStdFunction(),
57 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
58
59 EXPECT_CALL(on_expired_, Call).Times(0);
60 t1->Start();
61 EXPECT_TRUE(t1->is_running());
62
63 AdvanceTimeAndRunTimers(DurationMs(4000));
64
65 EXPECT_CALL(on_expired_, Call).Times(1);
66 AdvanceTimeAndRunTimers(DurationMs(1000));
67}
68
69TEST_F(TimerTest, TimerReschedulesAfterExpiredWithFixedBackoff) {
70 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
71 "t1", on_expired_.AsStdFunction(),
72 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
73
74 EXPECT_CALL(on_expired_, Call).Times(0);
75 t1->Start();
76 EXPECT_EQ(t1->expiration_count(), 0);
77
78 AdvanceTimeAndRunTimers(DurationMs(4000));
79
80 // Fire first time
81 EXPECT_CALL(on_expired_, Call).Times(1);
82 AdvanceTimeAndRunTimers(DurationMs(1000));
83 EXPECT_TRUE(t1->is_running());
84 EXPECT_EQ(t1->expiration_count(), 1);
85
86 EXPECT_CALL(on_expired_, Call).Times(0);
87 AdvanceTimeAndRunTimers(DurationMs(4000));
88
89 // Second time
90 EXPECT_CALL(on_expired_, Call).Times(1);
91 AdvanceTimeAndRunTimers(DurationMs(1000));
92 EXPECT_TRUE(t1->is_running());
93 EXPECT_EQ(t1->expiration_count(), 2);
94
95 EXPECT_CALL(on_expired_, Call).Times(0);
96 AdvanceTimeAndRunTimers(DurationMs(4000));
97
98 // Third time
99 EXPECT_CALL(on_expired_, Call).Times(1);
100 AdvanceTimeAndRunTimers(DurationMs(1000));
101 EXPECT_TRUE(t1->is_running());
102 EXPECT_EQ(t1->expiration_count(), 3);
103}
104
105TEST_F(TimerTest, TimerWithNoRestarts) {
106 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
107 "t1", on_expired_.AsStdFunction(),
108 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
109 /*max_restart=*/0));
110
111 EXPECT_CALL(on_expired_, Call).Times(0);
112 t1->Start();
113 AdvanceTimeAndRunTimers(DurationMs(4000));
114
115 // Fire first time
116 EXPECT_CALL(on_expired_, Call).Times(1);
117 AdvanceTimeAndRunTimers(DurationMs(1000));
118
119 EXPECT_FALSE(t1->is_running());
120
121 // Second time - shouldn't fire
122 EXPECT_CALL(on_expired_, Call).Times(0);
123 AdvanceTimeAndRunTimers(DurationMs(5000));
124 EXPECT_FALSE(t1->is_running());
125}
126
127TEST_F(TimerTest, TimerWithOneRestart) {
128 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
129 "t1", on_expired_.AsStdFunction(),
130 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
131 /*max_restart=*/1));
132
133 EXPECT_CALL(on_expired_, Call).Times(0);
134 t1->Start();
135 AdvanceTimeAndRunTimers(DurationMs(4000));
136
137 // Fire first time
138 EXPECT_CALL(on_expired_, Call).Times(1);
139 AdvanceTimeAndRunTimers(DurationMs(1000));
140 EXPECT_TRUE(t1->is_running());
141
142 EXPECT_CALL(on_expired_, Call).Times(0);
143 AdvanceTimeAndRunTimers(DurationMs(4000));
144
145 // Second time - max restart limit reached.
146 EXPECT_CALL(on_expired_, Call).Times(1);
147 AdvanceTimeAndRunTimers(DurationMs(1000));
148 EXPECT_FALSE(t1->is_running());
149
150 // Third time - should not fire.
151 EXPECT_CALL(on_expired_, Call).Times(0);
152 AdvanceTimeAndRunTimers(DurationMs(5000));
153 EXPECT_FALSE(t1->is_running());
154}
155
156TEST_F(TimerTest, TimerWithTwoRestart) {
157 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
158 "t1", on_expired_.AsStdFunction(),
159 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed,
160 /*max_restart=*/2));
161
162 EXPECT_CALL(on_expired_, Call).Times(0);
163 t1->Start();
164 AdvanceTimeAndRunTimers(DurationMs(4000));
165
166 // Fire first time
167 EXPECT_CALL(on_expired_, Call).Times(1);
168 AdvanceTimeAndRunTimers(DurationMs(1000));
169 EXPECT_TRUE(t1->is_running());
170
171 EXPECT_CALL(on_expired_, Call).Times(0);
172 AdvanceTimeAndRunTimers(DurationMs(4000));
173
174 // Second 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 // Third time
183 EXPECT_CALL(on_expired_, Call).Times(1);
184 AdvanceTimeAndRunTimers(DurationMs(1000));
185 EXPECT_FALSE(t1->is_running());
186}
187
188TEST_F(TimerTest, TimerWithExponentialBackoff) {
189 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
190 "t1", on_expired_.AsStdFunction(),
191 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
192
193 t1->Start();
194
195 // Fire first time at 5 seconds
196 EXPECT_CALL(on_expired_, Call).Times(1);
197 AdvanceTimeAndRunTimers(DurationMs(5000));
198
199 // Second time at 5*2^1 = 10 seconds later.
200 EXPECT_CALL(on_expired_, Call).Times(0);
201 AdvanceTimeAndRunTimers(DurationMs(9000));
202 EXPECT_CALL(on_expired_, Call).Times(1);
203 AdvanceTimeAndRunTimers(DurationMs(1000));
204
205 // Third time at 5*2^2 = 20 seconds later.
206 EXPECT_CALL(on_expired_, Call).Times(0);
207 AdvanceTimeAndRunTimers(DurationMs(19000));
208 EXPECT_CALL(on_expired_, Call).Times(1);
209 AdvanceTimeAndRunTimers(DurationMs(1000));
210
211 // Fourth time at 5*2^3 = 40 seconds later.
212 EXPECT_CALL(on_expired_, Call).Times(0);
213 AdvanceTimeAndRunTimers(DurationMs(39000));
214 EXPECT_CALL(on_expired_, Call).Times(1);
215 AdvanceTimeAndRunTimers(DurationMs(1000));
216}
217
218TEST_F(TimerTest, StartTimerWillStopAndStart) {
219 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
220 "t1", on_expired_.AsStdFunction(),
221 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
222
223 t1->Start();
224
225 AdvanceTimeAndRunTimers(DurationMs(3000));
226
227 t1->Start();
228
229 EXPECT_CALL(on_expired_, Call).Times(0);
230 AdvanceTimeAndRunTimers(DurationMs(2000));
231
232 EXPECT_CALL(on_expired_, Call).Times(1);
233 AdvanceTimeAndRunTimers(DurationMs(3000));
234}
235
236TEST_F(TimerTest, ExpirationCounterWillResetIfStopped) {
237 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
238 "t1", on_expired_.AsStdFunction(),
239 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
240
241 t1->Start();
242
243 // Fire first time at 5 seconds
244 EXPECT_CALL(on_expired_, Call).Times(1);
245 AdvanceTimeAndRunTimers(DurationMs(5000));
246 EXPECT_EQ(t1->expiration_count(), 1);
247
248 // Second time at 5*2^1 = 10 seconds later.
249 EXPECT_CALL(on_expired_, Call).Times(0);
250 AdvanceTimeAndRunTimers(DurationMs(9000));
251 EXPECT_CALL(on_expired_, Call).Times(1);
252 AdvanceTimeAndRunTimers(DurationMs(1000));
253 EXPECT_EQ(t1->expiration_count(), 2);
254
255 t1->Start();
256 EXPECT_EQ(t1->expiration_count(), 0);
257
258 // Third time at 5*2^0 = 5 seconds later.
259 EXPECT_CALL(on_expired_, Call).Times(0);
260 AdvanceTimeAndRunTimers(DurationMs(4000));
261 EXPECT_CALL(on_expired_, Call).Times(1);
262 AdvanceTimeAndRunTimers(DurationMs(1000));
263 EXPECT_EQ(t1->expiration_count(), 1);
264}
265
266TEST_F(TimerTest, StopTimerWillMakeItNotExpire) {
267 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
268 "t1", on_expired_.AsStdFunction(),
269 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential));
270
271 t1->Start();
272 EXPECT_TRUE(t1->is_running());
273
274 EXPECT_CALL(on_expired_, Call).Times(0);
275 AdvanceTimeAndRunTimers(DurationMs(4000));
276 t1->Stop();
277 EXPECT_FALSE(t1->is_running());
278
279 EXPECT_CALL(on_expired_, Call).Times(0);
280 AdvanceTimeAndRunTimers(DurationMs(1000));
281}
282
283TEST_F(TimerTest, ReturningNewDurationWhenExpired) {
284 std::unique_ptr<Timer> t1 = manager_.CreateTimer(
285 "t1", on_expired_.AsStdFunction(),
286 TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed));
287
288 EXPECT_CALL(on_expired_, Call).Times(0);
289 t1->Start();
290 EXPECT_EQ(t1->duration(), DurationMs(5000));
291
292 AdvanceTimeAndRunTimers(DurationMs(4000));
293
294 // Fire first time
295 EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(2000)));
296 AdvanceTimeAndRunTimers(DurationMs(1000));
297 EXPECT_EQ(t1->duration(), DurationMs(2000));
298
299 EXPECT_CALL(on_expired_, Call).Times(0);
300 AdvanceTimeAndRunTimers(DurationMs(1000));
301
302 // Second time
303 EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(10000)));
304 AdvanceTimeAndRunTimers(DurationMs(1000));
305 EXPECT_EQ(t1->duration(), DurationMs(10000));
306
307 EXPECT_CALL(on_expired_, Call).Times(0);
308 AdvanceTimeAndRunTimers(DurationMs(9000));
309 EXPECT_CALL(on_expired_, Call).Times(1);
310 AdvanceTimeAndRunTimers(DurationMs(1000));
311}
312
313} // namespace
314} // namespace dcsctp