Generates typeIDs at compilation time (#1218)

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
Takeshi Yoneda
2023-03-09 20:46:08 -08:00
committed by GitHub
parent 4d90a5c364
commit 24e4d5dfa0
13 changed files with 126 additions and 58 deletions

View File

@@ -328,6 +328,13 @@ func (b *hostModuleBuilder) Compile(ctx context.Context) (CompiledModule, error)
return nil, err
}
// typeIDs are static and compile-time known.
typeIDs, err := b.r.store.GetFunctionTypeIDs(module.TypeSection)
if err != nil {
return nil, err
}
c.typeIDs = typeIDs
return c, nil
}

View File

@@ -279,6 +279,11 @@ func TestNewHostModuleBuilder_Compile(t *testing.T) {
require.Equal(t, b.r.store.Engine, m.compiledEngine)
// TypeIDs must be assigned to compiledModule.
expTypeIDs, err := b.r.store.GetFunctionTypeIDs(tc.expected.TypeSection)
require.NoError(t, err)
require.Equal(t, expTypeIDs, m.typeIDs)
// Built module must be instantiable by Engine.
mod, err := b.r.InstantiateModule(testCtx, m, NewModuleConfig())
require.NoError(t, err)
@@ -353,6 +358,8 @@ func requireHostModuleEquals(t *testing.T, expected, actual *wasm.Module) {
// `require.Equal(t, expected, actual)` fails reflect pointers don't match, so brute compare:
for _, tp := range expected.TypeSection {
tp.CacheNumInUint64()
// When creating the compiled module, we get the type IDs for types, which results in caching type keys.
_ = tp.String()
}
require.Equal(t, expected.TypeSection, actual.TypeSection)
require.Equal(t, expected.ImportSection, actual.ImportSection)

View File

@@ -27,6 +27,18 @@ func TestCompilationCache(t *testing.T) {
foo, bar := getCacheSharedRuntimes(ctx, t)
cacheInst := foo.cache
// Create a different type id on the bar's store so that we can emulate that bar instantiated the module before facWasm.
_, err := bar.store.GetFunctionTypeIDs(
// Arbitrary one is fine as long as it is not used in facWasm.
[]*wasm.FunctionType{{Params: []wasm.ValueType{
wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32,
wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeI32,
wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeI32,
wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeV128, wasm.ValueTypeI32, wasm.ValueTypeI32,
wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32, wasm.ValueTypeI32,
}}})
require.NoError(t, err)
// add interpreter first, to ensure compiler support isn't order dependent
eng := foo.cache.engs[engineKindInterpreter]
if platform.CompilerSupported() {
@@ -41,8 +53,12 @@ func TestCompilationCache(t *testing.T) {
barCompiled, err := bar.CompileModule(ctx, facWasm)
require.NoError(t, err)
// Ensures compiled modules are the same.
require.Equal(t, compiled, barCompiled)
// Ensures compiled modules are the same modulo type IDs, which is unique per store.
require.Equal(t, compiled.(*compiledModule).module, barCompiled.(*compiledModule).module)
require.Equal(t, compiled.(*compiledModule).closeWithModule, barCompiled.(*compiledModule).closeWithModule)
require.Equal(t, compiled.(*compiledModule).compiledEngine, barCompiled.(*compiledModule).compiledEngine)
// TypeIDs must be different as we create a different type ID on bar beforehand.
require.NotEqual(t, compiled.(*compiledModule).typeIDs, barCompiled.(*compiledModule).typeIDs)
// Two runtimes are completely separate except the compilation cache,
// therefore it should be ok to instantiate the same name module for each of them.

View File

@@ -333,6 +333,7 @@ type compiledModule struct {
compiledEngine wasm.Engine
// closeWithModule prevents leaking compiled code when a module is compiled implicitly.
closeWithModule bool
typeIDs []wasm.FunctionTypeID
}
// Name implements CompiledModule.Name

View File

@@ -264,7 +264,10 @@ func TestCompiler_SliceAllocatedOnHeap(t *testing.T) {
err = s.Engine.CompileModule(testCtx, hm, nil, false)
require.NoError(t, err)
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil)
typeIDs, err := s.GetFunctionTypeIDs(hm.TypeSection)
require.NoError(t, err)
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil, typeIDs)
require.NoError(t, err)
const stackCorruption = "value_stack_corruption"
@@ -320,7 +323,10 @@ func TestCompiler_SliceAllocatedOnHeap(t *testing.T) {
err = s.Engine.CompileModule(testCtx, m, nil, false)
require.NoError(t, err)
mi, err := s.Instantiate(testCtx, m, t.Name(), nil)
typeIDs, err = s.GetFunctionTypeIDs(m.TypeSection)
require.NoError(t, err)
mi, err := s.Instantiate(testCtx, m, t.Name(), nil, typeIDs)
require.NoError(t, err)
for _, fnName := range []string{stackCorruption, callStackCorruption} {

View File

@@ -337,7 +337,10 @@ func addSpectestModule(t *testing.T, ctx context.Context, s *wasm.Store, enabled
err = s.Engine.CompileModule(ctx, mod, nil, false)
require.NoError(t, err)
_, err = s.Instantiate(ctx, mod, mod.NameSection.ModuleName, sys.DefaultContext(nil))
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
require.NoError(t, err)
_, err = s.Instantiate(ctx, mod, mod.NameSection.ModuleName, sys.DefaultContext(nil), typeIDs)
require.NoError(t, err)
}
@@ -404,7 +407,10 @@ func Run(t *testing.T, testDataFS embed.FS, ctx context.Context, fc filecache.Ca
err = s.Engine.CompileModule(ctx, mod, nil, false)
require.NoError(t, err, msg)
_, err = s.Instantiate(ctx, mod, moduleName, nil)
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
require.NoError(t, err)
_, err = s.Instantiate(ctx, mod, moduleName, nil, typeIDs)
lastInstantiatedModuleName = moduleName
require.NoError(t, err)
case "register":
@@ -542,7 +548,10 @@ func Run(t *testing.T, testDataFS embed.FS, ctx context.Context, fc filecache.Ca
err = s.Engine.CompileModule(ctx, mod, nil, false)
require.NoError(t, err, msg)
_, err = s.Instantiate(ctx, mod, t.Name(), nil)
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
require.NoError(t, err)
_, err = s.Instantiate(ctx, mod, t.Name(), nil, typeIDs)
require.NoError(t, err, msg)
} else {
requireInstantiationError(t, ctx, s, buf, msg)
@@ -578,7 +587,10 @@ func requireInstantiationError(t *testing.T, ctx context.Context, s *wasm.Store,
return
}
_, err = s.Instantiate(ctx, mod, t.Name(), nil)
typeIDs, err := s.GetFunctionTypeIDs(mod.TypeSection)
require.NoError(t, err)
_, err = s.Instantiate(ctx, mod, t.Name(), nil, typeIDs)
require.Error(t, err, msg)
}

View File

@@ -74,7 +74,10 @@ func RunTestEngine_MemoryGrowInRecursiveCall(t *testing.T, et EngineTester) {
err = s.Engine.CompileModule(testCtx, hm, nil, false)
require.NoError(t, err)
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil)
typeIDs, err := s.GetFunctionTypeIDs(hm.TypeSection)
require.NoError(t, err)
_, err = s.Instantiate(testCtx, hm, hostModuleName, nil, typeIDs)
require.NoError(t, err)
m := &wasm.Module{
@@ -106,7 +109,10 @@ func RunTestEngine_MemoryGrowInRecursiveCall(t *testing.T, et EngineTester) {
err = s.Engine.CompileModule(testCtx, m, nil, false)
require.NoError(t, err)
inst, err := s.Instantiate(testCtx, m, t.Name(), nil)
typeIDs, err = s.GetFunctionTypeIDs(m.TypeSection)
require.NoError(t, err)
inst, err := s.Instantiate(testCtx, m, t.Name(), nil, typeIDs)
require.NoError(t, err)
growFn = inst.Function(2)

View File

@@ -39,7 +39,7 @@ func TestCallContext_String(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
// Ensure paths that can create the host module can see the name.
m, err := s.Instantiate(testCtx, &Module{}, tc.moduleName, nil)
m, err := s.Instantiate(testCtx, &Module{}, tc.moduleName, nil, nil)
defer m.Close(testCtx) //nolint
require.NoError(t, err)
@@ -78,7 +78,7 @@ func TestCallContext_Close(t *testing.T) {
t.Run(fmt.Sprintf("%s calls ns.CloseWithExitCode(module.name))", tc.name), func(t *testing.T) {
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
moduleName := t.Name()
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil)
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil, nil)
require.NoError(t, err)
// We use side effects to see if Close called ns.CloseWithExitCode (without repeating store_test.go).
@@ -107,7 +107,7 @@ func TestCallContext_Close(t *testing.T) {
_, err := fsCtx.OpenFile(testFS, "/foo", os.O_RDONLY, 0)
require.NoError(t, err)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
require.NoError(t, err)
// We use side effects to determine if Close in fact called Context.Close (without repeating sys_test.go).
@@ -142,7 +142,7 @@ func TestCallContext_Close(t *testing.T) {
_, err := fsCtx.OpenFile(testFS, "/foo", os.O_RDONLY, 0)
require.NoError(t, err)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
require.NoError(t, err)
require.EqualError(t, m.Close(testCtx), "error closing")
@@ -182,7 +182,7 @@ func TestCallContext_CallDynamic(t *testing.T) {
t.Run(fmt.Sprintf("%s calls ns.CloseWithExitCode(module.name))", tc.name), func(t *testing.T) {
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
moduleName := t.Name()
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil)
m, err := s.Instantiate(ctx, &Module{}, moduleName, nil, nil)
require.NoError(t, err)
// We use side effects to see if Close called ns.CloseWithExitCode (without repeating store_test.go).
@@ -211,7 +211,7 @@ func TestCallContext_CallDynamic(t *testing.T) {
_, err := fsCtx.OpenFile(testFS, "/foo", os.O_RDONLY, 0)
require.NoError(t, err)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
require.NoError(t, err)
// We use side effects to determine if Close in fact called Context.Close (without repeating sys_test.go).
@@ -240,7 +240,7 @@ func TestCallContext_CallDynamic(t *testing.T) {
_, err := fsCtx.OpenFile(testFS, path, os.O_RDONLY, 0)
require.NoError(t, err)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx)
m, err := s.Instantiate(testCtx, &Module{}, t.Name(), sysCtx, nil)
require.NoError(t, err)
require.EqualError(t, m.Close(testCtx), "error closing")

View File

@@ -296,7 +296,7 @@ func TestPublicModule_Global(t *testing.T) {
s := newStore()
t.Run(tc.name, func(t *testing.T) {
// Instantiate the module and get the export of the above global
module, err := s.Instantiate(context.Background(), tc.module, t.Name(), nil)
module, err := s.Instantiate(context.Background(), tc.module, t.Name(), nil, nil)
require.NoError(t, err)
if global := module.ExportedGlobal("global"); tc.expected != nil {

View File

@@ -286,6 +286,7 @@ func (s *Store) Instantiate(
module *Module,
name string,
sys *internalsys.Context,
typeIDs []FunctionTypeID,
) (*CallContext, error) {
// Collect any imported modules to avoid locking the store too long.
importedModuleNames := map[string]struct{}{}
@@ -305,7 +306,7 @@ func (s *Store) Instantiate(
}
// Instantiate the module and add it to the store so that other modules can import it.
if callCtx, err := s.instantiate(ctx, module, name, sys, importedModules); err != nil {
if callCtx, err := s.instantiate(ctx, module, name, sys, importedModules, typeIDs); err != nil {
_ = s.deleteModule(name)
return nil, err
} else {
@@ -325,12 +326,8 @@ func (s *Store) instantiate(
name string,
sysCtx *internalsys.Context,
modules map[string]*ModuleInstance,
typeIDs []FunctionTypeID,
) (*CallContext, error) {
typeIDs, err := s.getFunctionTypeIDs(module.TypeSection)
if err != nil {
return nil, err
}
importedFunctions, importedGlobals, importedTables, importedMemory, err := resolveImports(module, modules)
if err != nil {
return nil, err
@@ -562,7 +559,7 @@ func executeConstExpression(importedGlobals []*GlobalInstance, expr *ConstantExp
return
}
func (s *Store) getFunctionTypeIDs(ts []*FunctionType) ([]FunctionTypeID, error) {
func (s *Store) GetFunctionTypeIDs(ts []*FunctionType) ([]FunctionTypeID, error) {
ret := make([]FunctionTypeID, len(ts))
for i, t := range ts {
inst, err := s.getFunctionTypeID(t)

View File

@@ -80,7 +80,7 @@ func TestModuleInstance_Memory(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
s := newStore()
instance, err := s.Instantiate(testCtx, tc.input, "test", nil)
instance, err := s.Instantiate(testCtx, tc.input, "test", nil, nil)
require.NoError(t, err)
mem := instance.ExportedMemory("memory")
@@ -109,7 +109,7 @@ func TestStore_Instantiate(t *testing.T) {
require.NoError(t, err)
sysCtx := sys.DefaultContext(nil)
mod, err := s.Instantiate(testCtx, m, "", sysCtx)
mod, err := s.Instantiate(testCtx, m, "", sysCtx, []FunctionTypeID{0})
require.NoError(t, err)
defer mod.Close(testCtx)
@@ -150,7 +150,7 @@ func TestStore_CloseWithExitCode(t *testing.T) {
CodeSection: []*Code{{Body: []byte{OpcodeEnd}}},
ExportSection: []*Export{{Type: ExternTypeFunc, Index: 0, Name: "fn"}},
FunctionDefinitionSection: []*FunctionDefinition{{funcType: v_v}},
}, importedModuleName, nil)
}, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
m2, err := s.Instantiate(testCtx, &Module{
@@ -160,7 +160,7 @@ func TestStore_CloseWithExitCode(t *testing.T) {
MemoryDefinitionSection: []*MemoryDefinition{{}},
GlobalSection: []*Global{{Type: &GlobalType{}, Init: &ConstantExpression{Opcode: OpcodeI32Const, Data: const1}}},
TableSection: []*Table{{Min: 10}},
}, importingModuleName, nil)
}, importingModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
if tc.testClosed {
@@ -187,7 +187,7 @@ func TestStore_hammer(t *testing.T) {
require.NoError(t, err)
s := newStore()
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil)
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
_, ok := s.nameToNode[imported.Name()]
@@ -219,7 +219,7 @@ func TestStore_hammer(t *testing.T) {
N = 100
}
hammer.NewHammer(t, P, N).Run(func(name string) {
mod, instantiateErr := s.Instantiate(testCtx, importingModule, name, sys.DefaultContext(nil))
mod, instantiateErr := s.Instantiate(testCtx, importingModule, name, sys.DefaultContext(nil), []FunctionTypeID{0})
require.NoError(t, instantiateErr)
require.NoError(t, mod.Close(testCtx))
}, nil)
@@ -241,7 +241,7 @@ func TestStore_hammer_close(t *testing.T) {
require.NoError(t, err)
s := newStore()
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil)
imported, err := s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
_, ok := s.nameToNode[imported.Name()]
@@ -267,7 +267,7 @@ func TestStore_hammer_close(t *testing.T) {
const instCount = 10000
instances := make([]api.Module, instCount)
for i := 0; i < instCount; i++ {
mod, instantiateErr := s.Instantiate(testCtx, importingModule, strconv.Itoa(i), sys.DefaultContext(nil))
mod, instantiateErr := s.Instantiate(testCtx, importingModule, strconv.Itoa(i), sys.DefaultContext(nil), []FunctionTypeID{0})
require.NoError(t, instantiateErr)
instances[i] = mod
}
@@ -301,17 +301,17 @@ func TestStore_Instantiate_Errors(t *testing.T) {
t.Run("Fails if module name already in use", func(t *testing.T) {
s := newStore()
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
// Trying to register it again should fail
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.EqualError(t, err, "module[imported] has already been instantiated")
})
t.Run("fail resolve import", func(t *testing.T) {
s := newStore()
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
hm := s.nameToNode[importedModuleName]
@@ -325,14 +325,14 @@ func TestStore_Instantiate_Errors(t *testing.T) {
// But the second one tries to import uninitialized-module ->
{Type: ExternTypeFunc, Module: "non-exist", Name: "fn", DescFunc: 0},
},
}, importingModuleName, nil)
}, importingModuleName, nil, nil)
require.EqualError(t, err, "module[non-exist] not instantiated")
})
t.Run("creating engine failed", func(t *testing.T) {
s := newStore()
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
hm := s.nameToNode[importedModuleName]
@@ -354,7 +354,7 @@ func TestStore_Instantiate_Errors(t *testing.T) {
}
importingModule.BuildFunctionDefinitions()
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil)
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil, []FunctionTypeID{0})
require.EqualError(t, err, "some engine creation error")
})
@@ -363,7 +363,7 @@ func TestStore_Instantiate_Errors(t *testing.T) {
engine := s.Engine.(*mockEngine)
engine.callFailIndex = 1
_, err = s.Instantiate(testCtx, m, importedModuleName, nil)
_, err = s.Instantiate(testCtx, m, importedModuleName, nil, []FunctionTypeID{0})
require.NoError(t, err)
hm := s.nameToNode[importedModuleName]
@@ -381,7 +381,7 @@ func TestStore_Instantiate_Errors(t *testing.T) {
}
importingModule.BuildFunctionDefinitions()
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil)
_, err = s.Instantiate(testCtx, importingModule, importingModuleName, nil, []FunctionTypeID{0})
require.EqualError(t, err, "start function[1] failed: call failed")
})
}

View File

@@ -203,6 +203,13 @@ func (r *runtime) CompileModule(ctx context.Context, binary []byte) (CompiledMod
c := &compiledModule{module: internal, compiledEngine: r.store.Engine}
// typeIDs are static and compile-time known.
typeIDs, err := r.store.GetFunctionTypeIDs(internal.TypeSection)
if err != nil {
return nil, err
}
c.typeIDs = typeIDs
listeners, err := buildListeners(ctx, internal)
if err != nil {
return nil, err
@@ -276,7 +283,7 @@ func (r *runtime) InstantiateModule(
}
// Instantiate the module.
mod, err = r.store.Instantiate(ctx, code.module, name, sysCtx)
mod, err = r.store.Instantiate(ctx, code.module, name, sysCtx, code.typeIDs)
if err != nil {
// If there was an error, don't leak the compiled module.
if code.closeWithModule {

View File

@@ -44,32 +44,32 @@ func TestRuntime_CompileModule(t *testing.T) {
tests := []struct {
name string
runtime Runtime
wasm []byte
wasm *wasm.Module
moduleBuilder HostModuleBuilder
expected func(CompiledModule)
}{
{
name: "no name section",
wasm: binaryencoding.EncodeModule(&wasm.Module{}),
wasm: &wasm.Module{},
},
{
name: "empty NameSection.ModuleName",
wasm: binaryencoding.EncodeModule(&wasm.Module{NameSection: &wasm.NameSection{}}),
wasm: &wasm.Module{NameSection: &wasm.NameSection{}},
},
{
name: "NameSection.ModuleName",
wasm: binaryencoding.EncodeModule(&wasm.Module{NameSection: &wasm.NameSection{ModuleName: "test"}}),
wasm: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "test"}},
expected: func(compiled CompiledModule) {
require.Equal(t, "test", compiled.Name())
},
},
{
name: "FunctionSection, but not exported",
wasm: binaryencoding.EncodeModule(&wasm.Module{
wasm: &wasm.Module{
TypeSection: []*wasm.FunctionType{{Params: []api.ValueType{api.ValueTypeI32}}},
FunctionSection: []wasm.Index{0},
CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}},
}),
},
expected: func(compiled CompiledModule) {
require.Nil(t, compiled.ImportedFunctions())
require.Zero(t, len(compiled.ExportedFunctions()))
@@ -77,7 +77,7 @@ func TestRuntime_CompileModule(t *testing.T) {
},
{
name: "FunctionSection exported",
wasm: binaryencoding.EncodeModule(&wasm.Module{
wasm: &wasm.Module{
TypeSection: []*wasm.FunctionType{{Params: []api.ValueType{api.ValueTypeI32}}},
FunctionSection: []wasm.Index{0},
CodeSection: []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}},
@@ -86,7 +86,7 @@ func TestRuntime_CompileModule(t *testing.T) {
Name: "function",
Index: 0,
}},
}),
},
expected: func(compiled CompiledModule) {
require.Nil(t, compiled.ImportedFunctions())
f := compiled.ExportedFunctions()["function"]
@@ -95,9 +95,9 @@ func TestRuntime_CompileModule(t *testing.T) {
},
{
name: "MemorySection, but not exported",
wasm: binaryencoding.EncodeModule(&wasm.Module{
wasm: &wasm.Module{
MemorySection: &wasm.Memory{Min: 2, Max: 3, IsMaxEncoded: true},
}),
},
expected: func(compiled CompiledModule) {
require.Nil(t, compiled.ImportedMemories())
require.Zero(t, len(compiled.ExportedMemories()))
@@ -105,14 +105,14 @@ func TestRuntime_CompileModule(t *testing.T) {
},
{
name: "MemorySection exported",
wasm: binaryencoding.EncodeModule(&wasm.Module{
wasm: &wasm.Module{
MemorySection: &wasm.Memory{Min: 2, Max: 3, IsMaxEncoded: true},
ExportSection: []*wasm.Export{{
Type: wasm.ExternTypeMemory,
Name: "memory",
Index: 0,
}},
}),
},
expected: func(compiled CompiledModule) {
require.Nil(t, compiled.ImportedMemories())
mem := compiled.ExportedMemories()["memory"]
@@ -124,20 +124,29 @@ func TestRuntime_CompileModule(t *testing.T) {
},
}
r := NewRuntime(testCtx)
defer r.Close(testCtx)
_r := NewRuntime(testCtx)
defer _r.Close(testCtx)
r := _r.(*runtime)
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
m, err := r.CompileModule(testCtx, tc.wasm)
bin := binaryencoding.EncodeModule(tc.wasm)
m, err := r.CompileModule(testCtx, bin)
require.NoError(t, err)
if tc.expected == nil {
tc.expected = func(CompiledModule) {}
}
tc.expected(m)
require.Equal(t, r.(*runtime).store.Engine, m.(*compiledModule).compiledEngine)
require.Equal(t, r.store.Engine, m.(*compiledModule).compiledEngine)
// TypeIDs must be assigned to compiledModule.
expTypeIDs, err := r.store.GetFunctionTypeIDs(tc.wasm.TypeSection)
require.NoError(t, err)
require.Equal(t, expTypeIDs, m.(*compiledModule).typeIDs)
})
}
}