Use tokio::test instead of dummy_waker in tests (#3975)

Currently wasmtime's async tests use a mixture of `#[tokio::test]` and
`dummy_waker`. To be consistent this tries to move all tests possible to
`#[tokio::test]` and just a two need to keep using `dummy_waker` (no
renamed to `noop_waker`) due to what they're testing.
This commit is contained in:
Alex Crichton
2022-04-18 15:56:35 -05:00
committed by GitHub
parent 5aa9bdc7eb
commit 534e4263ce
2 changed files with 260 additions and 334 deletions

View File

@@ -1,31 +1,8 @@
use std::future::Future;
use crate::async_functions::{CountPending, PollOnce};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
use wasmtime::*;
fn dummy_waker() -> Waker {
return unsafe { Waker::from_raw(clone(5 as *const _)) };
unsafe fn clone(ptr: *const ()) -> RawWaker {
assert_eq!(ptr as usize, 5);
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
RawWaker::new(ptr, &VTABLE)
}
unsafe fn wake(ptr: *const ()) {
assert_eq!(ptr as usize, 5);
}
unsafe fn wake_by_ref(ptr: *const ()) {
assert_eq!(ptr as usize, 5);
}
unsafe fn drop(ptr: *const ()) {
assert_eq!(ptr as usize, 5);
}
}
fn build_engine() -> Arc<Engine> {
let mut config = Config::new();
config.async_support(true);
@@ -59,7 +36,7 @@ fn make_env(engine: &Engine) -> Linker<()> {
///
/// Returns `Some(yields)` if function completed normally, giving the
/// number of yields that occured, or `None` if a trap occurred.
fn run_and_count_yields_or_trap<F: Fn(Arc<Engine>)>(
async fn run_and_count_yields_or_trap<F: Fn(Arc<Engine>)>(
wasm: &str,
initial: u64,
delta: Option<u64>,
@@ -82,39 +59,15 @@ fn run_and_count_yields_or_trap<F: Fn(Arc<Engine>)>(
let engine_clone = engine.clone();
setup_func(engine_clone);
let mut future = Box::pin(async {
let instance = linker.instantiate_async(&mut store, &module).await.unwrap();
let f = instance.get_func(&mut store, "run").unwrap();
f.call_async(&mut store, &[], &mut []).await
});
let mut yields = 0;
loop {
match future
.as_mut()
.poll(&mut Context::from_waker(&dummy_waker()))
{
Poll::Pending => {
yields += 1;
}
Poll::Ready(Ok(..)) => {
break;
}
Poll::Ready(Err(e)) => match e.downcast::<wasmtime::Trap>() {
Ok(_) => {
return None;
}
e => {
e.unwrap();
}
},
}
}
Some(yields)
let instance = linker.instantiate_async(&mut store, &module).await.unwrap();
let f = instance.get_func(&mut store, "run").unwrap();
let (result, yields) =
CountPending::new(Box::pin(f.call_async(&mut store, &[], &mut []))).await;
return result.ok().map(|_| yields);
}
#[test]
fn epoch_yield_at_func_entry() {
#[tokio::test]
async fn epoch_yield_at_func_entry() {
// Should yield at start of call to func $subfunc.
assert_eq!(
Some(1),
@@ -131,11 +84,12 @@ fn epoch_yield_at_func_entry() {
Some(1),
|_| {},
)
.await
);
}
#[test]
fn epoch_yield_at_loop_header() {
#[tokio::test]
async fn epoch_yield_at_loop_header() {
// Should yield at top of loop, once per five iters.
assert_eq!(
Some(2),
@@ -154,11 +108,12 @@ fn epoch_yield_at_loop_header() {
Some(5),
|_| {},
)
.await
);
}
#[test]
fn epoch_yield_immediate() {
#[tokio::test]
async fn epoch_yield_immediate() {
// We should see one yield immediately when the initial deadline
// is zero.
assert_eq!(
@@ -173,11 +128,12 @@ fn epoch_yield_immediate() {
Some(1),
|_| {},
)
.await
);
}
#[test]
fn epoch_yield_only_once() {
#[tokio::test]
async fn epoch_yield_only_once() {
// We should yield from the subfunction, and then when we return
// to the outer function and hit another loop header, we should
// not yield again (the double-check block will reload the correct
@@ -202,11 +158,12 @@ fn epoch_yield_only_once() {
Some(1),
|_| {},
)
.await
);
}
#[test]
fn epoch_interrupt_infinite_loop() {
#[tokio::test]
async fn epoch_interrupt_infinite_loop() {
assert_eq!(
None,
run_and_count_yields_or_trap(
@@ -226,11 +183,12 @@ fn epoch_interrupt_infinite_loop() {
});
},
)
.await
);
}
#[test]
fn epoch_interrupt_function_entries() {
#[tokio::test]
async fn epoch_interrupt_function_entries() {
assert_eq!(
None,
run_and_count_yields_or_trap(
@@ -347,11 +305,12 @@ fn epoch_interrupt_function_entries() {
});
},
)
.await
);
}
#[test]
fn drop_future_on_epoch_yield() {
#[tokio::test]
async fn drop_future_on_epoch_yield() {
let wasm = "
(module
(import \"\" \"bump_epoch\" (func $bump))
@@ -399,26 +358,9 @@ fn drop_future_on_epoch_yield() {
store.set_epoch_deadline(1);
store.epoch_deadline_async_yield_and_update(1);
let mut future = Box::pin(async {
let instance = linker.instantiate_async(&mut store, &module).await.unwrap();
let f = instance.get_func(&mut store, "run").unwrap();
f.call_async(&mut store, &[], &mut []).await
});
match future
.as_mut()
.poll(&mut Context::from_waker(&dummy_waker()))
{
Poll::Pending => {
// OK: expected yield.
}
Poll::Ready(Ok(..)) => {
panic!("Shoulud not have returned");
}
Poll::Ready(e) => {
e.unwrap();
}
}
let instance = linker.instantiate_async(&mut store, &module).await.unwrap();
let f = instance.get_func(&mut store, "run").unwrap();
PollOnce::new(Box::pin(f.call_async(&mut store, &[], &mut []))).await;
drop(future);
assert_eq!(true, alive_flag.load(Ordering::Acquire));
}