use std::time;
use context_async::{Context, Error, TimeChecker, Timer};
#[tokio::test]
async fn test_timer_deadline() {
let timer = Timer::background();
assert!(timer.deadline().await.is_none());
let timer = Timer::todo();
assert!(timer.deadline().await.is_none());
let now = time::Instant::now();
let timer = Timer::with_timeout(time::Duration::from_secs(10));
let deadline = timer.deadline().await;
assert!(deadline.is_some());
let deadline = deadline.unwrap();
let diff = deadline - (now + time::Duration::from_secs(10));
assert!(diff < time::Duration::from_millis(100));
}
#[tokio::test]
async fn test_timer_cancel() {
let timer = Timer::background();
let timer_1 = timer.clone();
let child_1 = timer.spawn().await;
let child_1_clone = child_1.clone();
let child_2 = timer_1.spawn().await;
let child_1_1 = child_1.spawn().await;
let child_1_2 = child_1_clone.spawn().await;
let child_1_1_1 = child_1_1.spawn().await;
let child_2_1_1 = child_2.spawn().await.spawn().await;
assert!(!timer.is_cancelled().await);
assert!(!child_2_1_1.is_cancelled().await);
child_1.cancel().await;
assert!(!timer.is_cancelled().await);
assert!(!timer_1.is_cancelled().await);
assert!(child_1.is_cancelled().await);
assert!(child_1_clone.is_cancelled().await);
assert!(child_1_1.is_cancelled().await);
assert!(child_1_2.is_cancelled().await);
assert!(child_1_1_1.is_cancelled().await);
assert!(!child_2.is_cancelled().await);
assert!(!child_2_1_1.is_cancelled().await);
child_2_1_1.cancel().await;
assert!(!timer.is_cancelled().await);
assert!(!timer_1.is_cancelled().await);
assert!(child_1.is_cancelled().await);
assert!(child_1_clone.is_cancelled().await);
assert!(child_1_1.is_cancelled().await);
assert!(child_1_2.is_cancelled().await);
assert!(child_1_1_1.is_cancelled().await);
assert!(!child_2.is_cancelled().await);
assert!(child_2_1_1.is_cancelled().await);
timer_1.cancel().await;
assert!(timer.is_cancelled().await);
assert!(timer_1.is_cancelled().await);
assert!(child_1.is_cancelled().await);
assert!(child_1_clone.is_cancelled().await);
assert!(child_1_1.is_cancelled().await);
assert!(child_1_2.is_cancelled().await);
assert!(child_1_1_1.is_cancelled().await);
assert!(child_2.is_cancelled().await);
assert!(child_2_1_1.is_cancelled().await);
assert!(child_2_1_1.is_cancelled().await);
assert_eq!(child_2_1_1.error().await, Some(Error::ContextCancelled));
}
#[tokio::test]
async fn test_timer_timeout() {
let timer = Timer::with_timeout(time::Duration::from_secs(1));
assert!(!timer.is_timeout().await);
tokio::time::sleep(time::Duration::from_secs(2)).await;
assert!(timer.is_timeout().await);
let timer = Timer::with_timeout(time::Duration::from_secs(10));
let child = timer.spawn_with_timeout(time::Duration::from_secs(1)).await;
tokio::time::sleep(time::Duration::from_secs(2)).await;
assert!(!timer.is_timeout().await);
assert!(child.is_timeout().await);
let timer = Timer::with_timeout(time::Duration::from_secs(5));
let child = timer.spawn_with_timeout(time::Duration::from_secs(10)).await;
tokio::time::sleep(time::Duration::from_secs(2)).await;
assert!(!timer.is_timeout().await);
assert!(!child.is_timeout().await);
tokio::time::sleep(time::Duration::from_secs(4)).await;
assert!(timer.is_timeout().await);
assert!(child.is_timeout().await);
assert_eq!(timer.error().await, Some(Error::ContextTimeout));
assert_eq!(child.error().await, Some(Error::ContextTimeout));
}
#[tokio::test]
async fn timer_handle_simple() {
let timer = Timer::todo();
timer.handle(tokio::time::sleep(time::Duration::from_secs(1))).await.unwrap();
}
#[tokio::test]
async fn timer_handle_timeout() {
let tc = TimeChecker::new();
let timer = Timer::with_timeout(time::Duration::from_secs(1));
let err = timer.handle(tokio::time::sleep(time::Duration::from_secs(10))).await
.err().unwrap();
assert_eq!(err, Error::ContextTimeout);
assert!(tc.not_exceed(time::Duration::from_millis(1300)));
}
#[tokio::test]
async fn timer_handle_timeout_2() {
let tc = TimeChecker::new();
let timer = Timer::with_timeout(time::Duration::from_secs(4));
let t1 = timer.clone();
let t2 = timer.clone();
let t1 = tokio::spawn(async move {
t1.handle(tokio::time::sleep(time::Duration::from_secs(2))).await.unwrap();
});
let t2 = tokio::spawn(async move {
let err = t2.handle(tokio::time::sleep(time::Duration::from_secs(10))).await.err().unwrap();
assert_eq!(err, Error::ContextTimeout);
});
t1.await.unwrap();
t2.await.unwrap();
assert!(tc.not_exceed(time::Duration::from_millis(4300)));
}
#[tokio::test]
async fn timer_partial_cancel() {
let tc = TimeChecker::new();
let timer = Timer::with_timeout(time::Duration::from_secs(6));
let t1 = timer.clone();
let t2 = timer.clone();
let t1 = tokio::spawn(async move {
t1.handle(tokio::time::sleep(time::Duration::from_secs(1))).await.unwrap();
});
let t2 = tokio::spawn(async move {
let err = t2.handle(tokio::time::sleep(time::Duration::from_secs(8))).await.err().unwrap();
assert_eq!(err, Error::ContextCancelled);
});
tokio::time::sleep(time::Duration::from_secs(3)).await;
timer.cancel().await;
t1.await.unwrap();
t2.await.unwrap();
assert!(tc.not_exceed(time::Duration::from_millis(3300)));
}
#[tokio::test]
async fn timer_handle_result() {
let timer = Timer::background();
mod def {
#[derive(Debug, Clone)]
pub struct MyError;
impl From<context_async::Error> for MyError {
fn from(_: context_async::Error) -> Self {
MyError
}
}
}
async fn my_func() -> Result<u8, MyError> {
Ok(1)
}
use def::*;
timer.handle_result(my_func()).await.unwrap();
}