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

     1  package wasm
     2  
     3  import (
     4  	"testing"
     5  
     6  	"wa-lang.org/wazero/internal/testing/require"
     7  )
     8  
     9  func TestModule_ImportFuncCount(t *testing.T) {
    10  	tests := []struct {
    11  		name     string
    12  		input    *Module
    13  		expected uint32
    14  	}{
    15  		{
    16  			name:  "none",
    17  			input: &Module{},
    18  		},
    19  		{
    20  			name:  "none with function section",
    21  			input: &Module{FunctionSection: []Index{0}},
    22  		},
    23  		{
    24  			name:     "one",
    25  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeFunc}}},
    26  			expected: 1,
    27  		},
    28  		{
    29  			name:     "one with function section",
    30  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeFunc}}, FunctionSection: []Index{0}},
    31  			expected: 1,
    32  		},
    33  		{
    34  			name:     "one with other imports",
    35  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeFunc}, {Type: ExternTypeMemory}}},
    36  			expected: 1,
    37  		},
    38  		{
    39  			name:     "two",
    40  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeFunc}, {Type: ExternTypeFunc}}},
    41  			expected: 2,
    42  		},
    43  	}
    44  
    45  	for _, tt := range tests {
    46  		tc := tt
    47  
    48  		t.Run(tc.name, func(t *testing.T) {
    49  			require.Equal(t, tc.expected, tc.input.ImportFuncCount())
    50  		})
    51  	}
    52  }
    53  
    54  func TestModule_ImportTableCount(t *testing.T) {
    55  	tests := []struct {
    56  		name     string
    57  		input    *Module
    58  		expected uint32
    59  	}{
    60  		{
    61  			name:  "none",
    62  			input: &Module{},
    63  		},
    64  		{
    65  			name:  "none with table section",
    66  			input: &Module{TableSection: []*Table{{Min: 1, Max: nil}}},
    67  		},
    68  		{
    69  			name:     "one",
    70  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeTable}}},
    71  			expected: 1,
    72  		},
    73  		{
    74  			name: "one with table section",
    75  			input: &Module{
    76  				ImportSection: []*Import{{Type: ExternTypeTable}},
    77  				TableSection:  []*Table{{Min: 1, Max: nil}},
    78  			},
    79  			expected: 1,
    80  		},
    81  		{
    82  			name:     "one with other imports",
    83  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeTable}, {Type: ExternTypeMemory}}},
    84  			expected: 1,
    85  		},
    86  		{
    87  			name:     "two",
    88  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeTable}, {Type: ExternTypeTable}}},
    89  			expected: 2,
    90  		},
    91  	}
    92  
    93  	for _, tt := range tests {
    94  		tc := tt
    95  
    96  		t.Run(tc.name, func(t *testing.T) {
    97  			require.Equal(t, tc.expected, tc.input.ImportTableCount())
    98  		})
    99  	}
   100  }
   101  
   102  // TODO: once we fix up-front validation, this only needs to check zero or one
   103  func TestModule_ImportMemoryCount(t *testing.T) {
   104  	tests := []struct {
   105  		name     string
   106  		input    *Module
   107  		expected uint32
   108  	}{
   109  		{
   110  			name:  "none",
   111  			input: &Module{},
   112  		},
   113  		{
   114  			name:  "none with memory section",
   115  			input: &Module{MemorySection: &Memory{Min: 1}},
   116  		},
   117  		{
   118  			name:     "one",
   119  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeMemory}}},
   120  			expected: 1,
   121  		},
   122  		{
   123  			name: "one with memory section",
   124  			input: &Module{
   125  				ImportSection: []*Import{{Type: ExternTypeMemory}},
   126  				MemorySection: &Memory{Min: 1},
   127  			},
   128  			expected: 1,
   129  		},
   130  		{
   131  			name:     "one with other imports",
   132  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeMemory}, {Type: ExternTypeTable}}},
   133  			expected: 1,
   134  		},
   135  		{
   136  			name:     "two",
   137  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeMemory}, {Type: ExternTypeMemory}}},
   138  			expected: 2,
   139  		},
   140  	}
   141  
   142  	for _, tt := range tests {
   143  		tc := tt
   144  
   145  		t.Run(tc.name, func(t *testing.T) {
   146  			require.Equal(t, tc.expected, tc.input.ImportMemoryCount())
   147  		})
   148  	}
   149  }
   150  
   151  func TestModule_ImportGlobalCount(t *testing.T) {
   152  	tests := []struct {
   153  		name     string
   154  		input    *Module
   155  		expected uint32
   156  	}{
   157  		{
   158  			name:  "none",
   159  			input: &Module{},
   160  		},
   161  		{
   162  			name:  "none with global section",
   163  			input: &Module{GlobalSection: []*Global{{Type: &GlobalType{ValType: ValueTypeI64}}}},
   164  		},
   165  		{
   166  			name:     "one",
   167  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeGlobal}}},
   168  			expected: 1,
   169  		},
   170  		{
   171  			name: "one with global section",
   172  			input: &Module{
   173  				ImportSection: []*Import{{Type: ExternTypeGlobal}},
   174  				GlobalSection: []*Global{{Type: &GlobalType{ValType: ValueTypeI64}}},
   175  			},
   176  			expected: 1,
   177  		},
   178  		{
   179  			name:     "one with other imports",
   180  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeGlobal}, {Type: ExternTypeMemory}}},
   181  			expected: 1,
   182  		},
   183  		{
   184  			name:     "two",
   185  			input:    &Module{ImportSection: []*Import{{Type: ExternTypeGlobal}, {Type: ExternTypeGlobal}}},
   186  			expected: 2,
   187  		},
   188  	}
   189  
   190  	for _, tt := range tests {
   191  		tc := tt
   192  
   193  		t.Run(tc.name, func(t *testing.T) {
   194  			require.Equal(t, tc.expected, tc.input.ImportGlobalCount())
   195  		})
   196  	}
   197  }
   198  
   199  func TestModule_SectionElementCount(t *testing.T) {
   200  	i32, f32 := ValueTypeI32, ValueTypeF32
   201  	zero := uint32(0)
   202  	empty := &ConstantExpression{Opcode: OpcodeI32Const, Data: const0}
   203  
   204  	tests := []struct {
   205  		name     string
   206  		input    *Module
   207  		expected map[string]uint32
   208  	}{
   209  		{
   210  			name:     "empty",
   211  			input:    &Module{},
   212  			expected: map[string]uint32{},
   213  		},
   214  		{
   215  			name:     "NameSection",
   216  			input:    &Module{NameSection: &NameSection{ModuleName: "simple"}},
   217  			expected: map[string]uint32{"custom": 1},
   218  		},
   219  		{
   220  			name: "TypeSection",
   221  			input: &Module{
   222  				TypeSection: []*FunctionType{
   223  					{},
   224  					{Params: []ValueType{i32, i32}, Results: []ValueType{i32}},
   225  					{Params: []ValueType{i32, i32, i32, i32}, Results: []ValueType{i32}},
   226  				},
   227  			},
   228  			expected: map[string]uint32{"type": 3},
   229  		},
   230  		{
   231  			name: "TypeSection and ImportSection",
   232  			input: &Module{
   233  				TypeSection: []*FunctionType{
   234  					{Params: []ValueType{i32, i32}, Results: []ValueType{i32}},
   235  					{Params: []ValueType{f32, f32}, Results: []ValueType{f32}},
   236  				},
   237  				ImportSection: []*Import{
   238  					{
   239  						Module: "Math", Name: "Mul",
   240  						Type:     ExternTypeFunc,
   241  						DescFunc: 1,
   242  					}, {
   243  						Module: "Math", Name: "Add",
   244  						Type:     ExternTypeFunc,
   245  						DescFunc: 0,
   246  					},
   247  				},
   248  			},
   249  			expected: map[string]uint32{"import": 2, "type": 2},
   250  		},
   251  		{
   252  			name: "TypeSection, FunctionSection, CodeSection, ExportSection and StartSection",
   253  			input: &Module{
   254  				TypeSection:     []*FunctionType{{}},
   255  				FunctionSection: []Index{0},
   256  				CodeSection: []*Code{
   257  					{Body: []byte{OpcodeLocalGet, 0, OpcodeLocalGet, 1, OpcodeI32Add, OpcodeEnd}},
   258  				},
   259  				ExportSection: []*Export{
   260  					{Name: "AddInt", Type: ExternTypeFunc, Index: Index(0)},
   261  				},
   262  				StartSection: &zero,
   263  			},
   264  			expected: map[string]uint32{"code": 1, "export": 1, "function": 1, "start": 1, "type": 1},
   265  		},
   266  		{
   267  			name: "MemorySection and DataSection",
   268  			input: &Module{
   269  				MemorySection: &Memory{Min: 1},
   270  				DataSection:   []*DataSegment{{OffsetExpression: empty}},
   271  			},
   272  			expected: map[string]uint32{"data": 1, "memory": 1},
   273  		},
   274  		{
   275  			name: "TableSection and ElementSection",
   276  			input: &Module{
   277  				TableSection:   []*Table{{Min: 1}},
   278  				ElementSection: []*ElementSegment{{OffsetExpr: empty}},
   279  			},
   280  			expected: map[string]uint32{"element": 1, "table": 1},
   281  		},
   282  		{
   283  			name: "TableSection (multiple tables) and ElementSection",
   284  			input: &Module{
   285  				TableSection:   []*Table{{Min: 1}, {Min: 2}},
   286  				ElementSection: []*ElementSegment{{OffsetExpr: empty}},
   287  			},
   288  			expected: map[string]uint32{"element": 1, "table": 2},
   289  		},
   290  	}
   291  
   292  	for _, tt := range tests {
   293  		tc := tt
   294  
   295  		t.Run(tc.name, func(t *testing.T) {
   296  			actual := map[string]uint32{}
   297  			for i := SectionID(0); i <= SectionIDData; i++ {
   298  				if size := tc.input.SectionElementCount(i); size > 0 {
   299  					actual[SectionIDName(i)] = size
   300  				}
   301  			}
   302  			require.Equal(t, tc.expected, actual)
   303  		})
   304  	}
   305  }