wa-lang.org/wazero@v1.0.2/cmd/wazero/wazero_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 _ "embed" 6 "flag" 7 "fmt" 8 "os" 9 "path/filepath" 10 "testing" 11 12 "wa-lang.org/wazero/internal/testing/require" 13 ) 14 15 //go:embed testdata/wasi_arg.wasm 16 var wasmWasiArg []byte 17 18 //go:embed testdata/wasi_env.wasm 19 var wasmWasiEnv []byte 20 21 //go:embed testdata/wasi_fd.wasm 22 var wasmWasiFd []byte 23 24 //go:embed testdata/fs/bear.txt 25 var bearTxt []byte 26 27 func TestRun(t *testing.T) { 28 bearPath := filepath.Join(t.TempDir(), "bear.txt") 29 require.NoError(t, os.WriteFile(bearPath, bearTxt, 0o755)) 30 31 tests := []struct { 32 name string 33 wazeroOpts []string 34 wasm []byte 35 wasmArgs []string 36 stdOut string 37 stdErr string 38 }{ 39 { 40 name: "args", 41 wasm: wasmWasiArg, 42 wasmArgs: []string{"hello world"}, 43 // Executable name is first arg so is printed. 44 stdOut: "test.wasm\x00hello world\x00", 45 }, 46 { 47 name: "-- args", 48 wasm: wasmWasiArg, 49 wasmArgs: []string{"--", "hello world"}, 50 // Executable name is first arg so is printed. 51 stdOut: "test.wasm\x00hello world\x00", 52 }, 53 { 54 name: "env", 55 wasm: wasmWasiEnv, 56 wazeroOpts: []string{"--env=ANIMAL=bear", "--env=FOOD=sushi"}, 57 stdOut: "ANIMAL=bear\x00FOOD=sushi\x00", 58 }, 59 { 60 name: "fd", 61 wasm: wasmWasiFd, 62 wazeroOpts: []string{fmt.Sprintf("--mount=%s:/", filepath.Dir(bearPath))}, 63 stdOut: "pooh\n", 64 }, 65 } 66 67 for _, tc := range tests { 68 tt := tc 69 t.Run(tt.name, func(t *testing.T) { 70 wasmPath := filepath.Join(t.TempDir(), "test.wasm") 71 require.NoError(t, os.WriteFile(wasmPath, tt.wasm, 0o755)) 72 73 args := append([]string{"run"}, tt.wazeroOpts...) 74 args = append(args, wasmPath) 75 args = append(args, tt.wasmArgs...) 76 exitCode, stdOut, stdErr := runMain(t, args) 77 require.Equal(t, 0, exitCode, stdErr) 78 require.Equal(t, tt.stdOut, stdOut) 79 require.Equal(t, tt.stdErr, stdErr) 80 }) 81 } 82 } 83 84 func TestHelp(t *testing.T) { 85 exitCode, _, stdErr := runMain(t, []string{"-h"}) 86 require.Equal(t, 0, exitCode) 87 require.Contains(t, stdErr, "wazero CLI\n\nUsage:") 88 } 89 90 func TestErrors(t *testing.T) { 91 notWasmPath := filepath.Join(t.TempDir(), "bears.wasm") 92 require.NoError(t, os.WriteFile(notWasmPath, []byte("pooh"), 0o755)) 93 94 tests := []struct { 95 message string 96 args []string 97 }{ 98 { 99 message: "missing path to wasm file", 100 args: []string{}, 101 }, 102 { 103 message: "error reading wasm binary", 104 args: []string{"non-existent.wasm"}, 105 }, 106 { 107 message: "error compiling wasm binary", 108 args: []string{notWasmPath}, 109 }, 110 { 111 message: "invalid environment variable", 112 args: []string{"--env=ANIMAL", "testdata/wasi_env.wasm"}, 113 }, 114 { 115 message: "invalid mount", 116 args: []string{"--mount=.", "testdata/wasi_env.wasm"}, 117 }, 118 } 119 120 for _, tc := range tests { 121 tt := tc 122 t.Run(tt.message, func(t *testing.T) { 123 exitCode, _, stdErr := runMain(t, append([]string{"run"}, tt.args...)) 124 125 require.Equal(t, 1, exitCode) 126 require.Contains(t, stdErr, tt.message) 127 }) 128 } 129 } 130 131 func runMain(t *testing.T, args []string) (int, string, string) { 132 t.Helper() 133 oldArgs := os.Args 134 t.Cleanup(func() { 135 os.Args = oldArgs 136 }) 137 os.Args = append([]string{"wazero"}, args...) 138 139 var exitCode int 140 stdOut := &bytes.Buffer{} 141 stdErr := &bytes.Buffer{} 142 var exited bool 143 func() { 144 defer func() { 145 if r := recover(); r != nil { 146 exited = true 147 } 148 }() 149 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError) 150 doMain(stdOut, stdErr, func(code int) { 151 exitCode = code 152 panic(code) 153 }) 154 }() 155 156 require.True(t, exited) 157 158 return exitCode, stdOut.String(), stdErr.String() 159 }