Adds tests for multiple goroutines (#331)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
package wazero
|
||||
|
||||
const JITSupported = true
|
||||
|
||||
// NewRuntimeConfig returns NewRuntimeConfigJIT
|
||||
func NewRuntimeConfig() *RuntimeConfig {
|
||||
return NewRuntimeConfigJIT()
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
package wazero
|
||||
|
||||
const JITSupported = false
|
||||
|
||||
// NewRuntimeConfig returns NewRuntimeConfigInterpreter
|
||||
func NewRuntimeConfig() *RuntimeConfig {
|
||||
return NewRuntimeConfigInterpreter()
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -19,15 +17,15 @@ import (
|
||||
// ctx is a default context used to avoid lint warnings even though these tests don't use any context data.
|
||||
var ctx = context.Background()
|
||||
|
||||
func TestJIT(t *testing.T) {
|
||||
if runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64" {
|
||||
func TestJITAdhoc(t *testing.T) {
|
||||
if !wazero.JITSupported {
|
||||
t.Skip()
|
||||
}
|
||||
runTests(t, wazero.NewRuntimeConfigJIT)
|
||||
runAdhocTests(t, wazero.NewRuntimeConfigJIT)
|
||||
}
|
||||
|
||||
func TestInterpreter(t *testing.T) {
|
||||
runTests(t, wazero.NewRuntimeConfigInterpreter)
|
||||
func TestInterpreterAdhoc(t *testing.T) {
|
||||
runAdhocTests(t, wazero.NewRuntimeConfigInterpreter)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -45,7 +43,7 @@ var (
|
||||
hugestackWasm []byte
|
||||
)
|
||||
|
||||
func runTests(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
func runAdhocTests(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
t.Run("huge stack", func(t *testing.T) {
|
||||
testHugeStack(t, newRuntimeConfig)
|
||||
})
|
||||
@@ -73,35 +71,18 @@ func runTests(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
}
|
||||
|
||||
func testHugeStack(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
// We execute 1000 times in order to ensure the JIT engine is stable under high concurrency
|
||||
// and we have no conflict with Go's runtime.
|
||||
const goroutines = 1000
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(newRuntimeConfig())
|
||||
|
||||
module, err := r.NewModuleFromSource(hugestackWasm)
|
||||
require.NoError(t, err)
|
||||
|
||||
fn := module.Function("main")
|
||||
require.NotNil(t, fn)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(goroutines)
|
||||
for i := 0; i < goroutines; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, err = fn.Call(ctx)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func testFibonacci(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
// We execute 1000 times in order to ensure the JIT engine is stable under high concurrency
|
||||
// and we have no conflict with Go's runtime.
|
||||
const goroutines = 1000
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(newRuntimeConfig())
|
||||
module, err := r.NewModuleFromSource(fibWasm)
|
||||
require.NoError(t, err)
|
||||
@@ -109,17 +90,9 @@ func testFibonacci(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig)
|
||||
fib := module.Function("fib")
|
||||
require.NotNil(t, fib)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(goroutines)
|
||||
for i := 0; i < goroutines; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
results, err := fib.Call(ctx, 20)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(10946), results[0])
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func testFac(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
|
||||
68
tests/engine/concurrency_test.go
Normal file
68
tests/engine/concurrency_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package adhoc
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
)
|
||||
|
||||
func TestJITConcurrency(t *testing.T) {
|
||||
if !wazero.JITSupported {
|
||||
t.Skip()
|
||||
}
|
||||
runAdhocTestsUnderHighConcurrency(t, wazero.NewRuntimeConfigJIT)
|
||||
// TODO: Add conccurent instantiation, invocation and release on a single store test case in https://github.com/tetratelabs/wazero/issues/293
|
||||
|
||||
}
|
||||
|
||||
func TestInterpreterConcurrency(t *testing.T) {
|
||||
runAdhocTestsUnderHighConcurrency(t, wazero.NewRuntimeConfigInterpreter)
|
||||
// TODO: Add conccurent instantiation, invocation and release on a single store test case in https://github.com/tetratelabs/wazero/issues/293
|
||||
}
|
||||
|
||||
func runAdhocTestsUnderHighConcurrency(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
|
||||
t.Run("huge stack", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testHugeStack)
|
||||
})
|
||||
t.Run("fibonacci", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testFibonacci)
|
||||
})
|
||||
t.Run("fac", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testFac)
|
||||
})
|
||||
t.Run("unreachable", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testUnreachable)
|
||||
})
|
||||
t.Run("memory", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testMemory)
|
||||
})
|
||||
t.Run("recursive entry", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testRecursiveEntry)
|
||||
})
|
||||
t.Run("imported-and-exported func", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runAdhocTestUnderHighConcurrency(t, newRuntimeConfig, testImportedAndExportedFunc)
|
||||
})
|
||||
}
|
||||
|
||||
// runAdhocTestUnderHighConcurrency runs a test case in adhoc_test.go with multiple goroutines.
|
||||
func runAdhocTestUnderHighConcurrency(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig,
|
||||
adhocTest func(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig)) {
|
||||
const goroutinesPerCase = 1000
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(goroutinesPerCase)
|
||||
for i := 0; i < goroutinesPerCase; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
adhocTest(t, newRuntimeConfig)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
Reference in New Issue
Block a user