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

     1  package binary
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
     8  	"github.com/tetratelabs/wazero/internal/testing/require"
     9  	"github.com/tetratelabs/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  }