wa-lang.org/wazero@v1.0.2/internal/wasm/binary/function_test.go (about)

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