github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/api/wasm_test.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "math" 6 "testing" 7 "unsafe" 8 9 "github.com/bananabytelabs/wazero/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 }