1
2
3 package wasi_snapshot_preview1_test
4
5 import (
6 "bufio"
7 "bytes"
8 "fmt"
9 "io"
10 "math/rand"
11 "os"
12 "path/filepath"
13 "strings"
14 "syscall"
15 "testing"
16
17 "github.com/tetratelabs/wazero"
18 "github.com/tetratelabs/wazero/api"
19 "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
20 "github.com/tetratelabs/wazero/internal/testing/require"
21 "github.com/tetratelabs/wazero/sys"
22 )
23
24 func Test_NonblockingFile(t *testing.T) {
25 const fifo = "/test-fifo"
26 tempDir := t.TempDir()
27 fifoAbsPath := tempDir + fifo
28
29 moduleConfig := wazero.NewModuleConfig().
30 WithArgs("wasi", "nonblock", fifo).
31 WithFSConfig(wazero.NewFSConfig().WithDirMount(tempDir, "/")).
32 WithSysNanosleep()
33
34 err := syscall.Mkfifo(fifoAbsPath, 0o666)
35 require.NoError(t, err)
36
37 ch := make(chan string, 2)
38 go func() {
39 ch <- compileAndRunWithPreStart(t, testCtx, moduleConfig, wasmZigCc, func(t *testing.T, mod api.Module) {
40
41 ch <- "ready"
42 })
43 }()
44
45
46 require.Equal(t, "ready", <-ch)
47
48
49
50 sleepALittle()
51
52 f, err := os.OpenFile(fifoAbsPath, os.O_APPEND|os.O_WRONLY, 0)
53 require.NoError(t, err)
54 n, err := f.Write([]byte("wazero"))
55 require.NoError(t, err)
56 require.NotEqual(t, 0, n)
57 console := <-ch
58 lines := strings.Split(console, "\n")
59
60
61 require.True(t, strings.HasPrefix(lines[0], "."))
62 require.Equal(t, "wazero", lines[1])
63 }
64
65 type fifo struct {
66 file *os.File
67 path string
68 }
69
70 func Test_NonblockGotip(t *testing.T) {
71
72
73
74
75
76
77
78
79
80
81
82
83
84 if wasmGotip == nil {
85 t.Skip("skipping because wasi.go was not compiled (gotip missing or compilation error)")
86 }
87 const numFifos = 8
88
89 for _, mode := range []string{"open", "create"} {
90 t.Run(mode, func(t *testing.T) {
91 tempDir := t.TempDir()
92
93 args := []string{"wasi", "nonblock", mode}
94 fifos := make([]*fifo, numFifos)
95 for i := range fifos {
96 tempFile := fmt.Sprintf("wasip1-nonblock-fifo-%d-%d", rand.Uint32(), i)
97 path := filepath.Join(tempDir, tempFile)
98 err := syscall.Mkfifo(path, 0o666)
99 require.NoError(t, err)
100
101 file, err := os.OpenFile(path, os.O_RDWR, 0)
102 require.NoError(t, err)
103 defer file.Close()
104
105 args = append(args, tempFile)
106 fifos[len(fifos)-i-1] = &fifo{file, path}
107 }
108
109 pr, pw := io.Pipe()
110 defer pw.Close()
111
112 var consoleBuf bytes.Buffer
113
114 moduleConfig := wazero.NewModuleConfig().
115 WithArgs(args...).
116 WithFSConfig(
117 wazero.NewFSConfig().WithDirMount(tempDir, "/")).
118 WithStderr(pw).
119 WithStdout(&consoleBuf).
120 WithStartFunctions().
121 WithSysNanosleep()
122
123 ch := make(chan string, 1)
124 go func() {
125 r := wazero.NewRuntime(testCtx)
126 defer r.Close(testCtx)
127
128 _, err := wasi_snapshot_preview1.Instantiate(testCtx, r)
129 require.NoError(t, err)
130
131 mod, err := r.InstantiateWithConfig(testCtx, wasmGotip, moduleConfig)
132 require.NoError(t, err)
133
134 _, err = mod.ExportedFunction("_start").Call(testCtx)
135 if exitErr, ok := err.(*sys.ExitError); ok {
136 require.Zero(t, exitErr.ExitCode(), consoleBuf.String())
137 }
138 ch <- consoleBuf.String()
139 }()
140
141 scanner := bufio.NewScanner(pr)
142 require.True(t, scanner.Scan(), fmt.Sprintf("expected line: %s", scanner.Err()))
143 require.Equal(t, "waiting", scanner.Text(), fmt.Sprintf("unexpected output: %s", scanner.Text()))
144
145 for _, fifo := range fifos {
146 _, err := fifo.file.WriteString(fifo.path + "\n")
147 require.NoError(t, err)
148 require.True(t, scanner.Scan(), fmt.Sprintf("expected line: %s", scanner.Err()))
149 require.Equal(t, fifo.path, scanner.Text(), fmt.Sprintf("unexpected line: %s", scanner.Text()))
150 }
151
152 s := <-ch
153 require.Equal(t, "", s)
154 })
155 }
156 }
157
View as plain text