diff --git a/tests/all/limits.rs b/tests/all/limits.rs index 7e1b303906..dab1542794 100644 --- a/tests/all/limits.rs +++ b/tests/all/limits.rs @@ -65,6 +65,96 @@ fn test_limits() -> Result<()> { Ok(()) } +#[tokio::test] +async fn test_limits_async() -> Result<()> { + let mut config = Config::new(); + config.async_support(true); + let engine = Engine::new(&config).unwrap(); + let module = Module::new( + &engine, + r#"(module (memory (export "m") 0) (table (export "t") 0 anyfunc))"#, + )?; + + struct LimitsAsync { + memory_size: usize, + table_elements: u32, + } + #[async_trait::async_trait] + impl ResourceLimiterAsync for LimitsAsync { + async fn memory_growing( + &mut self, + _current: usize, + desired: usize, + _maximum: Option, + ) -> bool { + desired <= self.memory_size + } + fn memory_grow_failed(&mut self, _error: &anyhow::Error) {} + async fn table_growing( + &mut self, + _current: u32, + desired: u32, + _maximum: Option, + ) -> bool { + desired <= self.table_elements + } + } + + let mut store = Store::new( + &engine, + LimitsAsync { + memory_size: 10 * WASM_PAGE_SIZE, + table_elements: 5, + }, + ); + + store.limiter_async(|s| s as &mut dyn ResourceLimiterAsync); + + let instance = Instance::new_async(&mut store, &module, &[]).await?; + + // Test instance exports and host objects hitting the limit + for memory in std::array::IntoIter::new([ + instance.get_memory(&mut store, "m").unwrap(), + Memory::new(&mut store, MemoryType::new(0, None))?, + ]) { + memory.grow(&mut store, 3)?; + memory.grow(&mut store, 5)?; + memory.grow(&mut store, 2)?; + + assert_eq!( + memory + .grow(&mut store, 1) + .map_err(|e| e.to_string()) + .unwrap_err(), + "failed to grow memory by `1`" + ); + } + + // Test instance exports and host objects hitting the limit + for table in std::array::IntoIter::new([ + instance.get_table(&mut store, "t").unwrap(), + Table::new( + &mut store, + TableType::new(ValType::FuncRef, 0, None), + Val::FuncRef(None), + )?, + ]) { + table.grow(&mut store, 2, Val::FuncRef(None))?; + table.grow(&mut store, 1, Val::FuncRef(None))?; + table.grow(&mut store, 2, Val::FuncRef(None))?; + + assert_eq!( + table + .grow(&mut store, 1, Val::FuncRef(None)) + .map_err(|e| e.to_string()) + .unwrap_err(), + "failed to grow table by `1`" + ); + } + + Ok(()) +} + #[test] fn test_limits_memory_only() -> Result<()> { let engine = Engine::default();