#[cfg(not(target_arch = "wasm32"))]
mod stdlib;
#[cfg(target_arch = "wasm32")]
mod wasm;
pub async fn async_sleep(duration: std::time::Duration) {
#[cfg(not(target_arch = "wasm32"))]
{
stdlib::async_sleep(duration).await;
}
#[cfg(target_arch = "wasm32")]
{
wasm::async_sleep(duration).await;
}
}
#[cfg(test)]
mod tests {
use crate::async_sleep;
#[cfg(not(target_arch = "wasm32"))]
use std::time;
#[cfg(target_arch = "wasm32")]
use web_time as time;
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
#[cfg(not(target_arch = "wasm32"))]
macro_rules! async_test {
($name:ident, $body:block) => {
#[test]
fn $name() {
futures::executor::block_on(async $body);
}
};
}
#[cfg(target_arch = "wasm32")]
macro_rules! async_test {
($name:ident, $body:block) => {
#[wasm_bindgen_test::wasm_bindgen_test]
async fn $name() $body
};
}
async_test!(test_async_sleep, {
let duration = time::Duration::from_millis(500);
let now = time::Instant::now();
async_sleep(duration).await;
let elapsed = now.elapsed();
assert!(
elapsed >= duration,
"Expected at least 500ms, got {:?}",
elapsed
);
});
async_test!(test_join, {
let duration = time::Duration::from_millis(500);
let now = time::Instant::now();
let f1 = async_sleep(duration);
let f2 = async_sleep(duration);
futures::join!(f1, f2);
let elapsed = now.elapsed();
assert!(elapsed >= duration);
assert!(
elapsed < std::time::Duration::from_millis(1000),
"expected simultaneous sleep, got {:?}",
elapsed
);
});
async_test!(test_join_2, {
let start = time::Instant::now();
let f1 = async {
let sleep_start = time::Instant::now();
async_sleep(time::Duration::from_millis(150)).await;
let elapsed = sleep_start.elapsed();
("f1", elapsed)
};
let f2 = async {
let sleep_start = time::Instant::now();
async_sleep(time::Duration::from_millis(50)).await;
let elapsed = sleep_start.elapsed();
("f2", elapsed)
};
let f3 = async {
let sleep_start = time::Instant::now();
async_sleep(time::Duration::from_millis(100)).await;
let elapsed = sleep_start.elapsed();
("f3", elapsed)
};
let (result1, result2, result3) = futures::join!(f1, f2, f3);
let total_elapsed = start.elapsed();
assert!(
result1.1 >= time::Duration::from_millis(150),
"{} completed too early: {:?}",
result1.0,
result1.1
);
assert!(
result1.1 < time::Duration::from_millis(250),
"{} took too long: {:?}",
result1.0,
result1.1
);
assert!(
result2.1 >= time::Duration::from_millis(50),
"{} completed too early: {:?}",
result2.0,
result2.1
);
assert!(
result2.1 < time::Duration::from_millis(150),
"{} took too long: {:?}",
result2.0,
result2.1
);
assert!(
result3.1 >= time::Duration::from_millis(100),
"{} completed too early: {:?}",
result3.0,
result3.1
);
assert!(
result3.1 < time::Duration::from_millis(200),
"{} took too long: {:?}",
result3.0,
result3.1
);
assert!(
total_elapsed >= time::Duration::from_millis(150),
"Total time too short: {:?}",
total_elapsed
);
assert!(
total_elapsed < time::Duration::from_millis(250),
"Total time too long (not concurrent): {:?}",
total_elapsed
);
});
#[cfg_attr(not(target_arch = "wasm32"), test)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn test_future_is_send() {
fn assert_send<T: Send>(_: T) {}
let future = async_sleep(time::Duration::from_millis(100));
assert_send(future);
}
}
#[cfg(all(test, target_arch = "wasm32"))]
mod wasm_tests {
use super::*;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
async fn test_wasm_sleep() {
let duration = std::time::Duration::from_millis(100);
async_sleep(duration).await;
}
#[wasm_bindgen_test]
async fn test_wasm_concurrent_sleeps() {
let duration = std::time::Duration::from_millis(50);
let sleep1 = async_sleep(duration);
let sleep2 = async_sleep(duration);
let sleep3 = async_sleep(duration);
futures::join!(sleep1, sleep2, sleep3);
}
#[wasm_bindgen_test]
async fn test_wasm_zero_duration() {
async_sleep(std::time::Duration::from_millis(0)).await;
}
}