Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/install-wasi-sdk/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ runs:
- name: Setup `wasm-tools`
uses: bytecodealliance/actions/wasm-tools/setup@v1
with:
version: "1.247.0"
version: "1.252.0"
- name: Setup `wasmtime`
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "44.0.0"
version: "46.0.1"
37 changes: 19 additions & 18 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,22 @@ jobs:
dotnet-version: '9.x'
if: matrix.lang == 'csharp'

# As of this writing async tests require [a patched build of
# Go](https://github.com/dicej/go/releases/tag/go1.25.5-wasi-on-idle).
# Install this on Linux to get coverage, but don't install it on
# macOS/Windows to also get coverage for test-without-a-patched-toolchain.
- name: Install Patched Go
run: |
curl -OL https://github.com/dicej/go/releases/download/go1.25.5-wasi-on-idle/go-linux-amd64-bootstrap.tbz
tar xf go-linux-amd64-bootstrap.tbz
echo "$(pwd)/go-linux-amd64-bootstrap/bin" >> $GITHUB_PATH
if: matrix.lang == 'go' && matrix.os == 'ubuntu-latest'

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.25.4
if: matrix.lang == 'go'
if: matrix.lang == 'go' && matrix.os != 'ubuntu-latest'

# Hacky work-around for https://github.com/dotnet/runtime/issues/80619
- run: dotnet new console -o /tmp/foo
Expand All @@ -130,17 +141,17 @@ jobs:
--artifacts target/artifacts \
--rust-wit-bindgen-path ./crates/guest-rust

# Run all runtime tests for this language, and also enable Rust in case this
# language only implements either the runner or test component
# Run all runtime tests for this language, and also enable Rust & C in case
# this language only implements either the runner or test component
- run: |
cargo run test --languages rust,${{ matrix.lang }} tests/runtime \
cargo run test --languages rust,c,${{ matrix.lang }} tests/runtime \
--artifacts target/artifacts \
--rust-wit-bindgen-path ./crates/guest-rust

# While async is off-by-default and toolchains are percolating this is a
# While threading is off-by-default and toolchains are percolating this is a
# separate job to get configured slightly differently.
async:
name: Test Async (allowed to fail)
threading:
name: Test WASIp3 Threading (allowed to fail)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -151,18 +162,9 @@ jobs:
run: rustup update stable --no-self-update && rustup default stable
- run: rustup target add wasm32-wasip2

# As of this writing, we need [a patched build of
# Go](https://github.com/dicej/go/releases/tag/go1.25.5-wasi-on-idle) to
# support async.
- name: Install Patched Go
run: |
curl -OL https://github.com/dicej/go/releases/download/go1.25.5-wasi-on-idle/go-linux-amd64-bootstrap.tbz
tar xf go-linux-amd64-bootstrap.tbz
echo "$(pwd)/go-linux-amd64-bootstrap/bin" >> $GITHUB_PATH

- uses: ./.github/actions/install-wasi-sdk
- run: |
cargo run test --languages rust,c,go tests/runtime-async \
cargo run test --languages rust,c,go tests/threading \
--artifacts target/artifacts \
--rust-wit-bindgen-path ./crates/guest-rust

Expand Down Expand Up @@ -287,7 +289,6 @@ jobs:
- verify-publish
- check
- msrv
# - async
if: always()

steps:
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ log = "0.4.26"
regex = "1.11.1"
serde = { workspace = true }
toml = "1.1.2"
wasi-preview1-component-adapter-provider = "45.0.1"
wasi-preview1-component-adapter-provider = "46.0.1"
wac-parser = "0.10.0"
wac-types = "0.10.0"
wac-graph = "0.10.0"
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl LanguageMethods for C {

fn should_fail_verify(
&self,
_runner: &Runner,
name: &str,
config: &crate::config::WitConfig,
_args: &[String],
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl LanguageMethods for Cpp {

fn should_fail_verify(
&self,
_runner: &Runner,
name: &str,
config: &crate::config::WitConfig,
_args: &[String],
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl LanguageMethods for Csharp {

fn should_fail_verify(
&self,
_runner: &Runner,
name: &str,
_config: &crate::config::WitConfig,
_args: &[String],
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ impl LanguageMethods for Language {

fn should_fail_verify(
&self,
_runner: &Runner,
_name: &str,
_config: &crate::config::WitConfig,
_args: &[String],
Expand Down
98 changes: 88 additions & 10 deletions crates/test/src/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ use std::process::Command;

pub struct Go;

/// Go-specific state, stored in `Runner`, detected during `prepare`.
pub struct State {
/// Whether the Go toolchain in use supports the `runtime.wasiOnIdle` hook
/// required for component model async support.
async_supported: bool,
}

impl Runner {
fn go_async_supported(&self) -> bool {
self.go_state
.as_ref()
.map(|s| s.async_supported)
.unwrap_or(false)
}
}

impl LanguageMethods for Go {
fn display(&self) -> &str {
"go"
Expand All @@ -18,19 +34,43 @@ impl LanguageMethods for Go {

fn should_fail_verify(
&self,
runner: &Runner,
name: &str,
config: &crate::config::WitConfig,
_args: &[String],
) -> bool {
// TODO: We _do_ support async, but only with a build of Go that has
// [this
// patch](https://github.com/dicej/go/commit/40fc123d5bce6448fc4e4601fd33bad4250b36a5).
// Once we upstream something equivalent, we can remove the ` || name ==
// "async-trait-function.wit"` here.
config.error_context
|| name == "async-trait-function.wit"
|| name == "named-fixed-length-list.wit"
|| name == "issue-1598.wit"
if config.error_context {
return true;
}
if name == "named-fixed-length-list.wit" {
return true;
}
if !runner.go_async_supported() {
return name == "async-trait-function.wit" || name == "issue-1598.wit";
}

false
}

fn should_fail_compile(
&self,
runner: &Runner,
path: &Path,
config: &crate::config::WitConfig,
) -> bool {
// This test, even though it's part of async, compiles on any
// toolchain.
if path.ends_with("incomplete-writes/leaf.go") {
return false;
}

// Bindings for async tests rely on `runtime.wasiOnIdle` (see `prepare`
// below) and fail to link without a toolchain that provides it.
if !runner.go_async_supported() {
return config.async_;
}

false
}

fn default_bindgen_args_for_codegen(&self) -> &[&str] {
Expand All @@ -56,7 +96,45 @@ impl LanguageMethods for Go {
.arg("build")
.arg("-buildmode=c-shared")
.arg("-ldflags=-checklinkname=0"),
)
)?;

// Component model async support requires a `runtime.wasiOnIdle` hook
// which, as of the time of this writing, is only available in a
// patched build of Go. Detect whether the toolchain in use has
// this hook by building a program that links against it, and if not
// then async tests are expected to fail to build.
println!("Testing if `go` supports `runtime.wasiOnIdle`...");
let probe_dir = dir.join("wasi-on-idle-probe");
super::write_if_different(
&probe_dir.join("main.go"),
r#"package main

import _ "unsafe"

//go:linkname wasiOnIdle runtime.wasiOnIdle
func wasiOnIdle(callback func() bool)
func init() { defer wasiOnIdle(func() bool { return false }) }
func main() {}
"#,
)?;
super::write_if_different(&probe_dir.join("go.mod"), "module probe\n\ngo 1.25")?;
let async_supported = runner
.run_command(
Command::new("go")
.current_dir(&probe_dir)
.env("GOOS", "wasip1")
.env("GOARCH", "wasm")
.arg("build")
.arg("-o")
.arg("probe.wasm")
.arg("-buildmode=c-shared")
.arg("-ldflags=-checklinkname=0"),
)
.is_ok();
println!("`runtime.wasiOnIdle` supported: {async_supported}");
runner.go_state = Some(State { async_supported });

Ok(())
}

fn compile(&self, runner: &Runner, compile: &Compile<'_>) -> Result<()> {
Expand Down
36 changes: 31 additions & 5 deletions crates/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl Opts {
Runner {
opts: self.clone(),
rust_state: None,
go_state: None,
wit_bindgen: wit_bindgen.to_path_buf(),
test_runner: runner::TestRunner::new(&self.runner)?,
}
Expand Down Expand Up @@ -254,6 +255,7 @@ struct Verify<'a> {
struct Runner {
opts: Opts,
rust_state: Option<rust::State>,
go_state: Option<go::State>,
wit_bindgen: PathBuf,
test_runner: runner::TestRunner,
}
Expand Down Expand Up @@ -578,7 +580,7 @@ impl Runner {
let me = self.clone();
let should_fail = language
.obj()
.should_fail_verify(&args_kind, &config, &args);
.should_fail_verify(self, &args_kind, &config, &args);

let name = format!("{language} {args_kind} {test:?}");
Trial::test(&name, move || {
Expand Down Expand Up @@ -703,17 +705,23 @@ impl Runner {
let compilations = compilations.clone();
let test = test.clone();
let component = component.clone();
let should_fail = component.language.obj().should_fail_compile(
self,
&component.path,
&component.bindgen.wit_config,
);
Trial::test(&component.path.display().to_string(), move || {
let result = me.compile_component(&test, &component).with_context(|| {
format!("failed to compile component {:?}", component.path)
});
match result {
Ok(path) => {
Ok(path) if !should_fail => {
compilations.lock().unwrap().push((test, component, path));
Ok(())
}
Err(e) => me.render_error(
StepResult::new(Err(e))
other => me.render_error(
StepResult::new(other.map(|_| ()))
.should_fail(should_fail)
.metadata("component", &component.name)
.metadata("path", component.path.display()),
),
Expand Down Expand Up @@ -1280,7 +1288,25 @@ trait LanguageMethods {

/// Returns whether this language is supposed to fail this codegen tests
/// given the `config` and `args` for the test.
fn should_fail_verify(&self, name: &str, config: &config::WitConfig, args: &[String]) -> bool;
fn should_fail_verify(
&self,
runner: &Runner,
name: &str,
config: &config::WitConfig,
args: &[String],
) -> bool;

/// Returns whether this language is expected to fail to compile the
/// runtime test component described by `config`.
fn should_fail_compile(
&self,
runner: &Runner,
path: &Path,
config: &config::WitConfig,
) -> bool {
let _ = (runner, path, config);
false
}

/// Performs a "check" or a verify that the generated bindings described by
/// `Verify` are indeed valid.
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/moonbit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ impl LanguageMethods for MoonBit {

fn should_fail_verify(
&self,
_runner: &Runner,
name: &str,
config: &crate::config::WitConfig,
_args: &[String],
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl LanguageMethods for Rust {

fn should_fail_verify(
&self,
_runner: &Runner,
name: &str,
_config: &crate::config::WitConfig,
_args: &[String],
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/wat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ impl LanguageMethods for Wat {

fn should_fail_verify(
&self,
_runner: &Runner,
_name: &str,
_config: &crate::config::WitConfig,
_args: &[String],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ async = true
package my:test;

interface i {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ async = true
package my:test;

interface i {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ async = true
package a:b;

interface the-test {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ async = true
package my:test;

interface i {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ async = true
package a:b;

interface the-test {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ async = true
package a:b;

interface the-test {
Expand Down
Loading
Loading