1*cc8d04f4SAlex Crichton #![cfg(not(miri))] // not testing unsafe code
2*cc8d04f4SAlex Crichton 
3*cc8d04f4SAlex Crichton use wasmtime::component::{Component, Func, Linker, ResourceAny};
4*cc8d04f4SAlex Crichton use wasmtime::{Config, Engine, Result, Store};
5*cc8d04f4SAlex Crichton 
async_store() -> Store<()>6*cc8d04f4SAlex Crichton fn async_store() -> Store<()> {
7*cc8d04f4SAlex Crichton     let engine = Engine::default();
8*cc8d04f4SAlex Crichton     let mut store = Store::new(&engine, ());
9*cc8d04f4SAlex Crichton     wasmtime::Func::wrap_async(&mut store, |_, ()| Box::new(async {}));
10*cc8d04f4SAlex Crichton     return store;
11*cc8d04f4SAlex Crichton }
12*cc8d04f4SAlex Crichton 
func_in_store(store: &mut Store<()>) -> Result<Func>13*cc8d04f4SAlex Crichton async fn func_in_store(store: &mut Store<()>) -> Result<Func> {
14*cc8d04f4SAlex Crichton     let component = Component::new(
15*cc8d04f4SAlex Crichton         store.engine(),
16*cc8d04f4SAlex Crichton         r#"
17*cc8d04f4SAlex Crichton             (component
18*cc8d04f4SAlex Crichton                 (core module $a
19*cc8d04f4SAlex Crichton                     (func (export "hi") )
20*cc8d04f4SAlex Crichton                 )
21*cc8d04f4SAlex Crichton                 (core instance $i (instantiate $a))
22*cc8d04f4SAlex Crichton                 (func (export "hi") (canon lift (core func $i "hi")))
23*cc8d04f4SAlex Crichton             )
24*cc8d04f4SAlex Crichton         "#,
25*cc8d04f4SAlex Crichton     )?;
26*cc8d04f4SAlex Crichton     let instance = Linker::new(store.engine())
27*cc8d04f4SAlex Crichton         .instantiate_async(&mut *store, &component)
28*cc8d04f4SAlex Crichton         .await?;
29*cc8d04f4SAlex Crichton     let func = instance.get_func(&mut *store, "hi").unwrap();
30*cc8d04f4SAlex Crichton     Ok(func)
31*cc8d04f4SAlex Crichton }
32*cc8d04f4SAlex Crichton 
assert_requires_async<T>(store: &mut Store<T>)33*cc8d04f4SAlex Crichton fn assert_requires_async<T>(store: &mut Store<T>) {
34*cc8d04f4SAlex Crichton     let module = wasmtime::Module::new(store.engine(), "(module)").unwrap();
35*cc8d04f4SAlex Crichton     assert!(wasmtime::Instance::new(&mut *store, &module, &[]).is_err());
36*cc8d04f4SAlex Crichton }
37*cc8d04f4SAlex Crichton 
38*cc8d04f4SAlex Crichton #[tokio::test]
async_disallows_func_call() -> Result<()>39*cc8d04f4SAlex Crichton async fn async_disallows_func_call() -> Result<()> {
40*cc8d04f4SAlex Crichton     let mut store = async_store();
41*cc8d04f4SAlex Crichton     let func = func_in_store(&mut store).await?;
42*cc8d04f4SAlex Crichton     assert!(func.call(&mut store, &[], &mut []).is_err());
43*cc8d04f4SAlex Crichton     func.call_async(&mut store, &[], &mut []).await?;
44*cc8d04f4SAlex Crichton     Ok(())
45*cc8d04f4SAlex Crichton }
46*cc8d04f4SAlex Crichton 
47*cc8d04f4SAlex Crichton #[tokio::test]
async_disallows_typed_func_call() -> Result<()>48*cc8d04f4SAlex Crichton async fn async_disallows_typed_func_call() -> Result<()> {
49*cc8d04f4SAlex Crichton     let mut store = async_store();
50*cc8d04f4SAlex Crichton     let func = func_in_store(&mut store).await?;
51*cc8d04f4SAlex Crichton     let func = func.typed::<(), ()>(&store)?;
52*cc8d04f4SAlex Crichton     assert!(func.call(&mut store, ()).is_err());
53*cc8d04f4SAlex Crichton     func.call_async(&mut store, ()).await?;
54*cc8d04f4SAlex Crichton     Ok(())
55*cc8d04f4SAlex Crichton }
56*cc8d04f4SAlex Crichton 
57*cc8d04f4SAlex Crichton #[tokio::test]
async_disallows_instantiate() -> Result<()>58*cc8d04f4SAlex Crichton async fn async_disallows_instantiate() -> Result<()> {
59*cc8d04f4SAlex Crichton     let mut store = async_store();
60*cc8d04f4SAlex Crichton     let component = Component::new(store.engine(), "(component)")?;
61*cc8d04f4SAlex Crichton     let linker = Linker::new(store.engine());
62*cc8d04f4SAlex Crichton     assert!(linker.instantiate(&mut store, &component).is_err());
63*cc8d04f4SAlex Crichton     linker.instantiate_async(&mut store, &component).await?;
64*cc8d04f4SAlex Crichton     Ok(())
65*cc8d04f4SAlex Crichton }
66*cc8d04f4SAlex Crichton 
67*cc8d04f4SAlex Crichton #[tokio::test]
require_async_after_linker_with_func_wrap_async() -> Result<()>68*cc8d04f4SAlex Crichton async fn require_async_after_linker_with_func_wrap_async() -> Result<()> {
69*cc8d04f4SAlex Crichton     let engine = Engine::default();
70*cc8d04f4SAlex Crichton     let mut store = Store::new(&engine, ());
71*cc8d04f4SAlex Crichton     let mut linker = Linker::new(store.engine());
72*cc8d04f4SAlex Crichton     linker
73*cc8d04f4SAlex Crichton         .root()
74*cc8d04f4SAlex Crichton         .func_wrap_async("hi", |_, ()| Box::new(async { Ok(()) }))?;
75*cc8d04f4SAlex Crichton     let module = Component::new(
76*cc8d04f4SAlex Crichton         store.engine(),
77*cc8d04f4SAlex Crichton         r#"
78*cc8d04f4SAlex Crichton             (component
79*cc8d04f4SAlex Crichton                 (import "hi" (func))
80*cc8d04f4SAlex Crichton                 (core func (canon lower (func 0)))
81*cc8d04f4SAlex Crichton             )
82*cc8d04f4SAlex Crichton         "#,
83*cc8d04f4SAlex Crichton     )?;
84*cc8d04f4SAlex Crichton     linker.instantiate_async(&mut store, &module).await?;
85*cc8d04f4SAlex Crichton     assert_requires_async(&mut store);
86*cc8d04f4SAlex Crichton     Ok(())
87*cc8d04f4SAlex Crichton }
88*cc8d04f4SAlex Crichton 
89*cc8d04f4SAlex Crichton #[tokio::test]
require_async_after_linker_with_func_wrap_concurrent() -> Result<()>90*cc8d04f4SAlex Crichton async fn require_async_after_linker_with_func_wrap_concurrent() -> Result<()> {
91*cc8d04f4SAlex Crichton     let mut config = Config::new();
92*cc8d04f4SAlex Crichton     config.wasm_component_model_async(true);
93*cc8d04f4SAlex Crichton     let engine = Engine::new(&config)?;
94*cc8d04f4SAlex Crichton     let mut store = Store::new(&engine, ());
95*cc8d04f4SAlex Crichton     let mut linker = Linker::new(store.engine());
96*cc8d04f4SAlex Crichton     linker
97*cc8d04f4SAlex Crichton         .root()
98*cc8d04f4SAlex Crichton         .func_wrap_concurrent("hi", |_, ()| Box::pin(async { Ok(()) }))?;
99*cc8d04f4SAlex Crichton     let module = Component::new(
100*cc8d04f4SAlex Crichton         store.engine(),
101*cc8d04f4SAlex Crichton         r#"
102*cc8d04f4SAlex Crichton             (component
103*cc8d04f4SAlex Crichton                 (import "hi" (func async))
104*cc8d04f4SAlex Crichton                 (core func (canon lower (func 0)))
105*cc8d04f4SAlex Crichton             )
106*cc8d04f4SAlex Crichton         "#,
107*cc8d04f4SAlex Crichton     )?;
108*cc8d04f4SAlex Crichton     linker.instantiate_async(&mut store, &module).await?;
109*cc8d04f4SAlex Crichton     assert_requires_async(&mut store);
110*cc8d04f4SAlex Crichton     Ok(())
111*cc8d04f4SAlex Crichton }
112*cc8d04f4SAlex Crichton 
113*cc8d04f4SAlex Crichton #[tokio::test]
require_async_after_linker_with_func_new_async() -> Result<()>114*cc8d04f4SAlex Crichton async fn require_async_after_linker_with_func_new_async() -> Result<()> {
115*cc8d04f4SAlex Crichton     let engine = Engine::default();
116*cc8d04f4SAlex Crichton     let mut store = Store::new(&engine, ());
117*cc8d04f4SAlex Crichton     let mut linker = Linker::new(store.engine());
118*cc8d04f4SAlex Crichton     linker
119*cc8d04f4SAlex Crichton         .root()
120*cc8d04f4SAlex Crichton         .func_new_async("hi", |_, _, _, _| Box::new(async { Ok(()) }))?;
121*cc8d04f4SAlex Crichton     let module = Component::new(
122*cc8d04f4SAlex Crichton         store.engine(),
123*cc8d04f4SAlex Crichton         r#"
124*cc8d04f4SAlex Crichton             (component
125*cc8d04f4SAlex Crichton                 (import "hi" (func))
126*cc8d04f4SAlex Crichton                 (core func (canon lower (func 0)))
127*cc8d04f4SAlex Crichton             )
128*cc8d04f4SAlex Crichton         "#,
129*cc8d04f4SAlex Crichton     )?;
130*cc8d04f4SAlex Crichton     linker.instantiate_async(&mut store, &module).await?;
131*cc8d04f4SAlex Crichton     assert_requires_async(&mut store);
132*cc8d04f4SAlex Crichton     Ok(())
133*cc8d04f4SAlex Crichton }
134*cc8d04f4SAlex Crichton 
135*cc8d04f4SAlex Crichton #[tokio::test]
require_async_after_linker_with_func_new_concurrent() -> Result<()>136*cc8d04f4SAlex Crichton async fn require_async_after_linker_with_func_new_concurrent() -> Result<()> {
137*cc8d04f4SAlex Crichton     let mut config = Config::new();
138*cc8d04f4SAlex Crichton     config.wasm_component_model_async(true);
139*cc8d04f4SAlex Crichton     let engine = Engine::new(&config)?;
140*cc8d04f4SAlex Crichton     let mut store = Store::new(&engine, ());
141*cc8d04f4SAlex Crichton     let mut linker = Linker::new(store.engine());
142*cc8d04f4SAlex Crichton     linker
143*cc8d04f4SAlex Crichton         .root()
144*cc8d04f4SAlex Crichton         .func_new_concurrent("hi", |_, _, _, _| Box::pin(async { Ok(()) }))?;
145*cc8d04f4SAlex Crichton     let module = Component::new(
146*cc8d04f4SAlex Crichton         store.engine(),
147*cc8d04f4SAlex Crichton         r#"
148*cc8d04f4SAlex Crichton             (component
149*cc8d04f4SAlex Crichton                 (import "hi" (func async))
150*cc8d04f4SAlex Crichton                 (core func (canon lower (func 0)))
151*cc8d04f4SAlex Crichton             )
152*cc8d04f4SAlex Crichton         "#,
153*cc8d04f4SAlex Crichton     )?;
154*cc8d04f4SAlex Crichton     linker.instantiate_async(&mut store, &module).await?;
155*cc8d04f4SAlex Crichton     assert_requires_async(&mut store);
156*cc8d04f4SAlex Crichton     Ok(())
157*cc8d04f4SAlex Crichton }
158*cc8d04f4SAlex Crichton 
159*cc8d04f4SAlex Crichton #[tokio::test]
async_disallows_resource_any_drop() -> Result<()>160*cc8d04f4SAlex Crichton async fn async_disallows_resource_any_drop() -> Result<()> {
161*cc8d04f4SAlex Crichton     let mut store = async_store();
162*cc8d04f4SAlex Crichton     let component = Component::new(
163*cc8d04f4SAlex Crichton         store.engine(),
164*cc8d04f4SAlex Crichton         r#"
165*cc8d04f4SAlex Crichton             (component
166*cc8d04f4SAlex Crichton                 (type $t' (resource (rep i32)))
167*cc8d04f4SAlex Crichton                 (export $t "t" (type $t'))
168*cc8d04f4SAlex Crichton 
169*cc8d04f4SAlex Crichton                 (core func $new (canon resource.new $t))
170*cc8d04f4SAlex Crichton                 (func (export "mk") (param "r" u32) (result (own $t))
171*cc8d04f4SAlex Crichton                     (canon lift (core func $new))
172*cc8d04f4SAlex Crichton                 )
173*cc8d04f4SAlex Crichton             )
174*cc8d04f4SAlex Crichton         "#,
175*cc8d04f4SAlex Crichton     )?;
176*cc8d04f4SAlex Crichton     let instance = Linker::new(store.engine())
177*cc8d04f4SAlex Crichton         .instantiate_async(&mut store, &component)
178*cc8d04f4SAlex Crichton         .await?;
179*cc8d04f4SAlex Crichton     let func = instance.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "mk")?;
180*cc8d04f4SAlex Crichton     let (resource,) = func.call_async(&mut store, (42,)).await?;
181*cc8d04f4SAlex Crichton 
182*cc8d04f4SAlex Crichton     assert!(resource.resource_drop(&mut store).is_err());
183*cc8d04f4SAlex Crichton     resource.resource_drop_async(&mut store).await?;
184*cc8d04f4SAlex Crichton 
185*cc8d04f4SAlex Crichton     Ok(())
186*cc8d04f4SAlex Crichton }
187