Skip to content

Commit 9427beb

Browse files
committed
Add some wast tests for async
1 parent 935c478 commit 9427beb

6 files changed

Lines changed: 260 additions & 0 deletions

File tree

test/async/deadlock.wast

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
(component
2+
(component $C
3+
(core module $Memory (memory (export "mem") 1))
4+
(core instance $memory (instantiate $Memory))
5+
(core module $CM
6+
(import "" "mem" (memory 1))
7+
(import "" "waitable-set.new" (func $waitable-set.new (result i32)))
8+
9+
(func (export "f") (result i32)
10+
(local $ws i32)
11+
;; return WAIT on an empty waitable set
12+
(local.set $ws (call $waitable-set.new))
13+
(i32.or (i32.const 2 (; WAIT ;)) (i32.shl (local.get $ws) (i32.const 4)))
14+
)
15+
(func (export "cb") (param $event_code i32) (param $index i32) (param $payload i32) (result i32)
16+
unreachable
17+
)
18+
)
19+
(canon waitable-set.new (core func $waitable-set.new))
20+
(core instance $cm (instantiate $CM (with "" (instance
21+
(export "mem" (memory $memory "mem"))
22+
(export "waitable-set.new" (func $waitable-set.new))
23+
))))
24+
(func (export "f") (result u32) (canon lift
25+
(core func $cm "f")
26+
async (memory $memory "mem") (callback (func $cm "cb"))
27+
))
28+
)
29+
30+
(component $D
31+
(import "f" (func $f (result u32)))
32+
33+
(core module $Memory (memory (export "mem") 1))
34+
(core instance $memory (instantiate $Memory))
35+
(core module $DM
36+
(import "" "mem" (memory 1))
37+
(import "" "waitable.join" (func $waitable.join (param i32 i32)))
38+
(import "" "waitable-set.new" (func $waitable-set.new (result i32)))
39+
(import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32)))
40+
(import "" "f" (func $f (param i32 i32) (result i32)))
41+
42+
(func (export "g") (result i32)
43+
(local $ws i32) (local $ret i32) (local $subtaski i32)
44+
(local.set $ws (call $waitable-set.new))
45+
(local.set $ret (call $f (i32.const 0) (i32.const 0)))
46+
(local.set $subtaski (i32.shr_u (local.get $ret) (i32.const 4)))
47+
(call $waitable.join (local.get $subtaski) (local.get $ws))
48+
(call $waitable-set.wait (local.get $ws) (i32.const 0))
49+
unreachable
50+
)
51+
)
52+
(canon waitable.join (core func $waitable.join))
53+
(canon waitable-set.new (core func $waitable-set.new))
54+
(canon waitable-set.wait (memory $memory "mem") (core func $waitable-set.wait))
55+
(canon lower (func $f) async (memory $memory "mem") (core func $f'))
56+
(core instance $dm (instantiate $DM (with "" (instance
57+
(export "mem" (memory $memory "mem"))
58+
(export "waitable.join" (func $waitable.join))
59+
(export "waitable-set.new" (func $waitable-set.new))
60+
(export "waitable-set.wait" (func $waitable-set.wait))
61+
(export "f" (func $f'))
62+
))))
63+
(func (export "f") (result u32) (canon lift (core func $dm "g")))
64+
)
65+
66+
(instance $c (instantiate $C))
67+
(instance $d (instantiate $D (with "f" (func $c "f"))))
68+
(func (export "f") (alias export $d "f"))
69+
)
70+
(assert_trap (invoke "f") "wasm trap: deadlock detected: event loop cannot make further progress")

test/async/empty-wait.wast

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
(component
2+
;; This test has two components $C and $D, where $D imports and calls $C
3+
(component $C
4+
(core module $Memory (memory (export "mem") 1))
5+
(core instance $memory (instantiate $Memory))
6+
(core module $CM
7+
(import "" "mem" (memory 1))
8+
(import "" "task.return" (func $task.return (param i32)))
9+
(import "" "waitable.join" (func $waitable.join (param i32 i32)))
10+
(import "" "waitable-set.new" (func $waitable-set.new (result i32)))
11+
(import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32)))
12+
(import "" "future.new" (func $future.new (result i64)))
13+
(import "" "future.read" (func $future.read (param i32 i32) (result i32)))
14+
(import "" "future.write" (func $future.write (param i32 i32) (result i32)))
15+
(import "" "future.close-readable" (func $future.close-readable (param i32)))
16+
(import "" "future.close-writable" (func $future.close-writable (param i32)))
17+
18+
(global $ws (mut i32) (i32.const 0))
19+
(func $start (global.set $ws (call $waitable-set.new)))
20+
(start $start)
21+
22+
(global $futr (mut i32) (i32.const 0))
23+
24+
(func $blocker (export "blocker") (result i32)
25+
;; wait on a waitable-set that is empty now, but will be extended by 'unblocker' to wake us
26+
(i32.or (i32.const 2 (; WAIT ;)) (i32.shl (global.get $ws) (i32.const 4)))
27+
)
28+
(func $blocker_cb (export "blocker_cb") (param $event_code i32) (param $index i32) (param $payload i32) (result i32)
29+
;; assert that we were in fact woken by 'unblocker' adding the readable end
30+
;; of a future and then writing to that future
31+
(if (i32.ne (i32.const 4 (; FUTURE_READ ;)) (local.get $event_code))
32+
(then unreachable))
33+
(if (i32.ne (global.get $futr) (local.get $index))
34+
(then unreachable))
35+
(if (i32.ne (i32.const 0x10) (local.get $payload)) ;; TODO: 0x11? (b/c CLOSED)
36+
(then unreachable))
37+
38+
(call $future.close-readable (global.get $futr))
39+
40+
(call $task.return (i32.const 42))
41+
(i32.const 0)
42+
)
43+
44+
(func $unblocker (export "unblocker") (result i32)
45+
(local $ret64 i64) (local $ret i32) (local $futw i32)
46+
47+
;; create a future that will be used to unblock 'blocker', storing r/w ends in $futr/$futw
48+
(local.set $ret64 (call $future.new))
49+
(global.set $futr (i32.wrap_i64 (local.get $ret64)))
50+
(if (i32.ne (i32.const 3) (global.get $futr)) ;; TODO: 2?
51+
(then unreachable))
52+
(local.set $futw (i32.wrap_i64 (i64.shr_u (local.get $ret64) (i64.const 32))))
53+
(if (i32.ne (i32.const 2) (local.get $futw)) ;; TODO: 3?
54+
(then unreachable))
55+
56+
;; perform a future.read which will block, and add this future to the waitable-set
57+
;; being waited on by 'blocker'
58+
(local.set $ret (call $future.read (global.get $futr) (i32.const 0xdeadbeef)))
59+
(if (i32.ne (i32.const -1 (; BLOCKED ;)) (local.get $ret))
60+
(then unreachable))
61+
(call $waitable.join (global.get $futr) (global.get $ws))
62+
63+
;; perform a future.write which will rendezvous with the write and complete
64+
(local.set $ret (call $future.write (local.get $futw) (i32.const 0xdeadbeef)))
65+
(if (i32.ne (i32.const 0x10) (local.get $ret)) ;; TODO: 0x11? (b/c CLOSED)
66+
(then unreachable))
67+
68+
(call $future.close-writable (local.get $futw))
69+
70+
;; return and exit
71+
(call $task.return (i32.const 43))
72+
(i32.const 0)
73+
)
74+
(func $unblocker_cb (export "unblocker_cb") (param i32 i32 i32) (result i32)
75+
unreachable
76+
)
77+
)
78+
(type $FT (future))
79+
(canon task.return (result u32) (core func $task.return))
80+
(canon waitable.join (core func $waitable.join))
81+
(canon waitable-set.new (core func $waitable-set.new))
82+
(canon waitable-set.wait (memory $memory "mem") (core func $waitable-set.wait))
83+
(canon future.new $FT (core func $future.new))
84+
(canon future.read $FT async (memory $memory "mem") (core func $future.read))
85+
(canon future.write $FT async (memory $memory "mem") (core func $future.write))
86+
(canon future.close-readable $FT (core func $future.close-readable))
87+
(canon future.close-writable $FT (core func $future.close-writable))
88+
(core instance $cm (instantiate $CM (with "" (instance
89+
(export "mem" (memory $memory "mem"))
90+
(export "task.return" (func $task.return))
91+
(export "waitable.join" (func $waitable.join))
92+
(export "waitable-set.new" (func $waitable-set.new))
93+
(export "waitable-set.wait" (func $waitable-set.wait))
94+
(export "future.new" (func $future.new))
95+
(export "future.read" (func $future.read))
96+
(export "future.write" (func $future.write))
97+
(export "future.close-readable" (func $future.close-readable))
98+
(export "future.close-writable" (func $future.close-writable))
99+
))))
100+
(func (export "blocker") (result u32) (canon lift
101+
(core func $cm "blocker")
102+
async (memory $memory "mem") (callback (func $cm "blocker_cb"))
103+
))
104+
(func (export "unblocker") (result u32) (canon lift
105+
(core func $cm "unblocker")
106+
async (memory $memory "mem") (callback (func $cm "unblocker_cb"))
107+
))
108+
)
109+
110+
(component $D
111+
(import "c" (instance $c
112+
(export "blocker" (func (result u32)))
113+
(export "unblocker" (func (result u32)))
114+
))
115+
116+
(core module $Memory (memory (export "mem") 1))
117+
(core instance $memory (instantiate $Memory))
118+
(core module $DM
119+
(import "" "mem" (memory 1))
120+
(import "" "waitable.join" (func $waitable.join (param i32 i32)))
121+
(import "" "waitable-set.new" (func $waitable-set.new (result i32)))
122+
(import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32)))
123+
(import "" "blocker" (func $blocker (param i32 i32) (result i32)))
124+
(import "" "unblocker" (func $unblocker (param i32 i32) (result i32)))
125+
126+
(global $ws (mut i32) (i32.const 0))
127+
(func $start (global.set $ws (call $waitable-set.new)))
128+
(start $start)
129+
130+
(func $run (export "run") (result i32)
131+
(local $ret i32) (local $subtaski i32) (local $event_code i32) (local $retp1 i32) (local $retp2 i32)
132+
133+
;; call 'blocker' will block on an empty waitable set
134+
(local.set $retp1 (i32.const 4))
135+
(local.set $ret (call $blocker (i32.const 0xdeadbeef) (local.get $retp1)))
136+
(if (i32.ne (i32.const 1 (; STARTING ;)) (i32.and (local.get $ret) (i32.const 0xf)))
137+
(then unreachable))
138+
(local.set $subtaski (i32.shr_u (local.get $ret) (i32.const 4)))
139+
(if (i32.ne (i32.const 2) (local.get $subtaski))
140+
(then unreachable))
141+
142+
;; call 'unblocker' to unblock the call to 'blocker'
143+
(local.set $retp2 (i32.const 8))
144+
(local.set $ret (call $unblocker (i32.const 0xbeefdead) (local.get $retp2)))
145+
(if (i32.ne (i32.const 2) (local.get $ret))
146+
(then unreachable))
147+
(if (i32.ne (i32.const 43) (i32.load (local.get $retp2)))
148+
(then unreachable))
149+
150+
;; wait for 'blocker' to be unblocked, run, and return
151+
(call $waitable.join (local.get $subtaski) (global.get $ws))
152+
(local.set $retp2 (i32.const 8))
153+
(local.set $event_code (call $waitable-set.wait (global.get $ws) (local.get $retp2)))
154+
(if (i32.ne (i32.const 1 (; SUBTASK ;)) (local.get $event_code))
155+
(then unreachable))
156+
(if (i32.ne (local.get $subtaski) (i32.load (local.get $retp2)))
157+
(then unreachable))
158+
(if (i32.ne (i32.const 2 (; RETURNED ;)) (i32.load offset=4 (local.get $retp2)))
159+
(then unreachable))
160+
(if (i32.ne (i32.const 42) (i32.load (local.get $retp1)))
161+
(then unreachable))
162+
163+
(i32.const 44)
164+
)
165+
)
166+
(canon waitable.join (core func $waitable.join))
167+
(canon waitable-set.new (core func $waitable-set.new))
168+
(canon waitable-set.wait (memory $memory "mem") (core func $waitable-set.wait))
169+
(canon lower (func $c "blocker") async (memory $memory "mem") (core func $blocker'))
170+
(canon lower (func $c "unblocker") async (memory $memory "mem") (core func $unblocker'))
171+
(core instance $dm (instantiate $DM (with "" (instance
172+
(export "mem" (memory $memory "mem"))
173+
(export "waitable.join" (func $waitable.join))
174+
(export "waitable-set.new" (func $waitable-set.new))
175+
(export "waitable-set.wait" (func $waitable-set.wait))
176+
(export "blocker" (func $blocker'))
177+
(export "unblocker" (func $unblocker'))
178+
))))
179+
(func (export "run") (result u32) (canon lift (core func $dm "run")))
180+
)
181+
182+
(instance $c (instantiate $C))
183+
(instance $d (instantiate $D (with "c" (instance $c))))
184+
(func (export "run") (alias export $d "run"))
185+
)
186+
(assert_return (invoke "run") (u32.const 44))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO: particularly multiple into the same buffer and it all happening eagerly w/o blocking

test/async/zero-length.wast

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO

test/resources/basic.wast

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO

test/values/basic.wast

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO

0 commit comments

Comments
 (0)