github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/wasm/binary/function_test.go (about)

     1  package binary
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/tetratelabs/wazero/api"
     9  	"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
    10  	"github.com/tetratelabs/wazero/internal/testing/require"
    11  	"github.com/tetratelabs/wazero/internal/wasm"
    12  )
    13  
    14  func TestFunctionType(t *testing.T) {
    15  	i32, i64, funcRef, externRef := wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeFuncref, wasm.ValueTypeExternref
    16  	tests := []struct {
    17  		name     string
    18  		input    wasm.FunctionType
    19  		expected []byte
    20  	}{
    21  		{
    22  			name:     "empty",
    23  			input:    wasm.FunctionType{},
    24  			expected: []byte{0x60, 0, 0},
    25  		},
    26  		{
    27  			name:     "one param no result",
    28  			input:    wasm.FunctionType{Params: []wasm.ValueType{i32}},
    29  			expected: []byte{0x60, 1, i32, 0},
    30  		},
    31  		{
    32  			name:     "no param one result",
    33  			input:    wasm.FunctionType{Results: []wasm.ValueType{i32}},
    34  			expected: []byte{0x60, 0, 1, i32},
    35  		},
    36  		{
    37  			name:     "one param one result",
    38  			input:    wasm.FunctionType{Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32}},
    39  			expected: []byte{0x60, 1, i64, 1, i32},
    40  		},
    41  		{
    42  			name:     "two params no result",
    43  			input:    wasm.FunctionType{Params: []wasm.ValueType{i32, i64}},
    44  			expected: []byte{0x60, 2, i32, i64, 0},
    45  		},
    46  		{
    47  			name:     "two param one result",
    48  			input:    wasm.FunctionType{Params: []wasm.ValueType{i32, i64}, Results: []wasm.ValueType{i32}},
    49  			expected: []byte{0x60, 2, i32, i64, 1, i32},
    50  		},
    51  		{
    52  			name:     "no param two results",
    53  			input:    wasm.FunctionType{Results: []wasm.ValueType{i32, i64}},
    54  			expected: []byte{0x60, 0, 2, i32, i64},
    55  		},
    56  		{
    57  			name:     "one param two results",
    58  			input:    wasm.FunctionType{Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32, i64}},
    59  			expected: []byte{0x60, 1, i64, 2, i32, i64},
    60  		},
    61  		{
    62  			name:     "two param two results",
    63  			input:    wasm.FunctionType{Params: []wasm.ValueType{i32, i64}, Results: []wasm.ValueType{i32, i64}},
    64  			expected: []byte{0x60, 2, i32, i64, 2, i32, i64},
    65  		},
    66  		{
    67  			name:     "two param two results with funcrefs",
    68  			input:    wasm.FunctionType{Params: []wasm.ValueType{i32, funcRef}, Results: []wasm.ValueType{funcRef, i64}},
    69  			expected: []byte{0x60, 2, i32, funcRef, 2, funcRef, i64},
    70  		},
    71  		{
    72  			name:     "two param two results with externrefs",
    73  			input:    wasm.FunctionType{Params: []wasm.ValueType{i32, externRef}, Results: []wasm.ValueType{externRef, i64}},
    74  			expected: []byte{0x60, 2, i32, externRef, 2, externRef, i64},
    75  		},
    76  	}
    77  
    78  	for _, tt := range tests {
    79  		tc := tt
    80  
    81  		b := binaryencoding.EncodeFunctionType(&tc.input)
    82  		t.Run(fmt.Sprintf("encode - %s", tc.name), func(t *testing.T) {
    83  			require.Equal(t, tc.expected, b)
    84  		})
    85  
    86  		t.Run(fmt.Sprintf("decode - %s", tc.name), func(t *testing.T) {
    87  			var actual wasm.FunctionType
    88  			err := decodeFunctionType(api.CoreFeaturesV2, bytes.NewReader(b), &actual)
    89  			require.NoError(t, err)
    90  			// Set the FunctionType key on the input.
    91  			_ = tc.input.String()
    92  			require.Equal(t, actual, tc.input)
    93  		})
    94  	}
    95  }
    96  
    97  func TestDecodeFunctionType_Errors(t *testing.T) {
    98  	i32, i64 := wasm.ValueTypeI32, wasm.ValueTypeI64
    99  	tests := []struct {
   100  		name            string
   101  		input           []byte
   102  		enabledFeatures api.CoreFeatures
   103  		expectedErr     string
   104  	}{
   105  		{
   106  			name:        "undefined param no result",
   107  			input:       []byte{0x60, 1, 0x6e, 0},
   108  			expectedErr: "could not read parameter types: invalid value type: 110",
   109  		},
   110  		{
   111  			name:        "no param undefined result",
   112  			input:       []byte{0x60, 0, 1, 0x6e},
   113  			expectedErr: "could not read result types: invalid value type: 110",
   114  		},
   115  		{
   116  			name:        "undefined param undefined result",
   117  			input:       []byte{0x60, 1, 0x6e, 1, 0x6e},
   118  			expectedErr: "could not read parameter types: invalid value type: 110",
   119  		},
   120  		{
   121  			name:        "no param two results - multi-value not enabled",
   122  			input:       []byte{0x60, 0, 2, i32, i64},
   123  			expectedErr: "multiple result types invalid as feature \"multi-value\" is disabled",
   124  		},
   125  		{
   126  			name:        "one param two results - multi-value not enabled",
   127  			input:       []byte{0x60, 1, i64, 2, i32, i64},
   128  			expectedErr: "multiple result types invalid as feature \"multi-value\" is disabled",
   129  		},
   130  		{
   131  			name:        "two param two results - multi-value not enabled",
   132  			input:       []byte{0x60, 2, i32, i64, 2, i32, i64},
   133  			expectedErr: "multiple result types invalid as feature \"multi-value\" is disabled",
   134  		},
   135  	}
   136  
   137  	for _, tt := range tests {
   138  		tc := tt
   139  
   140  		t.Run(tc.name, func(t *testing.T) {
   141  			var actual wasm.FunctionType
   142  			err := decodeFunctionType(api.CoreFeaturesV1, bytes.NewReader(tc.input), &actual)
   143  			require.EqualError(t, err, tc.expectedErr)
   144  		})
   145  	}
   146  }