From 1c80e1b73a8b1a71bd4f1fe43ce37d6b9bdb4db0 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 21 Dec 2022 15:37:47 +0900 Subject: [PATCH] Add some wasi-threads tests ``` (venv) spacetanuki% TOYWASM=~/git/toywasm/b/toywasm python3 test-runner/wasi_test_runner.py -t tests/wat/testsuite -r ~/git/toywasm/test/wasi-testsuite-adapter.py Test wasi_threads_exit_nonmain_wasi passed Test wasi_threads_exit_main_busy passed Test wasi_threads_exit_main_wasi passed Test wasi_threads_exit_nonmain_busy passed Test wasi_threads_spawn passed Test wasi_threads_exit_main_block passed Test wasi_threads_exit_nonmain_block passed ===== Test results ===== Runtime: toywasm v0.0 Suite: WASI wat tests Total: 7 Passed: 7 Failed: 0 Test suites: 1 passed, 0 total Tests: 7 passed, 0 total (venv) spacetanuki% ``` --- tests/wat/build.sh | 6 ++ tests/wat/testsuite/manifest.json | 3 + .../wasi_threads_exit_main_block.json | 3 + .../wasi_threads_exit_main_block.wat | 39 +++++++++++ .../wasi_threads_exit_main_busy.json | 3 + .../testsuite/wasi_threads_exit_main_busy.wat | 38 +++++++++++ .../wasi_threads_exit_main_wasi.json | 3 + .../testsuite/wasi_threads_exit_main_wasi.wat | 45 +++++++++++++ .../wasi_threads_exit_nonmain_block.json | 3 + .../wasi_threads_exit_nonmain_block.wat | 39 +++++++++++ .../wasi_threads_exit_nonmain_busy.json | 3 + .../wasi_threads_exit_nonmain_busy.wat | 38 +++++++++++ .../wasi_threads_exit_nonmain_wasi.json | 3 + .../wasi_threads_exit_nonmain_wasi.wat | 45 +++++++++++++ tests/wat/testsuite/wasi_threads_spawn.json | 3 + tests/wat/testsuite/wasi_threads_spawn.wat | 67 +++++++++++++++++++ 16 files changed, 341 insertions(+) create mode 100755 tests/wat/build.sh create mode 100644 tests/wat/testsuite/manifest.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_main_block.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_main_block.wat create mode 100644 tests/wat/testsuite/wasi_threads_exit_main_busy.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_main_busy.wat create mode 100644 tests/wat/testsuite/wasi_threads_exit_main_wasi.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_main_wasi.wat create mode 100644 tests/wat/testsuite/wasi_threads_exit_nonmain_block.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_nonmain_block.wat create mode 100644 tests/wat/testsuite/wasi_threads_exit_nonmain_busy.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_nonmain_busy.wat create mode 100644 tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.json create mode 100644 tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.wat create mode 100644 tests/wat/testsuite/wasi_threads_spawn.json create mode 100644 tests/wat/testsuite/wasi_threads_spawn.wat diff --git a/tests/wat/build.sh b/tests/wat/build.sh new file mode 100755 index 00000000..3df8bef9 --- /dev/null +++ b/tests/wat/build.sh @@ -0,0 +1,6 @@ +#! /bin/sh + +WAT2WASM=${WAT2WASM:-wat2wasm} +for wat in testsuite/*.wat; do + ${WAT2WASM} --enable-threads -o ${wat%%.wat}.wasm ${wat} +done diff --git a/tests/wat/testsuite/manifest.json b/tests/wat/testsuite/manifest.json new file mode 100644 index 00000000..8ebdfd63 --- /dev/null +++ b/tests/wat/testsuite/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "WASI wat tests" +} diff --git a/tests/wat/testsuite/wasi_threads_exit_main_block.json b/tests/wat/testsuite/wasi_threads_exit_main_block.json new file mode 100644 index 00000000..e8a2acf8 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_main_block.json @@ -0,0 +1,3 @@ +{ + "exit_code": 99 +} diff --git a/tests/wat/testsuite/wasi_threads_exit_main_block.wat b/tests/wat/testsuite/wasi_threads_exit_main_block.wat new file mode 100644 index 00000000..315858dc --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_main_block.wat @@ -0,0 +1,39 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; infinite wait + i32.const 0 + i32.const 0 + i64.const -1 + memory.atomic.wait32 + unreachable + ) + (func (export "_start") + ;; spawn a thread + i32.const 0 + call $thread_spawn + ;; check error + i32.const 0 + i32.le_s + if + unreachable + end + ;; wait 500ms to ensure the other thread block + i32.const 0 + i32.const 0 + i64.const 500_000_000 + memory.atomic.wait32 + ;; assert a timeout + i32.const 2 + i32.ne + if + unreachable + end + ;; exit + i32.const 99 + call $proc_exit + unreachable + ) + (memory 1 1 shared) +) diff --git a/tests/wat/testsuite/wasi_threads_exit_main_busy.json b/tests/wat/testsuite/wasi_threads_exit_main_busy.json new file mode 100644 index 00000000..e8a2acf8 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_main_busy.json @@ -0,0 +1,3 @@ +{ + "exit_code": 99 +} diff --git a/tests/wat/testsuite/wasi_threads_exit_main_busy.wat b/tests/wat/testsuite/wasi_threads_exit_main_busy.wat new file mode 100644 index 00000000..c699f6f1 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_main_busy.wat @@ -0,0 +1,38 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; infinite loop + loop + br 0 + end + unreachable + ) + (func (export "_start") + ;; spawn a thread + i32.const 0 + call $thread_spawn + ;; check error + i32.const 0 + i32.le_s + if + unreachable + end + ;; wait 500ms to ensure the other thread to enter the busy loop + i32.const 0 + i32.const 0 + i64.const 500_000_000 + memory.atomic.wait32 + ;; assert a timeout + i32.const 2 + i32.ne + if + unreachable + end + ;; exit + i32.const 99 + call $proc_exit + unreachable + ) + (memory 1 1 shared) +) diff --git a/tests/wat/testsuite/wasi_threads_exit_main_wasi.json b/tests/wat/testsuite/wasi_threads_exit_main_wasi.json new file mode 100644 index 00000000..e8a2acf8 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_main_wasi.json @@ -0,0 +1,3 @@ +{ + "exit_code": 99 +} diff --git a/tests/wat/testsuite/wasi_threads_exit_main_wasi.wat b/tests/wat/testsuite/wasi_threads_exit_main_wasi.wat new file mode 100644 index 00000000..68ea016e --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_main_wasi.wat @@ -0,0 +1,45 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func $poll_oneoff (import "wasi_snapshot_preview1" "poll_oneoff") (param i32 i32 i32 i32) (result i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; long enough block + ;; clock_realtime, !abstime (zeros) + i32.const 124 ;; 100 + offsetof(subscription, timeout) + i64.const 1_000_000_000 ;; 1s + i64.store + i32.const 100 ;; subscription + i32.const 200 ;; event (out) + i32.const 1 ;; nsubscriptions + i32.const 300 ;; retp (out) + call $poll_oneoff + unreachable + ) + (func (export "_start") + ;; spawn a thread + i32.const 0 + call $thread_spawn + ;; check error + i32.const 0 + i32.le_s + if + unreachable + end + ;; wait 500ms to ensure the other thread block + i32.const 0 + i32.const 0 + i64.const 500_000_000 + memory.atomic.wait32 + ;; assert a timeout + i32.const 2 + i32.ne + if + unreachable + end + ;; exit + i32.const 99 + call $proc_exit + unreachable + ) + (memory 1 1 shared) +) diff --git a/tests/wat/testsuite/wasi_threads_exit_nonmain_block.json b/tests/wat/testsuite/wasi_threads_exit_nonmain_block.json new file mode 100644 index 00000000..e8a2acf8 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_nonmain_block.json @@ -0,0 +1,3 @@ +{ + "exit_code": 99 +} diff --git a/tests/wat/testsuite/wasi_threads_exit_nonmain_block.wat b/tests/wat/testsuite/wasi_threads_exit_nonmain_block.wat new file mode 100644 index 00000000..6fb63844 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_nonmain_block.wat @@ -0,0 +1,39 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; wait 500ms to ensure the other thread block + i32.const 0 + i32.const 0 + i64.const 500_000_000 + memory.atomic.wait32 + ;; assert a timeout + i32.const 2 + i32.ne + if + unreachable + end + ;; exit + i32.const 99 + call $proc_exit + unreachable + ) + (func (export "_start") + ;; spawn a thread + i32.const 0 + call $thread_spawn + ;; check error + i32.const 0 + i32.le_s + if + unreachable + end + ;; infinite wait + i32.const 0 + i32.const 0 + i64.const -1 + memory.atomic.wait32 + unreachable + ) + (memory 1 1 shared) +) diff --git a/tests/wat/testsuite/wasi_threads_exit_nonmain_busy.json b/tests/wat/testsuite/wasi_threads_exit_nonmain_busy.json new file mode 100644 index 00000000..e8a2acf8 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_nonmain_busy.json @@ -0,0 +1,3 @@ +{ + "exit_code": 99 +} diff --git a/tests/wat/testsuite/wasi_threads_exit_nonmain_busy.wat b/tests/wat/testsuite/wasi_threads_exit_nonmain_busy.wat new file mode 100644 index 00000000..39fe16f5 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_nonmain_busy.wat @@ -0,0 +1,38 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; wait 500ms to ensure the other thread to enter the busy loop + i32.const 0 + i32.const 0 + i64.const 500_000_000 + memory.atomic.wait32 + ;; assert a timeout + i32.const 2 + i32.ne + if + unreachable + end + ;; exit + i32.const 99 + call $proc_exit + unreachable + ) + (func (export "_start") + ;; spawn a thread + i32.const 0 + call $thread_spawn + ;; check error + i32.const 0 + i32.le_s + if + unreachable + end + ;; infinite loop + loop + br 0 + end + unreachable + ) + (memory 1 1 shared) +) diff --git a/tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.json b/tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.json new file mode 100644 index 00000000..e8a2acf8 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.json @@ -0,0 +1,3 @@ +{ + "exit_code": 99 +} diff --git a/tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.wat b/tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.wat new file mode 100644 index 00000000..9f1772fd --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_exit_nonmain_wasi.wat @@ -0,0 +1,45 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func $poll_oneoff (import "wasi_snapshot_preview1" "poll_oneoff") (param i32 i32 i32 i32) (result i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; wait 500ms to ensure the other thread block + i32.const 0 + i32.const 0 + i64.const 500_000_000 + memory.atomic.wait32 + ;; assert a timeout + i32.const 2 + i32.ne + if + unreachable + end + ;; exit + i32.const 99 + call $proc_exit + unreachable + ) + (func (export "_start") + ;; spawn a thread + i32.const 0 + call $thread_spawn + ;; check error + i32.const 0 + i32.le_s + if + unreachable + end + ;; long enough block + ;; clock_realtime, !abstime (zeros) + i32.const 124 ;; 100 + offsetof(subscription, timeout) + i64.const 1_000_000_000 ;; 1s + i64.store + i32.const 100 ;; subscription + i32.const 200 ;; event (out) + i32.const 1 ;; nsubscriptions + i32.const 300 ;; retp (out) + call $poll_oneoff + unreachable + ) + (memory 1 1 shared) +) diff --git a/tests/wat/testsuite/wasi_threads_spawn.json b/tests/wat/testsuite/wasi_threads_spawn.json new file mode 100644 index 00000000..3e5ce1c7 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_spawn.json @@ -0,0 +1,3 @@ +{ + "exit_code": 22 +} diff --git a/tests/wat/testsuite/wasi_threads_spawn.wat b/tests/wat/testsuite/wasi_threads_spawn.wat new file mode 100644 index 00000000..c3dca696 --- /dev/null +++ b/tests/wat/testsuite/wasi_threads_spawn.wat @@ -0,0 +1,67 @@ +(module + (func $thread_spawn (import "wasi" "thread_spawn") (param i32) (result i32)) + (func $proc_exit (import "wasi_snapshot_preview1" "proc_exit") (param i32)) + (func (export "wasi_thread_start") (param i32 i32) + ;; store tid + i32.const 4 + local.get 0 + i32.store + ;; store user pointer + i32.const 8 + local.get 1 + i32.store + ;; notify the main + i32.const 0 + i32.const 1 + i32.atomic.store + i32.const 0 + i32.const 1 + memory.atomic.notify + drop + ;; returning from wasi_thread_start terminates only this thread + ) + (func (export "_start") (local i32) + ;; spawn a thread + i32.const 12345 ;; user pointer + call $thread_spawn + ;; check error + local.tee 0 ;; save the tid to check later + i32.const 0 + i32.le_s + if + unreachable + end + ;; wait for the spawned thread to run + i32.const 0 + i32.const 0 + i64.const -1 + memory.atomic.wait32 + ;; assert it was not a timeout + i32.const 2 + i32.eq + if + unreachable + end + ;; check the tid + local.get 0 + i32.const 4 + i32.load + i32.ne + if + unreachable + end + ;; check the user pointer + i32.const 8 + i32.load + i32.const 12345 + i32.ne + if + unreachable + end + ;; exit + i32.const 22 + call $proc_exit + unreachable + ) + (memory 1 1 shared) +)