github.com/tetratelabs/wazero@v1.2.1/config_test.go (about)

     1  package wazero
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	_ "embed"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/tetratelabs/wazero/api"
    11  	"github.com/tetratelabs/wazero/internal/fstest"
    12  	"github.com/tetratelabs/wazero/internal/platform"
    13  	internalsys "github.com/tetratelabs/wazero/internal/sys"
    14  	"github.com/tetratelabs/wazero/internal/sysfs"
    15  	testfs "github.com/tetratelabs/wazero/internal/testing/fs"
    16  	"github.com/tetratelabs/wazero/internal/testing/require"
    17  	"github.com/tetratelabs/wazero/internal/wasm"
    18  	"github.com/tetratelabs/wazero/sys"
    19  )
    20  
    21  func TestRuntimeConfig(t *testing.T) {
    22  	tests := []struct {
    23  		name     string
    24  		with     func(RuntimeConfig) RuntimeConfig
    25  		expected RuntimeConfig
    26  	}{
    27  		{
    28  			name: "features",
    29  			with: func(c RuntimeConfig) RuntimeConfig {
    30  				return c.WithCoreFeatures(api.CoreFeaturesV1)
    31  			},
    32  			expected: &runtimeConfig{
    33  				enabledFeatures: api.CoreFeaturesV1,
    34  			},
    35  		},
    36  		{
    37  			name: "memoryLimitPages",
    38  			with: func(c RuntimeConfig) RuntimeConfig {
    39  				return c.WithMemoryLimitPages(10)
    40  			},
    41  			expected: &runtimeConfig{
    42  				memoryLimitPages: 10,
    43  			},
    44  		},
    45  		{
    46  			name: "memoryCapacityFromMax",
    47  			with: func(c RuntimeConfig) RuntimeConfig {
    48  				return c.WithMemoryCapacityFromMax(true)
    49  			},
    50  			expected: &runtimeConfig{
    51  				memoryCapacityFromMax: true,
    52  			},
    53  		},
    54  		{
    55  			name: "WithDebugInfoEnabled",
    56  			with: func(c RuntimeConfig) RuntimeConfig {
    57  				return c.WithDebugInfoEnabled(false)
    58  			},
    59  			expected: &runtimeConfig{
    60  				dwarfDisabled: true, // dwarf is a more technical name and ok here.
    61  			},
    62  		},
    63  		{
    64  			name: "WithCustomSections",
    65  			with: func(c RuntimeConfig) RuntimeConfig {
    66  				return c.WithCustomSections(true)
    67  			},
    68  			expected: &runtimeConfig{
    69  				storeCustomSections: true,
    70  			},
    71  		},
    72  		{
    73  			name:     "WithCloseOnContextDone",
    74  			with:     func(c RuntimeConfig) RuntimeConfig { return c.WithCloseOnContextDone(true) },
    75  			expected: &runtimeConfig{ensureTermination: true},
    76  		},
    77  	}
    78  
    79  	for _, tt := range tests {
    80  		tc := tt
    81  
    82  		t.Run(tc.name, func(t *testing.T) {
    83  			input := &runtimeConfig{}
    84  			rc := tc.with(input)
    85  			require.Equal(t, tc.expected, rc)
    86  			// The source wasn't modified
    87  			require.Equal(t, &runtimeConfig{}, input)
    88  		})
    89  	}
    90  
    91  	t.Run("memoryLimitPages invalid panics", func(t *testing.T) {
    92  		err := require.CapturePanic(func() {
    93  			input := &runtimeConfig{}
    94  			input.WithMemoryLimitPages(wasm.MemoryLimitPages + 1)
    95  		})
    96  		require.EqualError(t, err, "memoryLimitPages invalid: 65537 > 65536")
    97  	})
    98  }
    99  
   100  func TestModuleConfig(t *testing.T) {
   101  	tests := []struct {
   102  		name          string
   103  		with          func(ModuleConfig) ModuleConfig
   104  		expectNameSet bool
   105  		expectedName  string
   106  	}{
   107  		{
   108  			name: "WithName default",
   109  			with: func(c ModuleConfig) ModuleConfig {
   110  				return c
   111  			},
   112  			expectNameSet: false,
   113  			expectedName:  "",
   114  		},
   115  		{
   116  			name: "WithName",
   117  			with: func(c ModuleConfig) ModuleConfig {
   118  				return c.WithName("wazero")
   119  			},
   120  			expectNameSet: true,
   121  			expectedName:  "wazero",
   122  		},
   123  		{
   124  			name: "WithName empty",
   125  			with: func(c ModuleConfig) ModuleConfig {
   126  				return c.WithName("")
   127  			},
   128  			expectNameSet: true,
   129  			expectedName:  "",
   130  		},
   131  		{
   132  			name: "WithName twice",
   133  			with: func(c ModuleConfig) ModuleConfig {
   134  				return c.WithName("wazero").WithName("wa0")
   135  			},
   136  			expectNameSet: true,
   137  			expectedName:  "wa0",
   138  		},
   139  		{
   140  			name: "WithName can clear",
   141  			with: func(c ModuleConfig) ModuleConfig {
   142  				return c.WithName("wazero").WithName("")
   143  			},
   144  			expectNameSet: true,
   145  			expectedName:  "",
   146  		},
   147  	}
   148  	for _, tt := range tests {
   149  		tc := tt
   150  
   151  		t.Run(tc.name, func(t *testing.T) {
   152  			input := NewModuleConfig()
   153  			rc := tc.with(input)
   154  			require.Equal(t, tc.expectNameSet, rc.(*moduleConfig).nameSet)
   155  			require.Equal(t, tc.expectedName, rc.(*moduleConfig).name)
   156  			// The source wasn't modified
   157  			require.Equal(t, NewModuleConfig(), input)
   158  		})
   159  	}
   160  }
   161  
   162  // TestModuleConfig_toSysContext only tests the cases that change the inputs to
   163  // sys.NewContext.
   164  func TestModuleConfig_toSysContext(t *testing.T) {
   165  	base := NewModuleConfig()
   166  
   167  	tests := []struct {
   168  		name  string
   169  		input func() (mc ModuleConfig, verify func(t *testing.T, sys *internalsys.Context))
   170  	}{
   171  		{
   172  			name: "empty",
   173  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   174  				return base, func(t *testing.T, sys *internalsys.Context) { require.NotNil(t, sys) }
   175  			},
   176  		},
   177  		{
   178  			name: "WithNanotime",
   179  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   180  				config := base.WithNanotime(func() int64 { return 1234567 }, 54321)
   181  				return config, func(t *testing.T, sys *internalsys.Context) {
   182  					require.Equal(t, 1234567, int(sys.Nanotime()))
   183  					require.Equal(t, 54321, int(sys.NanotimeResolution()))
   184  				}
   185  			},
   186  		},
   187  		{
   188  			name: "WithSysNanotime",
   189  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   190  				config := base.WithSysNanotime()
   191  				return config, func(t *testing.T, sys *internalsys.Context) {
   192  					require.Equal(t, int(1), int(sys.NanotimeResolution()))
   193  				}
   194  			},
   195  		},
   196  		{
   197  			name: "WithWalltime",
   198  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   199  				config := base.WithWalltime(func() (sec int64, nsec int32) { return 5, 10 }, 54321)
   200  				return config, func(t *testing.T, sys *internalsys.Context) {
   201  					actualSec, actualNano := sys.Walltime()
   202  					require.Equal(t, 5, int(actualSec))
   203  					require.Equal(t, 10, int(actualNano))
   204  					require.Equal(t, 54321, int(sys.WalltimeResolution()))
   205  				}
   206  			},
   207  		},
   208  		{
   209  			name: "WithSysWalltime",
   210  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   211  				config := base.WithSysWalltime()
   212  				return config, func(t *testing.T, sys *internalsys.Context) {
   213  					require.Equal(t, int(time.Microsecond.Nanoseconds()), int(sys.WalltimeResolution()))
   214  				}
   215  			},
   216  		},
   217  		{
   218  			name: "WithArgs empty",
   219  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   220  				config := base.WithArgs()
   221  				return config, func(t *testing.T, sys *internalsys.Context) {
   222  					args := sys.Args()
   223  					require.Equal(t, 0, len(args))
   224  				}
   225  			},
   226  		},
   227  		{
   228  			name: "WithArgs",
   229  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   230  				config := base.WithArgs("a", "bc")
   231  				return config, func(t *testing.T, sys *internalsys.Context) {
   232  					args := sys.Args()
   233  					require.Equal(t, 2, len(args))
   234  					require.Equal(t, "a", string(args[0]))
   235  					require.Equal(t, "bc", string(args[1]))
   236  				}
   237  			},
   238  		},
   239  		{
   240  			name: "WithArgs empty ok", // Particularly argv[0] can be empty, and we have no rules about others.
   241  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   242  				config := base.WithArgs("", "bc")
   243  				return config, func(t *testing.T, sys *internalsys.Context) {
   244  					args := sys.Args()
   245  					require.Equal(t, 2, len(args))
   246  					require.Equal(t, "", string(args[0]))
   247  					require.Equal(t, "bc", string(args[1]))
   248  				}
   249  			},
   250  		},
   251  		{
   252  			name: "WithArgs second call overwrites",
   253  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   254  				config := base.WithArgs("a", "bc").WithArgs("bc", "a")
   255  				return config, func(t *testing.T, sys *internalsys.Context) {
   256  					args := sys.Args()
   257  					require.Equal(t, 2, len(args))
   258  					require.Equal(t, "bc", string(args[0]))
   259  					require.Equal(t, "a", string(args[1]))
   260  				}
   261  			},
   262  		},
   263  		{
   264  			name: "WithEnv",
   265  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   266  				config := base.WithEnv("a", "b")
   267  				return config, func(t *testing.T, sys *internalsys.Context) {
   268  					envs := sys.Environ()
   269  					require.Equal(t, 1, len(envs))
   270  					require.Equal(t, "a=b", string(envs[0]))
   271  				}
   272  			},
   273  		},
   274  		{
   275  			name: "WithEnv empty value",
   276  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   277  				config := base.WithEnv("a", "")
   278  				return config, func(t *testing.T, sys *internalsys.Context) {
   279  					envs := sys.Environ()
   280  					require.Equal(t, 1, len(envs))
   281  					require.Equal(t, "a=", string(envs[0]))
   282  				}
   283  			},
   284  		},
   285  		{
   286  			name: "WithEnv twice",
   287  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   288  				config := base.WithEnv("a", "b").WithEnv("c", "de")
   289  				return config, func(t *testing.T, sys *internalsys.Context) {
   290  					envs := sys.Environ()
   291  					require.Equal(t, 2, len(envs))
   292  					require.Equal(t, "a=b", string(envs[0]))
   293  					require.Equal(t, "c=de", string(envs[1]))
   294  				}
   295  			},
   296  		},
   297  		{
   298  			name: "WithEnv overwrites",
   299  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   300  				config := base.WithEnv("a", "bc").WithEnv("c", "de").WithEnv("a", "ff")
   301  				return config, func(t *testing.T, sys *internalsys.Context) {
   302  					envs := sys.Environ()
   303  					require.Equal(t, 2, len(envs))
   304  					require.Equal(t, "a=ff", string(envs[0]))
   305  					require.Equal(t, "c=de", string(envs[1]))
   306  				}
   307  			},
   308  		},
   309  		{
   310  			name: "WithEnv twice",
   311  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   312  				config := base.WithEnv("a", "b").WithEnv("c", "de")
   313  				return config, func(t *testing.T, sys *internalsys.Context) {
   314  					envs := sys.Environ()
   315  					require.Equal(t, 2, len(envs))
   316  					require.Equal(t, "a=b", string(envs[0]))
   317  					require.Equal(t, "c=de", string(envs[1]))
   318  				}
   319  			},
   320  		},
   321  		{
   322  			name: "WithFS",
   323  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   324  				testFS := &testfs.FS{}
   325  				config := base.WithFS(testFS)
   326  				return config, func(t *testing.T, sys *internalsys.Context) {
   327  					rootfs := sys.FS().RootFS()
   328  					require.Equal(t, sysfs.Adapt(testFS), rootfs)
   329  				}
   330  			},
   331  		},
   332  		{
   333  			name: "WithFS overwrites",
   334  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   335  				testFS, testFS2 := &testfs.FS{}, &testfs.FS{}
   336  				config := base.WithFS(testFS).WithFS(testFS2)
   337  				return config, func(t *testing.T, sys *internalsys.Context) {
   338  					rootfs := sys.FS().RootFS()
   339  					require.Equal(t, sysfs.Adapt(testFS2), rootfs)
   340  				}
   341  			},
   342  		},
   343  		{
   344  			name: "WithFS nil",
   345  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   346  				config := base.WithFS(nil)
   347  				return config, func(t *testing.T, sys *internalsys.Context) {
   348  					rootfs := sys.FS().RootFS()
   349  					require.Equal(t, sysfs.Adapt(nil), rootfs)
   350  				}
   351  			},
   352  		},
   353  		{
   354  			name: "WithRandSource",
   355  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   356  				r := bytes.NewReader([]byte{1, 2, 3, 4})
   357  				config := base.WithRandSource(r)
   358  				return config, func(t *testing.T, sys *internalsys.Context) {
   359  					actual := sys.RandSource()
   360  					require.Equal(t, r, actual)
   361  				}
   362  			},
   363  		},
   364  		{
   365  			name: "WithRandSource nil",
   366  			input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
   367  				config := base.WithRandSource(nil)
   368  				return config, func(t *testing.T, sys *internalsys.Context) {
   369  					actual := sys.RandSource()
   370  					require.Equal(t, platform.NewFakeRandSource(), actual)
   371  				}
   372  			},
   373  		},
   374  	}
   375  
   376  	for _, tt := range tests {
   377  		tc := tt
   378  
   379  		t.Run(tc.name, func(t *testing.T) {
   380  			config, verify := tc.input()
   381  			actual, err := config.(*moduleConfig).toSysContext()
   382  			require.NoError(t, err)
   383  			verify(t, actual)
   384  		})
   385  	}
   386  }
   387  
   388  // TestModuleConfig_toSysContext_WithWalltime has to test differently because we can't
   389  // compare function pointers when functions are passed by value.
   390  func TestModuleConfig_toSysContext_WithWalltime(t *testing.T) {
   391  	tests := []struct {
   392  		name               string
   393  		input              ModuleConfig
   394  		expectedSec        int64
   395  		expectedNsec       int32
   396  		expectedResolution sys.ClockResolution
   397  		expectedErr        string
   398  	}{
   399  		{
   400  			name: "ok",
   401  			input: NewModuleConfig().
   402  				WithWalltime(func() (sec int64, nsec int32) {
   403  					return 1, 2
   404  				}, 3),
   405  			expectedSec:        1,
   406  			expectedNsec:       2,
   407  			expectedResolution: 3,
   408  		},
   409  		{
   410  			name: "overwrites",
   411  			input: NewModuleConfig().
   412  				WithWalltime(func() (sec int64, nsec int32) {
   413  					return 3, 4
   414  				}, 5).
   415  				WithWalltime(func() (sec int64, nsec int32) {
   416  					return 1, 2
   417  				}, 3),
   418  			expectedSec:        1,
   419  			expectedNsec:       2,
   420  			expectedResolution: 3,
   421  		},
   422  		{
   423  			name: "invalid resolution",
   424  			input: NewModuleConfig().
   425  				WithWalltime(func() (sec int64, nsec int32) {
   426  					return 1, 2
   427  				}, 0),
   428  			expectedErr: "invalid Walltime resolution: 0",
   429  		},
   430  	}
   431  
   432  	for _, tt := range tests {
   433  		tc := tt
   434  
   435  		t.Run(tc.name, func(t *testing.T) {
   436  			sysCtx, err := tc.input.(*moduleConfig).toSysContext()
   437  			if tc.expectedErr == "" {
   438  				require.Nil(t, err)
   439  				sec, nsec := sysCtx.Walltime()
   440  				require.Equal(t, tc.expectedSec, sec)
   441  				require.Equal(t, tc.expectedNsec, nsec)
   442  				require.Equal(t, tc.expectedResolution, sysCtx.WalltimeResolution())
   443  			} else {
   444  				require.EqualError(t, err, tc.expectedErr)
   445  			}
   446  		})
   447  	}
   448  
   449  	t.Run("context", func(t *testing.T) {
   450  		sysCtx, err := NewModuleConfig().
   451  			WithWalltime(func() (sec int64, nsec int32) {
   452  				return 1, 2
   453  			}, 3).(*moduleConfig).toSysContext()
   454  		require.NoError(t, err)
   455  		sec, nsec := sysCtx.Walltime()
   456  		// If below pass, the context was correct!
   457  		require.Equal(t, int64(1), sec)
   458  		require.Equal(t, int32(2), nsec)
   459  	})
   460  }
   461  
   462  // TestModuleConfig_toSysContext_WithNanotime has to test differently because we can't
   463  // compare function pointers when functions are passed by value.
   464  func TestModuleConfig_toSysContext_WithNanotime(t *testing.T) {
   465  	tests := []struct {
   466  		name               string
   467  		input              ModuleConfig
   468  		expectedNanos      int64
   469  		expectedResolution sys.ClockResolution
   470  		expectedErr        string
   471  	}{
   472  		{
   473  			name: "ok",
   474  			input: NewModuleConfig().
   475  				WithNanotime(func() int64 {
   476  					return 1
   477  				}, 2),
   478  			expectedNanos:      1,
   479  			expectedResolution: 2,
   480  		},
   481  		{
   482  			name: "overwrites",
   483  			input: NewModuleConfig().
   484  				WithNanotime(func() int64 {
   485  					return 3
   486  				}, 4).
   487  				WithNanotime(func() int64 {
   488  					return 1
   489  				}, 2),
   490  			expectedNanos:      1,
   491  			expectedResolution: 2,
   492  		},
   493  		{
   494  			name: "invalid resolution",
   495  			input: NewModuleConfig().
   496  				WithNanotime(func() int64 {
   497  					return 1
   498  				}, 0),
   499  			expectedErr: "invalid Nanotime resolution: 0",
   500  		},
   501  	}
   502  
   503  	for _, tt := range tests {
   504  		tc := tt
   505  
   506  		t.Run(tc.name, func(t *testing.T) {
   507  			sysCtx, err := tc.input.(*moduleConfig).toSysContext()
   508  			if tc.expectedErr == "" {
   509  				require.Nil(t, err)
   510  				nanos := sysCtx.Nanotime()
   511  				require.Equal(t, tc.expectedNanos, nanos)
   512  				require.Equal(t, tc.expectedResolution, sysCtx.NanotimeResolution())
   513  			} else {
   514  				require.EqualError(t, err, tc.expectedErr)
   515  			}
   516  		})
   517  	}
   518  }
   519  
   520  // TestModuleConfig_toSysContext_WithNanosleep has to test differently because
   521  // we can't compare function pointers when functions are passed by value.
   522  func TestModuleConfig_toSysContext_WithNanosleep(t *testing.T) {
   523  	sysCtx, err := NewModuleConfig().
   524  		WithNanosleep(func(ns int64) {
   525  			require.Equal(t, int64(2), ns)
   526  		}).(*moduleConfig).toSysContext()
   527  	require.NoError(t, err)
   528  	sysCtx.Nanosleep(2)
   529  }
   530  
   531  // TestModuleConfig_toSysContext_WithOsyield has to test differently because
   532  // we can't compare function pointers when functions are passed by value.
   533  func TestModuleConfig_toSysContext_WithOsyield(t *testing.T) {
   534  	var yielded bool
   535  	sysCtx, err := NewModuleConfig().
   536  		WithOsyield(func() {
   537  			yielded = true
   538  		}).(*moduleConfig).toSysContext()
   539  	require.NoError(t, err)
   540  	sysCtx.Osyield()
   541  	require.True(t, yielded)
   542  }
   543  
   544  func TestModuleConfig_toSysContext_Errors(t *testing.T) {
   545  	tests := []struct {
   546  		name        string
   547  		input       ModuleConfig
   548  		expectedErr string
   549  	}{
   550  		{
   551  			name:        "WithArgs arg contains NUL",
   552  			input:       NewModuleConfig().WithArgs("", string([]byte{'a', 0})),
   553  			expectedErr: "args invalid: contains NUL character",
   554  		},
   555  		{
   556  			name:        "WithEnv key contains NUL",
   557  			input:       NewModuleConfig().WithEnv(string([]byte{'a', 0}), "a"),
   558  			expectedErr: "environ invalid: contains NUL character",
   559  		},
   560  		{
   561  			name:        "WithEnv value contains NUL",
   562  			input:       NewModuleConfig().WithEnv("a", string([]byte{'a', 0})),
   563  			expectedErr: "environ invalid: contains NUL character",
   564  		},
   565  		{
   566  			name:        "WithEnv key contains equals",
   567  			input:       NewModuleConfig().WithEnv("a=", "a"),
   568  			expectedErr: "environ invalid: key contains '=' character",
   569  		},
   570  		{
   571  			name:        "WithEnv empty key",
   572  			input:       NewModuleConfig().WithEnv("", "a"),
   573  			expectedErr: "environ invalid: empty key",
   574  		},
   575  	}
   576  	for _, tt := range tests {
   577  		tc := tt
   578  
   579  		t.Run(tc.name, func(t *testing.T) {
   580  			_, err := tc.input.(*moduleConfig).toSysContext()
   581  			require.EqualError(t, err, tc.expectedErr)
   582  		})
   583  	}
   584  }
   585  
   586  func TestModuleConfig_clone(t *testing.T) {
   587  	mc := NewModuleConfig().(*moduleConfig)
   588  	cloned := mc.clone()
   589  
   590  	// Make post-clone changes
   591  	mc.fsConfig = NewFSConfig().WithFSMount(fstest.FS, "/")
   592  	mc.environKeys["2"] = 2
   593  
   594  	cloned.environKeys["1"] = 1
   595  
   596  	// Ensure the maps are not shared
   597  	require.Equal(t, map[string]int{"2": 2}, mc.environKeys)
   598  	require.Equal(t, map[string]int{"1": 1}, cloned.environKeys)
   599  
   600  	// Ensure the fs is not shared
   601  	require.Nil(t, cloned.fsConfig)
   602  }
   603  
   604  func Test_compiledModule_Name(t *testing.T) {
   605  	tests := []struct {
   606  		name     string
   607  		input    *compiledModule
   608  		expected string
   609  	}{
   610  		{
   611  			name:  "no name section",
   612  			input: &compiledModule{module: &wasm.Module{}},
   613  		},
   614  		{
   615  			name:  "empty name",
   616  			input: &compiledModule{module: &wasm.Module{NameSection: &wasm.NameSection{}}},
   617  		},
   618  		{
   619  			name:     "name",
   620  			input:    &compiledModule{module: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "foo"}}},
   621  			expected: "foo",
   622  		},
   623  	}
   624  
   625  	for _, tt := range tests {
   626  		tc := tt
   627  
   628  		t.Run(tc.name, func(t *testing.T) {
   629  			require.Equal(t, tc.expected, tc.input.Name())
   630  		})
   631  	}
   632  }
   633  
   634  func Test_compiledModule_CustomSections(t *testing.T) {
   635  	tests := []struct {
   636  		name     string
   637  		input    *compiledModule
   638  		expected []string
   639  	}{
   640  		{
   641  			name:     "no custom section",
   642  			input:    &compiledModule{module: &wasm.Module{}},
   643  			expected: []string{},
   644  		},
   645  		{
   646  			name: "name",
   647  			input: &compiledModule{module: &wasm.Module{
   648  				CustomSections: []*wasm.CustomSection{
   649  					{Name: "custom1"},
   650  					{Name: "custom2"},
   651  					{Name: "customDup"},
   652  					{Name: "customDup"},
   653  				},
   654  			}},
   655  			expected: []string{
   656  				"custom1",
   657  				"custom2",
   658  				"customDup",
   659  				"customDup",
   660  			},
   661  		},
   662  	}
   663  
   664  	for _, tt := range tests {
   665  		tc := tt
   666  
   667  		t.Run(tc.name, func(t *testing.T) {
   668  			customSections := tc.input.CustomSections()
   669  			require.Equal(t, len(tc.expected), len(customSections))
   670  			for i := 0; i < len(tc.expected); i++ {
   671  				require.Equal(t, tc.expected[i], customSections[i].Name())
   672  			}
   673  		})
   674  	}
   675  }
   676  
   677  func Test_compiledModule_Close(t *testing.T) {
   678  	for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
   679  		e := &mockEngine{name: "1", cachedModules: map[*wasm.Module]struct{}{}}
   680  
   681  		var cs []*compiledModule
   682  		for i := 0; i < 10; i++ {
   683  			m := &wasm.Module{}
   684  			err := e.CompileModule(ctx, m, nil, false)
   685  			require.NoError(t, err)
   686  			cs = append(cs, &compiledModule{module: m, compiledEngine: e})
   687  		}
   688  
   689  		// Before Close.
   690  		require.Equal(t, 10, len(e.cachedModules))
   691  
   692  		for _, c := range cs {
   693  			require.NoError(t, c.Close(ctx))
   694  		}
   695  
   696  		// After Close.
   697  		require.Zero(t, len(e.cachedModules))
   698  	}
   699  }
   700  
   701  func TestNewRuntimeConfig(t *testing.T) {
   702  	c, ok := NewRuntimeConfig().(*runtimeConfig)
   703  	require.True(t, ok)
   704  	// Should be cloned from the source.
   705  	require.NotEqual(t, engineLessConfig, c)
   706  	// Ensures if the correct engine is selected.
   707  	if platform.CompilerSupported() {
   708  		require.Equal(t, engineKindCompiler, c.engineKind)
   709  	} else {
   710  		require.Equal(t, engineKindInterpreter, c.engineKind)
   711  	}
   712  }