Removes integration_test/vs (#2270)

vs was introduced to bench various things including
the tests against other runtimes. However, the
cases are not representative, and also some are
just unable to build plus some are simply failing.

This removes the entire vs directory, and reduces
the maintenance burden.

Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
Takeshi Yoneda
2024-06-26 10:44:51 -07:00
committed by GitHub
parent d425b9eedc
commit c4516ae243
35 changed files with 5 additions and 1548 deletions

View File

@@ -128,9 +128,8 @@ jobs:
go-version: ${{ matrix.go-version }}
- name: Build test binaries
# Exclude benchmarks as we don't run those in Docker
run: |
go list -f '{{.Dir}}' ./... | egrep -v '(bench|vs|spectest)' | xargs -Ipkg go test pkg -c -o pkg.test
go list -f '{{.Dir}}' ./... | egrep -v '(vs|spectest)' | xargs -Ipkg go test pkg -c -o pkg.test
go build -o wazerocli ./cmd/wazero
env:
GOARCH: ${{ matrix.arch }}
@@ -167,28 +166,6 @@ jobs:
- run: tinygo build ./cmd/wazero
- run: tinygo build -size short -target pico -stack-size=8kb ./cmd/wazero
bench:
name: Benchmark
runs-on: ubuntu-22.04
steps:
# Unlike the other CGO libraries, WasmEdge requires offline installation.
- name: Install WasmEdge
run: |
wget -qO- https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | sudo bash -s -- -p /usr/local -v ${WASMEDGE_VERSION}
# The version here is coupled to internal/integration_test/go.mod, but it
# isn't always the same as sometimes the Go layer has a broken release.
env:
WASMEDGE_VERSION: 0.12.1
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- run: make bench
# This ensures that internal/integration_test/fuzz is runnable, and is not intended to
# run full-length fuzzing while trying to find low-hanging frontend bugs.
fuzz:

View File

@@ -104,9 +104,5 @@ jobs:
source ./emsdk/emsdk_env.sh
make build.examples.emscripten
- name: Build bench cases
run: make build.bench
if: matrix.go-version != '1.20' # fails with TinyGo v0.32.0
- name: Run example tests
run: make test.examples

View File

@@ -20,22 +20,6 @@ main_packages := $(sort $(foreach f,$(dir $(main_sources)),$(if $(findstring ./,
go_test_options ?= -timeout 300s
ensureCompilerFastest := -ldflags '-X github.com/tetratelabs/wazero/internal/integration_test/vs.ensureCompilerFastest=true'
.PHONY: bench
bench:
@go build ./internal/integration_test/bench/...
@# Don't use -test.benchmem as it isn't accurate when comparing against CGO libs
@for d in vs/time vs/wasmedge vs/wasmtime ; do \
cd ./internal/integration_test/$$d ; \
go test -bench=. . -tags='wasmedge' $(ensureCompilerFastest) ; \
cd - ;\
done
bench_testdata_dir := internal/integration_test/bench/testdata
.PHONY: build.bench
build.bench:
@tinygo build -o $(bench_testdata_dir)/case.wasm -scheduler=none --no-debug -target=wasi $(bench_testdata_dir)/case.go
.PHONY: test.examples
test.examples:
@go test $(go_test_options) ./examples/... ./imports/assemblyscript/example/... ./imports/emscripten/... ./imports/wasi_snapshot_preview1/example/...

View File

@@ -14,10 +14,10 @@ import (
"github.com/tetratelabs/wazero/internal/wasm"
)
//go:embed internal/integration_test/vs/testdata/fac.wasm
//go:embed testdata/fac.wasm
var facWasm []byte
//go:embed internal/integration_test/vs/testdata/mem_grow.wasm
//go:embed testdata/mem_grow.wasm
var memGrowWasm []byte
func TestCompilationCache(t *testing.T) {

View File

@@ -1,10 +0,0 @@
# VS
This directory contains tests which compare against other runtimes. As all
known alternatives use CGO, this contains its own [go.mod](go.mod), as
otherwise project dependencies are tainted and multi-platform tests more
difficult to manage.
Examples of portability issues besides CGO
* Wasmtime can only be used in amd64
* Wasmer doesn't link on Windows

View File

@@ -1,187 +0,0 @@
package vs
import (
"context"
"fmt"
"os"
"path"
"runtime"
"sort"
"testing"
"text/tabwriter"
"github.com/tetratelabs/wazero/internal/testing/require"
)
// testCtx is an arbitrary, non-default context. Non-nil also prevents linter errors.
var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
// ensureCompilerFastest is overridable via ldflags. e.g.
//
// -ldflags '-X github.com/tetratelabs/wazero/internal/integration_test/vs.ensureCompilerFastest=true'
var ensureCompilerFastest = "false"
const compilerRuntime = "wazero-compiler"
// runTestBenchmark_Call_CompilerFastest ensures that Compiler is the fastest engine for function invocations.
// This is disabled by default, and can be run with -ldflags '-X github.com/tetratelabs/wazero/vs.ensureCompilerFastest=true'.
func runTestBenchmark_Call_CompilerFastest(t *testing.T, rtCfg *RuntimeConfig, name string, call func(Module, int) error, vsRuntime Runtime) {
if ensureCompilerFastest != "true" {
t.Skip()
}
type benchResult struct {
name string
nsOp float64
}
results := make([]benchResult, 0, 2)
// Add the result for Compiler
compilerNsOp := runCallBenchmark(NewWazeroCompilerRuntime(), rtCfg, call)
results = append(results, benchResult{name: compilerRuntime, nsOp: compilerNsOp})
// Add a result for the runtime we're comparing against
vsNsOp := runCallBenchmark(vsRuntime, rtCfg, call)
results = append(results, benchResult{name: vsRuntime.Name(), nsOp: vsNsOp})
sort.Slice(results, func(i, j int) bool {
return results[i].nsOp < results[j].nsOp
})
// Print results before deciding if this failed
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
_, _ = fmt.Fprintf(w, "Benchmark%s/Call-16\n", name)
for _, result := range results {
_, _ = fmt.Fprintf(w, "%s\t%.2f\tns/op\n", result.name, result.nsOp)
}
_ = w.Flush()
// Fail if compiler wasn't fastest!
require.Equal(t, compilerRuntime, results[0].name, "%s is faster than %s. "+
"Run with ensureCompilerFastest=false instead to see the detailed result",
results[0].name, compilerRuntime)
}
func runCallBenchmark(rt Runtime, rtCfg *RuntimeConfig, call func(Module, int) error) float64 {
result := testing.Benchmark(func(b *testing.B) {
benchmarkCall(b, rt, rtCfg, call)
})
// https://github.com/golang/go/blob/go1.20/src/testing/benchmark.go#L428-L432
nsOp := float64(result.T.Nanoseconds()) / float64(result.N)
return nsOp
}
func benchmark(b *testing.B, runtime func() Runtime, rtCfg *RuntimeConfig, call func(Module, int) error) {
rt := runtime()
b.Run("Compile", func(b *testing.B) {
b.ReportAllocs()
benchmarkCompile(b, rt, rtCfg)
})
b.Run("Instantiate", func(b *testing.B) {
b.ReportAllocs()
benchmarkInstantiate(b, rt, rtCfg)
})
// Don't burn CPU when this is already going to be called in runTestBenchmark_Call_CompilerFastest
if call != nil && (ensureCompilerFastest != "true" || rt.Name() == compilerRuntime) {
b.Run("Call", func(b *testing.B) {
b.ReportAllocs()
benchmarkCall(b, rt, rtCfg, call)
})
}
}
func benchmarkCompile(b *testing.B, rt Runtime, rtCfg *RuntimeConfig) {
for i := 0; i < b.N; i++ {
if err := rt.Compile(testCtx, rtCfg); err != nil {
b.Fatal(err)
}
if err := rt.Close(testCtx); err != nil {
b.Fatal(err)
}
}
}
func benchmarkInstantiate(b *testing.B, rt Runtime, rtCfg *RuntimeConfig) {
// Compile outside the benchmark loop
if err := rt.Compile(testCtx, rtCfg); err != nil {
b.Fatal(err)
}
defer rt.Close(testCtx)
b.ResetTimer()
for i := 0; i < b.N; i++ {
mod, err := rt.Instantiate(testCtx, rtCfg)
if err != nil {
b.Fatal(err)
}
err = mod.Close(testCtx)
if err != nil {
b.Fatal(err)
}
}
}
func benchmarkCall(b *testing.B, rt Runtime, rtCfg *RuntimeConfig, call func(Module, int) error) {
// Initialize outside the benchmark loop
if err := rt.Compile(testCtx, rtCfg); err != nil {
b.Fatal(err)
}
defer rt.Close(testCtx)
mod, err := rt.Instantiate(testCtx, rtCfg)
if err != nil {
b.Fatal(err)
}
defer mod.Close(testCtx)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := call(mod, i); err != nil {
b.Fatal(err)
}
}
}
func testCall(t *testing.T, runtime func() Runtime, rtCfg *RuntimeConfig, testCall func(*testing.T, Module, int, int)) {
rt := runtime()
err := rt.Compile(testCtx, rtCfg)
require.NoError(t, err)
defer rt.Close(testCtx)
// Ensure the module can be re-instantiated times, even if not all runtimes allow renaming.
for i := 0; i < 10; i++ {
m, err := rt.Instantiate(testCtx, rtCfg)
require.NoError(t, err)
// Large loop in test is only to show the function is stable (ex doesn't leak or crash on Nth use).
for j := 0; j < 1000; j++ {
testCall(t, m, i, j)
}
require.NoError(t, m.Close(testCtx))
}
}
func testInstantiate(t *testing.T, runtime func() Runtime, rtCfg *RuntimeConfig) {
rt := runtime()
err := rt.Compile(testCtx, rtCfg)
require.NoError(t, err)
defer rt.Close(testCtx)
// Ensure the module can be re-instantiated times, even if not all runtimes allow renaming.
for i := 0; i < 10; i++ {
m, err := rt.Instantiate(testCtx, rtCfg)
require.NoError(t, err)
require.NoError(t, m.Close(testCtx))
}
}
func readRelativeFile(relativePath string) []byte {
// We can't resolve relative paths as init() is called from each of its subdirs
_, source, _, _ := runtime.Caller(1) // 1 as this utility is in a different source than the caller.
realPath := path.Join(path.Dir(source), relativePath)
bytes, err := os.ReadFile(realPath)
if err != nil {
panic(err)
}
return bytes
}

View File

@@ -1,83 +0,0 @@
package vs
import (
"bytes"
_ "embed"
"fmt"
"testing"
"github.com/tetratelabs/wazero/internal/testing/require"
)
var (
// allocationWasm is compiled from ../../../examples/allocation/tinygo/testdata/src/greet.go
// We can't use go:embed as it is outside this directory. Copying it isn't ideal due to size and drift.
allocationWasmPath = "../../../examples/allocation/tinygo/testdata/greet.wasm"
allocationWasm []byte
allocationParam = "wazero"
allocationResult = []byte("wasm >> Hello, wazero!")
allocationConfig *RuntimeConfig
)
func init() {
allocationWasm = readRelativeFile(allocationWasmPath)
allocationConfig = &RuntimeConfig{
ModuleName: "greet",
ModuleWasm: allocationWasm,
FuncNames: []string{"malloc", "free", "greet"},
NeedsWASI: true, // Needed for TinyGo
LogFn: func(buf []byte) error {
if !bytes.Equal(allocationResult, buf) {
return fmt.Errorf("expected %q, but was %q", allocationResult, buf)
}
return nil
},
}
}
func allocationCall(m Module, _ int) error {
nameSize := uint32(len(allocationParam))
// Instead of an arbitrary memory offset, use TinyGo's allocator. Notice
// there is nothing string-specific in this allocation function. The same
// function could be used to pass binary serialized data to Wasm.
namePtr, err := m.CallI32_I32(testCtx, "malloc", nameSize)
if err != nil {
return err
}
// The pointer is a linear memory offset, which is where we write the name.
if err = m.WriteMemory(namePtr, []byte(allocationParam)); err != nil {
return err
}
// Now, we can call "greeting", which reads the string we wrote to memory!
fnErr := m.CallI32I32_V(testCtx, "greet", namePtr, nameSize)
if fnErr != nil {
return fnErr
}
// This pointer was allocated by TinyGo, but owned by Go, So, we have to
// deallocate it when finished
if err := m.CallI32_V(testCtx, "free", namePtr); err != nil {
return err
}
return nil
}
func RunTestAllocation(t *testing.T, runtime func() Runtime) {
testCall(t, runtime, allocationConfig, testAllocationCall)
}
func testAllocationCall(t *testing.T, m Module, instantiation, iteration int) {
err := allocationCall(m, iteration)
require.NoError(t, err, "instantiation[%d] iteration[%d] failed: %v", instantiation, iteration, err)
}
func RunTestBenchmarkAllocation_Call_CompilerFastest(t *testing.T, vsRuntime Runtime) {
runTestBenchmark_Call_CompilerFastest(t, allocationConfig, "Allocation", allocationCall, vsRuntime)
}
func RunBenchmarkAllocation(b *testing.B, runtime func() Runtime) {
benchmark(b, runtime, allocationConfig, allocationCall)
}

View File

@@ -1,48 +0,0 @@
package vs
import (
_ "embed"
"testing"
"github.com/tetratelabs/wazero/internal/testing/require"
)
var (
// catFS is an embedded filesystem limited to test.txt
//go:embed testdata/fac.wasm
factorialWasm []byte
factorialParam = uint64(30)
factorialResult = uint64(9682165104862298112)
factorialConfig *RuntimeConfig
)
func init() {
factorialConfig = &RuntimeConfig{
ModuleName: "math",
ModuleWasm: factorialWasm,
FuncNames: []string{"fac-ssa"},
}
}
func factorialCall(m Module, _ int) error {
_, err := m.CallI64_I64(testCtx, "fac-ssa", factorialParam)
return err
}
func RunTestFactorial(t *testing.T, runtime func() Runtime) {
testCall(t, runtime, factorialConfig, testFactorialCall)
}
func testFactorialCall(t *testing.T, m Module, instantiation, iteration int) {
res, err := m.CallI64_I64(testCtx, "fac-ssa", factorialParam)
require.NoError(t, err, "instantiation[%d] iteration[%d] failed", instantiation, iteration)
require.Equal(t, factorialResult, res)
}
func RunTestBenchmarkFactorial_Call_CompilerFastest(t *testing.T, vsRuntime Runtime) {
runTestBenchmark_Call_CompilerFastest(t, factorialConfig, "Factorial", factorialCall, vsRuntime)
}
func RunBenchmarkFactorial(b *testing.B, runtime func() Runtime) {
benchmark(b, runtime, factorialConfig, factorialCall)
}

View File

@@ -1,48 +0,0 @@
package vs
import (
_ "embed"
"testing"
"github.com/tetratelabs/wazero/internal/testing/require"
)
var (
//go:embed testdata/hostcall.wasm
hostCallWasm []byte
hostCallConfig *RuntimeConfig
hostCallFunction = "call_host_func"
hostCallParam = uint64(12345)
)
func init() {
hostCallConfig = &RuntimeConfig{
ModuleName: "hostcall",
ModuleWasm: hostCallWasm,
FuncNames: []string{hostCallFunction},
EnvFReturnValue: 0xffff,
}
}
func RunTestHostCall(t *testing.T, runtime func() Runtime) {
testCall(t, runtime, hostCallConfig, testHostCall)
}
func testHostCall(t *testing.T, m Module, instantiation, iteration int) {
res, err := m.CallI64_I64(testCtx, hostCallFunction, hostCallParam)
require.NoError(t, err, "instantiation[%d] iteration[%d] failed", instantiation, iteration)
require.Equal(t, hostCallConfig.EnvFReturnValue, res)
}
func RunTestBenchmarkHostCall_CompilerFastest(t *testing.T, vsRuntime Runtime) {
runTestBenchmark_Call_CompilerFastest(t, hostCallConfig, "HostCall_CrossBoundary", hostCall, vsRuntime)
}
func RunBenchmarkHostCall(b *testing.B, runtime func() Runtime) {
benchmark(b, runtime, hostCallConfig, hostCall)
}
func hostCall(m Module, _ int) error {
_, err := m.CallI64_I64(testCtx, hostCallFunction, hostCallParam)
return err
}

View File

@@ -1,98 +0,0 @@
package vs
import (
_ "embed"
"encoding/binary"
"fmt"
"testing"
"github.com/tetratelabs/wazero/internal/testing/require"
)
const (
i32 = "i32"
i32ValueMemoryOffset = 32
i64 = "i64"
i64ValueMemoryOffset = 64
inWasmIteration = 100
)
var (
//go:embed testdata/memory.wasm
memoryWasm []byte
memoryConfig *RuntimeConfig
memoryFunctions = []string{i32, i64}
)
func init() {
memoryConfig = &RuntimeConfig{
ModuleName: "memory",
ModuleWasm: memoryWasm,
FuncNames: memoryFunctions,
NeedsMemoryExport: true,
}
}
func RunTestMemory(t *testing.T, runtime func() Runtime) {
t.Run(i32, func(t *testing.T) {
testCall(t, runtime, memoryConfig, func(t *testing.T, m Module, instantiation int, iteration int) {
buf := m.Memory()
binary.LittleEndian.PutUint32(buf[i32ValueMemoryOffset:], inWasmIteration)
err := m.CallV_V(testCtx, i32)
require.NoError(t, err)
if 0 != binary.LittleEndian.Uint32(buf[i32ValueMemoryOffset:]) {
panic(fmt.Sprintf("BUG at iteration %d: %d", iteration, binary.LittleEndian.Uint32(buf[i32ValueMemoryOffset:])))
}
})
})
t.Run(i64, func(t *testing.T) {
testCall(t, runtime, memoryConfig, func(t *testing.T, m Module, instantiation int, iteration int) {
buf := m.Memory()
binary.LittleEndian.PutUint64(buf[i64ValueMemoryOffset:], inWasmIteration)
err := m.CallV_V(testCtx, i64)
require.NoError(t, err)
if 0 != binary.LittleEndian.Uint64(buf[i64ValueMemoryOffset:]) {
panic(fmt.Sprintf("BUG at iteration %d: %d", iteration, binary.LittleEndian.Uint64(buf[i32ValueMemoryOffset:])))
}
})
})
}
func RunTestBenchmarkMemory_CompilerFastest(t *testing.T, vsRuntime Runtime) {
t.Run(i32, func(t *testing.T) {
runTestBenchmark_Call_CompilerFastest(t, memoryConfig, "/memory.i32", memoryI32, vsRuntime)
})
t.Run(i64, func(t *testing.T) {
runTestBenchmark_Call_CompilerFastest(t, memoryConfig, "/memory.i64", memoryI64, vsRuntime)
})
}
func RunBenchmarkMemory(b *testing.B, runtime func() Runtime) {
b.Run(i32, func(b *testing.B) {
benchmark(b, runtime, memoryConfig, memoryI32)
})
b.Run(i64, func(b *testing.B) {
benchmark(b, runtime, memoryConfig, memoryI64)
})
}
func memoryI32(m Module, iteration int) (err error) {
buf := m.Memory()
binary.LittleEndian.PutUint32(buf[i32ValueMemoryOffset:], inWasmIteration)
err = m.CallV_V(testCtx, i32)
if 0 != binary.LittleEndian.Uint32(buf[i32ValueMemoryOffset:]) {
panic(fmt.Sprintf("BUG at iteration %d", iteration))
}
return
}
func memoryI64(m Module, iteration int) (err error) {
buf := m.Memory()
binary.LittleEndian.PutUint64(buf[i64ValueMemoryOffset:], inWasmIteration)
err = m.CallV_V(testCtx, i64)
if 0 != binary.LittleEndian.Uint64(buf[i64ValueMemoryOffset:]) {
panic(fmt.Sprintf("BUG at iteration %d", iteration))
}
return
}

View File

@@ -1,33 +0,0 @@
package vs
import (
_ "embed"
"testing"
)
var (
// shorthashWasm is a wasi binary which runs the same wasm function inside
// a loop. See https://github.com/tetratelabs/wazero/issues/947
//
// Taken from https://github.com/jedisct1/webassembly-benchmarks/tree/master/2022-12/wasm
//go:embed testdata/shorthash.wasm
shorthashWasm []byte
shorthashConfig *RuntimeConfig
)
func init() {
shorthashConfig = &RuntimeConfig{
ModuleName: "shorthash",
ModuleWasm: shorthashWasm,
NeedsWASI: true, // runs as a _start function
}
}
func RunTestShorthash(t *testing.T, runtime func() Runtime) {
// not testCall as there are no exported functions except _start
testInstantiate(t, runtime, shorthashConfig)
}
func RunBenchmarkShorthash(b *testing.B, runtime func() Runtime) {
benchmark(b, runtime, shorthashConfig, nil)
}

View File

@@ -1,49 +0,0 @@
package compiler
import (
"testing"
"github.com/tetratelabs/wazero/internal/integration_test/vs"
)
var runtime = vs.NewWazeroCompilerRuntime
func TestAllocation(t *testing.T) {
vs.RunTestAllocation(t, runtime)
}
func BenchmarkAllocation(b *testing.B) {
vs.RunBenchmarkAllocation(b, runtime)
}
func TestFactorial(t *testing.T) {
vs.RunTestFactorial(t, runtime)
}
func BenchmarkFactorial(b *testing.B) {
vs.RunBenchmarkFactorial(b, runtime)
}
func TestHostCall(t *testing.T) {
vs.RunTestHostCall(t, runtime)
}
func BenchmarkHostCall(b *testing.B) {
vs.RunBenchmarkHostCall(b, runtime)
}
func TestMemory(t *testing.T) {
vs.RunTestMemory(t, runtime)
}
func BenchmarkMemory(b *testing.B) {
vs.RunBenchmarkMemory(b, runtime)
}
func TestShorthash(t *testing.T) {
vs.RunTestShorthash(t, runtime)
}
func BenchmarkShorthash(b *testing.B) {
vs.RunBenchmarkShorthash(b, runtime)
}

View File

@@ -1,57 +0,0 @@
package interpreter
import (
"testing"
"github.com/tetratelabs/wazero/internal/integration_test/vs"
)
var runtime = vs.NewWazeroInterpreterRuntime
func TestAllocation(t *testing.T) {
vs.RunTestAllocation(t, runtime)
}
func BenchmarkAllocation(b *testing.B) {
vs.RunBenchmarkAllocation(b, runtime)
}
func TestBenchmarkAllocation_Call_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkAllocation_Call_CompilerFastest(t, runtime())
}
func TestFactorial(t *testing.T) {
vs.RunTestFactorial(t, runtime)
}
func BenchmarkFactorial(b *testing.B) {
vs.RunBenchmarkFactorial(b, runtime)
}
func TestBenchmarkFactorial_Call_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkFactorial_Call_CompilerFastest(t, runtime())
}
func TestHostCall(t *testing.T) {
vs.RunTestHostCall(t, runtime)
}
func BenchmarkHostCall(b *testing.B) {
vs.RunBenchmarkHostCall(b, runtime)
}
func TestBenchmarkHostCall_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkHostCall_CompilerFastest(t, runtime())
}
func TestMemory(t *testing.T) {
vs.RunTestMemory(t, runtime)
}
func BenchmarkMemory(b *testing.B) {
vs.RunBenchmarkMemory(b, runtime)
}
func TestBenchmarkMemory_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkMemory_CompilerFastest(t, runtime())
}

View File

@@ -1,220 +0,0 @@
package vs
import (
"context"
"errors"
"fmt"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/tetratelabs/wazero/internal/wasm"
)
type RuntimeConfig struct {
Name string
ModuleName string
ModuleWasm []byte
FuncNames []string
NeedsWASI bool
NeedsMemoryExport bool
// LogFn requires the implementation to export a function "env.log" which accepts i32i32_v.
// The implementation invoke this with a byte slice allocated from the offset, length pair.
// This function simulates a host function that logs a message.
LogFn func([]byte) error
// EnvFReturnValue is set to non-zero if we want the runtime to instantiate "env" module with the function "f"
// which accepts one i64 value and returns the EnvFReturnValue as i64. This is mutually exclusive to LogFn.
EnvFReturnValue uint64
}
type Runtime interface {
Name() string
Compile(context.Context, *RuntimeConfig) error
Instantiate(context.Context, *RuntimeConfig) (Module, error)
Close(context.Context) error
}
type Module interface {
CallI32_I32(ctx context.Context, funcName string, param uint32) (uint32, error)
CallI32I32_V(ctx context.Context, funcName string, x, y uint32) error
CallI32_V(ctx context.Context, funcName string, param uint32) error
CallV_V(ctx context.Context, funcName string) error
CallI64_I64(ctx context.Context, funcName string, param uint64) (uint64, error)
WriteMemory(offset uint32, bytes []byte) error
Memory() []byte
Close(context.Context) error
}
func NewWazeroInterpreterRuntime() Runtime {
return newWazeroRuntime("wazero-interpreter", wazero.NewRuntimeConfigInterpreter())
}
func NewWazeroCompilerRuntime() Runtime {
return newWazeroRuntime(compilerRuntime, wazero.NewRuntimeConfigCompiler())
}
func newWazeroRuntime(name string, config wazero.RuntimeConfig) *wazeroRuntime {
return &wazeroRuntime{name: name, config: config}
}
type wazeroRuntime struct {
name string
config wazero.RuntimeConfig
runtime wazero.Runtime
logFn func([]byte) error
env, compiled wazero.CompiledModule
}
type wazeroModule struct {
wasi api.Closer
env, mod api.Module
funcs map[string]api.Function
}
func (r *wazeroRuntime) Name() string {
return r.name
}
func (m *wazeroModule) Memory() []byte {
return m.mod.Memory().(*wasm.MemoryInstance).Buffer
}
func (r *wazeroRuntime) log(_ context.Context, mod api.Module, stack []uint64) {
offset, byteCount := uint32(stack[0]), uint32(stack[1])
buf, ok := mod.Memory().Read(offset, byteCount)
if !ok {
panic("out of memory reading log buffer")
}
if err := r.logFn(buf); err != nil {
panic(err)
}
}
func (r *wazeroRuntime) Compile(ctx context.Context, cfg *RuntimeConfig) (err error) {
r.runtime = wazero.NewRuntimeWithConfig(ctx, r.config)
if cfg.LogFn != nil {
r.logFn = cfg.LogFn
if r.env, err = r.runtime.NewHostModuleBuilder("env").
NewFunctionBuilder().
WithGoModuleFunction(api.GoModuleFunc(r.log), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).
Export("log").
Compile(ctx); err != nil {
return err
}
} else if cfg.EnvFReturnValue != 0 {
if r.env, err = r.runtime.NewHostModuleBuilder("env").
NewFunctionBuilder().
WithGoFunction(api.GoFunc(func(ctx context.Context, stack []uint64) {
stack[0] = cfg.EnvFReturnValue
}), []api.ValueType{api.ValueTypeI64}, []api.ValueType{api.ValueTypeI64}).
Export("f").
Compile(ctx); err != nil {
return err
}
}
r.compiled, err = r.runtime.CompileModule(ctx, cfg.ModuleWasm)
return
}
func (r *wazeroRuntime) Instantiate(ctx context.Context, cfg *RuntimeConfig) (mod Module, err error) {
wazeroCfg := wazero.NewModuleConfig().WithName(cfg.ModuleName)
m := &wazeroModule{funcs: map[string]api.Function{}}
// Instantiate WASI, if configured.
if cfg.NeedsWASI {
if m.wasi, err = wasi_snapshot_preview1.Instantiate(ctx, r.runtime); err != nil {
return
}
}
// Instantiate the host module, "env", if configured.
if env := r.env; env != nil {
if m.env, err = r.runtime.InstantiateModule(ctx, env, wazero.NewModuleConfig()); err != nil {
return
}
}
// Instantiate the module.
if m.mod, err = r.runtime.InstantiateModule(ctx, r.compiled, wazeroCfg); err != nil {
return
}
// Ensure function exports exist.
for _, funcName := range cfg.FuncNames {
if fn := m.mod.ExportedFunction(funcName); fn == nil {
return nil, fmt.Errorf("%s is not an exported function", funcName)
} else {
m.funcs[funcName] = fn
}
}
mod = m
return
}
func (r *wazeroRuntime) Close(ctx context.Context) (err error) {
if compiled := r.compiled; compiled != nil {
err = compiled.Close(ctx)
}
r.compiled = nil
if env := r.env; env != nil {
err = env.Close(ctx)
}
r.env = nil
return
}
func (m *wazeroModule) CallV_V(ctx context.Context, funcName string) (err error) {
_, err = m.funcs[funcName].Call(ctx)
return
}
func (m *wazeroModule) CallI32_I32(ctx context.Context, funcName string, param uint32) (uint32, error) {
if results, err := m.funcs[funcName].Call(ctx, uint64(param)); err != nil {
return 0, err
} else if len(results) > 0 {
return uint32(results[0]), nil
}
return 0, nil
}
func (m *wazeroModule) CallI32I32_V(ctx context.Context, funcName string, x, y uint32) (err error) {
_, err = m.funcs[funcName].Call(ctx, uint64(x), uint64(y))
return
}
func (m *wazeroModule) CallI32_V(ctx context.Context, funcName string, param uint32) (err error) {
_, err = m.funcs[funcName].Call(ctx, uint64(param))
return
}
func (m *wazeroModule) CallI64_I64(ctx context.Context, funcName string, param uint64) (uint64, error) {
if results, err := m.funcs[funcName].Call(ctx, param); err != nil {
return 0, err
} else {
return results[0], nil
}
}
func (m *wazeroModule) WriteMemory(offset uint32, bytes []byte) error {
if !m.mod.Memory().Write(offset, bytes) {
return errors.New("out of memory writing name")
}
return nil
}
func (m *wazeroModule) Close(ctx context.Context) (err error) {
if mod := m.mod; mod != nil {
err = mod.Close(ctx)
}
m.mod = nil
if env := m.env; env != nil {
err = env.Close(ctx)
}
m.env = nil
if wasi := m.wasi; wasi != nil {
err = wasi.Close(ctx)
}
m.wasi = nil
return
}

View File

@@ -1,9 +0,0 @@
(module
;; env.f must be a host function for benchmarks on the cost of host calls which cross the Wasm<>Go boundary.
(func $host_func (import "env" "f") (param i64) (result i64))
;; call_host_func calls "env.f" and returns the resut as-is.
(func (export "call_host_func") (param i64) (result i64)
local.get 0
call $host_func
)
)

Binary file not shown.

View File

@@ -1,31 +0,0 @@
(module
(memory (export "memory") 1)
;; Load the i32 value at the offset 32, decrement it, and store it back at the same position
;; until the value becomes zero.
(func (export "i32")
(loop
i32.const 32
(i32.load align=1 (i32.const 32))
i32.const 1
i32.sub
i32.store
(br_if 1 (i32.eqz (i32.load align=1 (i32.const 32)))) ;; exit.
(br 0) ;; continue loop.
)
)
;; Load the i64 value at the offset 64, decrement it, and store it back at the same position
;; until the value becomes zero.
(func (export "i64")
(loop
i32.const 64
(i64.load align=1 (i32.const 64))
i64.const 1
i64.sub
i64.store
(br_if 1 (i64.eqz (i64.load align=1 (i32.const 64)))) ;; exit.
(br 0) ;; continue loop.
)
)
)

View File

@@ -1,7 +0,0 @@
module github.com/tetratelabs/wazero/internal/integration_test/vs/clock
go 1.20
require golang.org/x/sys v0.1.0
replace github.com/tetratelabs/wazero => ../../../..

View File

@@ -1,2 +0,0 @@
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@@ -1,57 +0,0 @@
// Package time benchmarks shows ways to implementing the platform clock more
// efficiently. As long as CGO is available, all platforms can use
// `runtime.nanotime` to more efficiently implement sys.Nanotime vs using
// time.Since or x/sys.
//
// While results would be more impressive, this doesn't show how to use
// `runtime.walltime` to avoid the double-performance vs using time.Now. The
// corresponding function only exists in darwin, so prevents this benchmark
// from running on other platforms.
package time
import (
"testing"
"time"
_ "unsafe" // for go:linkname
"golang.org/x/sys/unix"
)
//go:linkname nanotime runtime.nanotime
func nanotime() int64
func BenchmarkClock(b *testing.B) {
b.Run("time.Now", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = time.Now()
}
})
b.Run("ClockGettime(CLOCK_REALTIME)", func(b *testing.B) {
for i := 0; i < b.N; i++ {
var now unix.Timespec
if err := unix.ClockGettime(unix.CLOCK_REALTIME, &now); err != nil {
b.Fatal(err)
}
}
})
base := time.Now()
b.Run("time.Since", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = time.Since(base)
}
})
b.Run("runtime.nanotime", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = nanotime()
}
})
b.Run("ClockGettime(CLOCK_MONOTONIC)", func(b *testing.B) {
for i := 0; i < b.N; i++ {
var tick unix.Timespec
if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &tick); err != nil {
b.Fatal(err)
}
}
})
}

View File

@@ -1,10 +0,0 @@
module github.com/tetratelabs/wazero/internal/integration_test/vs/wasmedge
go 1.20
require (
github.com/second-state/WasmEdge-go v0.12.1
github.com/tetratelabs/wazero v0.0.0
)
replace github.com/tetratelabs/wazero => ../../../..

View File

@@ -1,2 +0,0 @@
github.com/second-state/WasmEdge-go v0.12.1 h1:rIRiRF35+8CtcYTsiW4KfFNIh3faRb3LoG2c7cCqQyI=
github.com/second-state/WasmEdge-go v0.12.1/go.mod h1:HyBf9hVj1sRAjklsjc1Yvs9b5RcmthPG9z99dY78TKg=

View File

@@ -1,200 +0,0 @@
//go:build cgo && !windows && wasmedge
// Note: WasmEdge depends on manual installation of a shared library.
// e.g. wget -qO- https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | \
// sudo bash -s -- -p /usr/local -e none -v ${WASMEDGE_VERSION}
package wasmedge
import (
"context"
"fmt"
"os"
"github.com/second-state/WasmEdge-go/wasmedge"
"github.com/tetratelabs/wazero/internal/integration_test/vs"
)
func newWasmedgeRuntime() vs.Runtime {
return &wasmedgeRuntime{}
}
type wasmedgeRuntime struct {
conf *wasmedge.Configure
logFn func([]byte) error
}
type wasmedgeModule struct {
store *wasmedge.Store
vm *wasmedge.VM
env *wasmedge.Module
}
func (r *wasmedgeRuntime) Name() string {
return "wasmedge"
}
func (r *wasmedgeRuntime) log(_ interface{}, callframe *wasmedge.CallingFrame, params []interface{}) ([]interface{}, wasmedge.Result) {
offset := params[0].(int32)
byteCount := params[1].(int32)
mem := callframe.GetMemoryByIndex(0)
buf, err := mem.GetData(uint(offset), uint(byteCount))
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
return nil, wasmedge.Result_Fail
}
if err = r.logFn(buf); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
panic(err)
}
return nil, wasmedge.Result_Success
}
func (r *wasmedgeRuntime) Compile(_ context.Context, cfg *vs.RuntimeConfig) (err error) {
if cfg.NeedsWASI {
r.conf = wasmedge.NewConfigure(wasmedge.WASI)
} else {
r.conf = wasmedge.NewConfigure()
}
// We can't re-use a store because "module name conflict" occurs even after releasing a VM
return
}
func (r *wasmedgeRuntime) Instantiate(_ context.Context, cfg *vs.RuntimeConfig) (mod vs.Module, err error) {
m := &wasmedgeModule{store: wasmedge.NewStore()}
m.vm = wasmedge.NewVMWithConfigAndStore(r.conf, m.store)
// Instantiate WASI, if configured.
if cfg.NeedsWASI {
wasi := m.vm.GetImportModule(wasmedge.WASI)
wasi.InitWasi(nil, nil, nil)
}
// Instantiate the host module, "env", if configured.
if cfg.LogFn != nil {
r.logFn = cfg.LogFn
m.env = wasmedge.NewModule("env")
logType := wasmedge.NewFunctionType([]wasmedge.ValType{wasmedge.ValType_I32, wasmedge.ValType_I32}, nil)
m.env.AddFunction("log", wasmedge.NewFunction(logType, r.log, nil, 0))
if err = m.vm.RegisterModule(m.env); err != nil {
return nil, err
}
} else if cfg.EnvFReturnValue != 0 {
m.env = wasmedge.NewModule("env")
fType := wasmedge.NewFunctionType([]wasmedge.ValType{wasmedge.ValType_I64}, []wasmedge.ValType{wasmedge.ValType_I64})
m.env.AddFunction("f", wasmedge.NewFunction(fType, func(interface{}, *wasmedge.CallingFrame, []interface{}) ([]interface{}, wasmedge.Result) {
return []interface{}{int64(cfg.EnvFReturnValue)}, wasmedge.Result_Success
}, nil, 0))
if err = m.vm.RegisterModule(m.env); err != nil {
return nil, err
}
}
// Instantiate the module.
if err = m.vm.RegisterWasmBuffer(cfg.ModuleName, cfg.ModuleWasm); err != nil {
return
}
if err = m.vm.LoadWasmBuffer(cfg.ModuleWasm); err != nil {
return
}
if err = m.vm.Validate(); err != nil {
return
}
if err = m.vm.Instantiate(); err != nil {
return
}
// If WASI is needed, we have to go back and invoke the _start function.
if cfg.NeedsWASI {
if _, err = m.vm.Execute("_start"); err != nil {
return
}
}
// Ensure function exports exist.
for _, funcName := range cfg.FuncNames {
if fn := m.vm.GetFunctionType(funcName); fn == nil {
err = fmt.Errorf("%s is not an exported function", funcName)
return
}
}
mod = m
return
}
func (r *wasmedgeRuntime) Close(context.Context) error {
if conf := r.conf; conf != nil {
conf.Release()
}
r.conf = nil
return nil
}
func (m *wasmedgeModule) Memory() []byte {
mod := m.vm.GetActiveModule()
mem := mod.FindMemory("memory")
d, err := mem.GetData(0, mem.GetPageSize()*65536)
if err != nil {
panic(err)
}
return d
}
func (m *wasmedgeModule) CallI32_I32(_ context.Context, funcName string, param uint32) (uint32, error) {
if result, err := m.vm.Execute(funcName, int32(param)); err != nil {
return 0, err
} else {
return uint32(result[0].(int32)), nil
}
}
func (m *wasmedgeModule) CallI32I32_V(_ context.Context, funcName string, x, y uint32) (err error) {
_, err = m.vm.Execute(funcName, int32(x), int32(y))
return
}
func (m *wasmedgeModule) CallV_V(_ context.Context, funcName string) (err error) {
_, err = m.vm.Execute(funcName)
return
}
func (m *wasmedgeModule) CallI32_V(_ context.Context, funcName string, param uint32) (err error) {
_, err = m.vm.Execute(funcName, int32(param))
return
}
func (m *wasmedgeModule) CallI64_I64(_ context.Context, funcName string, param uint64) (uint64, error) {
if result, err := m.vm.Execute(funcName, int64(param)); err != nil {
return 0, err
} else {
return uint64(result[0].(int64)), nil
}
}
func (m *wasmedgeModule) WriteMemory(offset uint32, bytes []byte) error {
mod := m.vm.GetActiveModule()
mem := mod.FindMemory("memory")
if unsafeSlice, err := mem.GetData(uint(offset), uint(len(bytes))); err != nil {
return err
} else {
copy(unsafeSlice, bytes)
}
return nil
}
func (m *wasmedgeModule) Close(context.Context) error {
if env := m.env; env != nil {
env.Release()
}
if vm := m.vm; vm != nil {
vm.Release()
}
m.vm = nil
if store := m.store; store != nil {
store.Release()
}
m.store = nil
return nil
}

View File

@@ -1,61 +0,0 @@
//go:build cgo && wasmedge
// wasmedge depends on manual installation of a shared library, so is guarded by a flag by default.
package wasmedge
import (
"testing"
"github.com/tetratelabs/wazero/internal/integration_test/vs"
)
var runtime = newWasmedgeRuntime
func TestAllocation(t *testing.T) {
vs.RunTestAllocation(t, runtime)
}
func BenchmarkAllocation(b *testing.B) {
vs.RunBenchmarkAllocation(b, runtime)
}
func TestBenchmarkAllocation_Call_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkAllocation_Call_CompilerFastest(t, runtime())
}
func TestFactorial(t *testing.T) {
vs.RunTestFactorial(t, runtime)
}
func BenchmarkFactorial(b *testing.B) {
vs.RunBenchmarkFactorial(b, runtime)
}
func TestBenchmarkFactorial_Call_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkFactorial_Call_CompilerFastest(t, runtime())
}
func TestHostCall(t *testing.T) {
vs.RunTestHostCall(t, runtime)
}
func BenchmarkHostCall(b *testing.B) {
vs.RunBenchmarkHostCall(b, runtime)
}
func TestBenchmarkHostCall_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkHostCall_CompilerFastest(t, runtime())
}
func TestMemory(t *testing.T) {
vs.RunTestMemory(t, runtime)
}
func BenchmarkMemory(b *testing.B) {
vs.RunBenchmarkMemory(b, runtime)
}
func TestBenchmarkMemory_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkMemory_CompilerFastest(t, runtime())
}

View File

@@ -1,10 +0,0 @@
module github.com/tetratelabs/wazero/internal/integration_test/vs/wasmtime
go 1.20
require (
github.com/bytecodealliance/wasmtime-go/v9 v9.0.0
github.com/tetratelabs/wazero v0.0.0
)
replace github.com/tetratelabs/wazero => ../../../..

View File

@@ -1,6 +0,0 @@
github.com/bytecodealliance/wasmtime-go/v9 v9.0.0 h1:lkyiPbbo++bSmDyJVxDQwxxaiu3LOFVm0iBHnTS1W5A=
github.com/bytecodealliance/wasmtime-go/v9 v9.0.0/go.mod h1:zpOxt1j5vj44AzXZVhS4H+hr39vMk4hDlyC42kGksbU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -1,205 +0,0 @@
//go:build cgo
package wasmtime
import (
"context"
"fmt"
wt "github.com/bytecodealliance/wasmtime-go/v9"
"github.com/tetratelabs/wazero/internal/integration_test/vs"
)
func newWasmtimeRuntime() vs.Runtime {
return &wasmtimeRuntime{}
}
type wasmtimeRuntime struct {
engine *wt.Engine
module *wt.Module
}
type wasmtimeModule struct {
store *wt.Store
// instance is here because there's no close/destroy function. The only thing is garbage collection.
instance *wt.Instance
funcs map[string]*wt.Func
logFn func([]byte) error
mem *wt.Memory
}
func (r *wasmtimeRuntime) Name() string {
return "wasmtime"
}
func (m *wasmtimeModule) log(_ *wt.Caller, args []wt.Val) ([]wt.Val, *wt.Trap) {
unsafeSlice := m.mem.UnsafeData(m.store)
offset := args[0].I32()
byteCount := args[1].I32()
if err := m.logFn(unsafeSlice[offset : offset+byteCount]); err != nil {
return nil, wt.NewTrap(err.Error())
}
return []wt.Val{}, nil
}
func (r *wasmtimeRuntime) Compile(_ context.Context, cfg *vs.RuntimeConfig) (err error) {
r.engine = wt.NewEngine()
if r.module, err = wt.NewModule(r.engine, cfg.ModuleWasm); err != nil {
return
}
return
}
func (r *wasmtimeRuntime) Instantiate(_ context.Context, cfg *vs.RuntimeConfig) (mod vs.Module, err error) {
wm := &wasmtimeModule{funcs: map[string]*wt.Func{}}
// We can't reuse a store because even if we call close, re-instantiating too many times leads to:
// >> resource limit exceeded: instance count too high at 10001
wm.store = wt.NewStore(r.engine)
linker := wt.NewLinker(wm.store.Engine)
// Instantiate WASI, if configured.
if cfg.NeedsWASI {
if err = linker.DefineWasi(); err != nil {
return
}
config := wt.NewWasiConfig() // defaults to toss stdout
config.InheritStderr() // see errors
wm.store.SetWasi(config)
}
// Instantiate the host module, "env", if configured.
if cfg.LogFn != nil {
wm.logFn = cfg.LogFn
if err = linker.Define(wm.store, "env", "log", wt.NewFunc(
wm.store,
wt.NewFuncType(
[]*wt.ValType{
wt.NewValType(wt.KindI32),
wt.NewValType(wt.KindI32),
},
[]*wt.ValType{},
),
wm.log,
)); err != nil {
return
}
} else if cfg.EnvFReturnValue != 0 {
ret := []wt.Val{wt.ValI64(int64(cfg.EnvFReturnValue))}
if err = linker.Define(wm.store, "env", "f", wt.NewFunc(
wm.store,
wt.NewFuncType(
[]*wt.ValType{
wt.NewValType(wt.KindI64),
},
[]*wt.ValType{wt.NewValType(wt.KindI64)},
),
func(_ *wt.Caller, args []wt.Val) ([]wt.Val, *wt.Trap) {
return ret, nil
},
)); err != nil {
return
}
}
// Set the module name.
if err = linker.DefineModule(wm.store, cfg.ModuleName, r.module); err != nil {
return
}
// Instantiate the module.
instance, instantiateErr := linker.Instantiate(wm.store, r.module)
if instantiateErr != nil {
err = instantiateErr
return
}
if cfg.LogFn != nil || cfg.NeedsMemoryExport {
// Wasmtime does not allow a host function parameter for memory, so you have to manually propagate it.
if wm.mem = instance.GetExport(wm.store, "memory").Memory(); wm.mem == nil {
err = fmt.Errorf(`"memory" not exported`)
return
}
}
// If WASI is needed, we have to go back and invoke the _start function.
if cfg.NeedsWASI {
start := instance.GetFunc(wm.store, "_start")
if _, err = start.Call(wm.store); err != nil {
return
}
}
// Ensure function exports exist.
for _, funcName := range cfg.FuncNames {
if fn := instance.GetFunc(wm.store, funcName); fn == nil {
err = fmt.Errorf("%s is not an exported function", funcName)
return
} else {
wm.funcs[funcName] = fn
}
}
mod = wm
return
}
func (r *wasmtimeRuntime) Close(context.Context) error {
r.module = nil
r.engine = nil
return nil // wt only closes via finalizer
}
func (m *wasmtimeModule) Memory() []byte {
return m.mem.UnsafeData(m.store)
}
func (m *wasmtimeModule) CallI32_I32(_ context.Context, funcName string, param uint32) (uint32, error) {
fn := m.funcs[funcName]
if result, err := fn.Call(m.store, int32(param)); err != nil {
return 0, err
} else {
return uint32(result.(int32)), nil
}
}
func (m *wasmtimeModule) CallI32I32_V(_ context.Context, funcName string, x, y uint32) (err error) {
fn := m.funcs[funcName]
_, err = fn.Call(m.store, int32(x), int32(y))
return
}
func (m *wasmtimeModule) CallV_V(_ context.Context, funcName string) (err error) {
fn := m.funcs[funcName]
_, err = fn.Call(m.store)
return
}
func (m *wasmtimeModule) CallI32_V(_ context.Context, funcName string, param uint32) (err error) {
fn := m.funcs[funcName]
_, err = fn.Call(m.store, int32(param))
return
}
func (m *wasmtimeModule) CallI64_I64(_ context.Context, funcName string, param uint64) (uint64, error) {
fn := m.funcs[funcName]
if result, err := fn.Call(m.store, int64(param)); err != nil {
return 0, err
} else {
return uint64(result.(int64)), nil
}
}
func (m *wasmtimeModule) WriteMemory(offset uint32, bytes []byte) error {
unsafeSlice := m.mem.UnsafeData(m.store)
copy(unsafeSlice[offset:], bytes)
return nil
}
func (m *wasmtimeModule) Close(context.Context) error {
m.store = nil
m.instance = nil
m.funcs = nil
return nil // wt only closes via finalizer
}

View File

@@ -1,67 +0,0 @@
//go:build cgo
package wasmtime
import (
"testing"
"github.com/tetratelabs/wazero/internal/integration_test/vs"
)
var runtime = newWasmtimeRuntime
func TestAllocation(t *testing.T) {
vs.RunTestAllocation(t, runtime)
}
func BenchmarkAllocation(b *testing.B) {
vs.RunBenchmarkAllocation(b, runtime)
}
func TestBenchmarkAllocation_Call_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkAllocation_Call_CompilerFastest(t, runtime())
}
func TestFactorial(t *testing.T) {
vs.RunTestFactorial(t, runtime)
}
func BenchmarkFactorial(b *testing.B) {
vs.RunBenchmarkFactorial(b, runtime)
}
func TestBenchmarkFactorial_Call_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkFactorial_Call_CompilerFastest(t, runtime())
}
func TestHostCall(t *testing.T) {
vs.RunTestHostCall(t, runtime)
}
func BenchmarkHostCall(b *testing.B) {
vs.RunBenchmarkHostCall(b, runtime)
}
func TestBenchmarkHostCall_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkHostCall_CompilerFastest(t, runtime())
}
func TestMemory(t *testing.T) {
vs.RunTestMemory(t, runtime)
}
func BenchmarkMemory(b *testing.B) {
vs.RunBenchmarkMemory(b, runtime)
}
func TestBenchmarkMemory_CompilerFastest(t *testing.T) {
vs.RunTestBenchmarkMemory_CompilerFastest(t, runtime())
}
func TestShorthash(t *testing.T) {
vs.RunTestShorthash(t, runtime)
}
func BenchmarkShorthash(b *testing.B) {
vs.RunBenchmarkShorthash(b, runtime)
}

View File

@@ -27,4 +27,4 @@
(drop) (return)
)
)
)
)

BIN
testdata/mem_grow.wasm vendored Normal file

Binary file not shown.

View File

@@ -11,4 +11,4 @@
return
)
(start $main)
)
)