wa-lang.org/wazero@v1.0.2/internal/wasm/counts_test.go (about) 1 package wasm 2 3 import ( 4 "testing" 5 6 "wa-lang.org/wazero/internal/testing/require" 7 ) 8 9 func TestModule_ImportFuncCount(t *testing.T) { 10 tests := []struct { 11 name string 12 input *Module 13 expected uint32 14 }{ 15 { 16 name: "none", 17 input: &Module{}, 18 }, 19 { 20 name: "none with function section", 21 input: &Module{FunctionSection: []Index{0}}, 22 }, 23 { 24 name: "one", 25 input: &Module{ImportSection: []*Import{{Type: ExternTypeFunc}}}, 26 expected: 1, 27 }, 28 { 29 name: "one with function section", 30 input: &Module{ImportSection: []*Import{{Type: ExternTypeFunc}}, FunctionSection: []Index{0}}, 31 expected: 1, 32 }, 33 { 34 name: "one with other imports", 35 input: &Module{ImportSection: []*Import{{Type: ExternTypeFunc}, {Type: ExternTypeMemory}}}, 36 expected: 1, 37 }, 38 { 39 name: "two", 40 input: &Module{ImportSection: []*Import{{Type: ExternTypeFunc}, {Type: ExternTypeFunc}}}, 41 expected: 2, 42 }, 43 } 44 45 for _, tt := range tests { 46 tc := tt 47 48 t.Run(tc.name, func(t *testing.T) { 49 require.Equal(t, tc.expected, tc.input.ImportFuncCount()) 50 }) 51 } 52 } 53 54 func TestModule_ImportTableCount(t *testing.T) { 55 tests := []struct { 56 name string 57 input *Module 58 expected uint32 59 }{ 60 { 61 name: "none", 62 input: &Module{}, 63 }, 64 { 65 name: "none with table section", 66 input: &Module{TableSection: []*Table{{Min: 1, Max: nil}}}, 67 }, 68 { 69 name: "one", 70 input: &Module{ImportSection: []*Import{{Type: ExternTypeTable}}}, 71 expected: 1, 72 }, 73 { 74 name: "one with table section", 75 input: &Module{ 76 ImportSection: []*Import{{Type: ExternTypeTable}}, 77 TableSection: []*Table{{Min: 1, Max: nil}}, 78 }, 79 expected: 1, 80 }, 81 { 82 name: "one with other imports", 83 input: &Module{ImportSection: []*Import{{Type: ExternTypeTable}, {Type: ExternTypeMemory}}}, 84 expected: 1, 85 }, 86 { 87 name: "two", 88 input: &Module{ImportSection: []*Import{{Type: ExternTypeTable}, {Type: ExternTypeTable}}}, 89 expected: 2, 90 }, 91 } 92 93 for _, tt := range tests { 94 tc := tt 95 96 t.Run(tc.name, func(t *testing.T) { 97 require.Equal(t, tc.expected, tc.input.ImportTableCount()) 98 }) 99 } 100 } 101 102 // TODO: once we fix up-front validation, this only needs to check zero or one 103 func TestModule_ImportMemoryCount(t *testing.T) { 104 tests := []struct { 105 name string 106 input *Module 107 expected uint32 108 }{ 109 { 110 name: "none", 111 input: &Module{}, 112 }, 113 { 114 name: "none with memory section", 115 input: &Module{MemorySection: &Memory{Min: 1}}, 116 }, 117 { 118 name: "one", 119 input: &Module{ImportSection: []*Import{{Type: ExternTypeMemory}}}, 120 expected: 1, 121 }, 122 { 123 name: "one with memory section", 124 input: &Module{ 125 ImportSection: []*Import{{Type: ExternTypeMemory}}, 126 MemorySection: &Memory{Min: 1}, 127 }, 128 expected: 1, 129 }, 130 { 131 name: "one with other imports", 132 input: &Module{ImportSection: []*Import{{Type: ExternTypeMemory}, {Type: ExternTypeTable}}}, 133 expected: 1, 134 }, 135 { 136 name: "two", 137 input: &Module{ImportSection: []*Import{{Type: ExternTypeMemory}, {Type: ExternTypeMemory}}}, 138 expected: 2, 139 }, 140 } 141 142 for _, tt := range tests { 143 tc := tt 144 145 t.Run(tc.name, func(t *testing.T) { 146 require.Equal(t, tc.expected, tc.input.ImportMemoryCount()) 147 }) 148 } 149 } 150 151 func TestModule_ImportGlobalCount(t *testing.T) { 152 tests := []struct { 153 name string 154 input *Module 155 expected uint32 156 }{ 157 { 158 name: "none", 159 input: &Module{}, 160 }, 161 { 162 name: "none with global section", 163 input: &Module{GlobalSection: []*Global{{Type: &GlobalType{ValType: ValueTypeI64}}}}, 164 }, 165 { 166 name: "one", 167 input: &Module{ImportSection: []*Import{{Type: ExternTypeGlobal}}}, 168 expected: 1, 169 }, 170 { 171 name: "one with global section", 172 input: &Module{ 173 ImportSection: []*Import{{Type: ExternTypeGlobal}}, 174 GlobalSection: []*Global{{Type: &GlobalType{ValType: ValueTypeI64}}}, 175 }, 176 expected: 1, 177 }, 178 { 179 name: "one with other imports", 180 input: &Module{ImportSection: []*Import{{Type: ExternTypeGlobal}, {Type: ExternTypeMemory}}}, 181 expected: 1, 182 }, 183 { 184 name: "two", 185 input: &Module{ImportSection: []*Import{{Type: ExternTypeGlobal}, {Type: ExternTypeGlobal}}}, 186 expected: 2, 187 }, 188 } 189 190 for _, tt := range tests { 191 tc := tt 192 193 t.Run(tc.name, func(t *testing.T) { 194 require.Equal(t, tc.expected, tc.input.ImportGlobalCount()) 195 }) 196 } 197 } 198 199 func TestModule_SectionElementCount(t *testing.T) { 200 i32, f32 := ValueTypeI32, ValueTypeF32 201 zero := uint32(0) 202 empty := &ConstantExpression{Opcode: OpcodeI32Const, Data: const0} 203 204 tests := []struct { 205 name string 206 input *Module 207 expected map[string]uint32 208 }{ 209 { 210 name: "empty", 211 input: &Module{}, 212 expected: map[string]uint32{}, 213 }, 214 { 215 name: "NameSection", 216 input: &Module{NameSection: &NameSection{ModuleName: "simple"}}, 217 expected: map[string]uint32{"custom": 1}, 218 }, 219 { 220 name: "TypeSection", 221 input: &Module{ 222 TypeSection: []*FunctionType{ 223 {}, 224 {Params: []ValueType{i32, i32}, Results: []ValueType{i32}}, 225 {Params: []ValueType{i32, i32, i32, i32}, Results: []ValueType{i32}}, 226 }, 227 }, 228 expected: map[string]uint32{"type": 3}, 229 }, 230 { 231 name: "TypeSection and ImportSection", 232 input: &Module{ 233 TypeSection: []*FunctionType{ 234 {Params: []ValueType{i32, i32}, Results: []ValueType{i32}}, 235 {Params: []ValueType{f32, f32}, Results: []ValueType{f32}}, 236 }, 237 ImportSection: []*Import{ 238 { 239 Module: "Math", Name: "Mul", 240 Type: ExternTypeFunc, 241 DescFunc: 1, 242 }, { 243 Module: "Math", Name: "Add", 244 Type: ExternTypeFunc, 245 DescFunc: 0, 246 }, 247 }, 248 }, 249 expected: map[string]uint32{"import": 2, "type": 2}, 250 }, 251 { 252 name: "TypeSection, FunctionSection, CodeSection, ExportSection and StartSection", 253 input: &Module{ 254 TypeSection: []*FunctionType{{}}, 255 FunctionSection: []Index{0}, 256 CodeSection: []*Code{ 257 {Body: []byte{OpcodeLocalGet, 0, OpcodeLocalGet, 1, OpcodeI32Add, OpcodeEnd}}, 258 }, 259 ExportSection: []*Export{ 260 {Name: "AddInt", Type: ExternTypeFunc, Index: Index(0)}, 261 }, 262 StartSection: &zero, 263 }, 264 expected: map[string]uint32{"code": 1, "export": 1, "function": 1, "start": 1, "type": 1}, 265 }, 266 { 267 name: "MemorySection and DataSection", 268 input: &Module{ 269 MemorySection: &Memory{Min: 1}, 270 DataSection: []*DataSegment{{OffsetExpression: empty}}, 271 }, 272 expected: map[string]uint32{"data": 1, "memory": 1}, 273 }, 274 { 275 name: "TableSection and ElementSection", 276 input: &Module{ 277 TableSection: []*Table{{Min: 1}}, 278 ElementSection: []*ElementSegment{{OffsetExpr: empty}}, 279 }, 280 expected: map[string]uint32{"element": 1, "table": 1}, 281 }, 282 { 283 name: "TableSection (multiple tables) and ElementSection", 284 input: &Module{ 285 TableSection: []*Table{{Min: 1}, {Min: 2}}, 286 ElementSection: []*ElementSegment{{OffsetExpr: empty}}, 287 }, 288 expected: map[string]uint32{"element": 1, "table": 2}, 289 }, 290 } 291 292 for _, tt := range tests { 293 tc := tt 294 295 t.Run(tc.name, func(t *testing.T) { 296 actual := map[string]uint32{} 297 for i := SectionID(0); i <= SectionIDData; i++ { 298 if size := tc.input.SectionElementCount(i); size > 0 { 299 actual[SectionIDName(i)] = size 300 } 301 } 302 require.Equal(t, tc.expected, actual) 303 }) 304 } 305 }