Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/missing_async.rs
3061 views
1
#![cfg(not(miri))] // not testing unsafe code
2
3
use wasmtime::*;
4
5
fn async_store() -> Store<()> {
6
let engine = Engine::default();
7
let mut store = Store::new(&engine, ());
8
Func::wrap_async(&mut store, |_, ()| Box::new(async {}));
9
return store;
10
}
11
12
struct MyAsyncLimiter;
13
14
#[async_trait::async_trait]
15
impl ResourceLimiterAsync for MyAsyncLimiter {
16
async fn memory_growing(
17
&mut self,
18
_current: usize,
19
_desired: usize,
20
_maximum: Option<usize>,
21
) -> Result<bool> {
22
Ok(true)
23
}
24
25
async fn table_growing(
26
&mut self,
27
_current: usize,
28
_desired: usize,
29
_maximum: Option<usize>,
30
) -> Result<bool> {
31
Ok(true)
32
}
33
}
34
35
fn async_limiter_store() -> Store<MyAsyncLimiter> {
36
let engine = Engine::default();
37
let mut store = Store::new(&engine, MyAsyncLimiter);
38
store.limiter_async(|x| x);
39
return store;
40
}
41
42
fn assert_requires_async<T>(store: &mut Store<T>) {
43
let module = Module::new(store.engine(), "(module)").unwrap();
44
assert!(Instance::new(&mut *store, &module, &[]).is_err());
45
}
46
47
#[test]
48
fn require_async_after_func_wrap() {
49
let engine = Engine::default();
50
let mut store = Store::new(&engine, ());
51
Func::wrap_async(&mut store, |_, ()| Box::new(async {}));
52
assert_requires_async(&mut store);
53
}
54
55
#[test]
56
fn require_async_after_func_new() {
57
let engine = Engine::default();
58
let mut store = Store::new(&engine, ());
59
let ty = FuncType::new(store.engine(), [], []);
60
Func::new_async(&mut store, ty, |_, _, _| Box::new(async { Ok(()) }));
61
assert_requires_async(&mut store);
62
}
63
64
#[tokio::test]
65
async fn require_async_after_linker_with_func_wrap() -> Result<()> {
66
let engine = Engine::default();
67
let mut store = Store::new(&engine, ());
68
let mut linker = Linker::new(store.engine());
69
linker.func_wrap_async("", "", |_, ()| Box::new(async {}))?;
70
let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
71
linker.instantiate_async(&mut store, &module).await?;
72
assert_requires_async(&mut store);
73
Ok(())
74
}
75
76
#[tokio::test]
77
async fn require_async_after_linker_with_func_new() -> Result<()> {
78
let engine = Engine::default();
79
let mut store = Store::new(&engine, ());
80
let mut linker = Linker::new(store.engine());
81
let ty = FuncType::new(store.engine(), [], []);
82
linker.func_new_async("", "", ty, |_, _, _| Box::new(async { Ok(()) }))?;
83
let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
84
linker.instantiate_async(&mut store, &module).await?;
85
assert_requires_async(&mut store);
86
Ok(())
87
}
88
89
#[test]
90
fn require_async_after_epochs() -> Result<()> {
91
let mut config = Config::new();
92
config.epoch_interruption(true);
93
let engine = Engine::new(&config)?;
94
let mut store = Store::new(&engine, ());
95
store.epoch_deadline_async_yield_and_update(1);
96
assert_requires_async(&mut store);
97
Ok(())
98
}
99
100
#[test]
101
fn require_async_after_fuel() -> Result<()> {
102
let mut config = Config::new();
103
config.consume_fuel(true);
104
let engine = Engine::new(&config)?;
105
let mut store = Store::new(&engine, ());
106
store.fuel_async_yield_interval(Some(1))?;
107
assert_requires_async(&mut store);
108
Ok(())
109
}
110
111
#[test]
112
fn require_async_after_async_limiter() -> Result<()> {
113
let mut store = async_limiter_store();
114
assert_requires_async(&mut store);
115
Ok(())
116
}
117
118
#[tokio::test]
119
async fn require_async_with_linker_func_wrap() -> Result<()> {
120
let engine = Engine::default();
121
let mut store = Store::new(&engine, ());
122
let mut linker = Linker::new(store.engine());
123
linker.func_wrap_async("", "", |_, ()| Box::new(async {}))?;
124
let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
125
assert!(linker.instantiate(&mut store, &module).is_err());
126
linker.instantiate_async(&mut store, &module).await?;
127
Ok(())
128
}
129
130
#[test]
131
fn require_async_with_debug_handler() -> Result<()> {
132
let mut config = Config::new();
133
config.guest_debug(true);
134
let engine = Engine::new(&config)?;
135
let mut store = Store::new(&engine, ());
136
store.set_debug_handler(MyDebugHandler);
137
assert_requires_async(&mut store);
138
return Ok(());
139
140
#[derive(Clone)]
141
struct MyDebugHandler;
142
143
impl DebugHandler for MyDebugHandler {
144
type Data = ();
145
146
async fn handle(&self, _: StoreContextMut<'_, ()>, _: DebugEvent<'_>) {}
147
}
148
}
149
150
struct MyAsyncCallHook;
151
152
#[async_trait::async_trait]
153
impl CallHookHandler<()> for MyAsyncCallHook {
154
async fn handle_call_event(&self, _: StoreContextMut<'_, ()>, _: CallHook) -> Result<()> {
155
Ok(())
156
}
157
}
158
159
#[test]
160
fn require_async_with_async_call_hook() -> Result<()> {
161
let engine = Engine::default();
162
let mut store = Store::new(&engine, ());
163
store.call_hook_async(MyAsyncCallHook);
164
assert_requires_async(&mut store);
165
Ok(())
166
}
167
168
#[tokio::test]
169
async fn async_disallows_instance_new() -> Result<()> {
170
let mut store = async_store();
171
let module = Module::new(store.engine(), "(module)")?;
172
assert!(Instance::new(&mut store, &module, &[]).is_err());
173
Instance::new_async(&mut store, &module, &[]).await?;
174
Ok(())
175
}
176
177
#[tokio::test]
178
async fn async_disallows_linker_instantiate() -> Result<()> {
179
let mut store = async_store();
180
let module = Module::new(store.engine(), "(module)")?;
181
let linker = Linker::new(store.engine());
182
assert!(linker.instantiate(&mut store, &module).is_err());
183
linker.instantiate_async(&mut store, &module).await?;
184
Ok(())
185
}
186
187
#[tokio::test]
188
async fn async_disallows_func_call() -> Result<()> {
189
let mut store = async_store();
190
let func = Func::wrap(&mut store, || {});
191
assert!(func.call(&mut store, &[], &mut []).is_err());
192
func.call_async(&mut store, &[], &mut []).await?;
193
Ok(())
194
}
195
196
#[tokio::test]
197
async fn async_disallows_typed_func_call() -> Result<()> {
198
let mut store = async_store();
199
let func = Func::wrap(&mut store, || {});
200
let func = func.typed::<(), ()>(&mut store)?;
201
assert!(func.call(&mut store, ()).is_err());
202
func.call_async(&mut store, ()).await?;
203
Ok(())
204
}
205
206
#[tokio::test]
207
async fn async_disallows_gc() -> Result<()> {
208
let mut store = async_limiter_store();
209
assert!(store.gc(None).is_err());
210
store.gc_async(None).await;
211
Ok(())
212
}
213
214
#[tokio::test]
215
async fn async_disallows_array_ref_new() -> Result<()> {
216
let mut store = async_limiter_store();
217
let ty = ArrayType::new(
218
store.engine(),
219
FieldType::new(Mutability::Var, StorageType::I8),
220
);
221
let pre = ArrayRefPre::new(&mut store, ty);
222
assert!(ArrayRef::new(&mut store, &pre, &Val::I32(0), 10).is_err());
223
ArrayRef::new_async(&mut store, &pre, &Val::I32(0), 10).await?;
224
Ok(())
225
}
226
227
#[tokio::test]
228
async fn async_disallows_array_ref_new_fixed() -> Result<()> {
229
let mut store = async_limiter_store();
230
let ty = ArrayType::new(
231
store.engine(),
232
FieldType::new(Mutability::Var, StorageType::I8),
233
);
234
let pre = ArrayRefPre::new(&mut store, ty);
235
assert!(ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(0)]).is_err());
236
ArrayRef::new_fixed_async(&mut store, &pre, &[Val::I32(0)]).await?;
237
Ok(())
238
}
239
240
#[tokio::test]
241
async fn async_disallows_exnref_new() -> Result<()> {
242
let mut store = async_limiter_store();
243
let ty = ExnType::new(store.engine(), [])?;
244
let pre = ExnRefPre::new(&mut store, ty);
245
let fty = FuncType::new(store.engine(), [], []);
246
let tag = Tag::new(&mut store, &TagType::new(fty))?;
247
assert!(ExnRef::new(&mut store, &pre, &tag, &[]).is_err());
248
ExnRef::new_async(&mut store, &pre, &tag, &[]).await?;
249
Ok(())
250
}
251
252
#[tokio::test]
253
async fn async_disallows_externref_new() -> Result<()> {
254
let mut store = async_limiter_store();
255
assert!(ExternRef::new(&mut store, 1).is_err());
256
ExternRef::new_async(&mut store, 1).await?;
257
Ok(())
258
}
259
260
#[tokio::test]
261
async fn async_disallows_structref_new() -> Result<()> {
262
let mut store = async_limiter_store();
263
let ty = StructType::new(
264
store.engine(),
265
[FieldType::new(Mutability::Var, StorageType::I8)],
266
)?;
267
let pre = StructRefPre::new(&mut store, ty);
268
assert!(StructRef::new(&mut store, &pre, &[Val::I32(0)]).is_err());
269
StructRef::new_async(&mut store, &pre, &[Val::I32(0)]).await?;
270
Ok(())
271
}
272
273
#[test]
274
fn epoch_yield_disallowed_without_async() -> Result<()> {
275
let mut config = Config::new();
276
config.epoch_interruption(true);
277
let engine = Engine::new(&config)?;
278
let mut store = Store::new(&engine, ());
279
280
let module = Module::new(&engine, r#"(module (func (export "") (loop br 0)))"#)?;
281
let instance = Instance::new(&mut store, &module, &[])?;
282
let func = instance.get_typed_func::<(), ()>(&mut store, "")?;
283
284
store.epoch_deadline_callback(|_store| Ok(UpdateDeadline::Yield(1)));
285
assert!(func.call(&mut store, ()).is_err());
286
287
store.epoch_deadline_callback(|_store| Ok(UpdateDeadline::YieldCustom(1, Box::pin(async {}))));
288
assert!(func.call(&mut store, ()).is_err());
289
290
store.epoch_deadline_trap();
291
let err = func.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
292
assert_eq!(err, Trap::Interrupt);
293
Ok(())
294
}
295
296
#[test]
297
fn start_sync_then_configure_async_then_do_async() -> Result<()> {
298
let mut config = Config::new();
299
config.consume_fuel(true);
300
let engine = Engine::new(&config)?;
301
let mut store = Store::new(&engine, MyAsyncLimiter);
302
303
let module = Module::new(
304
&engine,
305
r#"
306
(module
307
(import "" "" (func $host))
308
(memory 1)
309
(func (export "")
310
call $host
311
(loop br 0)
312
)
313
)
314
"#,
315
)?;
316
317
let mut linker = Linker::new(&engine);
318
linker.func_wrap("", "", |mut store: Caller<'_, MyAsyncLimiter>| {
319
store.as_context_mut().fuel_async_yield_interval(Some(1))
320
})?;
321
store.set_fuel(100)?;
322
let instance = linker.instantiate(&mut store, &module)?;
323
let func = instance.get_typed_func::<(), ()>(&mut store, "")?;
324
let err = func.call(&mut store, ()).unwrap_err();
325
assert!(
326
format!("{err:?}").contains("configured to do async things"),
327
"bad error {err:?}",
328
);
329
Ok(())
330
}
331
332
#[tokio::test]
333
async fn async_limiter_disallows_table_new() -> Result<()> {
334
let mut store = async_limiter_store();
335
let ty = TableType::new(RefType::FUNCREF, 1, None);
336
assert!(Table::new(&mut store, ty.clone(), Ref::Func(None)).is_err());
337
Table::new_async(&mut store, ty, Ref::Func(None)).await?;
338
Ok(())
339
}
340
341
#[tokio::test]
342
async fn async_limiter_disallows_table_grow() -> Result<()> {
343
let mut store = async_limiter_store();
344
let ty = TableType::new(RefType::FUNCREF, 1, None);
345
let table = Table::new_async(&mut store, ty, Ref::Func(None)).await?;
346
assert!(table.grow(&mut store, 1, Ref::Func(None)).is_err());
347
table.grow_async(&mut store, 1, Ref::Func(None)).await?;
348
Ok(())
349
}
350
351
#[tokio::test]
352
async fn async_limiter_disallows_memory_new() -> Result<()> {
353
let mut store = async_limiter_store();
354
let ty = MemoryType::new(1, None);
355
assert!(Memory::new(&mut store, ty.clone()).is_err());
356
Memory::new_async(&mut store, ty).await?;
357
Ok(())
358
}
359
360
#[tokio::test]
361
async fn async_limiter_disallows_memory_grow() -> Result<()> {
362
let mut store = async_limiter_store();
363
let ty = MemoryType::new(1, None);
364
let mem = Memory::new_async(&mut store, ty).await?;
365
assert!(mem.grow(&mut store, 1).is_err());
366
mem.grow_async(&mut store, 1).await?;
367
Ok(())
368
}
369
370