From ab6cdb244ec7237d4452c63873b506a49f5390e9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 3 Mar 2025 13:09:50 -0800 Subject: [PATCH] Start running some async tests in CI This commit starts to execute some async tests in CI via artifacts downloaded from the wasip3-prototyping repository. While the status is reported on PRs this won't actually result in failing to merge something if the job fails at this time since it's known that async is a bit of a shifting landscape. In the meantime it's hoped that at least having this status on PRs will be sufficient for seeing failures for now. The actual set of initial tests here are relatively edge-case-y where I added them some time ago when testing Rust bindings. They're not comprehensive by any means but are hopefully at least a start. I hope to next start adding more tests in follow-up PRs. --- .github/workflows/main.yml | 27 +++++++++++++++++++ .../future-cancel-write-then-read/runner.rs | 13 +++++++++ .../future-cancel-write-then-read/test.rs | 15 +++++++++++ .../future-cancel-write-then-read/test.wit | 12 +++++++++ .../future-close-after-coming-back/runner.rs | 11 ++++++++ .../future-close-after-coming-back/test.rs | 15 +++++++++++ .../future-close-after-coming-back/test.wit | 12 +++++++++ .../future-close-then-receive-read/runner.rs | 14 ++++++++++ .../future-close-then-receive-read/test.rs | 22 +++++++++++++++ .../future-close-then-receive-read/test.wit | 13 +++++++++ .../async/future-closes-with-error/runner.rs | 12 +++++++++ .../async/future-closes-with-error/test.rs | 14 ++++++++++ .../async/future-closes-with-error/test.wit | 12 +++++++++ .../runner.rs | 16 +++++++++++ .../future-write-then-read-comes-back/test.rs | 15 +++++++++++ .../test.wit | 12 +++++++++ .../future-write-then-read-remote/runner.rs | 18 +++++++++++++ .../future-write-then-read-remote/runner2.rs | 18 +++++++++++++ .../future-write-then-read-remote/test.rs | 17 ++++++++++++ .../future-write-then-read-remote/test.wit | 12 +++++++++ 20 files changed, 300 insertions(+) create mode 100644 tests/runtime-async/async/future-cancel-write-then-read/runner.rs create mode 100644 tests/runtime-async/async/future-cancel-write-then-read/test.rs create mode 100644 tests/runtime-async/async/future-cancel-write-then-read/test.wit create mode 100644 tests/runtime-async/async/future-close-after-coming-back/runner.rs create mode 100644 tests/runtime-async/async/future-close-after-coming-back/test.rs create mode 100644 tests/runtime-async/async/future-close-after-coming-back/test.wit create mode 100644 tests/runtime-async/async/future-close-then-receive-read/runner.rs create mode 100644 tests/runtime-async/async/future-close-then-receive-read/test.rs create mode 100644 tests/runtime-async/async/future-close-then-receive-read/test.wit create mode 100644 tests/runtime-async/async/future-closes-with-error/runner.rs create mode 100644 tests/runtime-async/async/future-closes-with-error/test.rs create mode 100644 tests/runtime-async/async/future-closes-with-error/test.wit create mode 100644 tests/runtime-async/async/future-write-then-read-comes-back/runner.rs create mode 100644 tests/runtime-async/async/future-write-then-read-comes-back/test.rs create mode 100644 tests/runtime-async/async/future-write-then-read-comes-back/test.wit create mode 100644 tests/runtime-async/async/future-write-then-read-remote/runner.rs create mode 100644 tests/runtime-async/async/future-write-then-read-remote/runner2.rs create mode 100644 tests/runtime-async/async/future-write-then-read-remote/test.rs create mode 100644 tests/runtime-async/async/future-write-then-read-remote/test.wit diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 50d2fe730..837629a36 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -111,6 +111,33 @@ jobs: --artifacts target/artifacts \ --rust-wit-bindgen-path ./crates/guest-rust + # While we're working on getting wasip3-prototyping upstream in wasmtime + # itself run tests here in separate async job. Note that this job is NOT + # required for merging but it reports its status anyway to alert folks to at + # least the "big red X" status. The goal here is that this is known to be a + # bit unstable as the async foundations are shifting over time but this at + # least enables testing async things in this repository more easily. + async: + name: Test Async + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust + run: rustup update stable --no-self-update && rustup default stable + - run: rustup target add wasm32-wasip1 + - uses: ./.github/actions/install-wasi-sdk + - run: | + curl -L https://github.com/bytecodealliance/wasip3-prototyping/releases/download/dev/wasmtime-dev-x86_64-linux.tar.xz | tar xJvf - + echo "WASMTIME=`pwd`/wasmtime-dev-x86_64-linux/wasmtime" >> $GITHUB_ENV + - run: | + cargo run test --languages rust tests/runtime-async \ + --artifacts target/artifacts \ + --rust-wit-bindgen-path ./crates/guest-rust \ + --rust-target wasm32-wasip1 \ + --runner "$WASMTIME -W component-model-async" + test_unit: name: Crate Unit Tests runs-on: ubuntu-latest diff --git a/tests/runtime-async/async/future-cancel-write-then-read/runner.rs b/tests/runtime-async/async/future-cancel-write-then-read/runner.rs new file mode 100644 index 000000000..5e5334997 --- /dev/null +++ b/tests/runtime-async/async/future-cancel-write-then-read/runner.rs @@ -0,0 +1,13 @@ +//@ args = '--async=-all' + +include!(env!("BINDINGS")); + +use crate::a::b::the_test::f; + +fn main() { + let (tx, rx) = wit_future::new(); + + drop(tx.write(())); + + f(rx); +} diff --git a/tests/runtime-async/async/future-cancel-write-then-read/test.rs b/tests/runtime-async/async/future-cancel-write-then-read/test.rs new file mode 100644 index 000000000..869b44aee --- /dev/null +++ b/tests/runtime-async/async/future-cancel-write-then-read/test.rs @@ -0,0 +1,15 @@ +include!(env!("BINDINGS")); + +struct Component; + +export!(Component); + +use crate::exports::a::b::the_test::Guest; + +use wit_bindgen::rt::async_support::FutureReader; + +impl Guest for Component { + async fn f(future: FutureReader<()>) { + assert!(future.await.is_none()); + } +} diff --git a/tests/runtime-async/async/future-cancel-write-then-read/test.wit b/tests/runtime-async/async/future-cancel-write-then-read/test.wit new file mode 100644 index 000000000..8dfce4db6 --- /dev/null +++ b/tests/runtime-async/async/future-cancel-write-then-read/test.wit @@ -0,0 +1,12 @@ +package a:b; + +interface the-test { + f: async func(param: future); +} + +world test { + export the-test; +} +world runner { + import the-test; +} diff --git a/tests/runtime-async/async/future-close-after-coming-back/runner.rs b/tests/runtime-async/async/future-close-after-coming-back/runner.rs new file mode 100644 index 000000000..c0d79b4cc --- /dev/null +++ b/tests/runtime-async/async/future-close-after-coming-back/runner.rs @@ -0,0 +1,11 @@ +include!(env!("BINDINGS")); + +use crate::a::b::the_test::f; + +fn main() { + let (tx, rx) = wit_future::new(); + + let rx = f(rx); + drop(tx); + drop(rx); +} diff --git a/tests/runtime-async/async/future-close-after-coming-back/test.rs b/tests/runtime-async/async/future-close-after-coming-back/test.rs new file mode 100644 index 000000000..2b6caa57c --- /dev/null +++ b/tests/runtime-async/async/future-close-after-coming-back/test.rs @@ -0,0 +1,15 @@ +include!(env!("BINDINGS")); + +struct Component; + +export!(Component); + +use crate::exports::a::b::the_test::Guest; + +use wit_bindgen::rt::async_support::FutureReader; + +impl Guest for Component { + fn f(future: FutureReader<()>) -> FutureReader<()> { + future + } +} diff --git a/tests/runtime-async/async/future-close-after-coming-back/test.wit b/tests/runtime-async/async/future-close-after-coming-back/test.wit new file mode 100644 index 000000000..aebf1f589 --- /dev/null +++ b/tests/runtime-async/async/future-close-after-coming-back/test.wit @@ -0,0 +1,12 @@ +package a:b; + +interface the-test { + f: func(param: future) -> future; +} + +world test { + export the-test; +} +world runner { + import the-test; +} diff --git a/tests/runtime-async/async/future-close-then-receive-read/runner.rs b/tests/runtime-async/async/future-close-then-receive-read/runner.rs new file mode 100644 index 000000000..fc13ead8c --- /dev/null +++ b/tests/runtime-async/async/future-close-then-receive-read/runner.rs @@ -0,0 +1,14 @@ +include!(env!("BINDINGS")); + +use crate::a::b::the_test::{get, set}; + +fn main() { + let (tx, rx) = wit_future::new(); + + set(rx); + let rx = get(); + drop(tx); + drop(rx); + + wit_future::new::<()>(); +} diff --git a/tests/runtime-async/async/future-close-then-receive-read/test.rs b/tests/runtime-async/async/future-close-then-receive-read/test.rs new file mode 100644 index 000000000..bfb00b5a3 --- /dev/null +++ b/tests/runtime-async/async/future-close-then-receive-read/test.rs @@ -0,0 +1,22 @@ +include!(env!("BINDINGS")); + +use crate::exports::a::b::the_test::Guest; +use std::cell::Cell; +use wit_bindgen::rt::async_support::FutureReader; + +struct Component; + +export!(Component); + +std::thread_local!( + static SLOT: Cell>> = const { Cell::new(None) }; +); + +impl Guest for Component { + fn set(future: FutureReader<()>) { + SLOT.with(|s| s.set(Some(future))); + } + fn get() -> FutureReader<()> { + SLOT.with(|s| s.replace(None).unwrap()) + } +} diff --git a/tests/runtime-async/async/future-close-then-receive-read/test.wit b/tests/runtime-async/async/future-close-then-receive-read/test.wit new file mode 100644 index 000000000..309ca4670 --- /dev/null +++ b/tests/runtime-async/async/future-close-then-receive-read/test.wit @@ -0,0 +1,13 @@ +package a:b; + +interface the-test { + set: func(param: future); + get: func() -> future; +} + +world test { + export the-test; +} +world runner { + import the-test; +} diff --git a/tests/runtime-async/async/future-closes-with-error/runner.rs b/tests/runtime-async/async/future-closes-with-error/runner.rs new file mode 100644 index 000000000..e0bd60df5 --- /dev/null +++ b/tests/runtime-async/async/future-closes-with-error/runner.rs @@ -0,0 +1,12 @@ +//@ args = '--async=-all' +include!(env!("BINDINGS")); + +use crate::a::b::the_test::f; + +fn main() { + let (tx, rx) = wit_future::new(); + + drop(tx); + + f(rx); +} diff --git a/tests/runtime-async/async/future-closes-with-error/test.rs b/tests/runtime-async/async/future-closes-with-error/test.rs new file mode 100644 index 000000000..0fcf9192a --- /dev/null +++ b/tests/runtime-async/async/future-closes-with-error/test.rs @@ -0,0 +1,14 @@ +include!(env!("BINDINGS")); + +struct Component; + +export!(Component); + +use crate::exports::a::b::the_test::Guest; +use wit_bindgen::rt::async_support::FutureReader; + +impl Guest for Component { + async fn f(future: FutureReader<()>) { + assert!(future.await.is_none()); + } +} diff --git a/tests/runtime-async/async/future-closes-with-error/test.wit b/tests/runtime-async/async/future-closes-with-error/test.wit new file mode 100644 index 000000000..8dfce4db6 --- /dev/null +++ b/tests/runtime-async/async/future-closes-with-error/test.wit @@ -0,0 +1,12 @@ +package a:b; + +interface the-test { + f: async func(param: future); +} + +world test { + export the-test; +} +world runner { + import the-test; +} diff --git a/tests/runtime-async/async/future-write-then-read-comes-back/runner.rs b/tests/runtime-async/async/future-write-then-read-comes-back/runner.rs new file mode 100644 index 000000000..a99531dc0 --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-comes-back/runner.rs @@ -0,0 +1,16 @@ +include!(env!("BINDINGS")); + +use wit_bindgen::rt::async_support; + +use crate::a::b::the_test::f; + +fn main() { + async_support::block_on(async { + let (tx, rx) = wit_future::new(); + + let a = async { tx.write(()).await }; + let b = async { f(rx).await.unwrap() }; + let (a_result, ()) = futures::join!(a, b); + a_result.unwrap() + }); +} diff --git a/tests/runtime-async/async/future-write-then-read-comes-back/test.rs b/tests/runtime-async/async/future-write-then-read-comes-back/test.rs new file mode 100644 index 000000000..2b6caa57c --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-comes-back/test.rs @@ -0,0 +1,15 @@ +include!(env!("BINDINGS")); + +struct Component; + +export!(Component); + +use crate::exports::a::b::the_test::Guest; + +use wit_bindgen::rt::async_support::FutureReader; + +impl Guest for Component { + fn f(future: FutureReader<()>) -> FutureReader<()> { + future + } +} diff --git a/tests/runtime-async/async/future-write-then-read-comes-back/test.wit b/tests/runtime-async/async/future-write-then-read-comes-back/test.wit new file mode 100644 index 000000000..aebf1f589 --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-comes-back/test.wit @@ -0,0 +1,12 @@ +package a:b; + +interface the-test { + f: func(param: future) -> future; +} + +world test { + export the-test; +} +world runner { + import the-test; +} diff --git a/tests/runtime-async/async/future-write-then-read-remote/runner.rs b/tests/runtime-async/async/future-write-then-read-remote/runner.rs new file mode 100644 index 000000000..fe2a2ce73 --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-remote/runner.rs @@ -0,0 +1,18 @@ +//@ args = '--async=-all' + +include!(env!("BINDINGS")); + +use wit_bindgen::rt::async_support; + +use crate::a::b::the_test::f; + +fn main() { + async_support::block_on(async { + let (tx, rx) = wit_future::new(); + + let a = async { tx.write(()).await }; + let b = async { f(rx) }; + let (a_result, ()) = futures::join!(a, b); + a_result.unwrap(); + }); +} diff --git a/tests/runtime-async/async/future-write-then-read-remote/runner2.rs b/tests/runtime-async/async/future-write-then-read-remote/runner2.rs new file mode 100644 index 000000000..2752cea68 --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-remote/runner2.rs @@ -0,0 +1,18 @@ +//@ args = '--async=-all' + +include!(env!("BINDINGS")); + +use wit_bindgen::rt::async_support; + +use crate::a::b::the_test::f; + +fn main() { + async_support::block_on(async { + let (tx, rx) = wit_future::new(); + + let a = tx.write(()); + let b = async { f(rx) }; + let (a_result, ()) = futures::join!(a, b); + a_result.unwrap(); + }); +} diff --git a/tests/runtime-async/async/future-write-then-read-remote/test.rs b/tests/runtime-async/async/future-write-then-read-remote/test.rs new file mode 100644 index 000000000..26d12faef --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-remote/test.rs @@ -0,0 +1,17 @@ +include!(env!("BINDINGS")); + +struct Component; + +export!(Component); + +use crate::exports::a::b::the_test::Guest; + +use wit_bindgen::rt::async_support::FutureReader; + +impl Guest for Component { + async fn f(future: FutureReader<()>) { + eprintln!("e1"); + future.await.unwrap(); + eprintln!("e2"); + } +} diff --git a/tests/runtime-async/async/future-write-then-read-remote/test.wit b/tests/runtime-async/async/future-write-then-read-remote/test.wit new file mode 100644 index 000000000..8dfce4db6 --- /dev/null +++ b/tests/runtime-async/async/future-write-then-read-remote/test.wit @@ -0,0 +1,12 @@ +package a:b; + +interface the-test { + f: async func(param: future); +} + +world test { + export the-test; +} +world runner { + import the-test; +}