github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/api/features_test.go (about)

     1  package api
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/bananabytelabs/wazero/internal/testing/require"
     7  )
     8  
     9  // TestCoreFeatures_ZeroIsInvalid reminds maintainers that a bitset cannot use zero as a flag!
    10  // This is why we start iota with 1.
    11  func TestCoreFeatures_ZeroIsInvalid(t *testing.T) {
    12  	f := CoreFeatures(0)
    13  	f = f.SetEnabled(0, true)
    14  	require.False(t, f.IsEnabled(0))
    15  }
    16  
    17  // TestCoreFeatures tests the bitset works as expected
    18  func TestCoreFeatures(t *testing.T) {
    19  	tests := []struct {
    20  		name    string
    21  		feature CoreFeatures
    22  	}{
    23  		{
    24  			name:    "one is the smallest flag",
    25  			feature: 1,
    26  		},
    27  		{
    28  			name:    "63 is the largest feature flag", // because uint64
    29  			feature: 1 << 63,
    30  		},
    31  	}
    32  
    33  	for _, tt := range tests {
    34  		tc := tt
    35  
    36  		t.Run(tc.name, func(t *testing.T) {
    37  			f := CoreFeatures(0)
    38  
    39  			// Defaults to false
    40  			require.False(t, f.IsEnabled(tc.feature))
    41  
    42  			// Set true makes it true
    43  			f = f.SetEnabled(tc.feature, true)
    44  			require.True(t, f.IsEnabled(tc.feature))
    45  
    46  			// Set false makes it false again
    47  			f = f.SetEnabled(tc.feature, false)
    48  			require.False(t, f.IsEnabled(tc.feature))
    49  		})
    50  	}
    51  }
    52  
    53  func TestCoreFeatures_String(t *testing.T) {
    54  	tests := []struct {
    55  		name     string
    56  		feature  CoreFeatures
    57  		expected string
    58  	}{
    59  		{name: "none", feature: 0, expected: ""},
    60  		{name: "mutable-global", feature: CoreFeatureMutableGlobal, expected: "mutable-global"},
    61  		{name: "sign-extension-ops", feature: CoreFeatureSignExtensionOps, expected: "sign-extension-ops"},
    62  		{name: "multi-value", feature: CoreFeatureMultiValue, expected: "multi-value"},
    63  		{name: "simd", feature: CoreFeatureSIMD, expected: "simd"},
    64  		{name: "features", feature: CoreFeatureMutableGlobal | CoreFeatureMultiValue, expected: "multi-value|mutable-global"},
    65  		{name: "undefined", feature: 1 << 63, expected: ""},
    66  		{
    67  			name: "2.0", feature: CoreFeaturesV2,
    68  			expected: "bulk-memory-operations|multi-value|mutable-global|" +
    69  				"nontrapping-float-to-int-conversion|reference-types|sign-extension-ops|simd",
    70  		},
    71  	}
    72  
    73  	for _, tt := range tests {
    74  		tc := tt
    75  		t.Run(tc.name, func(t *testing.T) {
    76  			require.Equal(t, tc.expected, tc.feature.String())
    77  		})
    78  	}
    79  }
    80  
    81  func TestCoreFeatures_Require(t *testing.T) {
    82  	tests := []struct {
    83  		name        string
    84  		feature     CoreFeatures
    85  		expectedErr string
    86  	}{
    87  		{name: "none", feature: 0, expectedErr: "feature \"mutable-global\" is disabled"},
    88  		{name: "mutable-global", feature: CoreFeatureMutableGlobal},
    89  		{name: "sign-extension-ops", feature: CoreFeatureSignExtensionOps, expectedErr: "feature \"mutable-global\" is disabled"},
    90  		{name: "multi-value", feature: CoreFeatureMultiValue, expectedErr: "feature \"mutable-global\" is disabled"},
    91  		{name: "undefined", feature: 1 << 63, expectedErr: "feature \"mutable-global\" is disabled"},
    92  	}
    93  
    94  	for _, tt := range tests {
    95  		tc := tt
    96  		t.Run(tc.name, func(t *testing.T) {
    97  			err := tc.feature.RequireEnabled(CoreFeatureMutableGlobal)
    98  			if tc.expectedErr != "" {
    99  				require.EqualError(t, err, tc.expectedErr)
   100  			} else {
   101  				require.NoError(t, err)
   102  			}
   103  		})
   104  	}
   105  }