Misc testsuite feature gated (#113)

* Put misc_testsuite behind a feature gate

This PR puts building and generating of misc_testsuite behind
a feature gate "misc_testsuite". This is mainly to allow projects
which pull `wasi-common` as a dependency not to have to have
`wasm32-wasi` target installed in order to build it as it currently
is.

* Update the CI

* Rename feature to wasm_tests

* Explain integration testing in the README
This commit is contained in:
Jakub Konka
2019-10-03 23:08:55 +02:00
committed by GitHub
parent da59c95f0c
commit 603f7a9f22
5 changed files with 217 additions and 177 deletions

View File

@@ -58,7 +58,7 @@ jobs:
displayName: Cargo build release displayName: Cargo build release
- script: cargo build - script: cargo build
displayName: Cargo build displayName: Cargo build
- bash: RUST_BACKTRACE=1 cargo test --all - bash: RUST_BACKTRACE=1 cargo test --features wasm_tests --all
displayName: Cargo test displayName: Cargo test
- script: cargo doc - script: cargo doc
condition: eq(variables['Agent.OS'], 'Darwin') condition: eq(variables['Agent.OS'], 'Darwin')

View File

@@ -10,6 +10,11 @@ edition = "2018"
license = "Apache-2.0 WITH LLVM-exception" license = "Apache-2.0 WITH LLVM-exception"
description = "WASI implementation in Rust" description = "WASI implementation in Rust"
[features]
# this feature requires wasm32-wasi target installed, and it enables wasm32
# integration tests when run with `cargo test --features wasm_tests`
wasm_tests = []
[dependencies] [dependencies]
wasi-common-cbindgen = { path = "wasi-common-cbindgen" } wasi-common-cbindgen = { path = "wasi-common-cbindgen" }
failure = "0.1" failure = "0.1"

View File

@@ -39,6 +39,28 @@ In our Windows implementation, we currently support the minimal subset of [WASI
which allows for running the very basic "Hello world!" style WASM apps. More coming shortly, which allows for running the very basic "Hello world!" style WASM apps. More coming shortly,
so stay tuned! so stay tuned!
## Development hints
When testing the crate, you may want to enable and run full wasm32 integration testsuite. This
requires `wasm32-wasi` target installed which can be done as follows using [rustup]
```
rustup target add wasm32-wasi
```
[rustup]: https://rustup.rs
Next initiate submodules containing the integration testsuite
```
git submodule update --init
```
Now, you should be able to run the integration testsuite by enabling the `wasm_tests` feature
```
cargo test --features wasm_tests
```
## Third-Party Code ## Third-Party Code
Significant parts of our hostcall implementations are derived from the C implementations in Significant parts of our hostcall implementations are derived from the C implementations in
`cloudabi-utils`. See [LICENSE.cloudabi-utils](LICENSE.cloudabi-utils) for license information. `cloudabi-utils`. See [LICENSE.cloudabi-utils](LICENSE.cloudabi-utils) for license information.

View File

@@ -6,24 +6,30 @@
//! Idea adapted from: https://github.com/CraneStation/wasmtime/blob/master/build.rs //! Idea adapted from: https://github.com/CraneStation/wasmtime/blob/master/build.rs
//! Thanks @sunfishcode //! Thanks @sunfishcode
use std::env;
use std::fs::{read_dir, DirEntry, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
fn main() { fn main() {
let out_dir = #[cfg(feature = "wasm_tests")]
PathBuf::from(env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set")); wasm_tests::build_and_generate_tests();
println!("OUT_DIR is {:?}", out_dir);
let mut out = File::create(out_dir.join("misc_testsuite_tests.rs"))
.expect("error generating test source file");
build_tests("misc_testsuite", &out_dir).expect("building tests");
test_directory(&mut out, "misc_testsuite", &out_dir).expect("generating tests");
} }
fn build_tests(testsuite: &str, out_dir: &Path) -> io::Result<()> { #[cfg(feature = "wasm_tests")]
mod wasm_tests {
use std::env;
use std::fs::{read_dir, DirEntry, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
pub(crate) fn build_and_generate_tests() {
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");
build_tests("misc_testsuite", &out_dir).expect("building tests");
test_directory(&mut out, "misc_testsuite", &out_dir).expect("generating tests");
}
fn build_tests(testsuite: &str, out_dir: &Path) -> io::Result<()> {
// if the submodule has not been checked out, the build will stall // if the submodule has not been checked out, the build will stall
if !Path::new(&format!("{}/Cargo.toml", testsuite)).exists() { if !Path::new(&format!("{}/Cargo.toml", testsuite)).exists() {
panic!("Testsuite {} not checked out", testsuite); panic!("Testsuite {} not checked out", testsuite);
@@ -51,9 +57,9 @@ fn build_tests(testsuite: &str, out_dir: &Path) -> io::Result<()> {
} }
Ok(()) Ok(())
} }
fn test_directory(out: &mut File, testsuite: &str, out_dir: &Path) -> io::Result<()> { fn test_directory(out: &mut File, testsuite: &str, out_dir: &Path) -> io::Result<()> {
let mut dir_entries: Vec<_> = read_dir(out_dir.join("wasm32-wasi/release")) let mut dir_entries: Vec<_> = read_dir(out_dir.join("wasm32-wasi/release"))
.expect("reading testsuite directory") .expect("reading testsuite directory")
.map(|r| r.expect("reading testsuite directory entry")) .map(|r| r.expect("reading testsuite directory entry"))
@@ -94,9 +100,13 @@ fn test_directory(out: &mut File, testsuite: &str, out_dir: &Path) -> io::Result
} }
writeln!(out, "}}")?; writeln!(out, "}}")?;
Ok(()) Ok(())
} }
fn write_testsuite_tests(out: &mut File, dir_entry: DirEntry, testsuite: &str) -> io::Result<()> { fn write_testsuite_tests(
out: &mut File,
dir_entry: DirEntry,
testsuite: &str,
) -> io::Result<()> {
let path = dir_entry.path(); let path = dir_entry.path();
let stemstr = path let stemstr = path
.file_stem() .file_stem()
@@ -143,10 +153,10 @@ fn write_testsuite_tests(out: &mut File, dir_entry: DirEntry, testsuite: &str) -
writeln!(out, " }}")?; writeln!(out, " }}")?;
writeln!(out)?; writeln!(out)?;
Ok(()) Ok(())
} }
/// Rename tests which have the same name as Rust keywords. /// Rename tests which have the same name as Rust keywords.
fn avoid_keywords(name: &str) -> &str { fn avoid_keywords(name: &str) -> &str {
match name { match name {
"if" => "if_", "if" => "if_",
"loop" => "loop_", "loop" => "loop_",
@@ -155,9 +165,9 @@ fn avoid_keywords(name: &str) -> &str {
"return" => "return_", "return" => "return_",
other => other, other => other,
} }
} }
cfg_if::cfg_if! { cfg_if::cfg_if! {
if #[cfg(not(windows))] { if #[cfg(not(windows))] {
/// Ignore tests that aren't supported yet. /// Ignore tests that aren't supported yet.
fn ignore(testsuite: &str, name: &str) -> bool { fn ignore(testsuite: &str, name: &str) -> bool {
@@ -191,10 +201,10 @@ cfg_if::cfg_if! {
} }
} }
} }
} }
/// Mark tests which do not require preopens /// Mark tests which do not require preopens
fn no_preopens(testsuite: &str, name: &str) -> bool { fn no_preopens(testsuite: &str, name: &str) -> bool {
if testsuite == "misc_testsuite" { if testsuite == "misc_testsuite" {
match name { match name {
"big_random_buf" => true, "big_random_buf" => true,
@@ -205,4 +215,5 @@ fn no_preopens(testsuite: &str, name: &str) -> bool {
} else { } else {
unreachable!() unreachable!()
} }
}
} }

View File

@@ -1,3 +1,5 @@
#![cfg(feature = "wasm_tests")]
mod runtime; mod runtime;
mod utils; mod utils;