From 035c0ffaf40a7ba47f5dccc6d144c367b67349e7 Mon Sep 17 00:00:00 2001 From: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com> Date: Thu, 30 Mar 2023 13:06:51 +0800 Subject: [PATCH] wasi: adds preopen test for use in homebrew (#1309) This adds a test to verify the wazero binary produced by homebrew. Notably, this was made to be small enough to copy/paste in hex format. Signed-off-by: Adrian Cole --- .../{wasi_arg.wasm => print_args.wasm} | Bin .../testdata/{wasi_arg.wat => print_args.wat} | 10 ++--- .../testdata/print_prestat_dirname.wasm | Bin 0 -> 231 bytes .../testdata/print_prestat_dirname.wat | 42 ++++++++++++++++++ imports/wasi_snapshot_preview1/usage_test.go | 33 ++++++++++++-- internal/wasip1/wasi.go | 3 +- 6 files changed, 77 insertions(+), 11 deletions(-) rename imports/wasi_snapshot_preview1/testdata/{wasi_arg.wasm => print_args.wasm} (100%) rename imports/wasi_snapshot_preview1/testdata/{wasi_arg.wat => print_args.wat} (92%) create mode 100644 imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wasm create mode 100644 imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wat diff --git a/imports/wasi_snapshot_preview1/testdata/wasi_arg.wasm b/imports/wasi_snapshot_preview1/testdata/print_args.wasm similarity index 100% rename from imports/wasi_snapshot_preview1/testdata/wasi_arg.wasm rename to imports/wasi_snapshot_preview1/testdata/print_args.wasm diff --git a/imports/wasi_snapshot_preview1/testdata/wasi_arg.wat b/imports/wasi_snapshot_preview1/testdata/print_args.wat similarity index 92% rename from imports/wasi_snapshot_preview1/testdata/wasi_arg.wat rename to imports/wasi_snapshot_preview1/testdata/print_args.wat index f7fb72e9..e1197041 100644 --- a/imports/wasi_snapshot_preview1/testdata/wasi_arg.wat +++ b/imports/wasi_snapshot_preview1/testdata/print_args.wat @@ -1,5 +1,5 @@ -;; $wasi_arg is a WASI command which copies null-terminated args to stdout. -(module $wasi_arg +;; $print_args is a WASI command which copies null-terminated args to stdout. +(module $print_args ;; args_get reads command-line argument data. ;; ;; See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-args_getargv-pointerpointeru8-argv_buf-pointeru8---errno @@ -24,9 +24,9 @@ ;; See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memories%E2%91%A7 (memory (export "memory") 1) - ;; $iovs are offset/length pairs in memory fd_write copies to the file descriptor. - ;; $main will only write one offset/length pair, corresponding to null-terminated args. - (global $iovs i32 i32.const 1024) ;; 1024 is an arbitrary offset larger than the args. + ;; $iovs are offset/length pairs in memory fd_write copies to the file + ;; descriptor. $main will only write one offset/length pair. + (global $iovs i32 i32.const 1024) ;; 1024 is an arbitrary offset ;; WASI parameters are usually memory offsets, you can ignore values by writing them to an unread offset. (global $ignored i32 i32.const 32768) diff --git a/imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wasm b/imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wasm new file mode 100644 index 0000000000000000000000000000000000000000..f10887985594a01bdd558c96c33096f850450578 GIT binary patch literal 231 zcmZ{d!3x4K5JYD;QHz2U3WEIs_2|WWz9bDaY7S{j60Dy3>!zN(bYXZi@L*x0CjfMm z4NntIjhKFr8S@1AEe@lJPRGs+@!2Om1p9J!yzcMq++#9HKWqXPyz0+uUC^EJ7PKH2 zSssH+7A%;=N>aW}#cOYUA3lt=&JRO^*k0%aB@{~38HJK(MoG1TDsBu#x#W~w@4ml? BKaBtY literal 0 HcmV?d00001 diff --git a/imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wat b/imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wat new file mode 100644 index 00000000..81f952d5 --- /dev/null +++ b/imports/wasi_snapshot_preview1/testdata/print_prestat_dirname.wat @@ -0,0 +1,42 @@ +;; $$print_prestat_dirname is a WASI command which copies the first preopen dirname to stdout. +(module $print_prestat_dirname + (import "wasi_snapshot_preview1" "fd_prestat_get" + (func $wasi.fd_prestat_get (param $fd i32) (param $result.prestat i32) (result (;errno;) i32))) + + (import "wasi_snapshot_preview1" "fd_prestat_dir_name" + (func $wasi.fd_prestat_dir_name (param $fd i32) (param $result.path i32) (param $result.path_len i32) (result (;errno;) i32))) + + (import "wasi_snapshot_preview1" "fd_write" + (func $wasi.fd_write (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $result.size i32) (result (;errno;) i32))) + + (memory (export "memory") 1 1) + + (func $main (export "_start") + ;; First, we need to know the size of the prestat dir name. + (call $wasi.fd_prestat_get + (i32.const 3) ;; preopen FD + (i32.const 0) ;; where to write prestat + ) + drop ;; ignore the errno returned + + ;; Next, write the dir name to offset 8 (past the prestat). + (call $wasi.fd_prestat_dir_name + (i32.const 3) ;; preopen FD + (i32.const 8) ;; where to write dir_name + (i32.load (i32.const 4)) ;; length is the last part of the prestat + ) + drop ;; ignore the errno returned + + ;; Now, convert the prestat to an iovec [offset, len] writing offset=8. + (i32.store (i32.const 0) (i32.const 8)) + + ;; Finally, write the dirname to stdout via its iovec [offset, len]. + (call $wasi.fd_write + (i32.const 1) ;; stdout + (i32.const 0) ;; where's the iovec + (i32.const 1) ;; only one iovec + (i32.const 0) ;; overwrite the iovec with the ignored result. + ) + drop ;; ignore the errno returned + ) +) diff --git a/imports/wasi_snapshot_preview1/usage_test.go b/imports/wasi_snapshot_preview1/usage_test.go index d267879a..88e25e87 100644 --- a/imports/wasi_snapshot_preview1/usage_test.go +++ b/imports/wasi_snapshot_preview1/usage_test.go @@ -8,13 +8,14 @@ import ( "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" + "github.com/tetratelabs/wazero/internal/fstest" "github.com/tetratelabs/wazero/internal/testing/require" ) -// wasiArg was compiled from testdata/wasi_arg.wat +// pringArgsWasm was compiled from testdata/wasi_arg.wat // -//go:embed testdata/wasi_arg.wasm -var wasiArg []byte +//go:embed testdata/print_args.wasm +var pringArgsWasm []byte func TestInstantiateModule(t *testing.T) { ctx := context.Background() @@ -28,7 +29,7 @@ func TestInstantiateModule(t *testing.T) { sys := wazero.NewModuleConfig().WithStdout(&stdout) wasi_snapshot_preview1.MustInstantiate(ctx, r) - compiled, err := r.CompileModule(ctx, wasiArg) + compiled, err := r.CompileModule(ctx, pringArgsWasm) require.NoError(t, err) // Re-use the same module many times. @@ -46,3 +47,27 @@ func TestInstantiateModule(t *testing.T) { require.NoError(t, mod.Close(ctx)) } } + +// printPrestatDirname was compiled from testdata/print_prestat_dirname.wat +// +//go:embed testdata/print_prestat_dirname.wasm +var printPrestatDirname []byte + +// TestInstantiateModule_Prestat +func TestInstantiateModule_Prestat(t *testing.T) { + ctx := context.Background() + + r := wazero.NewRuntime(ctx) + defer r.Close(ctx) + + var stdout bytes.Buffer + + wasi_snapshot_preview1.MustInstantiate(ctx, r) + + _, err := r.InstantiateWithConfig(ctx, printPrestatDirname, wazero.NewModuleConfig(). + WithStdout(&stdout). + WithFSConfig(wazero.NewFSConfig().WithFSMount(fstest.FS, "/wazero"))) + require.NoError(t, err) + + require.Equal(t, "/wazero", stdout.String()) +} diff --git a/internal/wasip1/wasi.go b/internal/wasip1/wasi.go index 4328b49a..299feea2 100644 --- a/internal/wasip1/wasi.go +++ b/internal/wasip1/wasi.go @@ -1,5 +1,4 @@ -// Package wasi_snapshot_preview1 is a helper to remove package cycles re-using -// constants. +// Package wasip1 is a helper to remove package cycles re-using constants. package wasip1 import (