github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/integration_test/spectest/spectest_test.go (about)

     1  package spectest
     2  
     3  import (
     4  	"encoding/json"
     5  	"math"
     6  	"testing"
     7  
     8  	"github.com/tetratelabs/wazero/internal/moremath"
     9  	"github.com/tetratelabs/wazero/internal/testing/require"
    10  	"github.com/tetratelabs/wazero/internal/wasm"
    11  )
    12  
    13  func Test_f32Equal(t *testing.T) {
    14  	tests := []struct {
    15  		f1, f2 float32
    16  		exp    bool
    17  	}{
    18  		{f1: 1.1, f2: 1.1, exp: true},
    19  		{f1: float32(math.NaN()), f2: float32(math.NaN()), exp: true},
    20  		{f1: float32(math.Inf(1)), f2: float32(math.Inf(1)), exp: true},
    21  		{f1: float32(math.Inf(-1)), f2: float32(math.Inf(-1)), exp: true},
    22  		{f1: 1.1, f2: -1.1, exp: false},
    23  		{f1: float32(math.NaN()), f2: -1.1, exp: false},
    24  		{f1: -1.1, f2: float32(math.NaN()), exp: false},
    25  		{f1: float32(math.NaN()), f2: float32(math.Inf(1)), exp: false},
    26  		{f1: float32(math.Inf(1)), f2: float32(math.NaN()), exp: false},
    27  		{f1: float32(math.NaN()), f2: float32(math.Inf(-1)), exp: false},
    28  		{f1: float32(math.Inf(-1)), f2: float32(math.NaN()), exp: false},
    29  		{
    30  			f1:  math.Float32frombits(moremath.F32CanonicalNaNBits),
    31  			f2:  math.Float32frombits(moremath.F32CanonicalNaNBits),
    32  			exp: true,
    33  		},
    34  		{
    35  			f1:  math.Float32frombits(moremath.F32CanonicalNaNBits),
    36  			f2:  math.Float32frombits(moremath.F32ArithmeticNaNBits),
    37  			exp: false,
    38  		},
    39  		{
    40  			f1:  math.Float32frombits(moremath.F32ArithmeticNaNBits),
    41  			f2:  math.Float32frombits(moremath.F32ArithmeticNaNBits),
    42  			exp: true,
    43  		},
    44  		{
    45  			f1: math.Float32frombits(moremath.F32ArithmeticNaNBits),
    46  			f2: math.Float32frombits(moremath.F32ArithmeticNaNBits | 1<<2),
    47  			// The Wasm spec doesn't differentiate different arithmetic nans.
    48  			exp: true,
    49  		},
    50  		{
    51  			f1: math.Float32frombits(moremath.F32CanonicalNaNBits),
    52  			f2: math.Float32frombits(moremath.F32CanonicalNaNBits | 1<<2),
    53  			// Canonical NaN is unique.
    54  			exp: false,
    55  		},
    56  	}
    57  
    58  	for i, tc := range tests {
    59  		require.Equal(t, tc.exp, f32Equal(tc.f1, tc.f2), i)
    60  	}
    61  }
    62  
    63  func Test_f64Equal(t *testing.T) {
    64  	tests := []struct {
    65  		f1, f2 float64
    66  		exp    bool
    67  	}{
    68  		{f1: 1.1, f2: 1.1, exp: true},
    69  		{f1: math.NaN(), f2: math.NaN(), exp: true},
    70  		{f1: math.Inf(1), f2: math.Inf(1), exp: true},
    71  		{f1: math.Inf(-1), f2: math.Inf(-1), exp: true},
    72  		{f1: 1.1, f2: -1.1, exp: false},
    73  		{f1: math.NaN(), f2: -1.1, exp: false},
    74  		{f1: -1.1, f2: math.NaN(), exp: false},
    75  		{f1: math.NaN(), f2: math.Inf(1), exp: false},
    76  		{f1: math.Inf(1), f2: math.NaN(), exp: false},
    77  		{f1: math.NaN(), f2: math.Inf(-1), exp: false},
    78  		{f1: math.Inf(-1), f2: math.NaN(), exp: false},
    79  		{
    80  			f1:  math.Float64frombits(moremath.F64CanonicalNaNBits),
    81  			f2:  math.Float64frombits(moremath.F64CanonicalNaNBits),
    82  			exp: true,
    83  		},
    84  		{
    85  			f1:  math.Float64frombits(moremath.F64CanonicalNaNBits),
    86  			f2:  math.Float64frombits(moremath.F64ArithmeticNaNBits),
    87  			exp: false,
    88  		},
    89  		{
    90  			f1:  math.Float64frombits(moremath.F64ArithmeticNaNBits),
    91  			f2:  math.Float64frombits(moremath.F64ArithmeticNaNBits),
    92  			exp: true,
    93  		},
    94  		{
    95  			f1: math.Float64frombits(moremath.F64ArithmeticNaNBits),
    96  			f2: math.Float64frombits(moremath.F64ArithmeticNaNBits | 1<<2),
    97  			// The Wasm spec doesn't differentiate different arithmetic nans.
    98  			exp: true,
    99  		},
   100  		{
   101  			f1: math.Float64frombits(moremath.F64CanonicalNaNBits),
   102  			f2: math.Float64frombits(moremath.F64CanonicalNaNBits | 1<<2),
   103  			// Canonical NaN is unique.
   104  			exp: false,
   105  		},
   106  	}
   107  
   108  	for i, tc := range tests {
   109  		require.Equal(t, tc.exp, f64Equal(tc.f1, tc.f2), i)
   110  	}
   111  }
   112  
   113  func Test_valuesEq(t *testing.T) {
   114  	i32, i64, f32, f64, v128 := wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeV128
   115  	tests := []struct {
   116  		name         string
   117  		exps, actual []uint64
   118  		valueTypes   []wasm.ValueType
   119  		laneTypes    map[int]laneType
   120  		expMatched   bool
   121  		expValuesMsg string
   122  	}{
   123  		{
   124  			name:       "matched/i32",
   125  			exps:       []uint64{0},
   126  			actual:     []uint64{0},
   127  			valueTypes: []wasm.ValueType{i32},
   128  			expMatched: true,
   129  		},
   130  		{
   131  			name:       "unmatched/i32",
   132  			exps:       []uint64{1},
   133  			actual:     []uint64{0},
   134  			valueTypes: []wasm.ValueType{i32},
   135  			expMatched: false,
   136  			expValuesMsg: `	have [0]
   137  	want [1]`,
   138  		},
   139  		{
   140  			name:       "unmatched/i32",
   141  			exps:       []uint64{math.MaxUint32},
   142  			actual:     []uint64{1123},
   143  			valueTypes: []wasm.ValueType{i32},
   144  			expMatched: false,
   145  			expValuesMsg: `	have [1123]
   146  	want [4294967295]`,
   147  		},
   148  		{
   149  			name:       "matched/i64",
   150  			exps:       []uint64{0},
   151  			actual:     []uint64{0},
   152  			valueTypes: []wasm.ValueType{i64},
   153  			expMatched: true,
   154  		},
   155  		{
   156  			name:       "unmatched/i64",
   157  			exps:       []uint64{1},
   158  			actual:     []uint64{0},
   159  			valueTypes: []wasm.ValueType{i64},
   160  			expMatched: false,
   161  			expValuesMsg: `	have [0]
   162  	want [1]`,
   163  		},
   164  		{
   165  			name:       "unmatched/i64",
   166  			exps:       []uint64{math.MaxUint64},
   167  			actual:     []uint64{1123},
   168  			valueTypes: []wasm.ValueType{i64},
   169  			expMatched: false,
   170  			expValuesMsg: `	have [1123]
   171  	want [18446744073709551615]`,
   172  		},
   173  		{
   174  			name:       "matched/f32",
   175  			exps:       []uint64{0},
   176  			actual:     []uint64{0},
   177  			valueTypes: []wasm.ValueType{f32},
   178  			expMatched: true,
   179  		},
   180  		{
   181  			name:       "unmatched/f32",
   182  			exps:       []uint64{uint64(math.Float32bits(-13123.1))},
   183  			actual:     []uint64{0},
   184  			valueTypes: []wasm.ValueType{f32},
   185  			expMatched: false,
   186  			expValuesMsg: `	have [0.000000]
   187  	want [-13123.099609]`,
   188  		},
   189  		{
   190  			name:       "matched/f64",
   191  			exps:       []uint64{0},
   192  			actual:     []uint64{0},
   193  			valueTypes: []wasm.ValueType{f64},
   194  			expMatched: true,
   195  		},
   196  		{
   197  			name:       "unmatched/f64",
   198  			exps:       []uint64{math.Float64bits(1.0)},
   199  			actual:     []uint64{0},
   200  			valueTypes: []wasm.ValueType{f64},
   201  			expMatched: false,
   202  			expValuesMsg: `	have [0.000000]
   203  	want [1.000000]`,
   204  		},
   205  		{
   206  			name:       "unmatched/f64",
   207  			actual:     []uint64{math.Float64bits(-1231231.0)},
   208  			exps:       []uint64{0},
   209  			valueTypes: []wasm.ValueType{f64},
   210  			expMatched: false,
   211  			expValuesMsg: `	have [-1231231.000000]
   212  	want [0.000000]`,
   213  		},
   214  		{
   215  			name:       "matched/i8x16",
   216  			exps:       []uint64{math.MaxUint64, 123},
   217  			actual:     []uint64{math.MaxUint64, 123},
   218  			laneTypes:  map[int]laneType{0: laneTypeI8},
   219  			valueTypes: []wasm.ValueType{v128},
   220  			expMatched: true,
   221  		},
   222  		{
   223  			name:       "unmatched/i8x16",
   224  			exps:       []uint64{0, 0xff<<56 | 0xaa},
   225  			actual:     []uint64{math.MaxUint64, 0xff<<48 | 0xcc},
   226  			laneTypes:  map[int]laneType{0: laneTypeI8},
   227  			valueTypes: []wasm.ValueType{v128},
   228  			expMatched: false,
   229  			expValuesMsg: `	have [i8x16(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0)]
   230  	want [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff)]`,
   231  		},
   232  		{
   233  			name:       "matched/i16x8",
   234  			exps:       []uint64{math.MaxUint64, 123},
   235  			actual:     []uint64{math.MaxUint64, 123},
   236  			laneTypes:  map[int]laneType{0: laneTypeI16},
   237  			valueTypes: []wasm.ValueType{v128},
   238  			expMatched: true,
   239  		},
   240  		{
   241  			name:       "unmatched/i16x8",
   242  			exps:       []uint64{0xffff << 32, 0},
   243  			actual:     []uint64{0xaabb << 16, ^uint64(0)},
   244  			laneTypes:  map[int]laneType{0: laneTypeI16},
   245  			valueTypes: []wasm.ValueType{v128},
   246  			expMatched: false,
   247  			expValuesMsg: `	have [i16x8(0x0, 0xaabb, 0x0, 0x0, 0xffff, 0xffff, 0xffff, 0xffff)]
   248  	want [i16x8(0x0, 0x0, 0xffff, 0x0, 0x0, 0x0, 0x0, 0x0)]`,
   249  		},
   250  		{
   251  			name:       "matched/i32x4",
   252  			exps:       []uint64{math.MaxUint64, 123},
   253  			actual:     []uint64{math.MaxUint64, 123},
   254  			laneTypes:  map[int]laneType{0: laneTypeI32},
   255  			valueTypes: []wasm.ValueType{v128},
   256  			expMatched: true,
   257  		},
   258  		{
   259  			name:       "matched/i32x4",
   260  			exps:       []uint64{0xffff_ffff<<32 | 0xa, 123},
   261  			actual:     []uint64{0x1a1a_1a1a<<32 | 0xa, 123},
   262  			laneTypes:  map[int]laneType{0: laneTypeI32},
   263  			valueTypes: []wasm.ValueType{v128},
   264  			expMatched: false,
   265  			expValuesMsg: `	have [i32x4(0xa, 0x1a1a1a1a, 0x7b, 0x0)]
   266  	want [i32x4(0xa, 0xffffffff, 0x7b, 0x0)]`,
   267  		},
   268  		{
   269  			name:       "matched/i64x2",
   270  			exps:       []uint64{math.MaxUint64, 123},
   271  			actual:     []uint64{math.MaxUint64, 123},
   272  			laneTypes:  map[int]laneType{0: laneTypeI64},
   273  			valueTypes: []wasm.ValueType{v128},
   274  			expMatched: true,
   275  		},
   276  		{
   277  			name:       "unmatched/i64x2",
   278  			exps:       []uint64{math.MaxUint64, 123},
   279  			actual:     []uint64{math.MaxUint64, 0},
   280  			laneTypes:  map[int]laneType{0: laneTypeI64},
   281  			valueTypes: []wasm.ValueType{v128},
   282  			expMatched: false,
   283  			expValuesMsg: `	have [i64x2(0xffffffffffffffff, 0x0)]
   284  	want [i64x2(0xffffffffffffffff, 0x7b)]`,
   285  		},
   286  		{
   287  			name: "matched/f32x4",
   288  			exps: []uint64{
   289  				(uint64(math.Float32bits(float32(math.NaN()))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   290  				(uint64(math.Float32bits(float32(math.NaN()))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   291  			},
   292  			actual: []uint64{
   293  				(uint64(math.Float32bits(float32(math.NaN()))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   294  				(uint64(math.Float32bits(float32(math.NaN()))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   295  			},
   296  			valueTypes: []wasm.ValueType{v128},
   297  			laneTypes:  map[int]laneType{0: laneTypeF32},
   298  			expMatched: true,
   299  		},
   300  		{
   301  			name: "unmatched/f32x4",
   302  			exps: []uint64{
   303  				(uint64(math.Float32bits(float32(1.213))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   304  				(uint64(math.Float32bits(float32(math.NaN()))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   305  			},
   306  			actual: []uint64{
   307  				(uint64(math.Float32bits(float32(math.NaN()))) << 32) | uint64(math.Float32bits(float32(math.Inf(1)))),
   308  				(uint64(math.Float32bits(float32(math.Inf(-1)))) << 32) | uint64(math.Float32bits(float32(math.NaN()))),
   309  			},
   310  			valueTypes: []wasm.ValueType{v128},
   311  			laneTypes:  map[int]laneType{0: laneTypeF32},
   312  			expMatched: false,
   313  			expValuesMsg: `	have [f32x4(+Inf, NaN, NaN, -Inf)]
   314  	want [f32x4(NaN, 1.213000, NaN, NaN)]`,
   315  		},
   316  		{
   317  			name:       "matched/f64x2",
   318  			exps:       []uint64{math.Float64bits(1.0), math.Float64bits(math.NaN())},
   319  			actual:     []uint64{math.Float64bits(1.0), math.Float64bits(math.NaN())},
   320  			valueTypes: []wasm.ValueType{v128},
   321  			laneTypes:  map[int]laneType{0: laneTypeF64},
   322  			expMatched: true,
   323  		},
   324  		{
   325  			name:       "unmatched/f64x2",
   326  			exps:       []uint64{math.Float64bits(1.0), math.Float64bits(math.NaN())},
   327  			actual:     []uint64{math.Float64bits(-1.0), math.Float64bits(math.Inf(1))},
   328  			valueTypes: []wasm.ValueType{v128},
   329  			laneTypes:  map[int]laneType{0: laneTypeF64},
   330  			expMatched: false,
   331  			expValuesMsg: `	have [f64x2(-1.000000, +Inf)]
   332  	want [f64x2(1.000000, NaN)]`,
   333  		},
   334  		{
   335  			name:       "unmatched/f64x2",
   336  			exps:       []uint64{math.Float64bits(math.Inf(1)), math.Float64bits(math.NaN())},
   337  			actual:     []uint64{math.Float64bits(math.Inf(-1)), math.Float64bits(math.NaN())},
   338  			valueTypes: []wasm.ValueType{v128},
   339  			laneTypes:  map[int]laneType{0: laneTypeF64},
   340  			expMatched: false,
   341  			expValuesMsg: `	have [f64x2(-Inf, NaN)]
   342  	want [f64x2(+Inf, NaN)]`,
   343  		},
   344  		{
   345  			name:       "matched/[i32,f64x2]",
   346  			exps:       []uint64{1, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   347  			actual:     []uint64{1, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   348  			valueTypes: []wasm.ValueType{i32, v128},
   349  			laneTypes:  map[int]laneType{1: laneTypeF64},
   350  			expMatched: true,
   351  		},
   352  		{
   353  			name:       "unmatched/[i32,f64x2]",
   354  			exps:       []uint64{123, math.Float64bits(math.Inf(1)), math.Float64bits(math.NaN())},
   355  			actual:     []uint64{123, math.Float64bits(math.Inf(-1)), math.Float64bits(math.NaN())},
   356  			valueTypes: []wasm.ValueType{i32, v128},
   357  			laneTypes:  map[int]laneType{1: laneTypeF64},
   358  			expMatched: false,
   359  			expValuesMsg: `	have [123, f64x2(-Inf, NaN)]
   360  	want [123, f64x2(+Inf, NaN)]`,
   361  		},
   362  		{
   363  			name:       "matched/[i32,f64x2]",
   364  			exps:       []uint64{math.Float64bits(1.0), math.Float64bits(math.NaN()), 1},
   365  			actual:     []uint64{math.Float64bits(1.0), math.Float64bits(math.NaN()), 1},
   366  			valueTypes: []wasm.ValueType{v128, i32},
   367  			laneTypes:  map[int]laneType{0: laneTypeF64},
   368  			expMatched: true,
   369  		},
   370  		{
   371  			name:       "unmatched/[f64x2,i32]",
   372  			exps:       []uint64{math.Float64bits(math.Inf(1)), math.Float64bits(math.NaN()), 123},
   373  			actual:     []uint64{math.Float64bits(math.Inf(-1)), math.Float64bits(math.NaN()), 123},
   374  			valueTypes: []wasm.ValueType{v128, i32},
   375  			laneTypes:  map[int]laneType{0: laneTypeF64},
   376  			expMatched: false,
   377  			expValuesMsg: `	have [f64x2(-Inf, NaN), 123]
   378  	want [f64x2(+Inf, NaN), 123]`,
   379  		},
   380  		{
   381  			name:       "matched/[f32,i32,f64x2]",
   382  			exps:       []uint64{uint64(math.Float32bits(float32(math.NaN()))), math.Float64bits(1.0), math.Float64bits(math.NaN()), 1},
   383  			actual:     []uint64{uint64(math.Float32bits(float32(math.NaN()))), math.Float64bits(1.0), math.Float64bits(math.NaN()), 1},
   384  			valueTypes: []wasm.ValueType{f32, v128, i32},
   385  			laneTypes:  map[int]laneType{1: laneTypeF64},
   386  			expMatched: true,
   387  		},
   388  		{
   389  			name:       "unmatched/[f32,f64x2,i32]",
   390  			exps:       []uint64{uint64(math.Float32bits(1.0)), math.Float64bits(math.Inf(1)), math.Float64bits(math.NaN()), 123},
   391  			actual:     []uint64{uint64(math.Float32bits(1.0)), math.Float64bits(math.Inf(-1)), math.Float64bits(math.NaN()), 123},
   392  			valueTypes: []wasm.ValueType{f32, v128, i32},
   393  			laneTypes:  map[int]laneType{1: laneTypeF64},
   394  			expMatched: false,
   395  			expValuesMsg: `	have [1.000000, f64x2(-Inf, NaN), 123]
   396  	want [1.000000, f64x2(+Inf, NaN), 123]`,
   397  		},
   398  		{
   399  			name:       "matched/[i8x16,f64x2]",
   400  			exps:       []uint64{0, 0, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   401  			actual:     []uint64{0, 0, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   402  			valueTypes: []wasm.ValueType{v128, v128},
   403  			laneTypes:  map[int]laneType{0: laneTypeI8, 1: laneTypeF64},
   404  			expMatched: true,
   405  		},
   406  		{
   407  			name:       "unmatched/[i8x16,f64x2]",
   408  			exps:       []uint64{0, 0xff << 56, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   409  			actual:     []uint64{0, 0xaa << 56, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   410  			valueTypes: []wasm.ValueType{v128, v128},
   411  			laneTypes:  map[int]laneType{0: laneTypeI8, 1: laneTypeF64},
   412  			expMatched: false,
   413  			expValuesMsg: `	have [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaa), f64x2(1.000000, NaN)]
   414  	want [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff), f64x2(1.000000, NaN)]`,
   415  		},
   416  		{
   417  			name:       "unmatched/[i8x16,f64x2]",
   418  			exps:       []uint64{0, 0xff << 56, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   419  			actual:     []uint64{0, 0xff << 56, math.Float64bits(1.0), math.Float64bits(math.Inf(1))},
   420  			valueTypes: []wasm.ValueType{v128, v128},
   421  			laneTypes:  map[int]laneType{0: laneTypeI8, 1: laneTypeF64},
   422  			expMatched: false,
   423  			expValuesMsg: `	have [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff), f64x2(1.000000, +Inf)]
   424  	want [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff), f64x2(1.000000, NaN)]`,
   425  		},
   426  		{
   427  			name:       "matched/[i8x16,i32,f64x2]",
   428  			exps:       []uint64{0, 0, math.MaxUint32, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   429  			actual:     []uint64{0, 0, math.MaxUint32, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   430  			valueTypes: []wasm.ValueType{v128, i32, v128},
   431  			laneTypes:  map[int]laneType{0: laneTypeI8, 2: laneTypeF64},
   432  			expMatched: true,
   433  		},
   434  		{
   435  			name:       "matched/[i8x16,i32,f64x2]",
   436  			exps:       []uint64{0, 0, math.MaxUint32, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   437  			actual:     []uint64{0, 0, math.MaxUint32 - 1, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   438  			valueTypes: []wasm.ValueType{v128, i32, v128},
   439  			laneTypes:  map[int]laneType{0: laneTypeI8, 2: laneTypeF64},
   440  			expMatched: false,
   441  			expValuesMsg: `	have [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0), 4294967294, f64x2(1.000000, NaN)]
   442  	want [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0), 4294967295, f64x2(1.000000, NaN)]`,
   443  		},
   444  		{
   445  			name:       "matched/[i8x16,i32,f64x2]",
   446  			exps:       []uint64{0, 0, math.MaxUint32, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   447  			actual:     []uint64{0, 0xff << 16, math.MaxUint32, math.Float64bits(1.0), math.Float64bits(math.NaN())},
   448  			valueTypes: []wasm.ValueType{v128, i32, v128},
   449  			laneTypes:  map[int]laneType{0: laneTypeI8, 2: laneTypeF64},
   450  			expMatched: false,
   451  			expValuesMsg: `	have [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0), 4294967295, f64x2(1.000000, NaN)]
   452  	want [i8x16(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0), 4294967295, f64x2(1.000000, NaN)]`,
   453  		},
   454  	}
   455  
   456  	for _, tc := range tests {
   457  		tc := tc
   458  		t.Run(tc.name, func(t *testing.T) {
   459  			actualMatched, actualValuesMsg := valuesEq(tc.actual, tc.exps, tc.valueTypes, tc.laneTypes)
   460  			require.Equal(t, tc.expMatched, actualMatched)
   461  			require.Equal(t, tc.expValuesMsg, actualValuesMsg)
   462  		})
   463  	}
   464  }
   465  
   466  func TestCommandActionVal_toUint64s(t *testing.T) {
   467  	tests := []struct {
   468  		name                string
   469  		rawCommandActionVal string
   470  		exp                 []uint64
   471  	}{
   472  		{
   473  			name:                "i32",
   474  			rawCommandActionVal: `{"type": "i32", "value": "0"}`,
   475  			exp:                 []uint64{0},
   476  		},
   477  		{
   478  			name:                "i32",
   479  			rawCommandActionVal: `{"type": "i32", "value": "4294967295"}`,
   480  			exp:                 []uint64{4294967295},
   481  		},
   482  		{
   483  			name:                "i64",
   484  			rawCommandActionVal: `{"type": "i64", "value": "0"}`,
   485  			exp:                 []uint64{0},
   486  		},
   487  		{
   488  			name:                "i64",
   489  			rawCommandActionVal: `{"type": "i64", "value": "7034535277573963776"}`,
   490  			exp:                 []uint64{7034535277573963776},
   491  		},
   492  		{
   493  			name:                "f32",
   494  			rawCommandActionVal: `{"type": "f32", "value": "0"}`,
   495  			exp:                 []uint64{0},
   496  		},
   497  		{
   498  			name:                "f32",
   499  			rawCommandActionVal: `{"type": "f32", "value": "2147483648"}`,
   500  			exp:                 []uint64{2147483648},
   501  		},
   502  		{
   503  			name:                "f64",
   504  			rawCommandActionVal: `{"type": "f64", "value": "0"}`,
   505  			exp:                 []uint64{0},
   506  		},
   507  		{
   508  			name:                "f64",
   509  			rawCommandActionVal: `{"type": "f64", "value": "4616189618054758400"}`,
   510  			exp:                 []uint64{4616189618054758400},
   511  		},
   512  		{
   513  			name:                "f32x4",
   514  			rawCommandActionVal: `{"type": "v128", "lane_type": "f32", "value": ["645922816", "645922816", "645922816", "645922816"]}`,
   515  			exp:                 []uint64{645922816<<32 | 645922816, 645922816<<32 | 645922816},
   516  		},
   517  		{
   518  			name:                "f32x4",
   519  			rawCommandActionVal: `{"type": "v128", "lane_type": "f32", "value": ["nan:canonical", "nan:arithmetic", "nan:canonical", "nan:arithmetic"]}`,
   520  			exp: []uint64{
   521  				uint64(moremath.F32CanonicalNaNBits) | (uint64(moremath.F32ArithmeticNaNBits) << 32),
   522  				uint64(moremath.F32CanonicalNaNBits) | (uint64(moremath.F32ArithmeticNaNBits) << 32),
   523  			},
   524  		},
   525  		{
   526  			name:                "f64x2",
   527  			rawCommandActionVal: `{"type": "v128", "lane_type": "f64", "value": ["9223372036854775808", "9223372036854775808"]}`,
   528  			exp:                 []uint64{9223372036854775808, 9223372036854775808},
   529  		},
   530  		{
   531  			name:                "f64x2",
   532  			rawCommandActionVal: `{"type": "v128", "lane_type": "f64", "value": ["nan:canonical", "nan:arithmetic"]}`,
   533  			exp:                 []uint64{moremath.F64CanonicalNaNBits, moremath.F64ArithmeticNaNBits},
   534  		},
   535  		{
   536  			name:                "i8x16",
   537  			rawCommandActionVal: `{"type": "v128", "lane_type": "i8", "value": ["128", "129", "130", "131", "253", "254", "255", "0", "0", "1", "2", "127", "128", "253", "254", "255"]}`,
   538  			exp: []uint64{
   539  				128 | (129 << 8) | (130 << 16) | (131 << 24) | (253 << 32) | (254 << 40) | (255 << 48),
   540  				1<<8 | 2<<16 | 127<<24 | 128<<32 | 253<<40 | 254<<48 | 255<<56,
   541  			},
   542  		},
   543  		{
   544  			name:                "i16x8",
   545  			rawCommandActionVal: `{"type": "v128", "lane_type": "i16", "value": ["256", "770", "1284", "1798", "2312", "2826", "3340", "3854"]}`,
   546  			exp: []uint64{
   547  				256 | 770<<16 | 1284<<32 | 1798<<48,
   548  				2312 | 2826<<16 | 3340<<32 | 3854<<48,
   549  			},
   550  		},
   551  		{
   552  			name:                "i32x4",
   553  			rawCommandActionVal: `{"type": "v128", "lane_type": "i32", "value": ["123", "32766", "32766", "40000"]}`,
   554  			exp: []uint64{
   555  				123 | 32766<<32,
   556  				32766 | 40000<<32,
   557  			},
   558  		},
   559  		{
   560  			name:                "i64x2",
   561  			rawCommandActionVal: `{"type": "v128", "lane_type": "i64", "value": ["18446744073709551615", "123124"]}`,
   562  			exp: []uint64{
   563  				18446744073709551615,
   564  				123124,
   565  			},
   566  		},
   567  	}
   568  
   569  	for _, tc := range tests {
   570  		tc := tc
   571  		t.Run(tc.name, func(t *testing.T) {
   572  			var c commandActionVal
   573  			err := json.Unmarshal([]byte(tc.rawCommandActionVal), &c)
   574  			require.NoError(t, err)
   575  			actual := c.toUint64s()
   576  			require.Equal(t, tc.exp, actual)
   577  		})
   578  	}
   579  }
   580  
   581  func TestCommand_getAssertReturnArgsExps(t *testing.T) {
   582  	tests := []struct {
   583  		name       string
   584  		rawCommand string
   585  		args, exps []uint64
   586  	}{
   587  		{
   588  			name: "1",
   589  			rawCommand: `
   590  {
   591    "type": "assert_return",
   592    "line": 148,
   593    "action": {
   594      "type": "invoke", "field": "f32x4.min",
   595      "args": [
   596        {"type": "v128", "lane_type": "f32", "value": ["2147483648", "123", "2147483648", "1"]},
   597        {"type": "v128", "lane_type": "i8", "value": ["128", "129", "130", "131", "253", "254", "255", "0", "0", "1", "2", "127", "128", "253", "254", "255"]}
   598      ]
   599    },
   600    "expected": [
   601      {"type": "v128", "lane_type": "f32", "value": ["2147483648", "0", "0", "2147483648"]}
   602    ]
   603  }`,
   604  			args: []uint64{
   605  				123<<32 | 2147483648,
   606  				1<<32 | 2147483648,
   607  				128 | (129 << 8) | (130 << 16) | (131 << 24) | (253 << 32) | (254 << 40) | (255 << 48),
   608  				1<<8 | 2<<16 | 127<<24 | 128<<32 | 253<<40 | 254<<48 | 255<<56,
   609  			},
   610  			exps: []uint64{
   611  				2147483648,
   612  				2147483648 << 32,
   613  			},
   614  		},
   615  	}
   616  
   617  	for _, tc := range tests {
   618  		tc := tc
   619  		t.Run(tc.name, func(t *testing.T) {
   620  			var c command
   621  			err := json.Unmarshal([]byte(tc.rawCommand), &c)
   622  			require.NoError(t, err)
   623  			actualArgs, actualExps := c.getAssertReturnArgsExps()
   624  			require.Equal(t, tc.args, actualArgs)
   625  			require.Equal(t, tc.exps, actualExps)
   626  		})
   627  	}
   628  }