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