diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index cddceb58fd..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "tests/misc-tests"] - path = tests/misc-tests - url = https://github.com/kubkon/misc-tests.git diff --git a/Cargo.toml b/Cargo.toml index 1f1b39fae5..0af0847081 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,9 @@ target-lexicon = "0.3.0" [patch."https://github.com/CraneStation/wasi-common"] wasi-common = { path = "." } +[build-dependencies] +cfg-if = "0.1.9" + [lib] name = "wasi_common" crate-type = ["rlib", "staticlib", "cdylib"] diff --git a/appveyor.yml b/appveyor.yml index b415d40596..b39a657009 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,5 @@ install: - rustc -vV - cargo -vV - rustup component add rustfmt - - cd %APPVEYOR_BUILD_FOLDER% - - git submodule update --init --recursive build: false test_script: test-all.bat diff --git a/build.rs b/build.rs new file mode 100644 index 0000000000..859d3c7cb3 --- /dev/null +++ b/build.rs @@ -0,0 +1,155 @@ +//! Build program to generate a program which runs all the testsuites. +//! +//! By generating a separate `#[test]` test for each file, we allow cargo test +//! to automatically run the files in parallel. +//! +//! Idea adapted from: https://github.com/CraneStation/wasmtime/blob/master/build.rs +//! Thanks @sunfishcode + +use std::env; +use std::fs::{read_dir, DirEntry, File}; +use std::io::{self, Write}; +use std::path::{Path, PathBuf}; + +fn main() { + let out_dir = + PathBuf::from(env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set")); + let mut out = File::create(out_dir.join("misc_testsuite_tests.rs")) + .expect("error generating test source file"); + + test_directory(&mut out, "misc_testsuite").expect("generating tests"); +} + +fn test_directory(out: &mut File, testsuite: &str) -> io::Result<()> { + let mut dir_entries: Vec<_> = read_dir(testsuite) + .expect("reading testsuite directory") + .map(|r| r.expect("reading testsuite directory entry")) + .filter(|dir_entry| { + let p = dir_entry.path(); + if let Some(ext) = p.extension() { + // Only look at wast files. + if ext == "wasm" { + // Ignore files starting with `.`, which could be editor temporary files + if let Some(stem) = p.file_stem() { + if let Some(stemstr) = stem.to_str() { + if !stemstr.starts_with('.') { + return true; + } + } + } + } + } + false + }) + .collect(); + + dir_entries.sort_by_key(|dir| dir.path()); + + writeln!( + out, + "mod {} {{", + Path::new(testsuite) + .file_stem() + .expect("testsuite filename should have a stem") + .to_str() + .expect("testsuite filename should be representable as a string") + .replace("-", "_") + )?; + writeln!(out, " use super::{{runtime, utils}};")?; + for dir_entry in dir_entries { + write_testsuite_tests(out, dir_entry, testsuite)?; + } + writeln!(out, "}}")?; + Ok(()) +} + +fn write_testsuite_tests(out: &mut File, dir_entry: DirEntry, testsuite: &str) -> io::Result<()> { + let path = dir_entry.path(); + let stemstr = path + .file_stem() + .expect("file_stem") + .to_str() + .expect("to_str"); + + writeln!(out, " #[test]")?; + if ignore(testsuite, stemstr) { + writeln!(out, " #[ignore]")?; + } + writeln!( + out, + " fn {}() -> Result<(), String> {{", + avoid_keywords(&stemstr.replace("-", "_")) + )?; + write!(out, " let path = std::path::Path::new(\"")?; + // Write out the string with escape_debug to prevent special characters such + // as backslash from being reinterpreted. + for c in path.display().to_string().chars() { + write!(out, "{}", c.escape_debug())?; + } + writeln!(out, "\");")?; + writeln!(out, " let data = utils::read_wasm(path)?;")?; + writeln!( + out, + " let bin_name = utils::extract_exec_name_from_path(path)?;" + )?; + let workspace = if no_preopens(testsuite, stemstr) { + "None" + } else { + "Some(&utils::prepare_workspace(&bin_name)?)" + }; + writeln!( + out, + " runtime::instantiate(&data, &bin_name, {})", + workspace + )?; + writeln!(out, " }}")?; + writeln!(out)?; + Ok(()) +} + +/// Rename tests which have the same name as Rust keywords. +fn avoid_keywords(name: &str) -> &str { + match name { + "if" => "if_", + "loop" => "loop_", + "type" => "type_", + "const" => "const_", + "return" => "return_", + other => other, + } +} + +cfg_if::cfg_if! { + if #[cfg(not(windows))] { + /// Ignore tests that aren't supported yet. + fn ignore(_testsuite: &str, _name: &str) -> bool { + false + } + } else { + /// Ignore tests that aren't supported yet. + fn ignore(testsuite: &str, name: &str) -> bool { + if testsuite == "misc_testsuite" { + match name { + "big_random_buf" => false, + _ => true, + } + } else { + unreachable!() + } + } + } +} + +/// Mark tests which do not require preopens +fn no_preopens(testsuite: &str, name: &str) -> bool { + if testsuite == "misc_testsuite" { + match name { + "big_random_buf" => true, + "clock_time_get" => true, + "sched_yield" => true, + _ => false, + } + } else { + unreachable!() + } +} diff --git a/misc_testsuite/big_random_buf.wasm b/misc_testsuite/big_random_buf.wasm new file mode 100755 index 0000000000..4932782d54 Binary files /dev/null and b/misc_testsuite/big_random_buf.wasm differ diff --git a/misc_testsuite/clock_time_get.wasm b/misc_testsuite/clock_time_get.wasm new file mode 100755 index 0000000000..0394d4a96f Binary files /dev/null and b/misc_testsuite/clock_time_get.wasm differ diff --git a/misc_testsuite/close_preopen.wasm b/misc_testsuite/close_preopen.wasm new file mode 100755 index 0000000000..47be68eda1 Binary files /dev/null and b/misc_testsuite/close_preopen.wasm differ diff --git a/misc_testsuite/directory_seek.wasm b/misc_testsuite/directory_seek.wasm new file mode 100755 index 0000000000..2775c5cda1 Binary files /dev/null and b/misc_testsuite/directory_seek.wasm differ diff --git a/misc_testsuite/interesting_paths.wasm b/misc_testsuite/interesting_paths.wasm new file mode 100755 index 0000000000..e83fefc65f Binary files /dev/null and b/misc_testsuite/interesting_paths.wasm differ diff --git a/misc_testsuite/isatty.wasm b/misc_testsuite/isatty.wasm new file mode 100755 index 0000000000..59484d3b58 Binary files /dev/null and b/misc_testsuite/isatty.wasm differ diff --git a/misc_testsuite/nofollow_errors.wasm b/misc_testsuite/nofollow_errors.wasm new file mode 100755 index 0000000000..0af04124e4 Binary files /dev/null and b/misc_testsuite/nofollow_errors.wasm differ diff --git a/misc_testsuite/readlink_no_buffer.wasm b/misc_testsuite/readlink_no_buffer.wasm new file mode 100755 index 0000000000..3262c25aa8 Binary files /dev/null and b/misc_testsuite/readlink_no_buffer.wasm differ diff --git a/misc_testsuite/remove_nonempty_directory.wasm b/misc_testsuite/remove_nonempty_directory.wasm new file mode 100755 index 0000000000..acb5981a70 Binary files /dev/null and b/misc_testsuite/remove_nonempty_directory.wasm differ diff --git a/misc_testsuite/sched_yield.wasm b/misc_testsuite/sched_yield.wasm new file mode 100755 index 0000000000..d740a0690f Binary files /dev/null and b/misc_testsuite/sched_yield.wasm differ diff --git a/misc_testsuite/symlink_loop.wasm b/misc_testsuite/symlink_loop.wasm new file mode 100755 index 0000000000..0af1c9480b Binary files /dev/null and b/misc_testsuite/symlink_loop.wasm differ diff --git a/misc_testsuite/truncation_rights.wasm b/misc_testsuite/truncation_rights.wasm new file mode 100755 index 0000000000..6ee65546b2 Binary files /dev/null and b/misc_testsuite/truncation_rights.wasm differ diff --git a/misc_testsuite/unlink_directory.wasm b/misc_testsuite/unlink_directory.wasm new file mode 100755 index 0000000000..0101a1c3b3 Binary files /dev/null and b/misc_testsuite/unlink_directory.wasm differ diff --git a/tests/misc-tests b/tests/misc-tests deleted file mode 160000 index 149048a645..0000000000 --- a/tests/misc-tests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 149048a6459700793159318503a661b77fc2cf8c diff --git a/tests/misc_tests.rs b/tests/misc_tests.rs index c7747f03fd..b980bb5760 100644 --- a/tests/misc_tests.rs +++ b/tests/misc_tests.rs @@ -1,102 +1,4 @@ mod runtime; mod utils; -use std::path::Path; - -fn run_test_with_workspace>(path: P) -> Result<(), String> { - // Load in the wasm testcase - let data = utils::read_wasm(path.as_ref())?; - let bin_name = utils::extract_exec_name_from_path(path.as_ref())?; - - // Prepare workspace - let workspace = utils::prepare_workspace(&bin_name)?; - - // Run! - runtime::instantiate(&data, bin_name, Some(workspace)) -} - -fn run_test_without_workspace>(path: P) -> Result<(), String> { - // Load in the wasm testcase - let data = utils::read_wasm(path.as_ref())?; - let bin_name = utils::extract_exec_name_from_path(path.as_ref())?; - - // Run! - runtime::instantiate(&data, bin_name, None) -} - -#[cfg(all(unix))] -#[test] -fn sched_yield() -> Result<(), String> { - run_test_without_workspace("tests/misc-tests/bin/sched_yield.wasm") -} - -#[cfg(all(unix))] -#[test] -fn truncation_rights() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/truncation_rights.wasm") -} - -#[cfg(all(unix))] -#[test] -fn unlink_directory() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/unlink_directory.wasm") -} - -#[cfg(all(unix))] -#[test] -fn remove_nonempty_directory() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/remove_nonempty_directory.wasm") -} - -#[cfg(all(unix))] -#[test] -fn interesting_paths() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/interesting_paths.wasm") -} - -#[cfg(all(unix))] -#[test] -fn nofollow_errors() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/nofollow_errors.wasm") -} - -#[cfg(all(unix))] -#[test] -fn symlink_loop() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/symlink_loop.wasm") -} - -#[cfg(all(unix))] -#[test] -fn close_preopen() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/close_preopen.wasm") -} - -#[cfg(all(unix))] -#[test] -fn clock_time_get() -> Result<(), String> { - run_test_without_workspace("tests/misc-tests/bin/clock_time_get.wasm") -} - -#[cfg(all(unix))] -#[test] -fn readlink_no_buffer() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/readlink_no_buffer.wasm") -} - -#[cfg(all(unix))] -#[test] -fn isatty() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/isatty.wasm") -} - -#[cfg(all(unix))] -#[test] -fn directory_seek() -> Result<(), String> { - run_test_with_workspace("tests/misc-tests/bin/directory_seek.wasm") -} - -#[test] -fn big_random_buf() -> Result<(), String> { - run_test_without_workspace("tests/misc-tests/bin/big_random_buf.wasm") -} +include!(concat!(env!("OUT_DIR"), "/misc_testsuite_tests.rs"));