github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/api/wasm_test.go (about)

     1  package api
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"testing"
     7  	"unsafe"
     8  
     9  	"github.com/wasilibs/wazerox/internal/testing/require"
    10  )
    11  
    12  func TestExternTypeName(t *testing.T) {
    13  	tests := []struct {
    14  		name     string
    15  		input    ExternType
    16  		expected string
    17  	}{
    18  		{"func", ExternTypeFunc, "func"},
    19  		{"table", ExternTypeTable, "table"},
    20  		{"mem", ExternTypeMemory, "memory"},
    21  		{"global", ExternTypeGlobal, "global"},
    22  		{"unknown", 100, "0x64"},
    23  	}
    24  
    25  	for _, tt := range tests {
    26  		tc := tt
    27  
    28  		t.Run(tc.name, func(t *testing.T) {
    29  			require.Equal(t, tc.expected, ExternTypeName(tc.input))
    30  		})
    31  	}
    32  }
    33  
    34  func TestValueTypeName(t *testing.T) {
    35  	tests := []struct {
    36  		name     string
    37  		input    ValueType
    38  		expected string
    39  	}{
    40  		{"i32", ValueTypeI32, "i32"},
    41  		{"i64", ValueTypeI64, "i64"},
    42  		{"f32", ValueTypeF32, "f32"},
    43  		{"f64", ValueTypeF64, "f64"},
    44  		{"externref", ValueTypeExternref, "externref"},
    45  		{"unknown", 100, "unknown"},
    46  	}
    47  
    48  	for _, tt := range tests {
    49  		tc := tt
    50  
    51  		t.Run(tc.name, func(t *testing.T) {
    52  			require.Equal(t, tc.expected, ValueTypeName(tc.input))
    53  		})
    54  	}
    55  }
    56  
    57  func TestEncodeDecodeExternRef(t *testing.T) {
    58  	for _, v := range []uintptr{
    59  		0, uintptr(unsafe.Pointer(t)),
    60  	} {
    61  		t.Run(fmt.Sprintf("%x", v), func(t *testing.T) {
    62  			encoded := EncodeExternref(v)
    63  			binary := DecodeExternref(encoded)
    64  			require.Equal(t, v, binary)
    65  		})
    66  	}
    67  }
    68  
    69  func TestEncodeDecodeF32(t *testing.T) {
    70  	for _, v := range []float32{
    71  		0, 100, -100, 1, -1,
    72  		100.01234124, -100.01234124, 200.12315,
    73  		math.MaxFloat32,
    74  		math.SmallestNonzeroFloat32,
    75  		float32(math.Inf(1)), float32(math.Inf(-1)), float32(math.NaN()),
    76  	} {
    77  		t.Run(fmt.Sprintf("%f", v), func(t *testing.T) {
    78  			encoded := EncodeF32(v)
    79  			binary := DecodeF32(encoded)
    80  			require.Zero(t, encoded>>32)     // Ensures high bits aren't set
    81  			if math.IsNaN(float64(binary)) { // NaN cannot be compared with themselves, so we have to use IsNaN
    82  				require.True(t, math.IsNaN(float64(binary)))
    83  			} else {
    84  				require.Equal(t, v, binary)
    85  			}
    86  		})
    87  	}
    88  }
    89  
    90  func TestEncodeDecodeF64(t *testing.T) {
    91  	for _, v := range []float64{
    92  		0, 100, -100, 1, -1,
    93  		100.01234124, -100.01234124, 200.12315,
    94  		math.MaxFloat32,
    95  		math.SmallestNonzeroFloat32,
    96  		math.MaxFloat64,
    97  		math.SmallestNonzeroFloat64,
    98  		6.8719476736e+10,  /* = 1 << 36 */
    99  		1.37438953472e+11, /* = 1 << 37 */
   100  		math.Inf(1), math.Inf(-1), math.NaN(),
   101  	} {
   102  		t.Run(fmt.Sprintf("%f", v), func(t *testing.T) {
   103  			encoded := EncodeF64(v)
   104  			val := DecodeF64(encoded)
   105  			if math.IsNaN(val) { // cannot use require.Equal as NaN by definition doesn't equal itself
   106  				require.True(t, math.IsNaN(val))
   107  			} else {
   108  				require.Equal(t, v, val)
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestEncodeI32(t *testing.T) {
   115  	for _, v := range []int32{
   116  		0, 100, -100, 1, -1,
   117  		math.MaxInt32,
   118  		math.MinInt32,
   119  	} {
   120  		t.Run(fmt.Sprintf("%d", v), func(t *testing.T) {
   121  			encoded := EncodeI32(v)
   122  			require.Zero(t, encoded>>32) // Ensures high bits aren't set
   123  			binary := int32(encoded)
   124  			require.Equal(t, v, binary)
   125  		})
   126  	}
   127  }
   128  
   129  func TestDecodeI32(t *testing.T) {
   130  	mini32 := math.MinInt32
   131  	for _, tc := range []struct {
   132  		in  uint64
   133  		exp int32
   134  	}{
   135  		{in: 0, exp: 0},
   136  		{in: 1 << 60, exp: 0},
   137  		{in: 1 << 30, exp: 1 << 30},
   138  		{in: 1<<30 | 1<<60, exp: 1 << 30},
   139  		{in: uint64(uint32(mini32)) | 1<<59, exp: math.MinInt32},
   140  		{in: uint64(uint32(math.MaxInt32)) | 1<<50, exp: math.MaxInt32},
   141  	} {
   142  		decoded := DecodeI32(tc.in)
   143  		require.Equal(t, tc.exp, decoded)
   144  	}
   145  }
   146  
   147  func TestEncodeU32(t *testing.T) {
   148  	for _, v := range []uint32{
   149  		0, 100, 1, 1 << 31,
   150  		math.MaxInt32,
   151  		math.MaxUint32,
   152  	} {
   153  		t.Run(fmt.Sprintf("%d", v), func(t *testing.T) {
   154  			encoded := EncodeU32(v)
   155  			require.Zero(t, encoded>>32) // Ensures high bits aren't set
   156  			require.Equal(t, v, uint32(encoded))
   157  		})
   158  	}
   159  }
   160  
   161  func TestDecodeU32(t *testing.T) {
   162  	mini32 := math.MinInt32
   163  	for _, tc := range []struct {
   164  		in  uint64
   165  		exp uint32
   166  	}{
   167  		{in: 0, exp: 0},
   168  		{in: 1 << 60, exp: 0},
   169  		{in: 1 << 30, exp: 1 << 30},
   170  		{in: 1<<30 | 1<<60, exp: 1 << 30},
   171  		{in: uint64(uint32(mini32)) | 1<<59, exp: uint32(mini32)},
   172  		{in: uint64(uint32(math.MaxInt32)) | 1<<50, exp: math.MaxInt32},
   173  	} {
   174  		decoded := DecodeU32(tc.in)
   175  		require.Equal(t, tc.exp, decoded)
   176  	}
   177  }
   178  
   179  func TestEncodeI64(t *testing.T) {
   180  	for _, v := range []int64{
   181  		0, 100, -100, 1, -1,
   182  		math.MaxInt64,
   183  		math.MinInt64,
   184  	} {
   185  		t.Run(fmt.Sprintf("%d", v), func(t *testing.T) {
   186  			encoded := EncodeI64(v)
   187  			binary := int64(encoded)
   188  			require.Equal(t, v, binary)
   189  		})
   190  	}
   191  }