Files
wazero/internal/wasm/binary/section_test.go
Anuraag Agrawal 714368bcea Remove threads support (#1487)
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
2023-05-22 12:18:36 +10:00

244 lines
6.1 KiB
Go

package binary
import (
"bytes"
"testing"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
"github.com/tetratelabs/wazero/internal/testing/require"
"github.com/tetratelabs/wazero/internal/wasm"
)
func TestTableSection(t *testing.T) {
three := uint32(3)
tests := []struct {
name string
input []byte
expected []wasm.Table
}{
{
name: "min and min with max",
input: []byte{
0x01, // 1 table
wasm.RefTypeFuncref, 0x01, 2, 3, // (table 2 3)
},
expected: []wasm.Table{{Min: 2, Max: &three, Type: wasm.RefTypeFuncref}},
},
{
name: "min and min with max - three tables",
input: []byte{
0x03, // 3 table
wasm.RefTypeFuncref, 0x01, 2, 3, // (table 2 3)
wasm.RefTypeExternref, 0x01, 2, 3, // (table 2 3)
wasm.RefTypeFuncref, 0x01, 2, 3, // (table 2 3)
},
expected: []wasm.Table{
{Min: 2, Max: &three, Type: wasm.RefTypeFuncref},
{Min: 2, Max: &three, Type: wasm.RefTypeExternref},
{Min: 2, Max: &three, Type: wasm.RefTypeFuncref},
},
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
tables, err := decodeTableSection(bytes.NewReader(tc.input), api.CoreFeatureReferenceTypes)
require.NoError(t, err)
require.Equal(t, tc.expected, tables)
})
}
}
func TestTableSection_Errors(t *testing.T) {
tests := []struct {
name string
input []byte
expectedErr string
features api.CoreFeatures
}{
{
name: "min and min with max",
input: []byte{
0x02, // 2 tables
wasm.RefTypeFuncref, 0x00, 0x01, // (table 1)
wasm.RefTypeFuncref, 0x01, 0x02, 0x03, // (table 2 3)
},
expectedErr: "at most one table allowed in module as feature \"reference-types\" is disabled",
features: api.CoreFeaturesV1,
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
_, err := decodeTableSection(bytes.NewReader(tc.input), tc.features)
require.EqualError(t, err, tc.expectedErr)
})
}
}
func TestMemorySection(t *testing.T) {
max := wasm.MemoryLimitPages
three := uint32(3)
tests := []struct {
name string
input []byte
expected *wasm.Memory
}{
{
name: "min and min with max",
input: []byte{
0x01, // 1 memory
0x01, 0x02, 0x03, // (memory 2 3)
},
expected: &wasm.Memory{Min: 2, Cap: 2, Max: three, IsMaxEncoded: true},
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
memories, err := decodeMemorySection(bytes.NewReader(tc.input), newMemorySizer(max, false), max)
require.NoError(t, err)
require.Equal(t, tc.expected, memories)
})
}
}
func TestMemorySection_Errors(t *testing.T) {
max := wasm.MemoryLimitPages
tests := []struct {
name string
input []byte
expectedErr string
}{
{
name: "min and min with max",
input: []byte{
0x02, // 2 memories
0x01, // (memory 1)
0x02, 0x03, // (memory 2 3)
},
expectedErr: "at most one memory allowed in module, but read 2",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
_, err := decodeMemorySection(bytes.NewReader(tc.input), newMemorySizer(max, false), max)
require.EqualError(t, err, tc.expectedErr)
})
}
}
func TestDecodeExportSection(t *testing.T) {
tests := []struct {
name string
input []byte
expected []wasm.Export
}{
{
name: "empty and non-empty name",
input: []byte{
0x02, // 2 exports
0x00, // Size of empty name
wasm.ExternTypeFunc, 0x02, // func[2]
0x01, 'a', // Size of name, name
wasm.ExternTypeFunc, 0x01, // func[1]
},
expected: []wasm.Export{
{Name: "", Type: wasm.ExternTypeFunc, Index: wasm.Index(2)},
{Name: "a", Type: wasm.ExternTypeFunc, Index: wasm.Index(1)},
},
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
actual, actualExpMap, err := decodeExportSection(bytes.NewReader(tc.input))
require.NoError(t, err)
require.Equal(t, tc.expected, actual)
expMap := make(map[string]*wasm.Export, len(tc.expected))
for i := range tc.expected {
exp := &tc.expected[i]
expMap[exp.Name] = exp
}
require.Equal(t, expMap, actualExpMap)
})
}
}
func TestDecodeExportSection_Errors(t *testing.T) {
tests := []struct {
name string
input []byte
expectedErr string
}{
{
name: "duplicates empty name",
input: []byte{
0x02, // 2 exports
0x00, // Size of empty name
wasm.ExternTypeFunc, 0x00, // func[0]
0x00, // Size of empty name
wasm.ExternTypeFunc, 0x00, // func[0]
},
expectedErr: "export[1] duplicates name \"\"",
},
{
name: "duplicates name",
input: []byte{
0x02, // 2 exports
0x01, 'a', // Size of name, name
wasm.ExternTypeFunc, 0x00, // func[0]
0x01, 'a', // Size of name, name
wasm.ExternTypeFunc, 0x00, // func[0]
},
expectedErr: "export[1] duplicates name \"a\"",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
_, _, err := decodeExportSection(bytes.NewReader(tc.input))
require.EqualError(t, err, tc.expectedErr)
})
}
}
func TestEncodeFunctionSection(t *testing.T) {
require.Equal(t, []byte{wasm.SectionIDFunction, 0x2, 0x01, 0x05}, binaryencoding.EncodeFunctionSection([]wasm.Index{5}))
}
// TestEncodeStartSection uses the same index as TestEncodeFunctionSection to highlight the encoding is different.
func TestEncodeStartSection(t *testing.T) {
require.Equal(t, []byte{wasm.SectionIDStart, 0x01, 0x05}, binaryencoding.EncodeStartSection(5))
}
func TestDecodeDataCountSection(t *testing.T) {
t.Run("ok", func(t *testing.T) {
v, err := decodeDataCountSection(bytes.NewReader([]byte{0x1}))
require.NoError(t, err)
require.Equal(t, uint32(1), *v)
})
t.Run("eof", func(t *testing.T) {
// EOF is fine as the datacount is optional.
_, err := decodeDataCountSection(bytes.NewReader([]byte{}))
require.NoError(t, err)
})
}