diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index decf030dfe..534ef95f9b 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -117,7 +117,8 @@ jobs: docker buildx build -t wazero:test --platform linux/${{ matrix.arch }} . - name: Run built test binaries - run: find . -name "*.test" | xargs -Itestbin docker run --platform linux/${{ matrix.arch }} -v $(pwd)/testbin:/test --rm -t wazero:test + # This runs all tests compiled above in sequence. Note: This mounts /tmp to allow t.TempDir() in tests. + run: find . -name "*.test" | xargs -Itestbin docker run --platform linux/${{ matrix.arch }} -v $(pwd)/testbin:/test --tmpfs /tmp --rm -t wazero:test bench: name: Benchmark diff --git a/examples/file_system_test.go b/examples/file_system_test.go index 87a1f73b82..a6be3f16dd 100644 --- a/examples/file_system_test.go +++ b/examples/file_system_test.go @@ -12,9 +12,49 @@ import ( "github.com/tetratelabs/wazero/wasi" ) -// filesystemWasm was compiled from TinyGo testdata/file_system.go -//go:embed testdata/file_system.wasm -var filesystemWasm []byte +// catGo is the TinyGo source +//go:embed testdata/cat.go +var catGo []byte + +// catWasm was compiled from catGo +//go:embed testdata/cat.wasm +var catWasm []byte + +// Test_Cat writes the input file to stdout, just like `cat`. +// +// This is a basic introduction to the WebAssembly System Interface (WASI). +// See https://github.com/WebAssembly/WASI +func Test_Cat(t *testing.T) { + r := wazero.NewRuntime() + + // First, configure where the WebAssembly Module (Wasm) console outputs to (stdout). + stdoutBuf := bytes.NewBuffer(nil) + wasiConfig := wazero.NewWASIConfig().WithStdout(stdoutBuf) + + // Next, configure a sand-boxed filesystem to include one file. + file := "cat.go" // arbitrary file + memFS := wazero.WASIMemFS() + err := writeFile(memFS, file, catGo) + require.NoError(t, err) + wasiConfig.WithPreopens(map[string]wasi.FS{".": memFS}) + + // Since this runs a main function (_start in WASI), configure the arguments. + // Remember, arg[0] is the program name! + wasiConfig.WithArgs("cat", file) + + // Now, instantiate WASI with the above configuration. + wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1WithConfig(wasiConfig)) + require.NoError(t, err) + defer wasi.Close() + + // Finally, start the `cat` program's main function (in WASI, this is named `_start`). + cat, err := wazero.StartWASICommandFromSource(r, catWasm) + require.NoError(t, err) + defer cat.Close() + + // To ensure it worked, verify stdout from WebAssembly had what we expected. + require.Equal(t, string(catGo), stdoutBuf.String()) +} func writeFile(fs wasi.FS, path string, data []byte) error { f, err := fs.OpenWASI(0, path, wasi.O_CREATE|wasi.O_TRUNC, wasi.R_FD_WRITE, 0, 0) @@ -28,40 +68,3 @@ func writeFile(fs wasi.FS, path string, data []byte) error { return f.Close() } - -func readFile(fs wasi.FS, path string) ([]byte, error) { - f, err := fs.OpenWASI(0, path, 0, 0, 0, 0) - if err != nil { - return nil, err - } - - buf := bytes.NewBuffer(nil) - - if _, err := io.Copy(buf, f); err != nil { - return buf.Bytes(), nil - } - - return buf.Bytes(), f.Close() -} - -func Test_file_system(t *testing.T) { - r := wazero.NewRuntime() - - memFS := wazero.WASIMemFS() - err := writeFile(memFS, "input.txt", []byte("Hello, file system!")) - require.NoError(t, err) - - wasiConfig := wazero.NewWASIConfig().WithPreopens(map[string]wasi.FS{".": memFS}) - wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1WithConfig(wasiConfig)) - require.NoError(t, err) - defer wasi.Close() - - // Note: TinyGo binaries must be treated as WASI Commands to initialize memory. - mod, err := wazero.StartWASICommandFromSource(r, filesystemWasm) - require.NoError(t, err) - defer mod.Close() - - out, err := readFile(memFS, "output.txt") - require.NoError(t, err) - require.Equal(t, "Hello, file system!", string(out)) -} diff --git a/examples/testdata/cat.go b/examples/testdata/cat.go new file mode 100644 index 0000000000..f66aad8de0 --- /dev/null +++ b/examples/testdata/cat.go @@ -0,0 +1,19 @@ +package main + +import ( + "os" +) + +// main is the same as cat: "concatenate and print files." +func main() { + // Start at arg[1] because args[0] is the program name. + for i := 1; i < len(os.Args); i++ { + bytes, err := os.ReadFile(os.Args[i]) + if err != nil { + os.Exit(1) + } + + // Use write to avoid needing to worry about Windows newlines. + os.Stdout.Write(bytes) + } +} diff --git a/examples/testdata/cat.wasm b/examples/testdata/cat.wasm new file mode 100755 index 0000000000..b817f6b60f Binary files /dev/null and b/examples/testdata/cat.wasm differ diff --git a/examples/testdata/fibonacci.wasm b/examples/testdata/fibonacci.wasm index a11a042bb7..00573e1996 100755 Binary files a/examples/testdata/fibonacci.wasm and b/examples/testdata/fibonacci.wasm differ diff --git a/examples/testdata/file_system.go b/examples/testdata/file_system.go deleted file mode 100644 index 2cd1b16bb6..0000000000 --- a/examples/testdata/file_system.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "io" - "os" -) - -func main() { - fileIn, err := os.Open("input.txt") - if err != nil { - panic(err) - } - defer fileIn.Close() - - fileOut, err := os.Create("output.txt") - if err != nil { - panic(err) - } - defer fileOut.Close() - - _, err = io.Copy(fileOut, fileIn) - if err != nil { - panic(err) - } -} diff --git a/examples/testdata/file_system.wasm b/examples/testdata/file_system.wasm deleted file mode 100755 index 708d459116..0000000000 Binary files a/examples/testdata/file_system.wasm and /dev/null differ diff --git a/examples/testdata/host_func.wasm b/examples/testdata/host_func.wasm index 24c26a6ed8..acf342b9df 100755 Binary files a/examples/testdata/host_func.wasm and b/examples/testdata/host_func.wasm differ diff --git a/examples/testdata/stdio.go b/examples/testdata/stdio.go index e8b240efce..9231968fce 100644 --- a/examples/testdata/stdio.go +++ b/examples/testdata/stdio.go @@ -12,11 +12,11 @@ func main() { for s.Scan() { line := s.Text() if _, err := fmt.Printf("Hello, %s!\n", strings.TrimSpace(line)); err != nil { - panic(err) + os.Exit(1) } if _, err := fmt.Fprintln(os.Stderr, "Error Message"); err != nil { - panic(err) + os.Exit(1) } } } diff --git a/examples/testdata/stdio.wasm b/examples/testdata/stdio.wasm index 31807440f4..3fe3a611a0 100755 Binary files a/examples/testdata/stdio.wasm and b/examples/testdata/stdio.wasm differ