xref: /webrtc/sctp/src/timer/timer_test.rs (revision 5d8fe953)
11f428f4dSVincent Esche // Silence warning on `for i in 0..vec.len() { … }`:
21f428f4dSVincent Esche #![allow(clippy::needless_range_loop)]
31f428f4dSVincent Esche // Silence warning on `..Default::default()` with no effect:
41f428f4dSVincent Esche #![allow(clippy::needless_update)]
51f428f4dSVincent Esche 
6ffe74184SMartin Algesten use async_trait::async_trait;
7ffe74184SMartin Algesten use tokio::sync::Mutex;
8ffe74184SMartin Algesten use tokio::time::{sleep, Duration};
9ffe74184SMartin Algesten 
10ffe74184SMartin Algesten use std::sync::atomic::{AtomicU32, Ordering};
11ffe74184SMartin Algesten use std::sync::Arc;
12ffe74184SMartin Algesten 
13ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
14ffe74184SMartin Algesten //ack_timer_test
15ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
16ffe74184SMartin Algesten use super::ack_timer::*;
17ffe74184SMartin Algesten 
18ffe74184SMartin Algesten mod test_ack_timer {
19ffe74184SMartin Algesten     use crate::error::Result;
20ffe74184SMartin Algesten 
21ffe74184SMartin Algesten     use super::*;
22ffe74184SMartin Algesten 
23ffe74184SMartin Algesten     struct TestAckTimerObserver {
24ffe74184SMartin Algesten         ncbs: Arc<AtomicU32>,
25ffe74184SMartin Algesten     }
26ffe74184SMartin Algesten 
27ffe74184SMartin Algesten     #[async_trait]
28ffe74184SMartin Algesten     impl AckTimerObserver for TestAckTimerObserver {
on_ack_timeout(&mut self)29ffe74184SMartin Algesten         async fn on_ack_timeout(&mut self) {
30ffe74184SMartin Algesten             log::trace!("ack timed out");
31ffe74184SMartin Algesten             self.ncbs.fetch_add(1, Ordering::SeqCst);
32ffe74184SMartin Algesten         }
33ffe74184SMartin Algesten     }
34ffe74184SMartin Algesten 
35ffe74184SMartin Algesten     #[tokio::test]
test_ack_timer_start_and_stop() -> Result<()>36ffe74184SMartin Algesten     async fn test_ack_timer_start_and_stop() -> Result<()> {
37ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
38ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestAckTimerObserver { ncbs: ncbs.clone() }));
39ffe74184SMartin Algesten 
40ffe74184SMartin Algesten         let mut rt = AckTimer::new(Arc::downgrade(&obs), ACK_INTERVAL);
41ffe74184SMartin Algesten 
42ffe74184SMartin Algesten         // should start ok
43ffe74184SMartin Algesten         let ok = rt.start();
44ffe74184SMartin Algesten         assert!(ok, "start() should succeed");
45ffe74184SMartin Algesten         assert!(rt.is_running(), "should be running");
46ffe74184SMartin Algesten 
47ffe74184SMartin Algesten         // stop immedidately
48ffe74184SMartin Algesten         rt.stop();
49ffe74184SMartin Algesten         assert!(!rt.is_running(), "should not be running");
50ffe74184SMartin Algesten 
51ffe74184SMartin Algesten         // Sleep more than 200msec of interval to test if it never times out
52ffe74184SMartin Algesten         sleep(ACK_INTERVAL + Duration::from_millis(50)).await;
53ffe74184SMartin Algesten 
54ffe74184SMartin Algesten         assert_eq!(
55ffe74184SMartin Algesten             ncbs.load(Ordering::SeqCst),
5683f2d1bbSVincent Esche             0,
57ffe74184SMartin Algesten             "should not be timed out (actual: {})",
58ffe74184SMartin Algesten             ncbs.load(Ordering::SeqCst)
59ffe74184SMartin Algesten         );
60ffe74184SMartin Algesten 
61ffe74184SMartin Algesten         // can start again
62ffe74184SMartin Algesten         let ok = rt.start();
63ffe74184SMartin Algesten         assert!(ok, "start() should succeed again");
64ffe74184SMartin Algesten         assert!(rt.is_running(), "should be running");
65ffe74184SMartin Algesten 
66ffe74184SMartin Algesten         // should close ok
67ffe74184SMartin Algesten         rt.stop();
68ffe74184SMartin Algesten         assert!(!rt.is_running(), "should not be running");
69ffe74184SMartin Algesten 
70ffe74184SMartin Algesten         Ok(())
71ffe74184SMartin Algesten     }
72ffe74184SMartin Algesten }
73ffe74184SMartin Algesten 
74ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
75ffe74184SMartin Algesten //rtx_timer_test
76ffe74184SMartin Algesten ///////////////////////////////////////////////////////////////////
77ffe74184SMartin Algesten use super::rtx_timer::*;
78ffe74184SMartin Algesten 
79ffe74184SMartin Algesten mod test_rto_manager {
80ffe74184SMartin Algesten     use crate::error::Result;
81ffe74184SMartin Algesten 
82ffe74184SMartin Algesten     use super::*;
83ffe74184SMartin Algesten 
84ffe74184SMartin Algesten     #[tokio::test]
test_rto_manager_initial_values() -> Result<()>85ffe74184SMartin Algesten     async fn test_rto_manager_initial_values() -> Result<()> {
86ffe74184SMartin Algesten         let m = RtoManager::new();
8783f2d1bbSVincent Esche         assert_eq!(m.rto, RTO_INITIAL, "should be rtoInitial");
8883f2d1bbSVincent Esche         assert_eq!(m.get_rto(), RTO_INITIAL, "should be rtoInitial");
8983f2d1bbSVincent Esche         assert_eq!(m.srtt, 0, "should be 0");
9083f2d1bbSVincent Esche         assert_eq!(m.rttvar, 0.0, "should be 0.0");
91ffe74184SMartin Algesten 
92ffe74184SMartin Algesten         Ok(())
93ffe74184SMartin Algesten     }
94ffe74184SMartin Algesten 
95ffe74184SMartin Algesten     #[tokio::test]
test_rto_manager_rto_calculation_small_rtt() -> Result<()>96ffe74184SMartin Algesten     async fn test_rto_manager_rto_calculation_small_rtt() -> Result<()> {
97ffe74184SMartin Algesten         let mut m = RtoManager::new();
98ffe74184SMartin Algesten         let exp = vec![
99ffe74184SMartin Algesten             1800, 1500, 1275, 1106, 1000, // capped at RTO.Min
100ffe74184SMartin Algesten         ];
101ffe74184SMartin Algesten 
102ffe74184SMartin Algesten         for i in 0..5 {
103ffe74184SMartin Algesten             m.set_new_rtt(600);
104ffe74184SMartin Algesten             let rto = m.get_rto();
105*5d8fe953SJoão Oliveira             assert_eq!(rto, exp[i], "should be equal: {i}");
106ffe74184SMartin Algesten         }
107ffe74184SMartin Algesten 
108ffe74184SMartin Algesten         Ok(())
109ffe74184SMartin Algesten     }
110ffe74184SMartin Algesten 
111ffe74184SMartin Algesten     #[tokio::test]
test_rto_manager_rto_calculation_large_rtt() -> Result<()>112ffe74184SMartin Algesten     async fn test_rto_manager_rto_calculation_large_rtt() -> Result<()> {
113ffe74184SMartin Algesten         let mut m = RtoManager::new();
114ffe74184SMartin Algesten         let exp = vec![
115ffe74184SMartin Algesten             60000, // capped at RTO.Max
116ffe74184SMartin Algesten             60000, // capped at RTO.Max
117ffe74184SMartin Algesten             60000, // capped at RTO.Max
118ffe74184SMartin Algesten             55312, 48984,
119ffe74184SMartin Algesten         ];
120ffe74184SMartin Algesten 
121ffe74184SMartin Algesten         for i in 0..5 {
122ffe74184SMartin Algesten             m.set_new_rtt(30000);
123ffe74184SMartin Algesten             let rto = m.get_rto();
124*5d8fe953SJoão Oliveira             assert_eq!(rto, exp[i], "should be equal: {i}");
125ffe74184SMartin Algesten         }
126ffe74184SMartin Algesten 
127ffe74184SMartin Algesten         Ok(())
128ffe74184SMartin Algesten     }
129ffe74184SMartin Algesten 
130ffe74184SMartin Algesten     #[tokio::test]
test_rto_manager_calculate_next_timeout() -> Result<()>131ffe74184SMartin Algesten     async fn test_rto_manager_calculate_next_timeout() -> Result<()> {
132ffe74184SMartin Algesten         let rto = calculate_next_timeout(1, 0);
13383f2d1bbSVincent Esche         assert_eq!(rto, 1, "should match");
134ffe74184SMartin Algesten         let rto = calculate_next_timeout(1, 1);
13583f2d1bbSVincent Esche         assert_eq!(rto, 2, "should match");
136ffe74184SMartin Algesten         let rto = calculate_next_timeout(1, 2);
13783f2d1bbSVincent Esche         assert_eq!(rto, 4, "should match");
138ffe74184SMartin Algesten         let rto = calculate_next_timeout(1, 30);
13983f2d1bbSVincent Esche         assert_eq!(rto, 60000, "should match");
140ffe74184SMartin Algesten         let rto = calculate_next_timeout(1, 63);
14183f2d1bbSVincent Esche         assert_eq!(rto, 60000, "should match");
142ffe74184SMartin Algesten         let rto = calculate_next_timeout(1, 64);
14383f2d1bbSVincent Esche         assert_eq!(rto, 60000, "should match");
144ffe74184SMartin Algesten 
145ffe74184SMartin Algesten         Ok(())
146ffe74184SMartin Algesten     }
147ffe74184SMartin Algesten 
148ffe74184SMartin Algesten     #[tokio::test]
test_rto_manager_reset() -> Result<()>149ffe74184SMartin Algesten     async fn test_rto_manager_reset() -> Result<()> {
150ffe74184SMartin Algesten         let mut m = RtoManager::new();
151ffe74184SMartin Algesten         for _ in 0..10 {
152ffe74184SMartin Algesten             m.set_new_rtt(200);
153ffe74184SMartin Algesten         }
154ffe74184SMartin Algesten 
155ffe74184SMartin Algesten         m.reset();
15683f2d1bbSVincent Esche         assert_eq!(m.get_rto(), RTO_INITIAL, "should be rtoInitial");
15783f2d1bbSVincent Esche         assert_eq!(m.srtt, 0, "should be 0");
15883f2d1bbSVincent Esche         assert_eq!(m.rttvar, 0.0, "should be 0");
159ffe74184SMartin Algesten 
160ffe74184SMartin Algesten         Ok(())
161ffe74184SMartin Algesten     }
162ffe74184SMartin Algesten }
163ffe74184SMartin Algesten 
164ffe74184SMartin Algesten //TODO: remove this conditional test
16528e59432SMartin Algesten #[cfg(not(any(target_os = "macos", target_os = "windows")))]
166ffe74184SMartin Algesten mod test_rtx_timer {
167ffe74184SMartin Algesten     use super::*;
168ffe74184SMartin Algesten     use crate::association::RtxTimerId;
169ffe74184SMartin Algesten     use crate::error::Result;
170ffe74184SMartin Algesten 
171ffe74184SMartin Algesten     use std::time::SystemTime;
172ffe74184SMartin Algesten     use tokio::sync::mpsc;
173ffe74184SMartin Algesten 
174ffe74184SMartin Algesten     struct TestTimerObserver {
175ffe74184SMartin Algesten         ncbs: Arc<AtomicU32>,
176ffe74184SMartin Algesten         timer_id: RtxTimerId,
177ffe74184SMartin Algesten         done_tx: Option<mpsc::Sender<SystemTime>>,
178ffe74184SMartin Algesten         max_rtos: usize,
179ffe74184SMartin Algesten     }
180ffe74184SMartin Algesten 
181ffe74184SMartin Algesten     impl Default for TestTimerObserver {
default() -> Self182ffe74184SMartin Algesten         fn default() -> Self {
183ffe74184SMartin Algesten             TestTimerObserver {
184ffe74184SMartin Algesten                 ncbs: Arc::new(AtomicU32::new(0)),
185ffe74184SMartin Algesten                 timer_id: RtxTimerId::T1Init,
186ffe74184SMartin Algesten                 done_tx: None,
187ffe74184SMartin Algesten                 max_rtos: 0,
188ffe74184SMartin Algesten             }
189ffe74184SMartin Algesten         }
190ffe74184SMartin Algesten     }
191ffe74184SMartin Algesten 
192ffe74184SMartin Algesten     #[async_trait]
193ffe74184SMartin Algesten     impl RtxTimerObserver for TestTimerObserver {
on_retransmission_timeout(&mut self, timer_id: RtxTimerId, n_rtos: usize)194ffe74184SMartin Algesten         async fn on_retransmission_timeout(&mut self, timer_id: RtxTimerId, n_rtos: usize) {
195ffe74184SMartin Algesten             self.ncbs.fetch_add(1, Ordering::SeqCst);
196ffe74184SMartin Algesten             // 30 : 1 (30)
197ffe74184SMartin Algesten             // 60 : 2 (90)
198ffe74184SMartin Algesten             // 120: 3 (210)
199ffe74184SMartin Algesten             // 240: 4 (550) <== expected in 650 msec
200*5d8fe953SJoão Oliveira             assert_eq!(self.timer_id, timer_id, "unexpected timer ID: {timer_id}");
201ffe74184SMartin Algesten             if (self.max_rtos > 0 && n_rtos == self.max_rtos) || self.max_rtos == usize::MAX {
202ffe74184SMartin Algesten                 if let Some(done) = &self.done_tx {
203ffe74184SMartin Algesten                     let elapsed = SystemTime::now();
204ffe74184SMartin Algesten                     let _ = done.send(elapsed).await;
205ffe74184SMartin Algesten                 }
206ffe74184SMartin Algesten             }
207ffe74184SMartin Algesten         }
208ffe74184SMartin Algesten 
on_retransmission_failure(&mut self, timer_id: RtxTimerId)209ffe74184SMartin Algesten         async fn on_retransmission_failure(&mut self, timer_id: RtxTimerId) {
210ffe74184SMartin Algesten             if self.max_rtos == 0 {
211ffe74184SMartin Algesten                 if let Some(done) = &self.done_tx {
212*5d8fe953SJoão Oliveira                     assert_eq!(self.timer_id, timer_id, "unexpted timer ID: {timer_id}");
213ffe74184SMartin Algesten                     let elapsed = SystemTime::now();
214ffe74184SMartin Algesten                     //t.Logf("onRtxFailure: elapsed=%.03f\n", elapsed)
215ffe74184SMartin Algesten                     let _ = done.send(elapsed).await;
216ffe74184SMartin Algesten                 }
217ffe74184SMartin Algesten             } else {
2187bd9f39dSVincent Esche                 panic!("timer should not fail");
219ffe74184SMartin Algesten             }
220ffe74184SMartin Algesten         }
221ffe74184SMartin Algesten     }
222ffe74184SMartin Algesten 
223ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_callback_interval() -> Result<()>224ffe74184SMartin Algesten     async fn test_rtx_timer_callback_interval() -> Result<()> {
225ffe74184SMartin Algesten         let timer_id = RtxTimerId::T1Init;
226ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
227ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
228ffe74184SMartin Algesten             ncbs: ncbs.clone(),
229ffe74184SMartin Algesten             timer_id,
230ffe74184SMartin Algesten             ..Default::default()
231ffe74184SMartin Algesten         }));
232ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
233ffe74184SMartin Algesten 
234ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should not be running");
235ffe74184SMartin Algesten 
236ffe74184SMartin Algesten         // since := time.Now()
237ffe74184SMartin Algesten         let ok = rt.start(30).await;
238ffe74184SMartin Algesten         assert!(ok, "should be true");
239ffe74184SMartin Algesten         assert!(rt.is_running().await, "should be running");
240ffe74184SMartin Algesten 
241ffe74184SMartin Algesten         sleep(Duration::from_millis(650)).await;
242ffe74184SMartin Algesten         rt.stop().await;
243ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should not be running");
244ffe74184SMartin Algesten 
24583f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 4, "should be called 4 times");
246ffe74184SMartin Algesten 
247ffe74184SMartin Algesten         Ok(())
248ffe74184SMartin Algesten     }
249ffe74184SMartin Algesten 
250ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_last_start_wins() -> Result<()>251ffe74184SMartin Algesten     async fn test_rtx_timer_last_start_wins() -> Result<()> {
252ffe74184SMartin Algesten         let timer_id = RtxTimerId::T3RTX;
253ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
254ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
255ffe74184SMartin Algesten             ncbs: ncbs.clone(),
256ffe74184SMartin Algesten             timer_id,
257ffe74184SMartin Algesten             ..Default::default()
258ffe74184SMartin Algesten         }));
259ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
260ffe74184SMartin Algesten 
261ffe74184SMartin Algesten         let interval = 30;
262ffe74184SMartin Algesten         let ok = rt.start(interval).await;
263ffe74184SMartin Algesten         assert!(ok, "should be accepted");
264ffe74184SMartin Algesten         let ok = rt.start(interval * 99).await; // should ignored
265ffe74184SMartin Algesten         assert!(!ok, "should be ignored");
266ffe74184SMartin Algesten         let ok = rt.start(interval * 99).await; // should ignored
267ffe74184SMartin Algesten         assert!(!ok, "should be ignored");
268ffe74184SMartin Algesten 
269ffe74184SMartin Algesten         sleep(Duration::from_millis((interval * 3) / 2)).await;
270ffe74184SMartin Algesten         rt.stop().await;
271ffe74184SMartin Algesten 
272ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should not be running");
27383f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 1, "must be called once");
274ffe74184SMartin Algesten 
275ffe74184SMartin Algesten         Ok(())
276ffe74184SMartin Algesten     }
277ffe74184SMartin Algesten 
278ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_stop_right_after_start() -> Result<()>279ffe74184SMartin Algesten     async fn test_rtx_timer_stop_right_after_start() -> Result<()> {
280ffe74184SMartin Algesten         let timer_id = RtxTimerId::T3RTX;
281ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
282ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
283ffe74184SMartin Algesten             ncbs: ncbs.clone(),
284ffe74184SMartin Algesten             timer_id,
285ffe74184SMartin Algesten             ..Default::default()
286ffe74184SMartin Algesten         }));
287ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
288ffe74184SMartin Algesten 
289ffe74184SMartin Algesten         let interval = 30;
290ffe74184SMartin Algesten         let ok = rt.start(interval).await;
291ffe74184SMartin Algesten         assert!(ok, "should be accepted");
292ffe74184SMartin Algesten         rt.stop().await;
293ffe74184SMartin Algesten 
294ffe74184SMartin Algesten         sleep(Duration::from_millis((interval * 3) / 2)).await;
295ffe74184SMartin Algesten         rt.stop().await;
296ffe74184SMartin Algesten 
297ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should not be running");
29883f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 0, "no callback should be made");
299ffe74184SMartin Algesten 
300ffe74184SMartin Algesten         Ok(())
301ffe74184SMartin Algesten     }
302ffe74184SMartin Algesten 
303ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_start_stop_then_start() -> Result<()>304ffe74184SMartin Algesten     async fn test_rtx_timer_start_stop_then_start() -> Result<()> {
305ffe74184SMartin Algesten         let timer_id = RtxTimerId::T1Cookie;
306ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
307ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
308ffe74184SMartin Algesten             ncbs: ncbs.clone(),
309ffe74184SMartin Algesten             timer_id,
310ffe74184SMartin Algesten             ..Default::default()
311ffe74184SMartin Algesten         }));
312ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
313ffe74184SMartin Algesten 
314ffe74184SMartin Algesten         let interval = 30;
315ffe74184SMartin Algesten         let ok = rt.start(interval).await;
316ffe74184SMartin Algesten         assert!(ok, "should be accepted");
317ffe74184SMartin Algesten         rt.stop().await;
318ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should NOT be running");
319ffe74184SMartin Algesten         let ok = rt.start(interval).await;
320ffe74184SMartin Algesten         assert!(ok, "should be accepted");
321ffe74184SMartin Algesten         assert!(rt.is_running().await, "should be running");
322ffe74184SMartin Algesten 
323ffe74184SMartin Algesten         sleep(Duration::from_millis((interval * 3) / 2)).await;
324ffe74184SMartin Algesten         rt.stop().await;
325ffe74184SMartin Algesten 
326ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should NOT be running");
32783f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 1, "must be called once");
328ffe74184SMartin Algesten 
329ffe74184SMartin Algesten         Ok(())
330ffe74184SMartin Algesten     }
331ffe74184SMartin Algesten 
332ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_start_and_stop_in_atight_loop() -> Result<()>333ffe74184SMartin Algesten     async fn test_rtx_timer_start_and_stop_in_atight_loop() -> Result<()> {
334ffe74184SMartin Algesten         let timer_id = RtxTimerId::T2Shutdown;
335ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
336ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
337ffe74184SMartin Algesten             ncbs: ncbs.clone(),
338ffe74184SMartin Algesten             timer_id,
339ffe74184SMartin Algesten             ..Default::default()
340ffe74184SMartin Algesten         }));
341ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
342ffe74184SMartin Algesten 
343ffe74184SMartin Algesten         for _ in 0..1000 {
344ffe74184SMartin Algesten             let ok = rt.start(30).await;
345ffe74184SMartin Algesten             assert!(ok, "should be accepted");
346ffe74184SMartin Algesten             assert!(rt.is_running().await, "should be running");
347ffe74184SMartin Algesten             rt.stop().await;
348ffe74184SMartin Algesten             assert!(!rt.is_running().await, "should NOT be running");
349ffe74184SMartin Algesten         }
350ffe74184SMartin Algesten 
35183f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 0, "no callback should be made");
352ffe74184SMartin Algesten 
353ffe74184SMartin Algesten         Ok(())
354ffe74184SMartin Algesten     }
355ffe74184SMartin Algesten 
356ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_should_stop_after_rtx_failure() -> Result<()>357ffe74184SMartin Algesten     async fn test_rtx_timer_should_stop_after_rtx_failure() -> Result<()> {
358ffe74184SMartin Algesten         let (done_tx, mut done_rx) = mpsc::channel(1);
359ffe74184SMartin Algesten 
360ffe74184SMartin Algesten         let timer_id = RtxTimerId::Reconfig;
361ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
362ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
363ffe74184SMartin Algesten             ncbs: ncbs.clone(),
364ffe74184SMartin Algesten             timer_id,
365ffe74184SMartin Algesten             done_tx: Some(done_tx),
366ffe74184SMartin Algesten             ..Default::default()
367ffe74184SMartin Algesten         }));
368ffe74184SMartin Algesten 
369ffe74184SMartin Algesten         let since = SystemTime::now();
370ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
371ffe74184SMartin Algesten 
372ffe74184SMartin Algesten         // RTO(msec) Total(msec)
373ffe74184SMartin Algesten         //  10          10    1st RTO
374ffe74184SMartin Algesten         //  20          30    2nd RTO
375ffe74184SMartin Algesten         //  40          70    3rd RTO
376ffe74184SMartin Algesten         //  80         150    4th RTO
377ffe74184SMartin Algesten         // 160         310    5th RTO (== Path.Max.Retrans)
378ffe74184SMartin Algesten         // 320         630    Failure
379ffe74184SMartin Algesten 
380ffe74184SMartin Algesten         let interval = 10;
381ffe74184SMartin Algesten         let ok = rt.start(interval).await;
382ffe74184SMartin Algesten         assert!(ok, "should be accepted");
383ffe74184SMartin Algesten         assert!(rt.is_running().await, "should be running");
384ffe74184SMartin Algesten 
385ffe74184SMartin Algesten         let elapsed = done_rx.recv().await;
386ffe74184SMartin Algesten 
387ffe74184SMartin Algesten         assert!(!rt.is_running().await, "should not be running");
38883f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 5, "should be called 5 times");
389ffe74184SMartin Algesten 
390ffe74184SMartin Algesten         if let Some(elapsed) = elapsed {
391ffe74184SMartin Algesten             let diff = elapsed.duration_since(since).unwrap();
392ffe74184SMartin Algesten             assert!(
393ffe74184SMartin Algesten                 diff > Duration::from_millis(600),
394ffe74184SMartin Algesten                 "must have taken more than 600 msec"
395ffe74184SMartin Algesten             );
396ffe74184SMartin Algesten             assert!(
397ffe74184SMartin Algesten                 diff < Duration::from_millis(700),
398ffe74184SMartin Algesten                 "must fail in less than 700 msec"
399ffe74184SMartin Algesten             );
400ffe74184SMartin Algesten         }
401ffe74184SMartin Algesten 
402ffe74184SMartin Algesten         Ok(())
403ffe74184SMartin Algesten     }
404ffe74184SMartin Algesten 
405ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_should_not_stop_if_max_retrans_is_zero() -> Result<()>406ffe74184SMartin Algesten     async fn test_rtx_timer_should_not_stop_if_max_retrans_is_zero() -> Result<()> {
407ffe74184SMartin Algesten         let (done_tx, mut done_rx) = mpsc::channel(1);
408ffe74184SMartin Algesten 
409ffe74184SMartin Algesten         let timer_id = RtxTimerId::Reconfig;
410ffe74184SMartin Algesten         let max_rtos = 6;
411ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
412ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
413ffe74184SMartin Algesten             ncbs: ncbs.clone(),
414ffe74184SMartin Algesten             timer_id,
415ffe74184SMartin Algesten             done_tx: Some(done_tx),
416ffe74184SMartin Algesten             max_rtos,
417ffe74184SMartin Algesten             ..Default::default()
418ffe74184SMartin Algesten         }));
419ffe74184SMartin Algesten 
420ffe74184SMartin Algesten         let since = SystemTime::now();
421ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, 0);
422ffe74184SMartin Algesten 
423ffe74184SMartin Algesten         // RTO(msec) Total(msec)
424ffe74184SMartin Algesten         //  10          10    1st RTO
425ffe74184SMartin Algesten         //  20          30    2nd RTO
426ffe74184SMartin Algesten         //  40          70    3rd RTO
427ffe74184SMartin Algesten         //  80         150    4th RTO
428ffe74184SMartin Algesten         // 160         310    5th RTO
429ffe74184SMartin Algesten         // 320         630    6th RTO => exit test (timer should still be running)
430ffe74184SMartin Algesten 
431ffe74184SMartin Algesten         let interval = 10;
432ffe74184SMartin Algesten         let ok = rt.start(interval).await;
433ffe74184SMartin Algesten         assert!(ok, "should be accepted");
434ffe74184SMartin Algesten         assert!(rt.is_running().await, "should be running");
435ffe74184SMartin Algesten 
436ffe74184SMartin Algesten         let elapsed = done_rx.recv().await;
437ffe74184SMartin Algesten 
438ffe74184SMartin Algesten         assert!(rt.is_running().await, "should still be running");
43983f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 6, "should be called 6 times");
440ffe74184SMartin Algesten 
441ffe74184SMartin Algesten         if let Some(elapsed) = elapsed {
442ffe74184SMartin Algesten             let diff = elapsed.duration_since(since).unwrap();
443ffe74184SMartin Algesten             assert!(
444ffe74184SMartin Algesten                 diff > Duration::from_millis(600),
445ffe74184SMartin Algesten                 "must have taken more than 600 msec"
446ffe74184SMartin Algesten             );
447ffe74184SMartin Algesten             assert!(
448ffe74184SMartin Algesten                 diff < Duration::from_millis(700),
449ffe74184SMartin Algesten                 "must fail in less than 700 msec"
450ffe74184SMartin Algesten             );
451ffe74184SMartin Algesten         }
452ffe74184SMartin Algesten 
453ffe74184SMartin Algesten         rt.stop().await;
454ffe74184SMartin Algesten 
455ffe74184SMartin Algesten         Ok(())
456ffe74184SMartin Algesten     }
457ffe74184SMartin Algesten 
458ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_stop_timer_that_is_not_running_is_noop() -> Result<()>459ffe74184SMartin Algesten     async fn test_rtx_timer_stop_timer_that_is_not_running_is_noop() -> Result<()> {
460ffe74184SMartin Algesten         let (done_tx, mut done_rx) = mpsc::channel(1);
461ffe74184SMartin Algesten 
462ffe74184SMartin Algesten         let timer_id = RtxTimerId::Reconfig;
463ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
464ffe74184SMartin Algesten             timer_id,
465ffe74184SMartin Algesten             done_tx: Some(done_tx),
466ffe74184SMartin Algesten             max_rtos: usize::MAX,
467ffe74184SMartin Algesten             ..Default::default()
468ffe74184SMartin Algesten         }));
469ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
470ffe74184SMartin Algesten 
471ffe74184SMartin Algesten         for _ in 0..10 {
472ffe74184SMartin Algesten             rt.stop().await;
473ffe74184SMartin Algesten         }
474ffe74184SMartin Algesten 
475ffe74184SMartin Algesten         let ok = rt.start(20).await;
476ffe74184SMartin Algesten         assert!(ok, "should be accepted");
477ffe74184SMartin Algesten         assert!(rt.is_running().await, "must be running");
478ffe74184SMartin Algesten 
479ffe74184SMartin Algesten         let _ = done_rx.recv().await;
480ffe74184SMartin Algesten         rt.stop().await;
481ffe74184SMartin Algesten         assert!(!rt.is_running().await, "must be false");
482ffe74184SMartin Algesten 
483ffe74184SMartin Algesten         Ok(())
484ffe74184SMartin Algesten     }
485ffe74184SMartin Algesten 
486ffe74184SMartin Algesten     #[tokio::test]
test_rtx_timer_closed_timer_wont_start() -> Result<()>487ffe74184SMartin Algesten     async fn test_rtx_timer_closed_timer_wont_start() -> Result<()> {
488ffe74184SMartin Algesten         let timer_id = RtxTimerId::Reconfig;
489ffe74184SMartin Algesten         let ncbs = Arc::new(AtomicU32::new(0));
490ffe74184SMartin Algesten         let obs = Arc::new(Mutex::new(TestTimerObserver {
491ffe74184SMartin Algesten             ncbs: ncbs.clone(),
492ffe74184SMartin Algesten             timer_id,
493ffe74184SMartin Algesten             ..Default::default()
494ffe74184SMartin Algesten         }));
495ffe74184SMartin Algesten         let rt = RtxTimer::new(Arc::downgrade(&obs), timer_id, PATH_MAX_RETRANS);
496ffe74184SMartin Algesten 
497ffe74184SMartin Algesten         let ok = rt.start(20).await;
498ffe74184SMartin Algesten         assert!(ok, "should be accepted");
499ffe74184SMartin Algesten         assert!(rt.is_running().await, "must be running");
500ffe74184SMartin Algesten 
501ffe74184SMartin Algesten         rt.stop().await;
502ffe74184SMartin Algesten         assert!(!rt.is_running().await, "must be false");
503ffe74184SMartin Algesten 
504ffe74184SMartin Algesten         //let ok = rt.start(obs.clone(), 20).await;
505ffe74184SMartin Algesten         //assert!(!ok, "should not start");
506ffe74184SMartin Algesten         assert!(!rt.is_running().await, "must not be running");
507ffe74184SMartin Algesten 
508ffe74184SMartin Algesten         sleep(Duration::from_millis(100)).await;
50983f2d1bbSVincent Esche         assert_eq!(ncbs.load(Ordering::SeqCst), 0, "RTO should not occur");
510ffe74184SMartin Algesten 
511ffe74184SMartin Algesten         Ok(())
512ffe74184SMartin Algesten     }
513ffe74184SMartin Algesten }
514