diff --git a/.gitmodules b/.gitmodules index ee264b99c4..ba7f679343 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "crates/wasi-crypto/spec"] path = crates/wasi-crypto/spec url = https://github.com/WebAssembly/wasi-crypto.git +[submodule "tests/wasi_testsuite/wasi-threads"] + path = tests/wasi_testsuite/wasi-threads + url = https://github.com/WebAssembly/wasi-threads diff --git a/Cargo.toml b/Cargo.toml index 407ab2fd05..e92983c12e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,8 @@ component-macro-test = { path = "crates/misc/component-macro-test" } component-test-util = { workspace = true } bstr = "0.2.17" libc = "0.2.60" +serde = "1.0" +serde_json = "1.0" [target.'cfg(windows)'.dev-dependencies] windows-sys = { workspace = true, features = ["Win32_System_Memory"] } diff --git a/tests/all/cli_tests.rs b/tests/all/cli_tests.rs index 7086ebea68..6a1baa47ed 100644 --- a/tests/all/cli_tests.rs +++ b/tests/all/cli_tests.rs @@ -7,7 +7,7 @@ use tempfile::{NamedTempFile, TempDir}; // Run the wasmtime CLI with the provided args and return the `Output`. // If the `stdin` is `Some`, opens the file and redirects to the child's stdin. -fn run_wasmtime_for_output(args: &[&str], stdin: Option<&Path>) -> Result { +pub fn run_wasmtime_for_output(args: &[&str], stdin: Option<&Path>) -> Result { let runner = std::env::vars() .filter(|(k, _v)| k.starts_with("CARGO_TARGET") && k.ends_with("RUNNER")) .next(); diff --git a/tests/all/main.rs b/tests/all/main.rs index 9b613ffb10..80455d383f 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -32,6 +32,7 @@ mod table; mod threads; mod traps; mod wait_notify; +mod wasi_testsuite; mod wast; /// A helper to compile a module in a new store with reference types enabled. diff --git a/tests/all/wasi_testsuite.rs b/tests/all/wasi_testsuite.rs new file mode 100644 index 0000000000..81d2bf434a --- /dev/null +++ b/tests/all/wasi_testsuite.rs @@ -0,0 +1,79 @@ +//! Run the tests in `wasi_testsuite` using Wasmtime's CLI binary and checking +//! the results with a [wasi-testsuite] spec. +//! +//! [wasi-testsuite]: https://github.com/WebAssembly/wasi-testsuite + +use crate::cli_tests::run_wasmtime_for_output; +use anyhow::Result; +use serde::Deserialize; +use std::ffi::OsStr; +use std::fs::{self, DirEntry}; +use std::path::{Path, PathBuf}; +use std::process::Output; + +#[test] +#[cfg_attr(target_os = "windows", ignore)] // TODO: https://github.com/WebAssembly/WASI/issues/524 +fn wasi_threads_testsuite() -> Result<()> { + for module in list_modules("tests/wasi_testsuite/wasi-threads/test/testsuite")? { + println!("Testing {}", module.display()); + let result = run(&module)?; + let spec = parse_spec(&module.with_extension("json"))?; + assert_eq!(spec, result); + } + Ok(()) +} + +fn list_modules(testsuite_dir: &str) -> Result> { + Ok(fs::read_dir(testsuite_dir)? + .filter_map(Result::ok) + .filter(is_wasm) + .map(|e| e.path())) +} + +fn is_wasm(entry: &DirEntry) -> bool { + let path = entry.path(); + let ext = path.extension().map(OsStr::to_str).flatten(); + path.is_file() && (ext == Some("wat") || ext == Some("wasm")) +} + +fn run>(module: P) -> Result { + run_wasmtime_for_output( + &[ + "run", + "--wasi-modules", + "experimental-wasi-threads", + "--wasm-features", + "threads", + "--disable-cache", + module.as_ref().to_str().unwrap(), + ], + None, + ) +} + +fn parse_spec>(spec_file: P) -> Result { + let contents = fs::read_to_string(spec_file)?; + let spec = serde_json::from_str(&contents)?; + Ok(spec) +} + +#[derive(Debug, Deserialize)] +struct Spec { + exit_code: i32, + stdout: Option, + stderr: Option, +} + +impl PartialEq for Spec { + fn eq(&self, other: &Output) -> bool { + self.exit_code == other.status.code().unwrap() + && matches_or_missing(&self.stdout, &other.stdout) + && matches_or_missing(&self.stderr, &other.stderr) + } +} + +fn matches_or_missing(a: &Option, b: &[u8]) -> bool { + a.as_ref() + .map(|s| s == &String::from_utf8_lossy(b)) + .unwrap_or(true) +} diff --git a/tests/wasi_testsuite/wasi-threads b/tests/wasi_testsuite/wasi-threads new file mode 160000 index 0000000000..e1893c0045 --- /dev/null +++ b/tests/wasi_testsuite/wasi-threads @@ -0,0 +1 @@ +Subproject commit e1893c00458de3e846f02c9cd2a435992ea8b32c