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.
117 lines
3.7 KiB
117 lines
3.7 KiB
use anyhow::{bail, Result};
|
|
use std::fs;
|
|
use wasmtime::*;
|
|
|
|
fn serialize(engine: &Engine, wat: &str) -> Result<Vec<u8>> {
|
|
let module = Module::new(&engine, wat)?;
|
|
Ok(module.serialize()?)
|
|
}
|
|
|
|
unsafe fn deserialize_and_instantiate(store: &mut Store<()>, buffer: &[u8]) -> Result<Instance> {
|
|
let module = Module::deserialize(store.engine(), buffer)?;
|
|
Ok(Instance::new(store, &module, &[])?)
|
|
}
|
|
|
|
#[test]
|
|
fn test_version_mismatch() -> Result<()> {
|
|
let engine = Engine::default();
|
|
let buffer = serialize(&engine, "(module)")?;
|
|
|
|
let mut config = Config::new();
|
|
config
|
|
.module_version(ModuleVersionStrategy::Custom("custom!".to_owned()))
|
|
.unwrap();
|
|
let custom_version_engine = Engine::new(&config).unwrap();
|
|
match unsafe { Module::deserialize(&custom_version_engine, &buffer) } {
|
|
Ok(_) => bail!("expected deserialization to fail"),
|
|
Err(e) => assert!(e
|
|
.to_string()
|
|
.starts_with("Module was compiled with incompatible version")),
|
|
}
|
|
|
|
let mut config = Config::new();
|
|
config.module_version(ModuleVersionStrategy::None).unwrap();
|
|
let none_version_engine = Engine::new(&config).unwrap();
|
|
unsafe { Module::deserialize(&none_version_engine, &buffer) }
|
|
.expect("accepts the wasmtime versioned module");
|
|
|
|
let buffer = serialize(&custom_version_engine, "(module)")?;
|
|
unsafe { Module::deserialize(&none_version_engine, &buffer) }
|
|
.expect("accepts the custom versioned module");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_module_serialize_simple() -> Result<()> {
|
|
let buffer = serialize(
|
|
&Engine::default(),
|
|
"(module (func (export \"run\") (result i32) i32.const 42))",
|
|
)?;
|
|
|
|
let mut store = Store::default();
|
|
let instance = unsafe { deserialize_and_instantiate(&mut store, &buffer)? };
|
|
let run = instance.get_typed_func::<(), i32>(&mut store, "run")?;
|
|
let result = run.call(&mut store, ())?;
|
|
|
|
assert_eq!(42, result);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_module_serialize_fail() -> Result<()> {
|
|
let buffer = serialize(
|
|
&Engine::default(),
|
|
"(module (func (export \"run\") (result i32) i32.const 42))",
|
|
)?;
|
|
|
|
let mut config = Config::new();
|
|
config.static_memory_maximum_size(0);
|
|
let mut store = Store::new(&Engine::new(&config)?, ());
|
|
match unsafe { deserialize_and_instantiate(&mut store, &buffer) } {
|
|
Ok(_) => bail!("expected failure at deserialization"),
|
|
Err(_) => (),
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_deserialize_from_file() -> Result<()> {
|
|
serialize_and_call("(module (func (export \"run\") (result i32) i32.const 42))")?;
|
|
serialize_and_call(
|
|
"(module
|
|
(func (export \"run\") (result i32)
|
|
call $answer)
|
|
|
|
(func $answer (result i32)
|
|
i32.const 42))
|
|
",
|
|
)?;
|
|
return Ok(());
|
|
|
|
fn serialize_and_call(wat: &str) -> Result<()> {
|
|
let mut store = Store::<()>::default();
|
|
let td = tempfile::TempDir::new()?;
|
|
let buffer = serialize(store.engine(), wat)?;
|
|
|
|
let path = td.path().join("module.bin");
|
|
fs::write(&path, &buffer)?;
|
|
let module = unsafe { Module::deserialize_file(store.engine(), &path)? };
|
|
let instance = Instance::new(&mut store, &module, &[])?;
|
|
let func = instance.get_typed_func::<(), i32>(&mut store, "run")?;
|
|
assert_eq!(func.call(&mut store, ())?, 42);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn deserialize_from_serialized() -> Result<()> {
|
|
let engine = Engine::default();
|
|
let buffer1 = serialize(
|
|
&engine,
|
|
"(module (func (export \"run\") (result i32) i32.const 42))",
|
|
)?;
|
|
let buffer2 = unsafe { Module::deserialize(&engine, &buffer1)?.serialize()? };
|
|
assert!(buffer1 == buffer2);
|
|
Ok(())
|
|
}
|
|
|