1 use wasmtime::{Engine, Linker, Module, Store, Val};
2 use wiggle::GuestMemory;
3
4 wiggle::from_witx!({
5 witx: ["tests/atoms.witx"],
6 async: {
7 atoms::{double_int_return_float}
8 }
9 });
10
11 pub struct Ctx;
12 impl wiggle::GuestErrorType for types::Errno {
success() -> Self13 fn success() -> Self {
14 types::Errno::Ok
15 }
16 }
17
18 impl atoms::Atoms for Ctx {
int_float_args( &mut self, _: &mut GuestMemory<'_>, an_int: u32, an_float: f32, ) -> Result<(), types::Errno>19 fn int_float_args(
20 &mut self,
21 _: &mut GuestMemory<'_>,
22 an_int: u32,
23 an_float: f32,
24 ) -> Result<(), types::Errno> {
25 println!("INT FLOAT ARGS: {an_int} {an_float}");
26 Ok(())
27 }
double_int_return_float( &mut self, _: &mut GuestMemory<'_>, an_int: u32, ) -> Result<types::AliasToFloat, types::Errno>28 async fn double_int_return_float(
29 &mut self,
30 _: &mut GuestMemory<'_>,
31 an_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.
35 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
36 Ok((an_int as f32) * 2.0)
37 }
38 }
39
40 #[tokio::test]
test_sync_host_func()41 async fn test_sync_host_func() {
42 let mut store = async_store();
43 let mut linker = Linker::<Ctx>::new(store.engine());
44 atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
45 let shim_mod = shim_module(linker.engine());
46 let shim_inst = linker
47 .instantiate_async(&mut store, &shim_mod)
48 .await
49 .unwrap();
50
51 let mut results = [Val::I32(0)];
52 shim_inst
53 .get_func(&mut store, "int_float_args_shim")
54 .unwrap()
55 .call_async(&mut store, &[0i32.into(), 123.45f32.into()], &mut results)
56 .await
57 .unwrap();
58
59 assert_eq!(
60 results[0].unwrap_i32(),
61 types::Errno::Ok as i32,
62 "int_float_args errno"
63 );
64 }
65
66 #[tokio::test]
test_async_host_func()67 async fn test_async_host_func() {
68 let mut store = async_store();
69 let mut linker = Linker::<Ctx>::new(store.engine());
70 atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
71
72 let shim_mod = shim_module(linker.engine());
73 let shim_inst = linker
74 .instantiate_async(&mut store, &shim_mod)
75 .await
76 .unwrap();
77
78 let input: i32 = 123;
79 let result_location: i32 = 0;
80
81 let mut results = [Val::I32(0)];
82 shim_inst
83 .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 .await
91 .unwrap();
92
93 assert_eq!(
94 results[0].unwrap_i32(),
95 types::Errno::Ok as i32,
96 "double_int_return_float errno"
97 );
98
99 // The actual result is in memory:
100 let mem = shim_inst.get_memory(&mut store, "memory").unwrap();
101 let mut result_bytes: [u8; 4] = [0, 0, 0, 0];
102 mem.read(&store, result_location as usize, &mut result_bytes)
103 .unwrap();
104 let result = f32::from_le_bytes(result_bytes);
105 assert_eq!((input * 2) as f32, result);
106 }
107
async_store() -> Store<Ctx>108 fn async_store() -> Store<Ctx> {
109 Store::new(&Engine::default(), Ctx)
110 }
111
112 // Wiggle expects the caller to have an exported memory. Wasmtime can only
113 // provide this if the caller is a WebAssembly module, so we need to write
114 // a shim module:
shim_module(engine: &Engine) -> Module115 fn shim_module(engine: &Engine) -> Module {
116 Module::new(
117 engine,
118 r#"
119 (module
120 (import "atoms" "int_float_args" (func $int_float_args (param i32 f32) (result i32)))
121 (import "atoms" "double_int_return_float" (func $double_int_return_float (param i32 i32) (result i32)))
122
123 (memory 1)
124 (export "memory" (memory 0))
125
126 (func $int_float_args_shim (param i32 f32) (result i32)
127 local.get 0
128 local.get 1
129 call $int_float_args
130 )
131 (func $double_int_return_float_shim (param i32 i32) (result i32)
132 local.get 0
133 local.get 1
134 call $double_int_return_float
135 )
136 (export "int_float_args_shim" (func $int_float_args_shim))
137 (export "double_int_return_float_shim" (func $double_int_return_float_shim))
138 )
139 "#,
140 )
141 .unwrap()
142 }
143