713 lines
19 KiB
Go
713 lines
19 KiB
Go
package wazero
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
_ "embed"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/tetratelabs/wazero/api"
|
|
"github.com/tetratelabs/wazero/internal/fstest"
|
|
"github.com/tetratelabs/wazero/internal/platform"
|
|
internalsys "github.com/tetratelabs/wazero/internal/sys"
|
|
"github.com/tetratelabs/wazero/internal/sysfs"
|
|
testfs "github.com/tetratelabs/wazero/internal/testing/fs"
|
|
"github.com/tetratelabs/wazero/internal/testing/require"
|
|
"github.com/tetratelabs/wazero/internal/wasm"
|
|
"github.com/tetratelabs/wazero/sys"
|
|
)
|
|
|
|
func TestRuntimeConfig(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
with func(RuntimeConfig) RuntimeConfig
|
|
expected RuntimeConfig
|
|
}{
|
|
{
|
|
name: "features",
|
|
with: func(c RuntimeConfig) RuntimeConfig {
|
|
return c.WithCoreFeatures(api.CoreFeaturesV1)
|
|
},
|
|
expected: &runtimeConfig{
|
|
enabledFeatures: api.CoreFeaturesV1,
|
|
},
|
|
},
|
|
{
|
|
name: "memoryLimitPages",
|
|
with: func(c RuntimeConfig) RuntimeConfig {
|
|
return c.WithMemoryLimitPages(10)
|
|
},
|
|
expected: &runtimeConfig{
|
|
memoryLimitPages: 10,
|
|
},
|
|
},
|
|
{
|
|
name: "memoryCapacityFromMax",
|
|
with: func(c RuntimeConfig) RuntimeConfig {
|
|
return c.WithMemoryCapacityFromMax(true)
|
|
},
|
|
expected: &runtimeConfig{
|
|
memoryCapacityFromMax: true,
|
|
},
|
|
},
|
|
{
|
|
name: "WithDebugInfoEnabled",
|
|
with: func(c RuntimeConfig) RuntimeConfig {
|
|
return c.WithDebugInfoEnabled(false)
|
|
},
|
|
expected: &runtimeConfig{
|
|
dwarfDisabled: true, // dwarf is a more technical name and ok here.
|
|
},
|
|
},
|
|
{
|
|
name: "WithCustomSections",
|
|
with: func(c RuntimeConfig) RuntimeConfig {
|
|
return c.WithCustomSections(true)
|
|
},
|
|
expected: &runtimeConfig{
|
|
storeCustomSections: true,
|
|
},
|
|
},
|
|
{
|
|
name: "WithCloseOnContextDone",
|
|
with: func(c RuntimeConfig) RuntimeConfig { return c.WithCloseOnContextDone(true) },
|
|
expected: &runtimeConfig{ensureTermination: true},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
input := &runtimeConfig{}
|
|
rc := tc.with(input)
|
|
require.Equal(t, tc.expected, rc)
|
|
// The source wasn't modified
|
|
require.Equal(t, &runtimeConfig{}, input)
|
|
})
|
|
}
|
|
|
|
t.Run("memoryLimitPages invalid panics", func(t *testing.T) {
|
|
err := require.CapturePanic(func() {
|
|
input := &runtimeConfig{}
|
|
input.WithMemoryLimitPages(wasm.MemoryLimitPages + 1)
|
|
})
|
|
require.EqualError(t, err, "memoryLimitPages invalid: 65537 > 65536")
|
|
})
|
|
}
|
|
|
|
func TestModuleConfig(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
with func(ModuleConfig) ModuleConfig
|
|
expectNameSet bool
|
|
expectedName string
|
|
}{
|
|
{
|
|
name: "WithName default",
|
|
with: func(c ModuleConfig) ModuleConfig {
|
|
return c
|
|
},
|
|
expectNameSet: false,
|
|
expectedName: "",
|
|
},
|
|
{
|
|
name: "WithName",
|
|
with: func(c ModuleConfig) ModuleConfig {
|
|
return c.WithName("wazero")
|
|
},
|
|
expectNameSet: true,
|
|
expectedName: "wazero",
|
|
},
|
|
{
|
|
name: "WithName empty",
|
|
with: func(c ModuleConfig) ModuleConfig {
|
|
return c.WithName("")
|
|
},
|
|
expectNameSet: true,
|
|
expectedName: "",
|
|
},
|
|
{
|
|
name: "WithName twice",
|
|
with: func(c ModuleConfig) ModuleConfig {
|
|
return c.WithName("wazero").WithName("wa0")
|
|
},
|
|
expectNameSet: true,
|
|
expectedName: "wa0",
|
|
},
|
|
{
|
|
name: "WithName can clear",
|
|
with: func(c ModuleConfig) ModuleConfig {
|
|
return c.WithName("wazero").WithName("")
|
|
},
|
|
expectNameSet: true,
|
|
expectedName: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
input := NewModuleConfig()
|
|
rc := tc.with(input)
|
|
require.Equal(t, tc.expectNameSet, rc.(*moduleConfig).nameSet)
|
|
require.Equal(t, tc.expectedName, rc.(*moduleConfig).name)
|
|
// The source wasn't modified
|
|
require.Equal(t, NewModuleConfig(), input)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestModuleConfig_toSysContext only tests the cases that change the inputs to
|
|
// sys.NewContext.
|
|
func TestModuleConfig_toSysContext(t *testing.T) {
|
|
base := NewModuleConfig()
|
|
|
|
tests := []struct {
|
|
name string
|
|
input func() (mc ModuleConfig, verify func(t *testing.T, sys *internalsys.Context))
|
|
}{
|
|
{
|
|
name: "empty",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
return base, func(t *testing.T, sys *internalsys.Context) { require.NotNil(t, sys) }
|
|
},
|
|
},
|
|
{
|
|
name: "WithNanotime",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithNanotime(func() int64 { return 1234567 }, 54321)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
require.Equal(t, 1234567, int(sys.Nanotime()))
|
|
require.Equal(t, 54321, int(sys.NanotimeResolution()))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithSysNanotime",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithSysNanotime()
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
require.Equal(t, int(1), int(sys.NanotimeResolution()))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithWalltime",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithWalltime(func() (sec int64, nsec int32) { return 5, 10 }, 54321)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
actualSec, actualNano := sys.Walltime()
|
|
require.Equal(t, 5, int(actualSec))
|
|
require.Equal(t, 10, int(actualNano))
|
|
require.Equal(t, 54321, int(sys.WalltimeResolution()))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithSysWalltime",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithSysWalltime()
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
require.Equal(t, int(time.Microsecond.Nanoseconds()), int(sys.WalltimeResolution()))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithArgs empty",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithArgs()
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
args := sys.Args()
|
|
require.Equal(t, 0, len(args))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithArgs",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithArgs("a", "bc")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
args := sys.Args()
|
|
require.Equal(t, 2, len(args))
|
|
require.Equal(t, "a", string(args[0]))
|
|
require.Equal(t, "bc", string(args[1]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithArgs empty ok", // Particularly argv[0] can be empty, and we have no rules about others.
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithArgs("", "bc")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
args := sys.Args()
|
|
require.Equal(t, 2, len(args))
|
|
require.Equal(t, "", string(args[0]))
|
|
require.Equal(t, "bc", string(args[1]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithArgs second call overwrites",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithArgs("a", "bc").WithArgs("bc", "a")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
args := sys.Args()
|
|
require.Equal(t, 2, len(args))
|
|
require.Equal(t, "bc", string(args[0]))
|
|
require.Equal(t, "a", string(args[1]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithEnv",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithEnv("a", "b")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
envs := sys.Environ()
|
|
require.Equal(t, 1, len(envs))
|
|
require.Equal(t, "a=b", string(envs[0]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithEnv empty value",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithEnv("a", "")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
envs := sys.Environ()
|
|
require.Equal(t, 1, len(envs))
|
|
require.Equal(t, "a=", string(envs[0]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithEnv twice",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithEnv("a", "b").WithEnv("c", "de")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
envs := sys.Environ()
|
|
require.Equal(t, 2, len(envs))
|
|
require.Equal(t, "a=b", string(envs[0]))
|
|
require.Equal(t, "c=de", string(envs[1]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithEnv overwrites",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithEnv("a", "bc").WithEnv("c", "de").WithEnv("a", "ff")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
envs := sys.Environ()
|
|
require.Equal(t, 2, len(envs))
|
|
require.Equal(t, "a=ff", string(envs[0]))
|
|
require.Equal(t, "c=de", string(envs[1]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithEnv twice",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithEnv("a", "b").WithEnv("c", "de")
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
envs := sys.Environ()
|
|
require.Equal(t, 2, len(envs))
|
|
require.Equal(t, "a=b", string(envs[0]))
|
|
require.Equal(t, "c=de", string(envs[1]))
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithFS",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
testFS := &testfs.FS{}
|
|
config := base.WithFS(testFS)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
rootfs := sys.FS().RootFS()
|
|
require.Equal(t, sysfs.Adapt(testFS), rootfs)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithFS overwrites",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
testFS, testFS2 := &testfs.FS{}, &testfs.FS{}
|
|
config := base.WithFS(testFS).WithFS(testFS2)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
rootfs := sys.FS().RootFS()
|
|
require.Equal(t, sysfs.Adapt(testFS2), rootfs)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithFS nil",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithFS(nil)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
rootfs := sys.FS().RootFS()
|
|
require.Equal(t, sysfs.Adapt(nil), rootfs)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithRandSource",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
r := bytes.NewReader([]byte{1, 2, 3, 4})
|
|
config := base.WithRandSource(r)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
actual := sys.RandSource()
|
|
require.Equal(t, r, actual)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "WithRandSource nil",
|
|
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
|
config := base.WithRandSource(nil)
|
|
return config, func(t *testing.T, sys *internalsys.Context) {
|
|
actual := sys.RandSource()
|
|
require.Equal(t, platform.NewFakeRandSource(), actual)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
config, verify := tc.input()
|
|
actual, err := config.(*moduleConfig).toSysContext()
|
|
require.NoError(t, err)
|
|
verify(t, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestModuleConfig_toSysContext_WithWalltime has to test differently because we can't
|
|
// compare function pointers when functions are passed by value.
|
|
func TestModuleConfig_toSysContext_WithWalltime(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input ModuleConfig
|
|
expectedSec int64
|
|
expectedNsec int32
|
|
expectedResolution sys.ClockResolution
|
|
expectedErr string
|
|
}{
|
|
{
|
|
name: "ok",
|
|
input: NewModuleConfig().
|
|
WithWalltime(func() (sec int64, nsec int32) {
|
|
return 1, 2
|
|
}, 3),
|
|
expectedSec: 1,
|
|
expectedNsec: 2,
|
|
expectedResolution: 3,
|
|
},
|
|
{
|
|
name: "overwrites",
|
|
input: NewModuleConfig().
|
|
WithWalltime(func() (sec int64, nsec int32) {
|
|
return 3, 4
|
|
}, 5).
|
|
WithWalltime(func() (sec int64, nsec int32) {
|
|
return 1, 2
|
|
}, 3),
|
|
expectedSec: 1,
|
|
expectedNsec: 2,
|
|
expectedResolution: 3,
|
|
},
|
|
{
|
|
name: "invalid resolution",
|
|
input: NewModuleConfig().
|
|
WithWalltime(func() (sec int64, nsec int32) {
|
|
return 1, 2
|
|
}, 0),
|
|
expectedErr: "invalid Walltime resolution: 0",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
sysCtx, err := tc.input.(*moduleConfig).toSysContext()
|
|
if tc.expectedErr == "" {
|
|
require.Nil(t, err)
|
|
sec, nsec := sysCtx.Walltime()
|
|
require.Equal(t, tc.expectedSec, sec)
|
|
require.Equal(t, tc.expectedNsec, nsec)
|
|
require.Equal(t, tc.expectedResolution, sysCtx.WalltimeResolution())
|
|
} else {
|
|
require.EqualError(t, err, tc.expectedErr)
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("context", func(t *testing.T) {
|
|
sysCtx, err := NewModuleConfig().
|
|
WithWalltime(func() (sec int64, nsec int32) {
|
|
return 1, 2
|
|
}, 3).(*moduleConfig).toSysContext()
|
|
require.NoError(t, err)
|
|
sec, nsec := sysCtx.Walltime()
|
|
// If below pass, the context was correct!
|
|
require.Equal(t, int64(1), sec)
|
|
require.Equal(t, int32(2), nsec)
|
|
})
|
|
}
|
|
|
|
// TestModuleConfig_toSysContext_WithNanotime has to test differently because we can't
|
|
// compare function pointers when functions are passed by value.
|
|
func TestModuleConfig_toSysContext_WithNanotime(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input ModuleConfig
|
|
expectedNanos int64
|
|
expectedResolution sys.ClockResolution
|
|
expectedErr string
|
|
}{
|
|
{
|
|
name: "ok",
|
|
input: NewModuleConfig().
|
|
WithNanotime(func() int64 {
|
|
return 1
|
|
}, 2),
|
|
expectedNanos: 1,
|
|
expectedResolution: 2,
|
|
},
|
|
{
|
|
name: "overwrites",
|
|
input: NewModuleConfig().
|
|
WithNanotime(func() int64 {
|
|
return 3
|
|
}, 4).
|
|
WithNanotime(func() int64 {
|
|
return 1
|
|
}, 2),
|
|
expectedNanos: 1,
|
|
expectedResolution: 2,
|
|
},
|
|
{
|
|
name: "invalid resolution",
|
|
input: NewModuleConfig().
|
|
WithNanotime(func() int64 {
|
|
return 1
|
|
}, 0),
|
|
expectedErr: "invalid Nanotime resolution: 0",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
sysCtx, err := tc.input.(*moduleConfig).toSysContext()
|
|
if tc.expectedErr == "" {
|
|
require.Nil(t, err)
|
|
nanos := sysCtx.Nanotime()
|
|
require.Equal(t, tc.expectedNanos, nanos)
|
|
require.Equal(t, tc.expectedResolution, sysCtx.NanotimeResolution())
|
|
} else {
|
|
require.EqualError(t, err, tc.expectedErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestModuleConfig_toSysContext_WithNanosleep has to test differently because
|
|
// we can't compare function pointers when functions are passed by value.
|
|
func TestModuleConfig_toSysContext_WithNanosleep(t *testing.T) {
|
|
sysCtx, err := NewModuleConfig().
|
|
WithNanosleep(func(ns int64) {
|
|
require.Equal(t, int64(2), ns)
|
|
}).(*moduleConfig).toSysContext()
|
|
require.NoError(t, err)
|
|
sysCtx.Nanosleep(2)
|
|
}
|
|
|
|
// TestModuleConfig_toSysContext_WithOsyield has to test differently because
|
|
// we can't compare function pointers when functions are passed by value.
|
|
func TestModuleConfig_toSysContext_WithOsyield(t *testing.T) {
|
|
var yielded bool
|
|
sysCtx, err := NewModuleConfig().
|
|
WithOsyield(func() {
|
|
yielded = true
|
|
}).(*moduleConfig).toSysContext()
|
|
require.NoError(t, err)
|
|
sysCtx.Osyield()
|
|
require.True(t, yielded)
|
|
}
|
|
|
|
func TestModuleConfig_toSysContext_Errors(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input ModuleConfig
|
|
expectedErr string
|
|
}{
|
|
{
|
|
name: "WithArgs arg contains NUL",
|
|
input: NewModuleConfig().WithArgs("", string([]byte{'a', 0})),
|
|
expectedErr: "args invalid: contains NUL character",
|
|
},
|
|
{
|
|
name: "WithEnv key contains NUL",
|
|
input: NewModuleConfig().WithEnv(string([]byte{'a', 0}), "a"),
|
|
expectedErr: "environ invalid: contains NUL character",
|
|
},
|
|
{
|
|
name: "WithEnv value contains NUL",
|
|
input: NewModuleConfig().WithEnv("a", string([]byte{'a', 0})),
|
|
expectedErr: "environ invalid: contains NUL character",
|
|
},
|
|
{
|
|
name: "WithEnv key contains equals",
|
|
input: NewModuleConfig().WithEnv("a=", "a"),
|
|
expectedErr: "environ invalid: key contains '=' character",
|
|
},
|
|
{
|
|
name: "WithEnv empty key",
|
|
input: NewModuleConfig().WithEnv("", "a"),
|
|
expectedErr: "environ invalid: empty key",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
_, err := tc.input.(*moduleConfig).toSysContext()
|
|
require.EqualError(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestModuleConfig_clone(t *testing.T) {
|
|
mc := NewModuleConfig().(*moduleConfig)
|
|
cloned := mc.clone()
|
|
|
|
// Make post-clone changes
|
|
mc.fsConfig = NewFSConfig().WithFSMount(fstest.FS, "/")
|
|
mc.environKeys["2"] = 2
|
|
|
|
cloned.environKeys["1"] = 1
|
|
|
|
// Ensure the maps are not shared
|
|
require.Equal(t, map[string]int{"2": 2}, mc.environKeys)
|
|
require.Equal(t, map[string]int{"1": 1}, cloned.environKeys)
|
|
|
|
// Ensure the fs is not shared
|
|
require.Nil(t, cloned.fsConfig)
|
|
}
|
|
|
|
func Test_compiledModule_Name(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input *compiledModule
|
|
expected string
|
|
}{
|
|
{
|
|
name: "no name section",
|
|
input: &compiledModule{module: &wasm.Module{}},
|
|
},
|
|
{
|
|
name: "empty name",
|
|
input: &compiledModule{module: &wasm.Module{NameSection: &wasm.NameSection{}}},
|
|
},
|
|
{
|
|
name: "name",
|
|
input: &compiledModule{module: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "foo"}}},
|
|
expected: "foo",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
require.Equal(t, tc.expected, tc.input.Name())
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_compiledModule_CustomSections(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input *compiledModule
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "no custom section",
|
|
input: &compiledModule{module: &wasm.Module{}},
|
|
expected: []string{},
|
|
},
|
|
{
|
|
name: "name",
|
|
input: &compiledModule{module: &wasm.Module{
|
|
CustomSections: []*wasm.CustomSection{
|
|
{Name: "custom1"},
|
|
{Name: "custom2"},
|
|
{Name: "customDup"},
|
|
{Name: "customDup"},
|
|
},
|
|
}},
|
|
expected: []string{
|
|
"custom1",
|
|
"custom2",
|
|
"customDup",
|
|
"customDup",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tc := tt
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
customSections := tc.input.CustomSections()
|
|
require.Equal(t, len(tc.expected), len(customSections))
|
|
for i := 0; i < len(tc.expected); i++ {
|
|
require.Equal(t, tc.expected[i], customSections[i].Name())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_compiledModule_Close(t *testing.T) {
|
|
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
|
|
e := &mockEngine{name: "1", cachedModules: map[*wasm.Module]struct{}{}}
|
|
|
|
var cs []*compiledModule
|
|
for i := 0; i < 10; i++ {
|
|
m := &wasm.Module{}
|
|
err := e.CompileModule(ctx, m, nil, false)
|
|
require.NoError(t, err)
|
|
cs = append(cs, &compiledModule{module: m, compiledEngine: e})
|
|
}
|
|
|
|
// Before Close.
|
|
require.Equal(t, 10, len(e.cachedModules))
|
|
|
|
for _, c := range cs {
|
|
require.NoError(t, c.Close(ctx))
|
|
}
|
|
|
|
// After Close.
|
|
require.Zero(t, len(e.cachedModules))
|
|
}
|
|
}
|
|
|
|
func TestNewRuntimeConfig(t *testing.T) {
|
|
c, ok := NewRuntimeConfig().(*runtimeConfig)
|
|
require.True(t, ok)
|
|
// Should be cloned from the source.
|
|
require.NotEqual(t, engineLessConfig, c)
|
|
// Ensures if the correct engine is selected.
|
|
if platform.CompilerSupported() {
|
|
require.Equal(t, engineKindCompiler, c.engineKind)
|
|
} else {
|
|
require.Equal(t, engineKindInterpreter, c.engineKind)
|
|
}
|
|
}
|