244 lines
6.1 KiB
Go
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)
|
|
})
|
|
}
|