github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/wasm/binary/memory_test.go (about) 1 package binary 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 "github.com/bananabytelabs/wazero/internal/testing/binaryencoding" 9 "github.com/bananabytelabs/wazero/internal/testing/require" 10 "github.com/bananabytelabs/wazero/internal/wasm" 11 ) 12 13 func Test_newMemorySizer(t *testing.T) { 14 zero := uint32(0) 15 ten := uint32(10) 16 defaultLimit := wasm.MemoryLimitPages 17 18 tests := []struct { 19 name string 20 memoryCapacityFromMax bool 21 limit uint32 22 min uint32 23 max *uint32 24 expectedMin, expectedCapacity, expectedMax uint32 25 }{ 26 { 27 name: "min 0", 28 limit: defaultLimit, 29 min: zero, 30 max: &defaultLimit, 31 expectedMin: zero, 32 expectedCapacity: zero, 33 expectedMax: defaultLimit, 34 }, 35 { 36 name: "min 0 defaults max to defaultLimit", 37 limit: defaultLimit, 38 min: zero, 39 expectedMin: zero, 40 expectedCapacity: zero, 41 expectedMax: defaultLimit, 42 }, 43 { 44 name: "min 0, max 0", 45 limit: defaultLimit, 46 min: zero, 47 max: &zero, 48 expectedMin: zero, 49 expectedCapacity: zero, 50 expectedMax: zero, 51 }, 52 { 53 name: "min 0, max 10", 54 limit: defaultLimit, 55 min: zero, 56 max: &ten, 57 expectedMin: zero, 58 expectedCapacity: zero, 59 expectedMax: ten, 60 }, 61 { 62 name: "min 0, max 10 memoryCapacityFromMax", 63 limit: defaultLimit, 64 memoryCapacityFromMax: true, 65 min: zero, 66 max: &ten, 67 expectedMin: zero, 68 expectedCapacity: ten, 69 expectedMax: ten, 70 }, 71 { 72 name: "min 10, no max", 73 limit: 200, 74 min: 10, 75 expectedMin: 10, 76 expectedCapacity: 10, 77 expectedMax: 200, 78 }, 79 { 80 name: "min 10, no max memoryCapacityFromMax", 81 memoryCapacityFromMax: true, 82 limit: 200, 83 min: 10, 84 expectedMin: 10, 85 expectedCapacity: 200, 86 expectedMax: 200, 87 }, 88 { 89 name: "min=max", 90 limit: defaultLimit, 91 min: ten, 92 max: &ten, 93 expectedMin: ten, 94 expectedCapacity: ten, 95 expectedMax: ten, 96 }, 97 { 98 name: "max > memoryLimitPages", 99 limit: 5, 100 min: 0, 101 max: &ten, 102 expectedMin: 0, 103 expectedCapacity: 0, 104 expectedMax: 5, 105 }, 106 } 107 108 for _, tt := range tests { 109 tc := tt 110 t.Run(tc.name, func(t *testing.T) { 111 sizer := newMemorySizer(tc.limit, tc.memoryCapacityFromMax) 112 min, capacity, max := sizer(tc.min, tc.max) 113 require.Equal(t, tc.expectedMin, min) 114 require.Equal(t, tc.expectedCapacity, capacity) 115 require.Equal(t, tc.expectedMax, max) 116 }) 117 } 118 } 119 120 func TestMemoryType(t *testing.T) { 121 zero := uint32(0) 122 max := wasm.MemoryLimitPages 123 124 tests := []struct { 125 name string 126 input *wasm.Memory 127 memoryLimitPages uint32 128 expected []byte 129 }{ 130 { 131 name: "min 0", 132 input: &wasm.Memory{Max: max, IsMaxEncoded: true}, 133 expected: []byte{0x1, 0, 0x80, 0x80, 0x4}, 134 }, 135 { 136 name: "min 0 default max", 137 input: &wasm.Memory{Max: max}, 138 expected: []byte{0x0, 0}, 139 }, 140 { 141 name: "min 0, max 0", 142 input: &wasm.Memory{Max: zero, IsMaxEncoded: true}, 143 expected: []byte{0x1, 0, 0}, 144 }, 145 { 146 name: "min=max", 147 input: &wasm.Memory{Min: 1, Cap: 1, Max: 1, IsMaxEncoded: true}, 148 expected: []byte{0x1, 1, 1}, 149 }, 150 { 151 name: "min 0, max largest", 152 input: &wasm.Memory{Max: max, IsMaxEncoded: true}, 153 expected: []byte{0x1, 0, 0x80, 0x80, 0x4}, 154 }, 155 { 156 name: "min largest max largest", 157 input: &wasm.Memory{Min: max, Cap: max, Max: max, IsMaxEncoded: true}, 158 expected: []byte{0x1, 0x80, 0x80, 0x4, 0x80, 0x80, 0x4}, 159 }, 160 { 161 name: "min 0, max largest, wazero limit", 162 input: &wasm.Memory{Max: max, IsMaxEncoded: true}, 163 memoryLimitPages: 512, 164 expected: []byte{0x1, 0, 0x80, 0x80, 0x4}, 165 }, 166 } 167 168 for _, tt := range tests { 169 tc := tt 170 171 b := binaryencoding.EncodeMemory(tc.input) 172 t.Run(fmt.Sprintf("encode %s", tc.name), func(t *testing.T) { 173 require.Equal(t, tc.expected, b) 174 }) 175 176 t.Run(fmt.Sprintf("decode %s", tc.name), func(t *testing.T) { 177 tmax := max 178 expectedDecoded := tc.input 179 if tc.memoryLimitPages != 0 { 180 // If a memory limit exists, then the expected module Max reflects that limit. 181 tmax = tc.memoryLimitPages 182 expectedDecoded.Max = tmax 183 } 184 185 binary, err := decodeMemory(bytes.NewReader(b), newMemorySizer(tmax, false), tmax) 186 require.NoError(t, err) 187 require.Equal(t, binary, expectedDecoded) 188 }) 189 } 190 } 191 192 func TestDecodeMemoryType_Errors(t *testing.T) { 193 max := wasm.MemoryLimitPages 194 195 tests := []struct { 196 name string 197 input []byte 198 expectedErr string 199 }{ 200 { 201 name: "max < min", 202 input: []byte{0x1, 0x80, 0x80, 0x4, 0}, 203 expectedErr: "min 65536 pages (4 Gi) > max 0 pages (0 Ki)", 204 }, 205 { 206 name: "min > limit", 207 input: []byte{0x0, 0xff, 0xff, 0xff, 0xff, 0xf}, 208 expectedErr: "min 4294967295 pages (3 Ti) over limit of 65536 pages (4 Gi)", 209 }, 210 { 211 name: "max > limit", 212 input: []byte{0x1, 0, 0xff, 0xff, 0xff, 0xff, 0xf}, 213 expectedErr: "max 4294967295 pages (3 Ti) over limit of 65536 pages (4 Gi)", 214 }, 215 } 216 217 for _, tt := range tests { 218 tc := tt 219 220 t.Run(tc.name, func(t *testing.T) { 221 _, err := decodeMemory(bytes.NewReader(tc.input), newMemorySizer(max, false), max) 222 require.EqualError(t, err, tc.expectedErr) 223 }) 224 } 225 }