use std::sync::Arc;
use tensor_wasm_core::types::TenantId;
use tensor_wasm_exec::engine::{EngineConfig, MemoryBackend, TensorWasmEngine};
use tensor_wasm_exec::executor::{SpawnConfig, TensorWasmExecutor};
fn growable_wasm() -> Vec<u8> {
wat::parse_str(
r#"
(module
(memory (export "mem") 1)
(func (export "grow_by_two_mb")
(drop (memory.grow (i32.const 32))))
)
"#,
)
.expect("valid wat")
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn memory_grow_past_limit_is_rejected() {
let cfg = EngineConfig {
max_memory_bytes: 1024 * 1024,
backend: MemoryBackend::PoolingMpk {
max_memories: 4,
memory_bytes: 8 * 1024 * 1024,
},
..EngineConfig::default()
};
let engine = Arc::new(TensorWasmEngine::with_config(cfg).expect("engine"));
let exec = TensorWasmExecutor::new(engine);
let id = exec
.spawn_instance(SpawnConfig::for_tenant(TenantId(1)), &growable_wasm())
.await
.expect("spawn");
exec.call_export_with_args(id, "grow_by_two_mb", &[])
.await
.expect("call returns Ok; grow rejection is in-band");
exec.terminate(id).await.expect("terminate");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn memory_grow_under_limit_succeeds() {
let cfg = EngineConfig {
max_memory_bytes: 16 * 1024 * 1024,
backend: MemoryBackend::PoolingMpk {
max_memories: 4,
memory_bytes: 16 * 1024 * 1024,
},
..EngineConfig::default()
};
let engine = Arc::new(TensorWasmEngine::with_config(cfg).expect("engine"));
let exec = TensorWasmExecutor::new(engine);
let id = exec
.spawn_instance(SpawnConfig::for_tenant(TenantId(1)), &growable_wasm())
.await
.expect("spawn");
exec.call_export_with_args(id, "grow_by_two_mb", &[])
.await
.expect("call");
exec.terminate(id).await.expect("terminate");
}