Skip to content

Commit dc2ffa4

Browse files
committed
Auto merge of rust-lang#122036 - alexcrichton:test-wasm-with-wasi, r=oli-obk
Test wasm32-wasip1 in CI, not wasm32-unknown-unknown This commit changes CI to no longer test the `wasm32-unknown-unknown` target and instead test the `wasm32-wasip1` target. There was some discussion of this in a [Zulip thread], and the motivations for this PR are: * Runtime failures on `wasm32-unknown-unknown` print nothing, meaning all you get is "something failed". In contrast `wasm32-wasip1` can print to stdout/stderr. * The unknown-unknown target is missing lots of pieces of libstd, and while `wasm32-wasip1` is also missing some pieces (e.g. threads) it's missing fewer pieces. This means that many more tests can be run. Overall my hope is to improve the debuggability of wasm failures on CI and ideally be a bit less of a maintenance burden. This commit specifically removes the testing of `wasm32-unknown-unknown` and replaces it with testing of `wasm32-wasip1`. Along the way there were a number of other archiectural changes made as well, including: * A new `target.*.runtool` option can now be specified in `config.toml` which is passed as `--runtool` to `compiletest`. This is used to reimplement execution of WebAssembly in a less-wasm-specific fashion. * The default value for `runtool` is an ambiently located WebAssembly runtime found on the system, if any. I've implemented logic for Wasmtime. * Existing testing support for `wasm32-unknown-unknown` and Emscripten has been removed. I'm not aware of Emscripten testing being run any time recently and otherwise `wasm32-wasip1` is in theory the focus now. * I've added a new `//@ needs-threads` directive for `compiletest` and classified a bunch of wasm-ignored tests as needing threads. In theory these tests can run on `wasm32-wasi-preview1-threads`, for example. * I've tried to audit all existing tests that are either `ignore-emscripten` or `ignore-wasm*`. Many now run on `wasm32-wasip1` due to being able to emit error messages, for example. Many are updated with comments as to why they can't run as well. * The `compiletest` output matching for `wasm32-wasip1` automatically uses "match a subset" mode implemented in `compiletest`. This is because WebAssembly runtimes often add extra information on failure, such as the `unreachable` instruction in `panic!`, which isn't able to be matched against the golden output from native platforms. * I've ported most existing `run-make` tests that use custom Node.js wrapper scripts to the new run-make-based-in-Rust infrastructure. To do this I added `wasmparser` as a dependency of `run-make-support` for the various wasm tests to use that parse wasm files. The one test that executed WebAssembly now uses `wasmtime`-the-CLI to execute the test instead. I have not ported over an exception-handling test as Wasmtime doesn't implement this yet. * I've updated the `test` crate to print out timing information for WASI targets as it can do that (gets a previously ignored test now passing). * The `test-various` image now builds a WASI sysroot for the WASI target and additionally downloads a fixed release of Wasmtime, currently the latest one at 18.0.2, and uses that for testing. [Zulip thread]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Have.20wasm.20tests.20ever.20caused.20problems.20on.20CI.3F/near/424317944
2 parents 4a0cc88 + cf6d605 commit dc2ffa4

File tree

236 files changed

+721
-791
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

236 files changed

+721
-791
lines changed

Cargo.lock

+3
Original file line numberDiff line numberDiff line change
@@ -3309,6 +3309,9 @@ dependencies = [
33093309
[[package]]
33103310
name = "run_make_support"
33113311
version = "0.0.0"
3312+
dependencies = [
3313+
"wasmparser",
3314+
]
33123315

33133316
[[package]]
33143317
name = "rust-demangler"

library/test/src/console.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,11 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
323323
// Prevent the usage of `Instant` in some cases:
324324
// - It's currently not supported for wasm targets.
325325
// - We disable it for miri because it's not available when isolation is enabled.
326-
let is_instant_supported =
327-
!cfg!(target_family = "wasm") && !cfg!(target_os = "zkvm") && !cfg!(miri);
326+
let is_instant_unsupported = (cfg!(target_family = "wasm") && !cfg!(target_os = "wasi"))
327+
|| cfg!(target_os = "zkvm")
328+
|| cfg!(miri);
328329

329-
let start_time = is_instant_supported.then(Instant::now);
330+
let start_time = (!is_instant_unsupported).then(Instant::now);
330331
run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?;
331332
st.exec_time = start_time.map(|t| TestSuiteExecTime(t.elapsed()));
332333

src/bootstrap/src/core/build_steps/test.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -1657,8 +1657,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
16571657
// ensure that `libproc_macro` is available on the host.
16581658
builder.ensure(compile::Std::new(compiler, compiler.host));
16591659

1660-
// As well as the target, except for plain wasm32, which can't build it
1661-
if suite != "mir-opt" && !target.contains("wasm") && !target.contains("emscripten") {
1660+
// As well as the target
1661+
if suite != "mir-opt" {
16621662
builder.ensure(TestHelpers { target });
16631663
}
16641664

@@ -2511,16 +2511,7 @@ fn prepare_cargo_test(
25112511
dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
25122512
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
25132513

2514-
if target.contains("emscripten") {
2515-
cargo.env(
2516-
format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2517-
builder.config.nodejs.as_ref().expect("nodejs not configured"),
2518-
);
2519-
} else if target.starts_with("wasm32") {
2520-
let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
2521-
let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
2522-
cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
2523-
} else if builder.remote_tested(target) {
2514+
if builder.remote_tested(target) {
25242515
cargo.env(
25252516
format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
25262517
format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),

src/bootstrap/src/lib.rs

+30-3
Original file line numberDiff line numberDiff line change
@@ -1361,9 +1361,36 @@ impl Build {
13611361
/// An example of this would be a WebAssembly runtime when testing the wasm
13621362
/// targets.
13631363
fn runner(&self, target: TargetSelection) -> Option<String> {
1364-
let target = self.config.target_config.get(&target)?;
1365-
let runner = target.runner.as_ref()?;
1366-
Some(runner.to_owned())
1364+
let configured_runner =
1365+
self.config.target_config.get(&target).and_then(|t| t.runner.as_ref()).map(|p| &**p);
1366+
if let Some(runner) = configured_runner {
1367+
return Some(runner.to_owned());
1368+
}
1369+
1370+
if target.starts_with("wasm") && target.contains("wasi") {
1371+
self.default_wasi_runner()
1372+
} else {
1373+
None
1374+
}
1375+
}
1376+
1377+
/// When a `runner` configuration is not provided and a WASI-looking target
1378+
/// is being tested this is consulted to prove the environment to see if
1379+
/// there's a runtime already lying around that seems reasonable to use.
1380+
fn default_wasi_runner(&self) -> Option<String> {
1381+
let mut finder = crate::core::sanity::Finder::new();
1382+
1383+
// Look for Wasmtime, and for its default options be sure to disable
1384+
// its caching system since we're executing quite a lot of tests and
1385+
// ideally shouldn't pollute the cache too much.
1386+
if let Some(path) = finder.maybe_have("wasmtime") {
1387+
if let Ok(mut path) = path.into_os_string().into_string() {
1388+
path.push_str(" run -C cache=n --dir .");
1389+
return Some(path);
1390+
}
1391+
}
1392+
1393+
None
13671394
}
13681395

13691396
/// Returns the root of the "rootfs" image that this target will be using,

src/ci/docker/host-x86_64/test-various/Dockerfile

+14-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ FROM ubuntu:22.04
33
ARG DEBIAN_FRONTEND=noninteractive
44
RUN apt-get update && apt-get install -y --no-install-recommends \
55
clang-11 \
6+
llvm-11 \
67
g++ \
78
make \
89
ninja-build \
@@ -38,10 +39,14 @@ WORKDIR /
3839
COPY scripts/sccache.sh /scripts/
3940
RUN sh /scripts/sccache.sh
4041

42+
COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
43+
RUN /tmp/build-wasi-toolchain.sh
44+
4145
ENV RUST_CONFIGURE_ARGS \
4246
--musl-root-x86_64=/usr/local/x86_64-linux-musl \
4347
--set build.nodejs=/node-v18.12.0-linux-x64/bin/node \
44-
--set rust.lld
48+
--set rust.lld \
49+
--set target.wasm32-wasip1.wasi-root=/wasm32-wasip1
4550

4651
# Some run-make tests have assertions about code size, and enabling debug
4752
# assertions in libstd causes the binary to be much bigger than it would
@@ -50,7 +55,11 @@ ENV RUST_CONFIGURE_ARGS \
5055
ENV NO_DEBUG_ASSERTIONS=1
5156
ENV NO_OVERFLOW_CHECKS=1
5257

53-
ENV WASM_TARGETS=wasm32-unknown-unknown
58+
RUN curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasmtime-v18.0.2-x86_64-linux.tar.xz | \
59+
tar -xJ
60+
ENV PATH "$PATH:/wasmtime-v18.0.2-x86_64-linux"
61+
62+
ENV WASM_TARGETS=wasm32-wasip1
5463
ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_TARGETS \
5564
tests/run-make \
5665
tests/ui \
@@ -59,7 +68,9 @@ ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_T
5968
tests/codegen \
6069
tests/assembly \
6170
library/core
62-
ENV CC_wasm32_unknown_unknown=clang-11
71+
ENV CC_wasm32_wasip1=clang-11 \
72+
CFLAGS_wasm32_wasip1="--sysroot /wasm32-wasip1" \
73+
AR_wasm32_wasip1=llvm-ar-11
6374

6475
ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
6576
ENV NVPTX_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $NVPTX_TARGETS \

src/etc/wasm32-shim.js

-24
This file was deleted.

src/tools/compiletest/src/runtest.rs

+21-78
Original file line numberDiff line numberDiff line change
@@ -493,12 +493,8 @@ impl<'test> TestCx<'test> {
493493
let expected_coverage_dump = self.load_expected_output(kind);
494494
let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]);
495495

496-
let coverage_dump_errors = self.compare_output(
497-
kind,
498-
&actual_coverage_dump,
499-
&expected_coverage_dump,
500-
self.props.compare_output_lines_by_subset,
501-
);
496+
let coverage_dump_errors =
497+
self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump);
502498

503499
if coverage_dump_errors > 0 {
504500
self.fatal_proc_rec(
@@ -591,12 +587,8 @@ impl<'test> TestCx<'test> {
591587
self.fatal_proc_rec(&err, &proc_res);
592588
});
593589

594-
let coverage_errors = self.compare_output(
595-
kind,
596-
&normalized_actual_coverage,
597-
&expected_coverage,
598-
self.props.compare_output_lines_by_subset,
599-
);
590+
let coverage_errors =
591+
self.compare_output(kind, &normalized_actual_coverage, &expected_coverage);
600592

601593
if coverage_errors > 0 {
602594
self.fatal_proc_rec(
@@ -2632,9 +2624,7 @@ impl<'test> TestCx<'test> {
26322624
// double the length.
26332625
let mut f = self.output_base_dir().join("a");
26342626
// FIXME: This is using the host architecture exe suffix, not target!
2635-
if self.config.target.contains("emscripten") {
2636-
f = f.with_extra_extension("js");
2637-
} else if self.config.target.contains("wasm32") {
2627+
if self.config.target.starts_with("wasm") {
26382628
f = f.with_extra_extension("wasm");
26392629
} else if self.config.target.contains("spirv") {
26402630
f = f.with_extra_extension("spv");
@@ -2649,32 +2639,6 @@ impl<'test> TestCx<'test> {
26492639
// then split apart its command
26502640
let mut args = self.split_maybe_args(&self.config.runner);
26512641

2652-
// If this is emscripten, then run tests under nodejs
2653-
if self.config.target.contains("emscripten") {
2654-
if let Some(ref p) = self.config.nodejs {
2655-
args.push(p.into());
2656-
} else {
2657-
self.fatal("emscripten target requested and no NodeJS binary found (--nodejs)");
2658-
}
2659-
// If this is otherwise wasm, then run tests under nodejs with our
2660-
// shim
2661-
} else if self.config.target.contains("wasm32") {
2662-
if let Some(ref p) = self.config.nodejs {
2663-
args.push(p.into());
2664-
} else {
2665-
self.fatal("wasm32 target requested and no NodeJS binary found (--nodejs)");
2666-
}
2667-
2668-
let src = self
2669-
.config
2670-
.src_base
2671-
.parent()
2672-
.unwrap() // chop off `ui`
2673-
.parent()
2674-
.unwrap(); // chop off `tests`
2675-
args.push(src.join("src/etc/wasm32-shim.js").into_os_string());
2676-
}
2677-
26782642
let exe_file = self.make_exe_name();
26792643

26802644
args.push(exe_file.into_os_string());
@@ -4079,35 +4043,17 @@ impl<'test> TestCx<'test> {
40794043
match output_kind {
40804044
TestOutput::Compile => {
40814045
if !self.props.dont_check_compiler_stdout {
4082-
errors += self.compare_output(
4083-
stdout_kind,
4084-
&normalized_stdout,
4085-
&expected_stdout,
4086-
self.props.compare_output_lines_by_subset,
4087-
);
4046+
errors +=
4047+
self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
40884048
}
40894049
if !self.props.dont_check_compiler_stderr {
4090-
errors += self.compare_output(
4091-
stderr_kind,
4092-
&normalized_stderr,
4093-
&expected_stderr,
4094-
self.props.compare_output_lines_by_subset,
4095-
);
4050+
errors +=
4051+
self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
40964052
}
40974053
}
40984054
TestOutput::Run => {
4099-
errors += self.compare_output(
4100-
stdout_kind,
4101-
&normalized_stdout,
4102-
&expected_stdout,
4103-
self.props.compare_output_lines_by_subset,
4104-
);
4105-
errors += self.compare_output(
4106-
stderr_kind,
4107-
&normalized_stderr,
4108-
&expected_stderr,
4109-
self.props.compare_output_lines_by_subset,
4110-
);
4055+
errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
4056+
errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
41114057
}
41124058
}
41134059
errors
@@ -4201,12 +4147,7 @@ impl<'test> TestCx<'test> {
42014147
)
42024148
});
42034149

4204-
errors += self.compare_output(
4205-
"fixed",
4206-
&fixed_code,
4207-
&expected_fixed,
4208-
self.props.compare_output_lines_by_subset,
4209-
);
4150+
errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
42104151
} else if !expected_fixed.is_empty() {
42114152
panic!(
42124153
"the `//@ run-rustfix` directive wasn't found but a `*.fixed` \
@@ -4701,17 +4642,19 @@ impl<'test> TestCx<'test> {
47014642
}
47024643
}
47034644

4704-
fn compare_output(
4705-
&self,
4706-
kind: &str,
4707-
actual: &str,
4708-
expected: &str,
4709-
compare_output_by_lines: bool,
4710-
) -> usize {
4645+
fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
47114646
if actual == expected {
47124647
return 0;
47134648
}
47144649

4650+
// If `compare-output-lines-by-subset` is not explicitly enabled then
4651+
// auto-enable it when a `runner` is in use since wrapper tools might
4652+
// provide extra output on failure, for example a WebAssembly runtime
4653+
// might print the stack trace of an `unreachable` instruction by
4654+
// default.
4655+
let compare_output_by_lines =
4656+
self.props.compare_output_lines_by_subset || self.config.runner.is_some();
4657+
47154658
let tmp;
47164659
let (expected, actual): (&str, &str) = if compare_output_by_lines {
47174660
let actual_lines: HashSet<_> = actual.lines().collect();

src/tools/run-make-support/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ version = "0.0.0"
44
edition = "2021"
55

66
[dependencies]
7+
wasmparser = "0.118.2"

src/tools/run-make-support/src/lib.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ use std::env;
22
use std::path::{Path, PathBuf};
33
use std::process::{Command, Output};
44

5+
pub use wasmparser;
6+
7+
pub fn out_dir() -> PathBuf {
8+
env::var_os("TMPDIR").unwrap().into()
9+
}
10+
511
fn setup_common_build_cmd() -> Command {
612
let rustc = env::var("RUSTC").unwrap();
713
let mut cmd = Command::new(rustc);
8-
cmd.arg("--out-dir")
9-
.arg(env::var("TMPDIR").unwrap())
10-
.arg("-L")
11-
.arg(env::var("TMPDIR").unwrap());
14+
cmd.arg("--out-dir").arg(out_dir()).arg("-L").arg(out_dir());
1215
cmd
1316
}
1417

@@ -45,6 +48,11 @@ impl RustcInvocationBuilder {
4548
self
4649
}
4750

51+
pub fn args(&mut self, args: &[&str]) -> &mut RustcInvocationBuilder {
52+
self.cmd.args(args);
53+
self
54+
}
55+
4856
#[track_caller]
4957
pub fn run(&mut self) -> Output {
5058
let caller_location = std::panic::Location::caller();

tests/assembly/wasm_exceptions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@ only-wasm32-bare
1+
//@ only-wasm32
22
//@ assembly-output: emit-asm
33
//@ compile-flags: -C target-feature=+exception-handling
44
//@ compile-flags: -C panic=unwind

tests/codegen/abi-main-signature-32bit-c-int.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// This test is for targets with 32bit c_int only.
55
//@ ignore-msp430
66
//@ ignore-avr
7+
//@ ignore-wasi wasi codegens the main symbol differently
78

89
fn main() {
910
}

tests/codegen/drop.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//@ ignore-wasm32-bare compiled with panic=abort by default
21
//@ needs-unwind - this test verifies the amount of drop calls when unwinding is used
32
//@ compile-flags: -C no-prepopulate-passes
43

tests/codegen/enum/enum-debug-clike.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
//
55
//@ ignore-msvc
6+
//@ ignore-wasi wasi codegens the main symbol differently
67

78
//@ compile-flags: -g -C no-prepopulate-passes
89

tests/codegen/enum/enum-debug-niche.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// This is ignored for the fallback mode on MSVC due to problems with PDB.
33

44
//@ ignore-msvc
5+
//@ ignore-wasi wasi codegens the main symbol differently
56

67
//@ compile-flags: -g -C no-prepopulate-passes
78

0 commit comments

Comments
 (0)