nio 0.1.4

Async runtime for Rust
Documentation
use std::{
    future::{Future, poll_fn},
    pin::Pin,
    time::{Duration, Instant},
};

use futures_lite::FutureExt;
use nio::{Sleep, sleep, spawn_local, test, timeout};

#[test]
async fn smoke() {
    let start = Instant::now();
    Sleep::at(start + Duration::from_secs(1)).await;
    assert!(start.elapsed() >= Duration::from_secs(1));
}

#[test]
async fn interval() {
    let period = Duration::from_secs(1);
    let jitter = Duration::from_millis(500);
    let start = Instant::now();
    let mut timer = nio::Interval::at(start + period, period);

    timer.tick().await;

    let elapsed = start.elapsed();
    assert!(elapsed >= period);
    assert!(elapsed - period < jitter);

    timer.tick().await;

    let elapsed = start.elapsed();
    assert!(elapsed >= period * 2);
    assert!(elapsed - period * 2 < jitter);
}

#[test]
async fn poll_across_tasks() {
    let start = Instant::now();
    let (sender, mut receiver) = tokio::sync::mpsc::channel(1);

    let task1 = spawn_local(async move {
        let mut timer = Sleep::at(Instant::now() + Duration::from_secs(1));

        async {
            (&mut timer).await;
            panic!("timer should not be ready")
        }
        .or(async {})
        .await;

        sender.send(timer).await.ok();
    });

    let task2 = spawn_local(async move {
        let timer = receiver.recv().await.unwrap();
        timer.await;
    });

    task1.await.unwrap();
    task2.await.unwrap();

    assert!(start.elapsed() >= Duration::from_secs(1));
}

#[test]
async fn set() {
    let start = Instant::now();
    let mut timer = Sleep::at(start + Duration::from_secs(1));

    poll_fn(|cx| {
        let _ = Pin::new(&mut timer).poll(cx);
        std::task::Poll::Ready(())
    })
    .await;

    timer.reset_at(Instant::now() + Duration::from_secs(1));

    (&mut timer).await;

    assert!(timer.is_elapsed());
    assert!(start.elapsed() >= Duration::from_secs(1));
    assert!(start.elapsed() < Duration::from_secs(5));
}

#[test]
async fn test_timeout() {
    let timer = timeout(Duration::from_secs(1), sleep(Duration::from_secs(2)));
    assert!(timer.await.is_none());

    let timer = timeout(Duration::from_secs(2), sleep(Duration::from_secs(1)));
    assert!(timer.await.is_some());
}