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; +}