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