wa-lang.org/wazero@v1.0.2/internal/wasm/binary/section_test.go (about) 1 package binary 2 3 import ( 4 "bytes" 5 "testing" 6 7 "wa-lang.org/wazero/api" 8 "wa-lang.org/wazero/internal/testing/require" 9 "wa-lang.org/wazero/internal/wasm" 10 ) 11 12 func TestTableSection(t *testing.T) { 13 three := uint32(3) 14 tests := []struct { 15 name string 16 input []byte 17 expected []*wasm.Table 18 }{ 19 { 20 name: "min and min with max", 21 input: []byte{ 22 0x01, // 1 table 23 wasm.RefTypeFuncref, 0x01, 2, 3, // (table 2 3) 24 }, 25 expected: []*wasm.Table{{Min: 2, Max: &three, Type: wasm.RefTypeFuncref}}, 26 }, 27 { 28 name: "min and min with max - three tables", 29 input: []byte{ 30 0x03, // 3 table 31 wasm.RefTypeFuncref, 0x01, 2, 3, // (table 2 3) 32 wasm.RefTypeExternref, 0x01, 2, 3, // (table 2 3) 33 wasm.RefTypeFuncref, 0x01, 2, 3, // (table 2 3) 34 }, 35 expected: []*wasm.Table{ 36 {Min: 2, Max: &three, Type: wasm.RefTypeFuncref}, 37 {Min: 2, Max: &three, Type: wasm.RefTypeExternref}, 38 {Min: 2, Max: &three, Type: wasm.RefTypeFuncref}, 39 }, 40 }, 41 } 42 43 for _, tt := range tests { 44 tc := tt 45 46 t.Run(tc.name, func(t *testing.T) { 47 tables, err := decodeTableSection(bytes.NewReader(tc.input), api.CoreFeatureReferenceTypes) 48 require.NoError(t, err) 49 require.Equal(t, tc.expected, tables) 50 }) 51 } 52 } 53 54 func TestTableSection_Errors(t *testing.T) { 55 tests := []struct { 56 name string 57 input []byte 58 expectedErr string 59 features api.CoreFeatures 60 }{ 61 { 62 name: "min and min with max", 63 input: []byte{ 64 0x02, // 2 tables 65 wasm.RefTypeFuncref, 0x00, 0x01, // (table 1) 66 wasm.RefTypeFuncref, 0x01, 0x02, 0x03, // (table 2 3) 67 }, 68 expectedErr: "at most one table allowed in module as feature \"reference-types\" is disabled", 69 features: api.CoreFeaturesV1, 70 }, 71 } 72 73 for _, tt := range tests { 74 tc := tt 75 76 t.Run(tc.name, func(t *testing.T) { 77 _, err := decodeTableSection(bytes.NewReader(tc.input), tc.features) 78 require.EqualError(t, err, tc.expectedErr) 79 }) 80 } 81 } 82 83 func TestMemorySection(t *testing.T) { 84 max := wasm.MemoryLimitPages 85 86 three := uint32(3) 87 tests := []struct { 88 name string 89 input []byte 90 expected *wasm.Memory 91 }{ 92 { 93 name: "min and min with max", 94 input: []byte{ 95 0x01, // 1 memory 96 0x01, 0x02, 0x03, // (memory 2 3) 97 }, 98 expected: &wasm.Memory{Min: 2, Cap: 2, Max: three, IsMaxEncoded: true}, 99 }, 100 } 101 102 for _, tt := range tests { 103 tc := tt 104 105 t.Run(tc.name, func(t *testing.T) { 106 memories, err := decodeMemorySection(bytes.NewReader(tc.input), newMemorySizer(max, false), max) 107 require.NoError(t, err) 108 require.Equal(t, tc.expected, memories) 109 }) 110 } 111 } 112 113 func TestMemorySection_Errors(t *testing.T) { 114 max := wasm.MemoryLimitPages 115 116 tests := []struct { 117 name string 118 input []byte 119 expectedErr string 120 }{ 121 { 122 name: "min and min with max", 123 input: []byte{ 124 0x02, // 2 memories 125 0x01, // (memory 1) 126 0x02, 0x03, // (memory 2 3) 127 }, 128 expectedErr: "at most one memory allowed in module, but read 2", 129 }, 130 } 131 132 for _, tt := range tests { 133 tc := tt 134 135 t.Run(tc.name, func(t *testing.T) { 136 _, err := decodeMemorySection(bytes.NewReader(tc.input), newMemorySizer(max, false), max) 137 require.EqualError(t, err, tc.expectedErr) 138 }) 139 } 140 } 141 142 func TestDecodeExportSection(t *testing.T) { 143 tests := []struct { 144 name string 145 input []byte 146 expected []*wasm.Export 147 }{ 148 { 149 name: "empty and non-empty name", 150 input: []byte{ 151 0x02, // 2 exports 152 0x00, // Size of empty name 153 wasm.ExternTypeFunc, 0x02, // func[2] 154 0x01, 'a', // Size of name, name 155 wasm.ExternTypeFunc, 0x01, // func[1] 156 }, 157 expected: []*wasm.Export{ 158 {Name: "", Type: wasm.ExternTypeFunc, Index: wasm.Index(2)}, 159 {Name: "a", Type: wasm.ExternTypeFunc, Index: wasm.Index(1)}, 160 }, 161 }, 162 } 163 164 for _, tt := range tests { 165 tc := tt 166 167 t.Run(tc.name, func(t *testing.T) { 168 exports, err := decodeExportSection(bytes.NewReader(tc.input)) 169 require.NoError(t, err) 170 require.Equal(t, tc.expected, exports) 171 }) 172 } 173 } 174 175 func TestDecodeExportSection_Errors(t *testing.T) { 176 tests := []struct { 177 name string 178 input []byte 179 expectedErr string 180 }{ 181 { 182 name: "duplicates empty name", 183 input: []byte{ 184 0x02, // 2 exports 185 0x00, // Size of empty name 186 wasm.ExternTypeFunc, 0x00, // func[0] 187 0x00, // Size of empty name 188 wasm.ExternTypeFunc, 0x00, // func[0] 189 }, 190 expectedErr: "export[1] duplicates name \"\"", 191 }, 192 { 193 name: "duplicates name", 194 input: []byte{ 195 0x02, // 2 exports 196 0x01, 'a', // Size of name, name 197 wasm.ExternTypeFunc, 0x00, // func[0] 198 0x01, 'a', // Size of name, name 199 wasm.ExternTypeFunc, 0x00, // func[0] 200 }, 201 expectedErr: "export[1] duplicates name \"a\"", 202 }, 203 } 204 205 for _, tt := range tests { 206 tc := tt 207 208 t.Run(tc.name, func(t *testing.T) { 209 _, err := decodeExportSection(bytes.NewReader(tc.input)) 210 require.EqualError(t, err, tc.expectedErr) 211 }) 212 } 213 } 214 215 func TestEncodeFunctionSection(t *testing.T) { 216 require.Equal(t, []byte{wasm.SectionIDFunction, 0x2, 0x01, 0x05}, encodeFunctionSection([]wasm.Index{5})) 217 } 218 219 // TestEncodeStartSection uses the same index as TestEncodeFunctionSection to highlight the encoding is different. 220 func TestEncodeStartSection(t *testing.T) { 221 require.Equal(t, []byte{wasm.SectionIDStart, 0x01, 0x05}, encodeStartSection(5)) 222 } 223 224 func TestDecodeDataCountSection(t *testing.T) { 225 t.Run("ok", func(t *testing.T) { 226 v, err := decodeDataCountSection(bytes.NewReader([]byte{0x1})) 227 require.NoError(t, err) 228 require.Equal(t, uint32(1), *v) 229 }) 230 t.Run("eof", func(t *testing.T) { 231 // EOF is fine as the datacount is optional. 232 _, err := decodeDataCountSection(bytes.NewReader([]byte{})) 233 require.NoError(t, err) 234 }) 235 }