1 package binary
2
3 import (
4 "bytes"
5 "fmt"
6 "testing"
7
8 "github.com/tetratelabs/wazero/api"
9 "github.com/tetratelabs/wazero/internal/testing/binaryencoding"
10 "github.com/tetratelabs/wazero/internal/testing/require"
11 "github.com/tetratelabs/wazero/internal/wasm"
12 )
13
14 func TestFunctionType(t *testing.T) {
15 i32, i64, funcRef, externRef := wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeFuncref, wasm.ValueTypeExternref
16 tests := []struct {
17 name string
18 input wasm.FunctionType
19 expected []byte
20 }{
21 {
22 name: "empty",
23 input: wasm.FunctionType{},
24 expected: []byte{0x60, 0, 0},
25 },
26 {
27 name: "one param no result",
28 input: wasm.FunctionType{Params: []wasm.ValueType{i32}},
29 expected: []byte{0x60, 1, i32, 0},
30 },
31 {
32 name: "no param one result",
33 input: wasm.FunctionType{Results: []wasm.ValueType{i32}},
34 expected: []byte{0x60, 0, 1, i32},
35 },
36 {
37 name: "one param one result",
38 input: wasm.FunctionType{Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32}},
39 expected: []byte{0x60, 1, i64, 1, i32},
40 },
41 {
42 name: "two params no result",
43 input: wasm.FunctionType{Params: []wasm.ValueType{i32, i64}},
44 expected: []byte{0x60, 2, i32, i64, 0},
45 },
46 {
47 name: "two param one result",
48 input: wasm.FunctionType{Params: []wasm.ValueType{i32, i64}, Results: []wasm.ValueType{i32}},
49 expected: []byte{0x60, 2, i32, i64, 1, i32},
50 },
51 {
52 name: "no param two results",
53 input: wasm.FunctionType{Results: []wasm.ValueType{i32, i64}},
54 expected: []byte{0x60, 0, 2, i32, i64},
55 },
56 {
57 name: "one param two results",
58 input: wasm.FunctionType{Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32, i64}},
59 expected: []byte{0x60, 1, i64, 2, i32, i64},
60 },
61 {
62 name: "two param two results",
63 input: wasm.FunctionType{Params: []wasm.ValueType{i32, i64}, Results: []wasm.ValueType{i32, i64}},
64 expected: []byte{0x60, 2, i32, i64, 2, i32, i64},
65 },
66 {
67 name: "two param two results with funcrefs",
68 input: wasm.FunctionType{Params: []wasm.ValueType{i32, funcRef}, Results: []wasm.ValueType{funcRef, i64}},
69 expected: []byte{0x60, 2, i32, funcRef, 2, funcRef, i64},
70 },
71 {
72 name: "two param two results with externrefs",
73 input: wasm.FunctionType{Params: []wasm.ValueType{i32, externRef}, Results: []wasm.ValueType{externRef, i64}},
74 expected: []byte{0x60, 2, i32, externRef, 2, externRef, i64},
75 },
76 }
77
78 for _, tt := range tests {
79 tc := tt
80
81 b := binaryencoding.EncodeFunctionType(&tc.input)
82 t.Run(fmt.Sprintf("encode - %s", tc.name), func(t *testing.T) {
83 require.Equal(t, tc.expected, b)
84 })
85
86 t.Run(fmt.Sprintf("decode - %s", tc.name), func(t *testing.T) {
87 var actual wasm.FunctionType
88 err := decodeFunctionType(api.CoreFeaturesV2, bytes.NewReader(b), &actual)
89 require.NoError(t, err)
90
91 _ = tc.input.String()
92 require.Equal(t, actual, tc.input)
93 })
94 }
95 }
96
97 func TestDecodeFunctionType_Errors(t *testing.T) {
98 i32, i64 := wasm.ValueTypeI32, wasm.ValueTypeI64
99 tests := []struct {
100 name string
101 input []byte
102 enabledFeatures api.CoreFeatures
103 expectedErr string
104 }{
105 {
106 name: "undefined param no result",
107 input: []byte{0x60, 1, 0x6e, 0},
108 expectedErr: "could not read parameter types: invalid value type: 110",
109 },
110 {
111 name: "no param undefined result",
112 input: []byte{0x60, 0, 1, 0x6e},
113 expectedErr: "could not read result types: invalid value type: 110",
114 },
115 {
116 name: "undefined param undefined result",
117 input: []byte{0x60, 1, 0x6e, 1, 0x6e},
118 expectedErr: "could not read parameter types: invalid value type: 110",
119 },
120 {
121 name: "no param two results - multi-value not enabled",
122 input: []byte{0x60, 0, 2, i32, i64},
123 expectedErr: "multiple result types invalid as feature \"multi-value\" is disabled",
124 },
125 {
126 name: "one param two results - multi-value not enabled",
127 input: []byte{0x60, 1, i64, 2, i32, i64},
128 expectedErr: "multiple result types invalid as feature \"multi-value\" is disabled",
129 },
130 {
131 name: "two param two results - multi-value not enabled",
132 input: []byte{0x60, 2, i32, i64, 2, i32, i64},
133 expectedErr: "multiple result types invalid as feature \"multi-value\" is disabled",
134 },
135 }
136
137 for _, tt := range tests {
138 tc := tt
139
140 t.Run(tc.name, func(t *testing.T) {
141 var actual wasm.FunctionType
142 err := decodeFunctionType(api.CoreFeaturesV1, bytes.NewReader(tc.input), &actual)
143 require.EqualError(t, err, tc.expectedErr)
144 })
145 }
146 }
147
View as plain text