From 7141379559e2ef17e48dfbadc898581cd34bef6f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 6 Mar 2024 12:39:07 -0800 Subject: Convert some WebAssembly run-make tests to Rust This commit rewrites a number of `run-make` tests centered around wasm to instead use `rmake.rs` and additionally use the `wasm32-wasip1` target instead of `wasm32-unknown-unknown`. Testing no longer requires Node.js and additionally uses the `wasmparser` crate from crates.io to parse outputs and power assertions. --- src/tools/run-make-support/Cargo.toml | 1 + src/tools/run-make-support/src/lib.rs | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/tools') diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 178deae6499..958aef69572 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -4,3 +4,4 @@ version = "0.0.0" edition = "2021" [dependencies] +wasmparser = "0.118.2" diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 820218732ce..674860f8413 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -2,13 +2,16 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; +pub use wasmparser; + +pub fn out_dir() -> PathBuf { + env::var_os("TMPDIR").unwrap().into() +} + fn setup_common_build_cmd() -> Command { let rustc = env::var("RUSTC").unwrap(); let mut cmd = Command::new(rustc); - cmd.arg("--out-dir") - .arg(env::var("TMPDIR").unwrap()) - .arg("-L") - .arg(env::var("TMPDIR").unwrap()); + cmd.arg("--out-dir").arg(out_dir()).arg("-L").arg(out_dir()); cmd } @@ -45,6 +48,11 @@ impl RustcInvocationBuilder { self } + pub fn args(&mut self, args: &[&str]) -> &mut RustcInvocationBuilder { + self.cmd.args(args); + self + } + #[track_caller] pub fn run(&mut self) -> Output { let caller_location = std::panic::Location::caller(); -- cgit 1.4.1-3-g733a5 From 7d9690a3bcb4ce57165341e5f5d0a2161283076d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 6 Mar 2024 12:41:08 -0800 Subject: Remove old support for emscripten/wasm32-u-u This commit removes the `wasm32-shim.js` file, for example, and deletes old support for Emscripten which hasn't been exercised in some time. --- src/bootstrap/src/core/build_steps/test.rs | 15 +++------------ src/etc/wasm32-shim.js | 24 ------------------------ src/tools/compiletest/src/runtest.rs | 30 +----------------------------- 3 files changed, 4 insertions(+), 65 deletions(-) delete mode 100644 src/etc/wasm32-shim.js (limited to 'src/tools') diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 248d831b6e3..47b0637538b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1657,8 +1657,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // ensure that `libproc_macro` is available on the host. builder.ensure(compile::Std::new(compiler, compiler.host)); - // As well as the target, except for plain wasm32, which can't build it - if suite != "mir-opt" && !target.contains("wasm") && !target.contains("emscripten") { + // As well as the target + if suite != "mir-opt" { builder.ensure(TestHelpers { target }); } @@ -2511,16 +2511,7 @@ fn prepare_cargo_test( dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target))); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - if target.contains("emscripten") { - cargo.env( - format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), - builder.config.nodejs.as_ref().expect("nodejs not configured"), - ); - } else if target.starts_with("wasm32") { - let node = builder.config.nodejs.as_ref().expect("nodejs not configured"); - let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display()); - cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner); - } else if builder.remote_tested(target) { + if builder.remote_tested(target) { cargo.env( format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()), diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js deleted file mode 100644 index 262a53eabe3..00000000000 --- a/src/etc/wasm32-shim.js +++ /dev/null @@ -1,24 +0,0 @@ -// This is a small "shim" program which is used when wasm32 unit tests are run -// in this repository. This program is intended to be run in node.js and will -// load a wasm module into memory, instantiate it with a set of imports, and -// then run it. -// -// There's a bunch of helper functions defined here in `imports.env`, but note -// that most of them aren't actually needed to execute most programs. Many of -// these are just intended for completeness or debugging. Hopefully over time -// nothing here is needed for completeness. - -const fs = require('fs'); -const process = require('process'); -const buffer = fs.readFileSync(process.argv[2]); - -Error.stackTraceLimit = 20; - -let m = new WebAssembly.Module(buffer); -let instance = new WebAssembly.Instance(m, {}); -try { - instance.exports.main(); -} catch (e) { - console.error(e); - process.exit(101); -} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9fd83c507ed..3e0021bf7c6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2632,9 +2632,7 @@ impl<'test> TestCx<'test> { // double the length. let mut f = self.output_base_dir().join("a"); // FIXME: This is using the host architecture exe suffix, not target! - if self.config.target.contains("emscripten") { - f = f.with_extra_extension("js"); - } else if self.config.target.contains("wasm32") { + if self.config.target.starts_with("wasm") { f = f.with_extra_extension("wasm"); } else if self.config.target.contains("spirv") { f = f.with_extra_extension("spv"); @@ -2649,32 +2647,6 @@ impl<'test> TestCx<'test> { // then split apart its command let mut args = self.split_maybe_args(&self.config.runner); - // If this is emscripten, then run tests under nodejs - if self.config.target.contains("emscripten") { - if let Some(ref p) = self.config.nodejs { - args.push(p.into()); - } else { - self.fatal("emscripten target requested and no NodeJS binary found (--nodejs)"); - } - // If this is otherwise wasm, then run tests under nodejs with our - // shim - } else if self.config.target.contains("wasm32") { - if let Some(ref p) = self.config.nodejs { - args.push(p.into()); - } else { - self.fatal("wasm32 target requested and no NodeJS binary found (--nodejs)"); - } - - let src = self - .config - .src_base - .parent() - .unwrap() // chop off `ui` - .parent() - .unwrap(); // chop off `tests` - args.push(src.join("src/etc/wasm32-shim.js").into_os_string()); - } - let exe_file = self.make_exe_name(); args.push(exe_file.into_os_string()); -- cgit 1.4.1-3-g733a5 From 4a5aa1a104a9a85cc765af863f64297f9e7e73f6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 6 Mar 2024 12:43:00 -0800 Subject: compiletest: Automatically compare output by subset with runners This commit updates compiletest to automatically compare test output with subsets if a `--runner` argument is configured. Runners might inject extra information on failures, for example a WebAssembly runtime printing a wasm stack trace, which won't be in the output of a native runtime. The output with a `--runner` argument, however, should still have all the native output present. --- src/tools/compiletest/src/runtest.rs | 69 +++++++++++------------------------- 1 file changed, 20 insertions(+), 49 deletions(-) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3e0021bf7c6..7be0571b111 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -493,12 +493,8 @@ impl<'test> TestCx<'test> { let expected_coverage_dump = self.load_expected_output(kind); let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); - let coverage_dump_errors = self.compare_output( - kind, - &actual_coverage_dump, - &expected_coverage_dump, - self.props.compare_output_lines_by_subset, - ); + let coverage_dump_errors = + self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); if coverage_dump_errors > 0 { self.fatal_proc_rec( @@ -591,12 +587,8 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec(&err, &proc_res); }); - let coverage_errors = self.compare_output( - kind, - &normalized_actual_coverage, - &expected_coverage, - self.props.compare_output_lines_by_subset, - ); + let coverage_errors = + self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); if coverage_errors > 0 { self.fatal_proc_rec( @@ -4051,35 +4043,17 @@ impl<'test> TestCx<'test> { match output_kind { TestOutput::Compile => { if !self.props.dont_check_compiler_stdout { - errors += self.compare_output( - stdout_kind, - &normalized_stdout, - &expected_stdout, - self.props.compare_output_lines_by_subset, - ); + errors += + self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); } if !self.props.dont_check_compiler_stderr { - errors += self.compare_output( - stderr_kind, - &normalized_stderr, - &expected_stderr, - self.props.compare_output_lines_by_subset, - ); + errors += + self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); } } TestOutput::Run => { - errors += self.compare_output( - stdout_kind, - &normalized_stdout, - &expected_stdout, - self.props.compare_output_lines_by_subset, - ); - errors += self.compare_output( - stderr_kind, - &normalized_stderr, - &expected_stderr, - self.props.compare_output_lines_by_subset, - ); + errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); + errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); } } errors @@ -4173,12 +4147,7 @@ impl<'test> TestCx<'test> { ) }); - errors += self.compare_output( - "fixed", - &fixed_code, - &expected_fixed, - self.props.compare_output_lines_by_subset, - ); + errors += self.compare_output("fixed", &fixed_code, &expected_fixed); } else if !expected_fixed.is_empty() { panic!( "the `//@ run-rustfix` directive wasn't found but a `*.fixed` \ @@ -4673,17 +4642,19 @@ impl<'test> TestCx<'test> { } } - fn compare_output( - &self, - kind: &str, - actual: &str, - expected: &str, - compare_output_by_lines: bool, - ) -> usize { + fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize { if actual == expected { return 0; } + // If `compare-output-lines-by-subset` is not explicitly enabled then + // auto-enable it when a `runner` is in use since wrapper tools might + // provide extra output on failure, for example a WebAssembly runtime + // might print the stack trace of an `unreachable` instruction by + // default. + let compare_output_by_lines = + self.props.compare_output_lines_by_subset || self.config.runner.is_some(); + let tmp; let (expected, actual): (&str, &str) = if compare_output_by_lines { let actual_lines: HashSet<_> = actual.lines().collect(); -- cgit 1.4.1-3-g733a5