github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/wasm/binary/names_test.go (about) 1 package binary 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/bananabytelabs/wazero/internal/testing/binaryencoding" 8 "github.com/bananabytelabs/wazero/internal/testing/require" 9 "github.com/bananabytelabs/wazero/internal/wasm" 10 ) 11 12 // TestDecodeNameSection relies on unit tests for NameSection.EncodeData, specifically that the encoding is 13 // both known and correct. This avoids having to copy/paste or share variables to assert against byte arrays. 14 func TestDecodeNameSection(t *testing.T) { 15 tests := []struct { 16 name string 17 input *wasm.NameSection // round trip test! 18 }{ 19 { 20 name: "empty", 21 input: &wasm.NameSection{}, 22 }, 23 { 24 name: "only module", 25 input: &wasm.NameSection{ModuleName: "simple"}, 26 }, 27 { 28 name: "module and function name", 29 input: &wasm.NameSection{ 30 ModuleName: "simple", 31 FunctionNames: wasm.NameMap{{Index: wasm.Index(0), Name: "wasi.hello"}}, 32 }, 33 }, 34 { 35 name: "two function names", 36 input: &wasm.NameSection{ 37 FunctionNames: wasm.NameMap{ 38 {Index: wasm.Index(0), Name: "wasi.args_sizes_get"}, 39 {Index: wasm.Index(1), Name: "wasi.fd_write"}, 40 }, 41 }, 42 }, 43 { 44 name: "function with local names", 45 input: &wasm.NameSection{ 46 FunctionNames: wasm.NameMap{ 47 {Index: wasm.Index(0), Name: "mul"}, 48 {Index: wasm.Index(1), Name: "add"}, 49 }, 50 LocalNames: wasm.IndirectNameMap{ 51 {Index: wasm.Index(0), NameMap: wasm.NameMap{ 52 {Index: wasm.Index(0), Name: "x"}, 53 {Index: wasm.Index(1), Name: "y"}, 54 }}, 55 {Index: wasm.Index(1), NameMap: wasm.NameMap{ 56 {Index: wasm.Index(0), Name: "l"}, 57 {Index: wasm.Index(1), Name: "r"}, 58 }}, 59 }, 60 }, 61 }, 62 } 63 64 for _, tt := range tests { 65 tc := tt 66 67 t.Run(tc.name, func(t *testing.T) { 68 data := binaryencoding.EncodeNameSectionData(tc.input) 69 ns, err := decodeNameSection(bytes.NewReader(data), uint64(len(data))) 70 require.NoError(t, err) 71 require.Equal(t, tc.input, ns) 72 }) 73 } 74 } 75 76 func TestDecodeNameSection_Errors(t *testing.T) { 77 // currently, we ignore the size of known subsections 78 ignoredSubsectionSize := byte(50) 79 tests := []struct { 80 name string 81 input []byte 82 expectedErr string 83 }{ 84 { 85 name: "EOF after module name subsection ID", 86 input: []byte{subsectionIDModuleName}, 87 expectedErr: "failed to read the size of subsection[0]: EOF", 88 }, 89 { 90 name: "EOF after function names subsection ID", 91 input: []byte{subsectionIDFunctionNames}, 92 expectedErr: "failed to read the size of subsection[1]: EOF", 93 }, 94 { 95 name: "EOF after local names subsection ID", 96 input: []byte{subsectionIDLocalNames}, 97 expectedErr: "failed to read the size of subsection[2]: EOF", 98 }, 99 { 100 name: "EOF after unknown subsection ID", 101 input: []byte{4}, 102 expectedErr: "failed to read the size of subsection[4]: EOF", 103 }, 104 { 105 name: "EOF after module name subsection size", 106 input: []byte{subsectionIDModuleName, ignoredSubsectionSize}, 107 expectedErr: "failed to read module name size: EOF", 108 }, 109 { 110 name: "EOF after function names subsection size", 111 input: []byte{subsectionIDFunctionNames, ignoredSubsectionSize}, 112 expectedErr: "failed to read the function count of subsection[1]: EOF", 113 }, 114 { 115 name: "EOF after local names subsection size", 116 input: []byte{subsectionIDLocalNames, ignoredSubsectionSize}, 117 expectedErr: "failed to read the function count of subsection[2]: EOF", 118 }, 119 { 120 name: "EOF skipping unknown subsection size", 121 input: []byte{4, 100}, 122 expectedErr: "failed to skip subsection[4]: EOF", 123 }, 124 { 125 name: "EOF after module name size", 126 input: []byte{subsectionIDModuleName, ignoredSubsectionSize, 5}, 127 expectedErr: "failed to read module name: EOF", 128 }, 129 { 130 name: "EOF after function name count", 131 input: []byte{subsectionIDFunctionNames, ignoredSubsectionSize, 2}, 132 expectedErr: "failed to read a function index in subsection[1]: EOF", 133 }, 134 { 135 name: "EOF after local names function count", 136 input: []byte{subsectionIDLocalNames, ignoredSubsectionSize, 2}, 137 expectedErr: "failed to read a function index in subsection[2]: EOF", 138 }, 139 { 140 name: "EOF after function name index", 141 input: []byte{subsectionIDFunctionNames, ignoredSubsectionSize, 2, 0}, 142 expectedErr: "failed to read function[0] name size: EOF", 143 }, 144 { 145 name: "EOF after local names function index", 146 input: []byte{subsectionIDLocalNames, ignoredSubsectionSize, 2, 0}, 147 expectedErr: "failed to read the local count for function[0]: EOF", 148 }, 149 { 150 name: "EOF after function name size", 151 input: []byte{subsectionIDFunctionNames, ignoredSubsectionSize, 2, 0, 5}, 152 expectedErr: "failed to read function[0] name: EOF", 153 }, 154 { 155 name: "EOF after local names count for a function index", 156 input: []byte{subsectionIDLocalNames, ignoredSubsectionSize, 2, 0, 2}, 157 expectedErr: "failed to read a local index of function[0]: EOF", 158 }, 159 { 160 name: "EOF after local name size", 161 input: []byte{subsectionIDLocalNames, ignoredSubsectionSize, 2, 0, 2, 1}, 162 expectedErr: "failed to read function[0] local[1] name size: EOF", 163 }, 164 } 165 166 for _, tt := range tests { 167 tc := tt 168 169 t.Run(tc.name, func(t *testing.T) { 170 _, err := decodeNameSection(bytes.NewReader(tc.input), uint64(len(tc.input))) 171 require.EqualError(t, err, tc.expectedErr) 172 }) 173 } 174 }