mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-04 18:10:18 +00:00
110 lines
3.4 KiB
Rust
110 lines
3.4 KiB
Rust
mod utils;
|
|
use crate::utils::StdioCapturer;
|
|
use serde::{Deserialize, Serialize};
|
|
use wasmer::compiler::{compile_with, compiler_for_backend};
|
|
use wasmer::Func;
|
|
use wasmer_wasi::state::WasiState;
|
|
use wasmer_wasi::{generate_import_object_from_state, get_wasi_version};
|
|
|
|
use lazy_static::lazy_static;
|
|
use std::sync::Mutex;
|
|
lazy_static! {
|
|
// We want to run wasi tests one by one
|
|
// Based from: https://stackoverflow.com/questions/51694017/how-can-i-avoid-running-some-tests-in-parallel
|
|
static ref WASI_LOCK: Mutex<()> = Mutex::new(());
|
|
}
|
|
|
|
/// This is the structure of the `.out` file
|
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
|
pub struct WasiTest {
|
|
/// The program expected output
|
|
pub output: String,
|
|
/// The program options
|
|
pub options: WasiOptions,
|
|
}
|
|
|
|
/// The options provied when executed a WASI Wasm program
|
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
|
pub struct WasiOptions {
|
|
/// Mapped pre-opened dirs
|
|
pub mapdir: Vec<(String, String)>,
|
|
/// Environment vars
|
|
pub env: Vec<(String, String)>,
|
|
/// Program arguments
|
|
pub args: Vec<String>,
|
|
/// Pre-opened directories
|
|
pub dir: Vec<String>,
|
|
}
|
|
|
|
// The generated tests (from build.rs) look like:
|
|
// #[cfg(test)]
|
|
// mod singlepass {
|
|
// mod wasi {
|
|
// #[test]
|
|
// fn hello() -> anyhow::Result<()> {
|
|
// crate::run_wasi(
|
|
// "tests/wasi_test_resources/snapshot1/hello.wasm",
|
|
// "tests/wasi_test_resources/snapshot1/hello.out",
|
|
// "singlepass"
|
|
// )
|
|
// }
|
|
// }
|
|
// }
|
|
include!(concat!(env!("OUT_DIR"), "/generated_wasitests.rs"));
|
|
|
|
fn run_wasi(
|
|
wasm_program_path: &str,
|
|
wasi_json_test_path: &str,
|
|
backend: &str,
|
|
) -> anyhow::Result<()> {
|
|
let _shared = WASI_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
|
|
|
let backend = utils::get_backend_from_str(backend)?;
|
|
|
|
let wasi_json_test = std::fs::read(wasi_json_test_path)?;
|
|
let wasitest: WasiTest = serde_json::from_slice(&wasi_json_test)?;
|
|
|
|
let wasm_binary = std::fs::read(wasm_program_path)?;
|
|
let compiler = compiler_for_backend(backend).expect("Backend not recognized");
|
|
let module = compile_with(&wasm_binary, &*compiler).unwrap();
|
|
|
|
let wasi_version = get_wasi_version(&module, true).expect("WASI module");
|
|
// println!("Executing WASI: {:?}", wasitest);
|
|
let mut state_builder = WasiState::new("");
|
|
let wasi_state = state_builder
|
|
.envs(wasitest.options.env)
|
|
.args(wasitest.options.args)
|
|
.preopen_dirs(wasitest.options.dir)?
|
|
.map_dirs(wasitest.options.mapdir)?
|
|
.build()?;
|
|
|
|
let import_object = generate_import_object_from_state(wasi_state, wasi_version);
|
|
|
|
let instance = module
|
|
.instantiate(&import_object)
|
|
.map_err(|err| format!("Can't instantiate the WebAssembly module: {:?}", err))
|
|
.unwrap(); // NOTE: Need to figure what the unwrap is for ??
|
|
|
|
let capturer = StdioCapturer::new();
|
|
|
|
let start: Func<(), ()> = instance
|
|
.exports
|
|
.get("_start")
|
|
.map_err(|e| format!("{:?}", e))
|
|
.expect("start function in wasi module");
|
|
|
|
start.call().expect("execute the wasm");
|
|
|
|
let output = capturer.end().unwrap().0;
|
|
let expected_output = wasitest.output;
|
|
|
|
assert!(
|
|
output.contains(&expected_output),
|
|
"Output: `{}` does not contain expected output: `{}`",
|
|
output,
|
|
expected_output
|
|
);
|
|
|
|
Ok(())
|
|
}
|