• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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