Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
86 lines
2.9 KiB
Rust
86 lines
2.9 KiB
Rust
use anyhow::Context;
|
|
use std::path::Path;
|
|
use wasi_common::pipe::WritePipe;
|
|
use wasmtime::{Engine, Linker, Module, Store};
|
|
use wasmtime_wasi::sync::{add_to_linker, WasiCtxBuilder};
|
|
|
|
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
|
run(data, bin_name, workspace, false)
|
|
}
|
|
pub fn instantiate_inherit_stdio(
|
|
data: &[u8],
|
|
bin_name: &str,
|
|
workspace: Option<&Path>,
|
|
) -> anyhow::Result<()> {
|
|
run(data, bin_name, workspace, true)
|
|
}
|
|
|
|
fn run(
|
|
data: &[u8],
|
|
bin_name: &str,
|
|
workspace: Option<&Path>,
|
|
inherit_stdio: bool,
|
|
) -> anyhow::Result<()> {
|
|
let stdout = WritePipe::new_in_memory();
|
|
let stderr = WritePipe::new_in_memory();
|
|
|
|
let r = {
|
|
let engine = Engine::default();
|
|
let module = Module::new(&engine, &data).context("failed to create wasm module")?;
|
|
let mut linker = Linker::new(&engine);
|
|
add_to_linker(&mut linker, |cx| cx)?;
|
|
|
|
// Create our wasi context.
|
|
// Additionally register any preopened directories if we have them.
|
|
let mut builder = WasiCtxBuilder::new();
|
|
|
|
if inherit_stdio {
|
|
builder = builder.inherit_stdio();
|
|
} else {
|
|
builder = builder
|
|
.stdout(Box::new(stdout.clone()))
|
|
.stderr(Box::new(stderr.clone()));
|
|
}
|
|
|
|
builder = builder.arg(bin_name)?.arg(".")?;
|
|
|
|
if let Some(workspace) = workspace {
|
|
println!("preopen: {:?}", workspace);
|
|
let preopen_dir = unsafe { cap_std::fs::Dir::open_ambient_dir(workspace) }?;
|
|
builder = builder.preopened_dir(preopen_dir, ".")?;
|
|
}
|
|
for (var, val) in super::test_suite_environment() {
|
|
builder = builder.env(var, val)?;
|
|
}
|
|
|
|
// cap-std-sync does not yet support the sync family of fdflags
|
|
builder = builder.env("NO_FDFLAGS_SYNC_SUPPORT", "1")?;
|
|
|
|
let mut store = Store::new(&engine, builder.build());
|
|
let instance = linker.instantiate(&mut store, &module)?;
|
|
let start = instance.get_typed_func::<(), (), _>(&mut store, "_start")?;
|
|
start.call(&mut store, ()).map_err(anyhow::Error::from)
|
|
};
|
|
|
|
match r {
|
|
Ok(()) => Ok(()),
|
|
Err(trap) => {
|
|
let stdout = stdout
|
|
.try_into_inner()
|
|
.expect("sole ref to stdout")
|
|
.into_inner();
|
|
if !stdout.is_empty() {
|
|
println!("guest stdout:\n{}\n===", String::from_utf8_lossy(&stdout));
|
|
}
|
|
let stderr = stderr
|
|
.try_into_inner()
|
|
.expect("sole ref to stderr")
|
|
.into_inner();
|
|
if !stderr.is_empty() {
|
|
println!("guest stderr:\n{}\n===", String::from_utf8_lossy(&stderr));
|
|
}
|
|
Err(trap.context(format!("error while testing Wasm module '{}'", bin_name,)))
|
|
}
|
|
}
|
|
}
|