Skip to content

Commit df24fe5

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

18 files changed

Lines changed: 1525 additions & 0 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO: async calls async which then does a sync thing
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
(component
2+
(component $C
3+
(core module $CM
4+
(import "" "yield" (func $yield (result i32)))
5+
(import "" "task.return" (func $task.return (param i32)))
6+
7+
(memory 1)
8+
(global $ready (mut i32) (i32.const 0))
9+
(global $started (mut i32) (i32.const 0))
10+
(global $finished (mut i32) (i32.const 0))
11+
12+
(func $f (export "f")
13+
(global.set $started (i32.add (global.get $started) (i32.const 1)))
14+
(loop $loop
15+
(drop (call $yield))
16+
(if (i32.eqz (global.get $ready)) (then (br $loop)))
17+
)
18+
(global.set $finished (i32.add (global.get $finished) (i32.const 1)))
19+
)
20+
(func $set-ready (export "set-ready") (result i32)
21+
(global.set $ready (i32.const 1))
22+
(i32.const 0 (; EXIT ;))
23+
)
24+
(func $set-ready-cb (export "set-ready-cb") (param i32 i32 i32) (result i32)
25+
unreachable
26+
)
27+
(func $get-started (export "get-started") (result i32)
28+
(call $task.return (global.get $started))
29+
(i32.const 0 (; EXIT ;))
30+
)
31+
(func $get-started-cb (export "get-started-cb") (param i32 i32 i32) (result i32)
32+
unreachable
33+
)
34+
(func $get-finished (export "get-finished") (result i32)
35+
(call $task.return (global.get $finished))
36+
(i32.const 0 (; EXIT ;))
37+
)
38+
(func $get-finished-cb (export "get-finished-cb") (param i32 i32 i32) (result i32)
39+
unreachable
40+
)
41+
)
42+
(canon yield (core func $yield))
43+
(canon task.return (result u32) (core func $task.return))
44+
(core instance $cm (instantiate $CM (with "" (instance
45+
(export "yield" (func $yield))
46+
(export "task.return" (func $task.return))
47+
))))
48+
(func (export "f") (canon lift
49+
(core func $cm "f")
50+
))
51+
(func (export "set-ready") (canon lift
52+
(core func $cm "set-ready")
53+
async (callback (func $cm "set-ready-cb"))
54+
))
55+
(func (export "get-started") (result u32) (canon lift
56+
(core func $cm "get-started")
57+
async (callback (func $cm "get-started-cb"))
58+
))
59+
(func (export "get-finished") (result u32) (canon lift
60+
(core func $cm "get-finished")
61+
async (callback (func $cm "get-finished-cb"))
62+
))
63+
)
64+
65+
(component $D
66+
(import "c" (instance $c
67+
(export "f" (func))
68+
(export "set-ready" (func))
69+
(export "get-started" (func (result u32)))
70+
(export "get-finished" (func (result u32)))
71+
))
72+
73+
(core module $Memory (memory (export "mem") 1))
74+
(core instance $memory (instantiate $Memory))
75+
(core module $DM
76+
(import "" "mem" (memory 1))
77+
(import "" "task.return" (func $task.return (param i32)))
78+
(import "" "waitable.join" (func $waitable.join (param i32 i32)))
79+
(import "" "waitable-set.new" (func $waitable-set.new (result i32)))
80+
(import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32)))
81+
(import "" "f" (func $f (param i32 i32) (result i32)))
82+
(import "" "set-ready" (func $set-ready (param i32 i32) (result i32)))
83+
(import "" "get-started" (func $get-started (param i32 i32) (result i32)))
84+
(import "" "get-finished" (func $get-finished (param i32 i32) (result i32)))
85+
86+
(global $ws (mut i32) (i32.const 0))
87+
(func $start (global.set $ws (call $waitable-set.new)))
88+
(start $start)
89+
90+
(global $expect-subtask (mut i32) (i32.const 0))
91+
92+
(func $run (export "run") (result i32)
93+
(local $ret i32) (local $retp i32)
94+
(local $sub1 i32) (local $sub2 i32) (local $sub3 i32)
95+
(local $event_code i32)
96+
97+
98+
;; start 3 'f' calls, all of which block, but the first starts+yields, the next 2
99+
;; don't even start because 'f' is implemented synchronously
100+
(local.set $ret (call $f (i32.const 0xdeadbeef) (i32.const 0xdeadbeef)))
101+
(if (i32.ne (i32.const 0x21 (; STARTED=1 | (subtask=2 << 4) ;)) (local.get $ret))
102+
(then unreachable))
103+
(call $waitable.join (i32.const 2) (global.get $ws))
104+
(local.set $ret (call $f (i32.const 0xdeadbeef) (i32.const 0xdeadbeef)))
105+
(if (i32.ne (i32.const 0x30 (; STARTING=0 | (subtask=3 << 4) ;)) (local.get $ret))
106+
(then unreachable))
107+
(local.set $sub2 (i32.shr_u (local.get $ret) (i32.const 4)))
108+
(call $waitable.join (i32.const 3) (global.get $ws))
109+
(local.set $ret (call $f (i32.const 0xdeadbeef) (i32.const 0xdeadbeef)))
110+
(if (i32.ne (i32.const 0x40 (; STARTING=0 | (subtask=4 << 4) ;)) (local.get $ret))
111+
(then unreachable))
112+
(call $waitable.join (i32.const 4) (global.get $ws))
113+
114+
;; we should have 1 started, 0 finished
115+
;;(i32.store (i32.const 0) (i32.const 0x13131313))
116+
;;(local.set $ret (call $get-started (i32.const 0xdeadbeef) (i32.const 0)))
117+
;;(if (i32.ne (i32.const 0 (; returned ;)) (local.get $ret))
118+
;; (then unreachable))
119+
;;(if (i32.ne (i32.const 1) (i32.load (i32.const 0)))
120+
;; (then unreachable))
121+
122+
(local.set $ret (call $set-ready (i32.const 0xdeadbeef) (i32.const 0xdeadbeef)))
123+
(if (i32.ne (i32.const 0 (; TODO: currently returns 0x50 = blocked ;)) (local.get $ret))
124+
(then unreachable))
125+
126+
;; wait on $ws until the first subtask is resumed after yield and makes progress
127+
(global.set $expect-subtask (i32.const 2))
128+
(i32.or (i32.const 2 (; WAIT ;)) (i32.shl (global.get $ws) (i32.const 4)))
129+
)
130+
(func $run-cb (export "run-cb") (param i32 i32 i32) (result i32)
131+
;; TODO: finish the test
132+
133+
(call $task.return (i32.const 42))
134+
(i32.const 0 (; EXIT ;))
135+
)
136+
)
137+
(canon task.return (result u32) (core func $task.return))
138+
(canon waitable.join (core func $waitable.join))
139+
(canon waitable-set.new (core func $waitable-set.new))
140+
(canon waitable-set.wait (memory $memory "mem") (core func $waitable-set.wait))
141+
(canon lower (func $c "f") async (memory $memory "mem") (core func $f'))
142+
(canon lower (func $c "set-ready") (memory $memory "mem") async (core func $set-ready'))
143+
(canon lower (func $c "get-started") (memory $memory "mem") async (core func $get-started'))
144+
(canon lower (func $c "get-finished") async (memory $memory "mem") (core func $get-finished'))
145+
(core instance $dm (instantiate $DM (with "" (instance
146+
(export "mem" (memory $memory "mem"))
147+
(export "task.return" (func $task.return))
148+
(export "waitable.join" (func $waitable.join))
149+
(export "waitable-set.new" (func $waitable-set.new))
150+
(export "waitable-set.wait" (func $waitable-set.wait))
151+
(export "f" (func $f'))
152+
(export "set-ready" (func $set-ready'))
153+
(export "get-started" (func $get-started'))
154+
(export "get-finished" (func $get-finished'))
155+
))))
156+
(func (export "run") (result u32) (canon lift
157+
(core func $dm "run")
158+
async (callback (func $dm "run-cb"))
159+
))
160+
)
161+
162+
(instance $c (instantiate $C))
163+
(instance $d (instantiate $D (with "c" (instance $c))))
164+
(func (export "run") (alias export $d "run"))
165+
)
166+
(assert_return (invoke "run") (u32.const 42))
167+
168+
;; TODO: (block 2 deep)

test/concurrency/backpressure.wast

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO: if multiple pending async calls, only start 1 at a time
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
;; This test contains two components $C and $D that test cancelling reads
2+
;; and writes in the presence and absence of partial reads/writes.
3+
;;
4+
;; $C exports a function 'start-stream' that creates and holds onto a writable
5+
;; stream in the global $sw as well as various operations that operate on $sw.
6+
;; $D calls $C.start-stream to get the readable end and then drives the test.
7+
(component
8+
(component $C
9+
(core module $Memory (memory (export "mem") 1))
10+
(core instance $memory (instantiate $Memory))
11+
(core module $CM
12+
(import "" "mem" (memory 1))
13+
(import "" "task.return" (func $task.return (param i32)))
14+
(import "" "stream.new" (func $stream.new (result i64)))
15+
(import "" "stream.write" (func $stream.write (param i32 i32 i32) (result i32)))
16+
(import "" "stream.cancel-write" (func $stream.cancel-write (param i32) (result i32)))
17+
(import "" "stream.close-writable" (func $stream.close-writable (param i32)))
18+
19+
(global $sw (mut i32) (i32.const 0))
20+
21+
(func $start-stream (export "start-stream") (result i32)
22+
;; create a new stream, return the readable end to the caller
23+
(local $ret64 i64)
24+
(local.set $ret64 (call $stream.new))
25+
(global.set $sw (i32.wrap_i64 (i64.shr_u (local.get $ret64) (i64.const 32))))
26+
(i32.wrap_i64 (local.get $ret64))
27+
)
28+
29+
(func $write4 (export "write4")
30+
;; write 6 bytes into the stream, expecting to rendezvous with a stream.read
31+
(local $ret i32)
32+
(i32.store (i32.const 8) (i32.const 0xabcd))
33+
(local.set $ret (call $stream.write (global.get $sw) (i32.const 8) (i32.const 4)))
34+
(if (i32.ne (i32.const 0x40 (; COMPLETED=0 | (4<<4) ;)) (local.get $ret))
35+
(then unreachable))
36+
)
37+
38+
(func $write4-and-close (export "write4-and-close")
39+
(call $write4)
40+
(call $stream.close-writable (global.get $sw))
41+
)
42+
43+
(func $start-blocking-write (export "start-blocking-write")
44+
(local $ret i32)
45+
46+
;; prepare the write buffer
47+
(i64.store (i32.const 8) (i64.const 0x123456789abcdef))
48+
49+
;; start one blocking write and immediately cancel it
50+
(local.set $ret (call $stream.write (global.get $sw) (i32.const 8) (i32.const 8)))
51+
(if (i32.ne (i32.const -1 (; BLOCKED ;)) (local.get $ret))
52+
(then unreachable))
53+
(local.set $ret (call $stream.cancel-write (global.get $sw)))
54+
(if (i32.ne (i32.const 0x2 (; CANCELLED ;)) (local.get $ret))
55+
(then unreachable))
56+
57+
;; start a second blockign write and leave it pending
58+
(local.set $ret (call $stream.write (global.get $sw) (i32.const 8) (i32.const 8)))
59+
(if (i32.ne (i32.const -1 (; BLOCKED ;)) (local.get $ret))
60+
(then unreachable))
61+
)
62+
63+
(func $cancel-after-read4 (export "cancel-after-read4")
64+
(local $ret i32)
65+
(local.set $ret (call $stream.cancel-write (global.get $sw)))
66+
(; TODO: currently returns 0x40 ;)
67+
(if (i32.ne (i32.const 0x42 (; CANCELLED=2 | (4<<4) ;)) (local.get $ret))
68+
(then unreachable))
69+
)
70+
)
71+
(type $ST (stream u8))
72+
(canon task.return (result u32) (core func $task.return))
73+
(canon stream.new $ST (core func $stream.new))
74+
(canon stream.write $ST async (memory $memory "mem") (core func $stream.write))
75+
(canon stream.cancel-write $ST (core func $stream.cancel-write))
76+
(canon stream.close-writable $ST (core func $stream.close-writable))
77+
(core instance $cm (instantiate $CM (with "" (instance
78+
(export "mem" (memory $memory "mem"))
79+
(export "task.return" (func $task.return))
80+
(export "stream.new" (func $stream.new))
81+
(export "stream.write" (func $stream.write))
82+
(export "stream.cancel-write" (func $stream.cancel-write))
83+
(export "stream.close-writable" (func $stream.close-writable))
84+
))))
85+
(func (export "start-stream") (result (stream u8)) (canon lift (core func $cm "start-stream")))
86+
(func (export "write4") (canon lift (core func $cm "write4")))
87+
(func (export "write4-and-close") (canon lift (core func $cm "write4-and-close")))
88+
(func (export "start-blocking-write") (canon lift (core func $cm "start-blocking-write")))
89+
(func (export "cancel-after-read4") (canon lift (core func $cm "cancel-after-read4")))
90+
)
91+
92+
(component $D
93+
(import "c" (instance $c
94+
(export "start-stream" (func (result (stream u8))))
95+
(export "write4" (func))
96+
(export "write4-and-close" (func))
97+
(export "start-blocking-write" (func))
98+
(export "cancel-after-read4" (func))
99+
))
100+
101+
(core module $Memory (memory (export "mem") 1))
102+
(core instance $memory (instantiate $Memory))
103+
(core module $DM
104+
(import "" "mem" (memory 1))
105+
(import "" "stream.read" (func $stream.read (param i32 i32 i32) (result i32)))
106+
(import "" "stream.cancel-read" (func $stream.cancel-read (param i32) (result i32)))
107+
(import "" "stream.close-readable" (func $stream.close-readable (param i32)))
108+
(import "" "start-stream" (func $start-stream (result i32)))
109+
(import "" "write4" (func $write4))
110+
(import "" "write4-and-close" (func $write4-and-close))
111+
(import "" "start-blocking-write" (func $start-blocking-write))
112+
(import "" "cancel-after-read4" (func $cancel-after-read4))
113+
114+
(func $run (export "run") (result i32)
115+
(local $ret i32)
116+
(local $sr i32)
117+
118+
;; call 'start-stream' to get the stream we'll be working with
119+
(local.set $sr (call $start-stream))
120+
(if (i32.ne (i32.const 1) (local.get $sr))
121+
(then unreachable))
122+
123+
;; start read that will block
124+
(local.set $ret (call $stream.read (local.get $sr) (i32.const 8) (i32.const 100)))
125+
(if (i32.ne (i32.const -1 (; BLOCKED;)) (local.get $ret))
126+
(then unreachable))
127+
128+
;; cancelling it will finish without anything having been written
129+
(local.set $ret (call $stream.cancel-read (local.get $sr)))
130+
(if (i32.ne (i32.const 0x2 (; CANCELLED ;)) (local.get $ret))
131+
(then unreachable))
132+
133+
;; read, block, call $C to write 4 bytes into the buffer,
134+
;; then cancel, which should show "4+cancelled"
135+
(local.set $ret (call $stream.read (local.get $sr) (i32.const 8) (i32.const 100)))
136+
(if (i32.ne (i32.const -1 (; BLOCKED;)) (local.get $ret))
137+
(then unreachable))
138+
(call $write4)
139+
(local.set $ret (call $stream.cancel-read (local.get $sr)))
140+
(; TODO: currently returns 0x40 ;)
141+
(if (i32.ne (i32.const 0x42 (; CANCELLED=2 | (4<<4) ;)) (local.get $ret))
142+
(then unreachable))
143+
(if (i32.ne (i32.const 0xabcd) (i32.load (i32.const 8)))
144+
(then unreachable))
145+
146+
;; read, block, call $C to write 4 bytes into the buffer and close,
147+
;; then cancel, which should show "4+closed"
148+
(local.set $ret (call $stream.read (local.get $sr) (i32.const 8) (i32.const 100)))
149+
(if (i32.ne (i32.const -1 (; BLOCKED;)) (local.get $ret))
150+
(then unreachable))
151+
(call $write4-and-close)
152+
(local.set $ret (call $stream.cancel-read (local.get $sr)))
153+
(; TODO: currently returns 0x40 ;)
154+
(if (i32.ne (i32.const 0x41 (; CLOSED=1 | (4<<4) ;)) (local.get $ret))
155+
(then unreachable))
156+
(if (i32.ne (i32.const 0xabcd) (i32.load (i32.const 8)))
157+
(then unreachable))
158+
(call $stream.close-readable (local.get $sr))
159+
160+
;; get a new $sr
161+
(local.set $sr (call $start-stream))
162+
(if (i32.ne (i32.const 1) (local.get $sr))
163+
(then unreachable))
164+
165+
;; start outstanding write in $C, read 4 of it, then call back into $C
166+
;; which will cancel and see 4 written.
167+
(call $start-blocking-write)
168+
(local.set $ret (call $stream.read (local.get $sr) (i32.const 8) (i32.const 4)))
169+
(if (i32.ne (i32.const 0x40 (; COMPLETED=0 | (4<<4) ;)) (local.get $ret))
170+
(then unreachable))
171+
(if (i32.ne (i32.const 0x89abcdef) (i32.load (i32.const 8)))
172+
(then unreachable))
173+
(call $cancel-after-read4)
174+
175+
;; return 42 to the top-level assert_return
176+
(i32.const 42)
177+
)
178+
)
179+
(type $ST (stream u8))
180+
(canon stream.read $ST async (memory $memory "mem") (core func $stream.read))
181+
(canon stream.cancel-read $ST (core func $stream.cancel-read))
182+
(canon stream.close-readable $ST (core func $stream.close-readable))
183+
(canon lower (func $c "start-stream") (core func $start-stream'))
184+
(canon lower (func $c "write4") (core func $write4'))
185+
(canon lower (func $c "write4-and-close") (core func $write4-and-close'))
186+
(canon lower (func $c "start-blocking-write") (core func $start-blocking-write'))
187+
(canon lower (func $c "cancel-after-read4") (core func $cancel-after-read4'))
188+
(core instance $dm (instantiate $DM (with "" (instance
189+
(export "mem" (memory $memory "mem"))
190+
(export "stream.read" (func $stream.read))
191+
(export "stream.cancel-read" (func $stream.cancel-read))
192+
(export "stream.close-readable" (func $stream.close-readable))
193+
(export "start-stream" (func $start-stream'))
194+
(export "write4" (func $write4'))
195+
(export "write4-and-close" (func $write4-and-close'))
196+
(export "start-blocking-write" (func $start-blocking-write'))
197+
(export "cancel-after-read4" (func $cancel-after-read4'))
198+
))))
199+
(func (export "run") (result u32) (canon lift (core func $dm "run")))
200+
)
201+
202+
(instance $c (instantiate $C))
203+
(instance $d (instantiate $D (with "c" (instance $c))))
204+
(func (export "run") (alias export $d "run"))
205+
)
206+
(assert_return (invoke "run") (u32.const 42))

0 commit comments

Comments
 (0)