diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1b7200c53b..93af94af87 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,6 +48,29 @@ jobs: - run: cmake -S ${{github.workspace}}/examples -B ${{github.workspace}}/examples/build -DCMAKE_BUILD_TYPE=Release - run: cmake --build ${{github.workspace}}/examples/build --config Release + wasm: + name: Test on WebAssembly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - name: Install Rust + run: rustup update stable --no-self-update && rustup default stable + - run: rustup target add wasm32-wasi + - run: | + tag=v10.0.1 + curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/${tag}/wasmtime-${tag}-x86_64-linux.tar.xz + tar xf wasmtime-${tag}-x86_64-linux.tar.xz + echo `pwd`/wasmtime-${tag}-x86_64-linux >> $GITHUB_PATH + echo CARGO_TARGET_WASM32_WASI_RUNNER='wasmtime run --dir . --' >> $GITHUB_ENV + echo CARGO_BUILD_TARGET='wasm32-wasi' >> $GITHUB_ENV + - run: | + cargo test --workspace \ + --exclude fuzz-stats \ + --exclude wasm-tools-fuzz \ + --exclude wasm-mutate-stats + rustfmt: name: Rustfmt runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 61f74b2e41..ccc8dd9dab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,6 @@ wasm-smith = { workspace = true, features = ["_internal_cli"], optional = true } # Dependencies of `shrink` wasm-shrink = { workspace = true, features = ["clap"], optional = true } -is_executable = { version = "1.0.1", optional = true } # Dependencies of `mutate` wasm-mutate = { workspace = true, features = ["clap"], optional = true } @@ -117,6 +116,9 @@ wit-smith = { workspace = true, features = ["clap"], optional = true } addr2line = { version = "0.20.0", optional = true } gimli = { version = "0.27.2", optional = true } +[target.'cfg(not(target_family = "wasm"))'.dependencies] +is_executable = { version = "1.0.1", optional = true } + [dev-dependencies] serde_json = "1.0" tempfile = "3.1" diff --git a/crates/wasm-compose/tests/compose.rs b/crates/wasm-compose/tests/compose.rs index a8344958ad..ff2ed13eaa 100644 --- a/crates/wasm-compose/tests/compose.rs +++ b/crates/wasm-compose/tests/compose.rs @@ -1,6 +1,7 @@ use anyhow::{bail, Context, Result}; use pretty_assertions::assert_eq; use std::fs; +use std::io; use wasm_compose::{composer::ComponentComposer, config::Config}; use wasmparser::{Validator, WasmFeatures}; @@ -51,13 +52,29 @@ fn component_composing() -> Result<()> { let (output, baseline_path) = if error_path.is_file() { match r { Ok(_) => bail!("composition should fail for test case `{}`", test_case), - Err(e) => ( - format!("{:?}", e).replace('\\', "/").replace( - "The system cannot find the file specified.", - "No such file or directory", - ), - &error_path, - ), + Err(e) => { + let mut err = format!("{e}"); + let causes = e.chain(); + let ncauses = causes.len(); + if ncauses > 1 { + err.push_str("\n\nCaused by:"); + } + for (i, cause) in causes.skip(1).enumerate() { + err.push_str("\n "); + if ncauses > 2 { + err.push_str(&format!("{i}: ")) + } + match cause.downcast_ref::() { + Some(_) => { + err.push_str("platform-specific error"); + } + None => { + err.push_str(&cause.to_string()); + } + } + } + (err.replace('\\', "/"), &error_path) + } } } else { let bytes = diff --git a/crates/wasm-compose/tests/compositions/component-missing/error.txt b/crates/wasm-compose/tests/compositions/component-missing/error.txt index dde33c0936..8b88baf34a 100644 --- a/crates/wasm-compose/tests/compositions/component-missing/error.txt +++ b/crates/wasm-compose/tests/compositions/component-missing/error.txt @@ -2,4 +2,4 @@ failed to parse component `tests/compositions/component-missing/a.wat` Caused by: 0: failed to read from `tests/compositions/component-missing/a.wat` - 1: No such file or directory (os error 2) + 1: platform-specific error diff --git a/crates/wasm-compose/tests/compositions/component-not-wat/error.txt b/crates/wasm-compose/tests/compositions/component-not-wat/error.txt index 39d3ab0458..8d8d29ed84 100644 --- a/crates/wasm-compose/tests/compositions/component-not-wat/error.txt +++ b/crates/wasm-compose/tests/compositions/component-not-wat/error.txt @@ -2,7 +2,7 @@ failed to parse component `tests/compositions/component-not-wat/root.wat` Caused by: expected `(` - --> tests/compositions/component-not-wat/root.wat:1:1 - | - 1 | not valid - | ^ + --> tests/compositions/component-not-wat/root.wat:1:1 + | + 1 | not valid + | ^ diff --git a/crates/wasm-compose/tests/compositions/missing-explicit-dep/error.txt b/crates/wasm-compose/tests/compositions/missing-explicit-dep/error.txt index 415ffcae6f..ed7bb6813f 100644 --- a/crates/wasm-compose/tests/compositions/missing-explicit-dep/error.txt +++ b/crates/wasm-compose/tests/compositions/missing-explicit-dep/error.txt @@ -2,4 +2,4 @@ failed to parse component `tests/compositions/missing-explicit-dep/a.wat` Caused by: 0: failed to read from `tests/compositions/missing-explicit-dep/a.wat` - 1: No such file or directory (os error 2) + 1: platform-specific error diff --git a/crates/wasm-compose/tests/compositions/missing-root/error.txt b/crates/wasm-compose/tests/compositions/missing-root/error.txt index 82aefdb9c3..d3d92144f4 100644 --- a/crates/wasm-compose/tests/compositions/missing-root/error.txt +++ b/crates/wasm-compose/tests/compositions/missing-root/error.txt @@ -2,4 +2,4 @@ failed to parse component `tests/compositions/missing-root/root.wat` Caused by: 0: failed to read from `tests/compositions/missing-root/root.wat` - 1: No such file or directory (os error 2) + 1: platform-specific error diff --git a/crates/wasm-mutate/src/mutators.rs b/crates/wasm-mutate/src/mutators.rs index 4c96c87b74..23e5e2c1fa 100644 --- a/crates/wasm-mutate/src/mutators.rs +++ b/crates/wasm-mutate/src/mutators.rs @@ -136,7 +136,7 @@ impl WasmMutate<'_> { assert!(can_mutate); - let attempts = 100; + let attempts = 2000; let mut last_mutation = None; for _ in 0..attempts { diff --git a/crates/wasm-mutate/src/mutators/peephole.rs b/crates/wasm-mutate/src/mutators/peephole.rs index 41ef663d8a..9110da9a2c 100644 --- a/crates/wasm-mutate/src/mutators/peephole.rs +++ b/crates/wasm-mutate/src/mutators/peephole.rs @@ -569,6 +569,7 @@ mod tests { /// Condition to apply the unfold operator /// check that the var is a constant + #[allow(dead_code)] fn is_const(vari: &'static str) -> impl Fn(&mut EG, Id, &Subst) -> bool { move |egraph: &mut EG, _, subst| { let var = vari.parse(); @@ -608,7 +609,11 @@ mod tests { } } + // Random numbers vary by pointer-width presumably due to `usize` at some + // point factoring in, and this test is only known to pass within a + // reasonable amount of time on 64-bit platforms. #[test] + #[cfg(target_pointer_width = "64")] fn test_peep_unfold2() { let rules: &[Rewrite] = &[ rewrite!("unfold-2"; "?x" => "(i32.unfold ?x)" if is_const("?x") if is_type("?x", PrimitiveTypeInfo::I32)), @@ -1588,7 +1593,7 @@ mod tests { seed: u64, ) { let mut config = WasmMutate::default(); - config.fuel(300); + config.fuel(10000); config.seed(seed); let mutator = PeepholeMutator::new_with_rules(3, rules.to_vec()); diff --git a/crates/wasm-smith/Cargo.toml b/crates/wasm-smith/Cargo.toml index 5d2116a653..20385676dd 100644 --- a/crates/wasm-smith/Cargo.toml +++ b/crates/wasm-smith/Cargo.toml @@ -26,10 +26,12 @@ wasmparser = { workspace = true } [dev-dependencies] criterion = { workspace = true } -libfuzzer-sys = { workspace = true } rand = { workspace = true } wasmprinter = { path = "../wasmprinter" } wat = { path = "../wat" } +[target.'cfg(not(target_family = "wasm"))'.dev-dependencies] +libfuzzer-sys = { workspace = true } + [features] _internal_cli = ["serde", "flagset/serde"] diff --git a/crates/wast/src/core/expr.rs b/crates/wast/src/core/expr.rs index 0f79d68a00..01316f9688 100644 --- a/crates/wast/src/core/expr.rs +++ b/crates/wast/src/core/expr.rs @@ -1155,8 +1155,8 @@ instructions! { // ideally it also wouldn't be as large as it is now. const _: () = { let size = std::mem::size_of::>(); - let pointer = std::mem::size_of::(); - assert!(size <= pointer * 20); + let pointer = std::mem::size_of::(); + assert!(size <= pointer * 10); }; impl<'a> Instruction<'a> { diff --git a/crates/wast/src/lexer.rs b/crates/wast/src/lexer.rs index 0888646c8f..f588ec2f15 100644 --- a/crates/wast/src/lexer.rs +++ b/crates/wast/src/lexer.rs @@ -61,7 +61,7 @@ pub struct Token { } const _: () = { - assert!(std::mem::size_of::() <= std::mem::size_of::() * 4); + assert!(std::mem::size_of::() <= std::mem::size_of::() * 2); }; /// Classification of what was parsed from the input stream. diff --git a/src/bin/wasm-tools/main.rs b/src/bin/wasm-tools/main.rs index e176f6713d..70c2849dd3 100644 --- a/src/bin/wasm-tools/main.rs +++ b/src/bin/wasm-tools/main.rs @@ -7,10 +7,11 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; macro_rules! subcommands { ($( $(#[$attr:meta])* - ($name:ident, $string:tt) + ($name:ident, $string:tt $($cfg:tt)*) )*) => { $( #[cfg(feature = $string)] + $($cfg)* mod $name; )* @@ -20,6 +21,7 @@ macro_rules! subcommands { enum WasmTools { $( #[cfg(feature = $string)] + $($cfg)* $(#[$attr])* $name($name::Opts), )* @@ -30,6 +32,7 @@ macro_rules! subcommands { match self { $( #[cfg(feature = $string)] + $($cfg)* Self::$name(opts) => opts.run(), )* } @@ -39,6 +42,7 @@ macro_rules! subcommands { match *self { $( #[cfg(feature = $string)] + $($cfg)* Self::$name(ref opts) => opts.general_opts(), )* } @@ -52,7 +56,10 @@ subcommands! { (validate, "validate") (print, "print") (smith, "smith") - (shrink, "shrink") + // The shrink subcommand relies on executing new processes to test a + // predicate which isn't supported on wasm, so always omit this command on + // wasm. + (shrink, "shrink" #[cfg(not(target_family = "wasm"))]) (mutate, "mutate") (dump, "dump") (objdump, "objdump") diff --git a/tests/cli.rs b/tests/cli.rs index c8d8a0e3fd..b9bb53c03e 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -34,6 +34,12 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; fn main() { + // This test suite can't run on wasm since it involves spawning + // subprocesses. + if cfg!(target_family = "wasm") { + return; + } + let mut tests = Vec::new(); find_tests("tests/cli".as_ref(), &mut tests); let filter = std::env::args().nth(1);