100 lines
2.6 KiB
Rust
100 lines
2.6 KiB
Rust
use std::future::Future;
|
|
use std::pin::Pin;
|
|
use std::sync::{Arc, Mutex};
|
|
use std::thread;
|
|
use std::time::{Duration, Instant};
|
|
|
|
use async_io::Timer;
|
|
use futures_lite::{future, FutureExt, StreamExt};
|
|
|
|
fn spawn<T: Send + 'static>(
|
|
f: impl Future<Output = T> + Send + 'static,
|
|
) -> impl Future<Output = T> + Send + 'static {
|
|
let (s, r) = async_channel::bounded(1);
|
|
|
|
thread::spawn(move || {
|
|
future::block_on(async {
|
|
s.send(f.await).await.ok();
|
|
})
|
|
});
|
|
|
|
Box::pin(async move { r.recv().await.unwrap() })
|
|
}
|
|
|
|
#[test]
|
|
fn smoke() {
|
|
future::block_on(async {
|
|
let start = Instant::now();
|
|
Timer::after(Duration::from_secs(1)).await;
|
|
assert!(start.elapsed() >= Duration::from_secs(1));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn interval() {
|
|
future::block_on(async {
|
|
let period = Duration::from_secs(1);
|
|
let jitter = Duration::from_millis(500);
|
|
let start = Instant::now();
|
|
let mut timer = Timer::interval(period);
|
|
timer.next().await;
|
|
let elapsed = start.elapsed();
|
|
assert!(elapsed >= period && elapsed - period < jitter);
|
|
timer.next().await;
|
|
let elapsed = start.elapsed();
|
|
assert!(elapsed >= period * 2 && elapsed - period * 2 < jitter);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn poll_across_tasks() {
|
|
future::block_on(async {
|
|
let start = Instant::now();
|
|
let (sender, receiver) = async_channel::bounded(1);
|
|
|
|
let task1 = spawn(async move {
|
|
let mut timer = Timer::after(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(async move {
|
|
let timer = receiver.recv().await.unwrap();
|
|
timer.await;
|
|
});
|
|
|
|
task1.await;
|
|
task2.await;
|
|
|
|
assert!(start.elapsed() >= Duration::from_secs(1));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn set() {
|
|
future::block_on(async {
|
|
let start = Instant::now();
|
|
let timer = Arc::new(Mutex::new(Timer::after(Duration::from_secs(10))));
|
|
|
|
thread::spawn({
|
|
let timer = timer.clone();
|
|
move || {
|
|
thread::sleep(Duration::from_secs(1));
|
|
timer.lock().unwrap().set_after(Duration::from_secs(2));
|
|
}
|
|
});
|
|
|
|
future::poll_fn(|cx| Pin::new(&mut *timer.lock().unwrap()).poll(cx)).await;
|
|
|
|
assert!(start.elapsed() >= Duration::from_secs(2));
|
|
assert!(start.elapsed() < Duration::from_secs(10));
|
|
});
|
|
}
|