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  }