1 package wasi_snapshot_preview1_test
2
3 import (
4 "io/fs"
5 "os"
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/tetratelabs/wazero"
11 "github.com/tetratelabs/wazero/api"
12 experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
13 "github.com/tetratelabs/wazero/internal/fsapi"
14 "github.com/tetratelabs/wazero/internal/sys"
15 "github.com/tetratelabs/wazero/internal/testing/require"
16 "github.com/tetratelabs/wazero/internal/wasip1"
17 "github.com/tetratelabs/wazero/internal/wasm"
18 sysapi "github.com/tetratelabs/wazero/sys"
19 )
20
21 func Test_pollOneoff(t *testing.T) {
22 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
23 defer r.Close(testCtx)
24
25 mem := []byte{
26 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
27 wasip1.EventTypeClock, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
28 wasip1.ClockIDMonotonic, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
29 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
30 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
31 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
32 '?',
33 }
34
35 expectedMem := []byte{
36 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
37 byte(wasip1.ErrnoSuccess), 0x0,
38 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
39 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
40 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '?',
41 }
42
43 in := uint32(0)
44 out := uint32(128)
45 nsubscriptions := uint32(1)
46 resultNevents := uint32(512)
47
48 maskMemory(t, mod, 1024)
49 mod.Memory().Write(in, mem)
50
51 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.PollOneoffName, uint64(in), uint64(out), uint64(nsubscriptions),
52 uint64(resultNevents))
53 require.Equal(t, `
54 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=1)
55 <== (nevents=1,errno=ESUCCESS)
56 `, "\n"+log.String())
57
58 outMem, ok := mod.Memory().Read(out, uint32(len(expectedMem)))
59 require.True(t, ok)
60 require.Equal(t, expectedMem, outMem)
61
62 nevents, ok := mod.Memory().ReadUint32Le(resultNevents)
63 require.True(t, ok)
64 require.Equal(t, nsubscriptions, nevents)
65 }
66
67 func Test_pollOneoff_Errors(t *testing.T) {
68 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
69 defer r.Close(testCtx)
70
71 tests := []struct {
72 name string
73 in, out, nsubscriptions, resultNevents uint32
74 mem []byte
75 expectedErrno wasip1.Errno
76 expectedMem []byte
77 expectedLog string
78 }{
79 {
80 name: "in out of range",
81 in: wasm.MemoryPageSize,
82 nsubscriptions: 1,
83 out: 128,
84 resultNevents: 512,
85 expectedErrno: wasip1.ErrnoFault,
86 expectedLog: `
87 ==> wasi_snapshot_preview1.poll_oneoff(in=65536,out=128,nsubscriptions=1)
88 <== (nevents=,errno=EFAULT)
89 `,
90 },
91 {
92 name: "out out of range",
93 out: wasm.MemoryPageSize,
94 resultNevents: 512,
95 nsubscriptions: 1,
96 expectedErrno: wasip1.ErrnoFault,
97 expectedLog: `
98 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=65536,nsubscriptions=1)
99 <== (nevents=,errno=EFAULT)
100 `,
101 },
102 {
103 name: "resultNevents out of range",
104 resultNevents: wasm.MemoryPageSize,
105 nsubscriptions: 1,
106 expectedErrno: wasip1.ErrnoFault,
107 expectedLog: `
108 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=0,nsubscriptions=1)
109 <== (nevents=,errno=EFAULT)
110 `,
111 },
112 {
113 name: "nsubscriptions zero",
114 out: 128,
115 resultNevents: 512,
116 expectedErrno: wasip1.ErrnoInval,
117 expectedLog: `
118 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=0)
119 <== (nevents=,errno=EINVAL)
120 `,
121 },
122 }
123
124 for _, tt := range tests {
125 tc := tt
126 t.Run(tc.name, func(t *testing.T) {
127 defer log.Reset()
128
129 maskMemory(t, mod, 1024)
130
131 if tc.mem != nil {
132 mod.Memory().Write(tc.in, tc.mem)
133 }
134
135 requireErrnoResult(t, tc.expectedErrno, mod, wasip1.PollOneoffName, uint64(tc.in), uint64(tc.out),
136 uint64(tc.nsubscriptions), uint64(tc.resultNevents))
137 require.Equal(t, tc.expectedLog, "\n"+log.String())
138
139 out, ok := mod.Memory().Read(tc.out, uint32(len(tc.expectedMem)))
140 require.True(t, ok)
141 require.Equal(t, tc.expectedMem, out)
142
143
144 if tc.expectedErrno == wasip1.ErrnoSuccess {
145 nevents, ok := mod.Memory().ReadUint32Le(tc.resultNevents)
146 require.True(t, ok)
147 require.Equal(t, uint32(1), nevents)
148 _ = nevents
149 }
150 })
151 }
152 }
153
154 func Test_pollOneoff_Stdin(t *testing.T) {
155 w, r, err := os.Pipe()
156 require.NoError(t, err)
157 defer w.Close()
158 defer r.Close()
159 _, _ = w.Write([]byte("wazero"))
160
161 tests := []struct {
162 name string
163 in, out, nsubscriptions, resultNevents uint32
164 mem []byte
165 stdin fsapi.File
166 expectedErrno wasip1.Errno
167 expectedMem []byte
168 expectedLog string
169 expectedNevents uint32
170 }{
171 {
172 name: "Read without explicit timeout (no tty)",
173 nsubscriptions: 1,
174 expectedNevents: 1,
175 stdin: &sys.StdinFile{Reader: strings.NewReader("test")},
176 mem: fdReadSub,
177 expectedErrno: wasip1.ErrnoSuccess,
178 out: 128,
179 resultNevents: 512,
180 expectedMem: []byte{
181 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
182 byte(wasip1.ErrnoSuccess), 0x0,
183 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
184 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
185 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
186 0x0, 0x0,
187
188 '?',
189 },
190 expectedLog: `
191 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=1)
192 <== (nevents=1,errno=ESUCCESS)
193 `,
194 },
195 {
196 name: "20ms timeout, fdread on tty (buffer ready): both events are written",
197 nsubscriptions: 2,
198 expectedNevents: 2,
199 stdin: &ttyStdinFile{StdinFile: sys.StdinFile{Reader: strings.NewReader("test")}},
200 mem: concat(
201 clockNsSub(20*1000*1000),
202 fdReadSub,
203 ),
204 expectedErrno: wasip1.ErrnoSuccess,
205 out: 128,
206 resultNevents: 512,
207 expectedMem: []byte{
208 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
209 byte(wasip1.ErrnoSuccess), 0x0,
210 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
211 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
212 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
213 0x0, 0x0,
214
215 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
216 byte(wasip1.ErrnoSuccess), 0x0,
217 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
218 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
219 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
220 0x0, 0x0,
221
222 '?',
223 },
224 expectedLog: `
225 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=2)
226 <== (nevents=2,errno=ESUCCESS)
227 `,
228 },
229 {
230 name: "0ns timeout, fdread on tty (buffer ready): both are written",
231 nsubscriptions: 2,
232 expectedNevents: 2,
233 stdin: &ttyStdinFile{StdinFile: sys.StdinFile{Reader: strings.NewReader("test")}},
234 mem: concat(
235 clockNsSub(20*1000*1000),
236 fdReadSub,
237 ),
238 expectedErrno: wasip1.ErrnoSuccess,
239 out: 128,
240 resultNevents: 512,
241 expectedMem: []byte{
242 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
243 byte(wasip1.ErrnoSuccess), 0x0,
244 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
245 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
246 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
247 0x0, 0x0,
248
249 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
250 byte(wasip1.ErrnoSuccess), 0x0,
251 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
252 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
253 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
254 0x0, 0x0,
255
256 '?',
257 },
258 expectedLog: `
259 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=2)
260 <== (nevents=2,errno=ESUCCESS)
261 `,
262 },
263 {
264 name: "0ns timeout, fdread on regular file: both events are written",
265 nsubscriptions: 2,
266 expectedNevents: 2,
267 stdin: &sys.StdinFile{Reader: strings.NewReader("test")},
268 mem: concat(
269 clockNsSub(20*1000*1000),
270 fdReadSub,
271 ),
272 expectedErrno: wasip1.ErrnoSuccess,
273 out: 128,
274 resultNevents: 512,
275 expectedMem: []byte{
276 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
277 byte(wasip1.ErrnoSuccess), 0x0,
278 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
279 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
280 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
281 0x0, 0x0,
282
283 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
284 byte(wasip1.ErrnoSuccess), 0x0,
285 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
286 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
287 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
288 0x0, 0x0,
289
290 '?',
291 },
292 expectedLog: `
293 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=2)
294 <== (nevents=2,errno=ESUCCESS)
295 `,
296 },
297 {
298 name: "1ns timeout, fdread on regular file: both events are written",
299 nsubscriptions: 2,
300 expectedNevents: 2,
301 stdin: &sys.StdinFile{Reader: strings.NewReader("test")},
302 mem: concat(
303 clockNsSub(20*1000*1000),
304 fdReadSub,
305 ),
306 expectedErrno: wasip1.ErrnoSuccess,
307 out: 128,
308 resultNevents: 512,
309 expectedMem: []byte{
310 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
311 byte(wasip1.ErrnoSuccess), 0x0,
312 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
313 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
314 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
315 0x0, 0x0,
316
317 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
318 byte(wasip1.ErrnoSuccess), 0x0,
319 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
320 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
321 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
322 0x0, 0x0,
323
324 '?',
325 },
326 expectedLog: `
327 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=2)
328 <== (nevents=2,errno=ESUCCESS)
329 `,
330 },
331 {
332 name: "20ms timeout, fdread on blocked tty: only clock event is written",
333 nsubscriptions: 2,
334 expectedNevents: 1,
335 stdin: &neverReadyTtyStdinFile{StdinFile: sys.StdinFile{Reader: newBlockingReader(t)}},
336 mem: concat(
337 clockNsSub(20*1000*1000),
338 fdReadSub,
339 ),
340
341 expectedErrno: wasip1.ErrnoSuccess,
342 out: 128,
343 resultNevents: 512,
344 expectedMem: []byte{
345 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
346 byte(wasip1.ErrnoSuccess), 0x0,
347 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
348 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
349 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
350 0x0, 0x0,
351
352
353 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
354 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
355 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
356 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
357
358 '?',
359 },
360 expectedLog: `
361 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=2)
362 <== (nevents=1,errno=ESUCCESS)
363 `,
364 },
365 {
366 name: "pollable pipe, multiple subs, events returned out of order",
367 nsubscriptions: 3,
368 expectedNevents: 3,
369 mem: concat(
370 fdReadSub,
371 clockNsSub(20*1000*1000),
372
373 fdReadSubFdWithUserData(100, []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77})),
374 stdin: &sys.StdinFile{Reader: w},
375 expectedErrno: wasip1.ErrnoSuccess,
376 out: 128,
377 resultNevents: 512,
378 expectedMem: []byte{
379
380 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
381 byte(wasip1.ErrnoSuccess), 0x0,
382 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
383 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
384 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
385 0x0, 0x0,
386
387
388 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
389 byte(wasip1.ErrnoBadf), 0x0,
390 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
391 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
392 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
393 0x0, 0x0,
394
395
396
397 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
398 byte(wasip1.ErrnoSuccess), 0x0,
399 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
400 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
401 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
402 0x0, 0x0,
403
404 '?',
405 },
406 expectedLog: `
407 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=3)
408 <== (nevents=3,errno=ESUCCESS)
409 `,
410 },
411 }
412
413 for _, tt := range tests {
414 tc := tt
415 t.Run(tc.name, func(t *testing.T) {
416 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
417 defer r.Close(testCtx)
418 defer log.Reset()
419
420 setStdin(t, mod, tc.stdin)
421
422 maskMemory(t, mod, 1024)
423 if tc.mem != nil {
424 mod.Memory().Write(tc.in, tc.mem)
425 }
426
427 requireErrnoResult(t, tc.expectedErrno, mod, wasip1.PollOneoffName, uint64(tc.in), uint64(tc.out),
428 uint64(tc.nsubscriptions), uint64(tc.resultNevents))
429 require.Equal(t, tc.expectedLog, "\n"+log.String())
430
431 out, ok := mod.Memory().Read(tc.out, uint32(len(tc.expectedMem)))
432 require.True(t, ok)
433 require.Equal(t, tc.expectedMem, out)
434
435
436 if tc.expectedErrno == wasip1.ErrnoSuccess {
437 nevents, ok := mod.Memory().ReadUint32Le(tc.resultNevents)
438 require.True(t, ok)
439 require.Equal(t, tc.expectedNevents, nevents)
440 _ = nevents
441 }
442 })
443 }
444 }
445
446 func setStdin(t *testing.T, mod api.Module, stdin fsapi.File) {
447 fsc := mod.(*wasm.ModuleInstance).Sys.FS()
448 f, ok := fsc.LookupFile(sys.FdStdin)
449 require.True(t, ok)
450 f.File = stdin
451 }
452
453 func Test_pollOneoff_Zero(t *testing.T) {
454 poller := &pollStdinFile{StdinFile: sys.StdinFile{Reader: strings.NewReader("test")}, ready: true}
455
456 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
457 defer r.Close(testCtx)
458 defer log.Reset()
459
460 setStdin(t, mod, poller)
461
462 maskMemory(t, mod, 1024)
463
464 out := uint32(128)
465 nsubscriptions := 2
466 resultNevents := uint32(512)
467
468 mod.Memory().Write(0,
469 concat(
470 clockNsSub(20*1000*1000),
471 fdReadSub,
472 ),
473 )
474
475 expectedMem := []byte{
476 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
477 byte(wasip1.ErrnoSuccess), 0x0,
478 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
479 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
480 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
481
482 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
483 byte(wasip1.ErrnoSuccess), 0x0,
484 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0,
485 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
486 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
487 0x0, 0x0,
488
489 '?',
490 }
491
492 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.PollOneoffName, uint64(0), uint64(out),
493 uint64(nsubscriptions), uint64(resultNevents))
494
495 outMem, ok := mod.Memory().Read(out, uint32(len(expectedMem)))
496 require.True(t, ok)
497 require.Equal(t, expectedMem, outMem)
498
499
500 nevents, ok := mod.Memory().ReadUint32Le(resultNevents)
501 require.True(t, ok)
502 require.Equal(t, uint32(2), nevents)
503
504
505 poller.ready = false
506
507 mod.Memory().Write(0,
508 concat(
509 clockNsSub(20*1000*1000),
510 fdReadSub,
511 ),
512 )
513
514 expectedMem = []byte{
515 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
516 byte(wasip1.ErrnoSuccess), 0x0,
517 wasip1.EventTypeClock, 0x0, 0x0, 0x0,
518 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
519 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
520
521 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
522 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
523 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
524 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
525
526 '?',
527 }
528
529 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.PollOneoffName, uint64(0), uint64(out),
530 uint64(nsubscriptions), uint64(resultNevents))
531
532 outMem, ok = mod.Memory().Read(out, uint32(len(expectedMem)))
533 require.True(t, ok)
534 require.Equal(t, expectedMem, outMem)
535
536 nevents, ok = mod.Memory().ReadUint32Le(resultNevents)
537 require.True(t, ok)
538 require.Equal(t, uint32(1), nevents)
539 }
540
541 func concat(bytes ...[]byte) []byte {
542 var res []byte
543 for i := range bytes {
544 res = append(res, bytes[i]...)
545 }
546 return res
547 }
548
549
550 func clockNsSub(ns uint64) []byte {
551 return []byte{
552 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
553 wasip1.EventTypeClock, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
554 wasip1.ClockIDMonotonic, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
555 byte(ns), byte(ns >> 8), byte(ns >> 16), byte(ns >> 24),
556 byte(ns >> 32), byte(ns >> 40), byte(ns >> 48), byte(ns >> 56),
557 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
558 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
559 }
560 }
561
562
563 func fdReadSubFd(fd byte) []byte {
564 return []byte{
565 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
566 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
567 fd, 0x0, 0x0, 0x0,
568 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
569 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
570 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
571 0x0, 0x0, 0x0, 0x0,
572 }
573 }
574
575 func fdReadSubFdWithUserData(fd byte, userdata []byte) []byte {
576 return concat(
577 userdata,
578 []byte{
579 wasip1.EventTypeFdRead, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
580 fd, 0x0, 0x0, 0x0,
581 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
582 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
583 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
584 0x0, 0x0, 0x0, 0x0,
585 })
586 }
587
588
589 var fdReadSub = fdReadSubFd(byte(sys.FdStdin))
590
591
592
593
594
595
596 type ttyStat struct{}
597
598
599 func (ttyStat) Stat() (sysapi.Stat_t, experimentalsys.Errno) {
600 return sysapi.Stat_t{
601 Mode: fs.ModeDevice | fs.ModeCharDevice,
602 Nlink: 1,
603 }, 0
604 }
605
606 type ttyStdinFile struct {
607 sys.StdinFile
608 ttyStat
609 }
610
611 type neverReadyTtyStdinFile struct {
612 sys.StdinFile
613 ttyStat
614 }
615
616
617 func (neverReadyTtyStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) {
618 if flag != fsapi.POLLIN {
619 return false, experimentalsys.ENOTSUP
620 }
621 switch {
622 case timeoutMillis <= 0:
623 return
624 }
625 time.Sleep(time.Duration(timeoutMillis) * time.Millisecond)
626 return false, 0
627 }
628
629 type pollStdinFile struct {
630 sys.StdinFile
631 ttyStat
632 ready bool
633 }
634
635
636 func (p *pollStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) {
637 if flag != fsapi.POLLIN {
638 return false, experimentalsys.ENOTSUP
639 }
640 return p.ready, 0
641 }
642
View as plain text