Path: blob/main/crates/wiggle/tests/wasmtime_async.rs
1692 views
use wasmtime::{Config, Engine, Linker, Module, Store, Val};1use wiggle::GuestMemory;23wiggle::from_witx!({4witx: ["tests/atoms.witx"],5async: {6atoms::{double_int_return_float}7}8});910pub struct Ctx;11impl wiggle::GuestErrorType for types::Errno {12fn success() -> Self {13types::Errno::Ok14}15}1617#[wiggle::async_trait]18impl atoms::Atoms for Ctx {19fn int_float_args(20&mut self,21_: &mut GuestMemory<'_>,22an_int: u32,23an_float: f32,24) -> Result<(), types::Errno> {25println!("INT FLOAT ARGS: {an_int} {an_float}");26Ok(())27}28async fn double_int_return_float(29&mut self,30_: &mut GuestMemory<'_>,31an_int: u32,32) -> Result<types::AliasToFloat, types::Errno> {33// Do something inside this test that is Pending for a trivial amount of time,34// to make sure we are hooked up to the tokio executor properly.35tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;36Ok((an_int as f32) * 2.0)37}38}3940#[tokio::test]41async fn test_sync_host_func() {42let mut store = async_store();43let mut linker = Linker::<Ctx>::new(store.engine());44atoms::add_to_linker(&mut linker, |cx| cx).unwrap();45let shim_mod = shim_module(linker.engine());46let shim_inst = linker47.instantiate_async(&mut store, &shim_mod)48.await49.unwrap();5051let mut results = [Val::I32(0)];52shim_inst53.get_func(&mut store, "int_float_args_shim")54.unwrap()55.call_async(&mut store, &[0i32.into(), 123.45f32.into()], &mut results)56.await57.unwrap();5859assert_eq!(60results[0].unwrap_i32(),61types::Errno::Ok as i32,62"int_float_args errno"63);64}6566#[tokio::test]67async fn test_async_host_func() {68let mut store = async_store();69let mut linker = Linker::<Ctx>::new(store.engine());70atoms::add_to_linker(&mut linker, |cx| cx).unwrap();7172let shim_mod = shim_module(linker.engine());73let shim_inst = linker74.instantiate_async(&mut store, &shim_mod)75.await76.unwrap();7778let input: i32 = 123;79let result_location: i32 = 0;8081let mut results = [Val::I32(0)];82shim_inst83.get_func(&mut store, "double_int_return_float_shim")84.unwrap()85.call_async(86&mut store,87&[input.into(), result_location.into()],88&mut results,89)90.await91.unwrap();9293assert_eq!(94results[0].unwrap_i32(),95types::Errno::Ok as i32,96"double_int_return_float errno"97);9899// The actual result is in memory:100let mem = shim_inst.get_memory(&mut store, "memory").unwrap();101let mut result_bytes: [u8; 4] = [0, 0, 0, 0];102mem.read(&store, result_location as usize, &mut result_bytes)103.unwrap();104let result = f32::from_le_bytes(result_bytes);105assert_eq!((input * 2) as f32, result);106}107108fn async_store() -> Store<Ctx> {109Store::new(110&Engine::new(Config::new().async_support(true)).unwrap(),111Ctx,112)113}114115// Wiggle expects the caller to have an exported memory. Wasmtime can only116// provide this if the caller is a WebAssembly module, so we need to write117// a shim module:118fn shim_module(engine: &Engine) -> Module {119Module::new(120engine,121r#"122(module123(import "atoms" "int_float_args" (func $int_float_args (param i32 f32) (result i32)))124(import "atoms" "double_int_return_float" (func $double_int_return_float (param i32 i32) (result i32)))125126(memory 1)127(export "memory" (memory 0))128129(func $int_float_args_shim (param i32 f32) (result i32)130local.get 0131local.get 1132call $int_float_args133)134(func $double_int_return_float_shim (param i32 i32) (result i32)135local.get 0136local.get 1137call $double_int_return_float138)139(export "int_float_args_shim" (func $int_float_args_shim))140(export "double_int_return_float_shim" (func $double_int_return_float_shim))141)142"#,143)144.unwrap()145}146147148