Files
wazero/internal/wasm/store_module_list_test.go
Takeshi Yoneda 50723a0fd2 Refactors spectest harness (#1489)
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
2023-05-23 09:59:49 +10:00

183 lines
5.3 KiB
Go

package wasm
import (
"context"
"fmt"
"testing"
"github.com/tetratelabs/wazero/internal/testing/require"
)
func TestStore_registerModule(t *testing.T) {
s := newStore()
m1 := &ModuleInstance{ModuleName: "m1"}
t.Run("adds module", func(t *testing.T) {
require.NoError(t, s.registerModule(m1))
require.Equal(t, map[string]*ModuleInstance{m1.ModuleName: m1}, s.nameToModule)
require.Equal(t, m1, s.moduleList)
require.Equal(t, nameToModuleShrinkThreshold, s.nameToModuleCap)
})
t.Run("adds second module", func(t *testing.T) {
m2 := &ModuleInstance{ModuleName: "m2"}
require.NoError(t, s.registerModule(m2))
require.Equal(t, map[string]*ModuleInstance{m1.ModuleName: m1, m2.ModuleName: m2}, s.nameToModule)
require.Equal(t, m2, s.moduleList)
require.Equal(t, nameToModuleShrinkThreshold, s.nameToModuleCap)
})
t.Run("error on duplicated non anonymous", func(t *testing.T) {
m1Second := &ModuleInstance{ModuleName: "m1"}
require.EqualError(t, s.registerModule(m1Second), "module[m1] has already been instantiated")
})
t.Run("error on closed", func(t *testing.T) {
require.NoError(t, s.CloseWithExitCode(context.Background(), 0))
require.Error(t, s.registerModule(m1))
})
}
func TestStore_deleteModule(t *testing.T) {
s, m1, m2 := newTestStore()
t.Run("delete one module", func(t *testing.T) {
require.NoError(t, s.deleteModule(m2))
// Leaves the other module alone.
require.Equal(t, map[string]*ModuleInstance{m1.ModuleName: m1}, s.nameToModule)
require.Equal(t, m1, s.moduleList)
require.Equal(t, nameToModuleShrinkThreshold, s.nameToModuleCap)
})
t.Run("ok if missing", func(t *testing.T) {
require.NoError(t, s.deleteModule(m2))
})
t.Run("delete last module", func(t *testing.T) {
require.NoError(t, s.deleteModule(m1))
require.Zero(t, len(s.nameToModule))
require.Nil(t, s.moduleList)
require.Equal(t, nameToModuleShrinkThreshold, s.nameToModuleCap)
})
t.Run("delete middle", func(t *testing.T) {
s := newStore()
one, two, three := &ModuleInstance{ModuleName: "1"}, &ModuleInstance{ModuleName: "2"}, &ModuleInstance{ModuleName: "3"}
require.NoError(t, s.registerModule(one))
require.NoError(t, s.registerModule(two))
require.NoError(t, s.registerModule(three))
require.Equal(t, three, s.moduleList)
require.Nil(t, three.prev)
require.Equal(t, two, three.next)
require.Equal(t, two.prev, three)
require.Equal(t, one, two.next)
require.Equal(t, one.prev, two)
require.Nil(t, one.next)
require.NoError(t, s.deleteModule(two))
require.Equal(t, three, s.moduleList)
require.Nil(t, three.prev)
require.Equal(t, one, three.next)
require.Equal(t, one.prev, three)
require.Nil(t, one.next)
})
}
func TestStore_module(t *testing.T) {
s, m1, _ := newTestStore()
t.Run("ok", func(t *testing.T) {
got, err := s.module(m1.ModuleName)
require.NoError(t, err)
require.Equal(t, m1, got)
})
t.Run("unknown", func(t *testing.T) {
got, err := s.module("unknown")
require.Error(t, err)
require.Nil(t, got)
})
t.Run("store closed", func(t *testing.T) {
require.NoError(t, s.CloseWithExitCode(context.Background(), 0))
got, err := s.module(m1.ModuleName)
require.Error(t, err)
require.Nil(t, got)
})
}
func TestStore_nameToModuleCap(t *testing.T) {
t.Run("nameToModuleCap grows beyond initial cap", func(t *testing.T) {
s := newStore()
for i := 0; i < 300; i++ {
require.NoError(t, s.registerModule(&ModuleInstance{ModuleName: fmt.Sprintf("m%d", i)}))
}
require.Equal(t, 300, s.nameToModuleCap)
})
t.Run("nameToModuleCap shrinks by half the cap", func(t *testing.T) {
s := newStore()
for i := 0; i < 400; i++ {
require.NoError(t, s.registerModule(&ModuleInstance{ModuleName: fmt.Sprintf("m%d", i)}))
}
for i := 0; i < 250; i++ {
require.NoError(t, s.deleteModule(s.nameToModule[fmt.Sprintf("m%d", i)]))
}
require.Equal(t, 200, s.nameToModuleCap)
})
t.Run("nameToModuleCap does not shrink below initial size", func(t *testing.T) {
s := newStore()
for i := 0; i < 400; i++ {
require.NoError(t, s.registerModule(&ModuleInstance{ModuleName: fmt.Sprintf("m%d", i)}))
}
for i := 0; i < 350; i++ {
require.NoError(t, s.deleteModule(s.nameToModule[fmt.Sprintf("m%d", i)]))
}
require.Equal(t, nameToModuleShrinkThreshold, s.nameToModuleCap)
})
t.Run("nameToModuleCap does not grow when if nameToModule does not grow", func(t *testing.T) {
s := newStore()
for i := 0; i < 99; i++ {
require.NoError(t, s.registerModule(&ModuleInstance{ModuleName: fmt.Sprintf("m%d", i)}))
}
for i := 0; i < 400; i++ {
require.NoError(t, s.registerModule(&ModuleInstance{ModuleName: fmt.Sprintf("m%d", i+99)}))
require.NoError(t, s.deleteModule(s.nameToModule[fmt.Sprintf("m%d", i+99)]))
require.Equal(t, nameToModuleShrinkThreshold, s.nameToModuleCap)
}
})
}
func TestStore_Module(t *testing.T) {
s, m1, _ := newTestStore()
t.Run("ok", func(t *testing.T) {
require.Equal(t, m1, s.Module(m1.ModuleName))
})
t.Run("unknown", func(t *testing.T) {
require.Nil(t, s.Module("unknown"))
})
}
// newTestStore sets up a new Store without adding test coverage its functions.
func newTestStore() (*Store, *ModuleInstance, *ModuleInstance) {
s := newStore()
m1 := &ModuleInstance{ModuleName: "m1"}
m2 := &ModuleInstance{ModuleName: "m2"}
m1.prev = m2
m2.next = m1
s.nameToModule = map[string]*ModuleInstance{m1.ModuleName: m1, m2.ModuleName: m2}
s.moduleList = m2
return s, m1, m2
}