You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
8.6 KiB
298 lines
8.6 KiB
use anyhow::Result;
|
|
use wasmtime::*;
|
|
|
|
fn engine() -> Engine {
|
|
let mut config = Config::new();
|
|
config.wasm_module_linking(true);
|
|
Engine::new(&config)
|
|
}
|
|
|
|
#[test]
|
|
fn compile() -> Result<()> {
|
|
let engine = engine();
|
|
Module::new(&engine, "(module (module))")?;
|
|
Module::new(&engine, "(module (module) (module))")?;
|
|
Module::new(&engine, "(module (module (module)))")?;
|
|
Module::new(
|
|
&engine,
|
|
"
|
|
(module
|
|
(func)
|
|
(module (func))
|
|
(module (func))
|
|
)
|
|
",
|
|
)?;
|
|
let m = Module::new(
|
|
&engine,
|
|
"
|
|
(module
|
|
(global i32 (i32.const 0))
|
|
(func)
|
|
(module (memory 1) (func))
|
|
(module (memory 2) (func))
|
|
(module (table 2 funcref) (func))
|
|
(module (global i64 (i64.const 0)) (func))
|
|
)
|
|
",
|
|
)?;
|
|
assert_eq!(m.imports().len(), 0);
|
|
assert_eq!(m.exports().len(), 0);
|
|
let bytes = m.serialize()?;
|
|
Module::deserialize(&engine, &bytes)?;
|
|
assert_eq!(m.imports().len(), 0);
|
|
assert_eq!(m.exports().len(), 0);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn types() -> Result<()> {
|
|
let engine = engine();
|
|
Module::new(&engine, "(module (type (module)))")?;
|
|
Module::new(&engine, "(module (type (instance)))")?;
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn imports_exports() -> Result<()> {
|
|
let engine = engine();
|
|
|
|
// empty module type
|
|
let module = Module::new(&engine, "(module (module (export \"\")))")?;
|
|
let mut e = module.exports();
|
|
assert_eq!(e.len(), 1);
|
|
let export = e.next().unwrap();
|
|
assert_eq!(export.name(), "");
|
|
let module_ty = match export.ty() {
|
|
ExternType::Module(m) => m,
|
|
_ => panic!("unexpected type"),
|
|
};
|
|
assert_eq!(module_ty.imports().len(), 0);
|
|
assert_eq!(module_ty.exports().len(), 0);
|
|
|
|
// empty instance type
|
|
let module = Module::new(
|
|
&engine,
|
|
"
|
|
(module
|
|
(module)
|
|
(instance (export \"\") (instantiate 0)))
|
|
",
|
|
)?;
|
|
let mut e = module.exports();
|
|
assert_eq!(e.len(), 1);
|
|
let export = e.next().unwrap();
|
|
assert_eq!(export.name(), "");
|
|
let instance_ty = match export.ty() {
|
|
ExternType::Instance(i) => i,
|
|
_ => panic!("unexpected type"),
|
|
};
|
|
assert_eq!(instance_ty.exports().len(), 0);
|
|
|
|
// full module type
|
|
let module = Module::new(
|
|
&engine,
|
|
"
|
|
(module
|
|
(import \"\" \"a\" (module
|
|
(import \"a\" (func))
|
|
(export \"\" (global i32))
|
|
))
|
|
)
|
|
",
|
|
)?;
|
|
let mut i = module.imports();
|
|
assert_eq!(i.len(), 1);
|
|
let import = i.next().unwrap();
|
|
assert_eq!(import.module(), "");
|
|
assert_eq!(import.name(), None);
|
|
let instance_ty = match import.ty() {
|
|
ExternType::Instance(t) => t,
|
|
_ => panic!("unexpected type"),
|
|
};
|
|
assert_eq!(instance_ty.exports().len(), 1);
|
|
let module_ty = match instance_ty.exports().next().unwrap().ty() {
|
|
ExternType::Module(m) => m,
|
|
_ => panic!("unexpected type"),
|
|
};
|
|
assert_eq!(module_ty.imports().len(), 1);
|
|
assert_eq!(module_ty.exports().len(), 1);
|
|
let import = module_ty.imports().next().unwrap();
|
|
assert_eq!(import.module(), "a");
|
|
assert_eq!(import.name(), None);
|
|
match import.ty() {
|
|
ExternType::Func(f) => {
|
|
assert_eq!(f.results().len(), 0);
|
|
assert_eq!(f.params().len(), 0);
|
|
}
|
|
_ => panic!("unexpected type"),
|
|
}
|
|
let export = module_ty.exports().next().unwrap();
|
|
assert_eq!(export.name(), "");
|
|
match export.ty() {
|
|
ExternType::Global(g) => {
|
|
assert_eq!(*g.content(), ValType::I32);
|
|
assert_eq!(g.mutability(), Mutability::Const);
|
|
}
|
|
_ => panic!("unexpected type"),
|
|
}
|
|
|
|
// full instance type
|
|
let module = Module::new(
|
|
&engine,
|
|
"
|
|
(module
|
|
(import \"\" \"b\" (instance
|
|
(export \"m\" (memory 1))
|
|
(export \"t\" (table 1 funcref))
|
|
))
|
|
)
|
|
",
|
|
)?;
|
|
let mut i = module.imports();
|
|
assert_eq!(i.len(), 1);
|
|
let import = i.next().unwrap();
|
|
assert_eq!(import.module(), "");
|
|
assert_eq!(import.name(), None);
|
|
let instance_ty = match import.ty() {
|
|
ExternType::Instance(t) => t,
|
|
_ => panic!("unexpected type"),
|
|
};
|
|
assert_eq!(instance_ty.exports().len(), 1);
|
|
let instance_ty = match instance_ty.exports().next().unwrap().ty() {
|
|
ExternType::Instance(m) => m,
|
|
_ => panic!("unexpected type"),
|
|
};
|
|
assert_eq!(instance_ty.exports().len(), 2);
|
|
let mem_export = instance_ty.exports().nth(0).unwrap();
|
|
assert_eq!(mem_export.name(), "m");
|
|
match mem_export.ty() {
|
|
ExternType::Memory(m) => {
|
|
assert_eq!(m.limits().min(), 1);
|
|
assert_eq!(m.limits().max(), None);
|
|
}
|
|
_ => panic!("unexpected type"),
|
|
}
|
|
let table_export = instance_ty.exports().nth(1).unwrap();
|
|
assert_eq!(table_export.name(), "t");
|
|
match table_export.ty() {
|
|
ExternType::Table(t) => {
|
|
assert_eq!(t.limits().min(), 1);
|
|
assert_eq!(t.limits().max(), None);
|
|
assert_eq!(*t.element(), ValType::FuncRef);
|
|
}
|
|
_ => panic!("unexpected type"),
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn limit_instances() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_module_linking(true);
|
|
config.max_instances(10);
|
|
let engine = Engine::new(&config);
|
|
let module = Module::new(
|
|
&engine,
|
|
r#"
|
|
(module $PARENT
|
|
(module $m0)
|
|
(module $m1
|
|
(instance (instantiate (module outer $PARENT $m0)))
|
|
(instance (instantiate (module outer $PARENT $m0))))
|
|
(module $m2
|
|
(instance (instantiate (module outer $PARENT $m1)))
|
|
(instance (instantiate (module outer $PARENT $m1))))
|
|
(module $m3
|
|
(instance (instantiate (module outer $PARENT $m2)))
|
|
(instance (instantiate (module outer $PARENT $m2))))
|
|
(module $m4
|
|
(instance (instantiate (module outer $PARENT $m3)))
|
|
(instance (instantiate (module outer $PARENT $m3))))
|
|
(module $m5
|
|
(instance (instantiate (module outer $PARENT $m4)))
|
|
(instance (instantiate (module outer $PARENT $m4))))
|
|
(instance (instantiate $m5))
|
|
)
|
|
"#,
|
|
)?;
|
|
let store = Store::new(&engine);
|
|
let err = Instance::new(&store, &module, &[]).err().unwrap();
|
|
assert!(
|
|
err.to_string().contains("resource limit exceeded"),
|
|
"bad error: {}",
|
|
err
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn limit_memories() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_module_linking(true);
|
|
config.wasm_multi_memory(true);
|
|
config.max_memories(10);
|
|
let engine = Engine::new(&config);
|
|
let module = Module::new(
|
|
&engine,
|
|
r#"
|
|
(module
|
|
(module $m0
|
|
(memory 1 1)
|
|
(memory 1 1)
|
|
(memory 1 1)
|
|
(memory 1 1)
|
|
(memory 1 1)
|
|
)
|
|
|
|
(instance (instantiate $m0))
|
|
(instance (instantiate $m0))
|
|
(instance (instantiate $m0))
|
|
(instance (instantiate $m0))
|
|
)
|
|
"#,
|
|
)?;
|
|
let store = Store::new(&engine);
|
|
let err = Instance::new(&store, &module, &[]).err().unwrap();
|
|
assert!(
|
|
err.to_string().contains("resource limit exceeded"),
|
|
"bad error: {}",
|
|
err
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn limit_tables() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_module_linking(true);
|
|
config.max_tables(10);
|
|
let engine = Engine::new(&config);
|
|
let module = Module::new(
|
|
&engine,
|
|
r#"
|
|
(module
|
|
(module $m0
|
|
(table 1 1 funcref)
|
|
(table 1 1 funcref)
|
|
(table 1 1 funcref)
|
|
(table 1 1 funcref)
|
|
(table 1 1 funcref)
|
|
)
|
|
|
|
(instance (instantiate $m0))
|
|
(instance (instantiate $m0))
|
|
(instance (instantiate $m0))
|
|
(instance (instantiate $m0))
|
|
)
|
|
"#,
|
|
)?;
|
|
let store = Store::new(&engine);
|
|
let err = Instance::new(&store, &module, &[]).err().unwrap();
|
|
assert!(
|
|
err.to_string().contains("resource limit exceeded"),
|
|
"bad error: {}",
|
|
err
|
|
);
|
|
Ok(())
|
|
}
|
|
|