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