github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/validator/validator_z_float_test.go (about)

     1  package validator_test
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  	"testing"
     8  
     9  	. "github.com/onsi/gomega"
    10  
    11  	"github.com/machinefi/w3bstream/pkg/depends/kit/validator"
    12  	"github.com/machinefi/w3bstream/pkg/depends/x/ptrx"
    13  	"github.com/machinefi/w3bstream/pkg/depends/x/typesx"
    14  )
    15  
    16  func TestFloat_New(t *testing.T) {
    17  	cases := []struct {
    18  		name   string
    19  		rule   string
    20  		typ    reflect.Type
    21  		expect *validator.Float
    22  	}{
    23  		{
    24  			"01", "@float[1,1000]", rtFloat32,
    25  			&validator.Float{
    26  				Minimum: ptrx.Float64(1),
    27  				Maximum: ptrx.Float64(1000),
    28  			},
    29  		},
    30  		{
    31  			"02", "@float[1,1000]", rtFloat64,
    32  			&validator.Float{
    33  				Minimum: ptrx.Float64(1),
    34  				Maximum: ptrx.Float64(1000),
    35  			},
    36  		},
    37  		{
    38  			"03", "@float32[1,1000]", rtFloat64,
    39  			&validator.Float{
    40  				Minimum: ptrx.Float64(1),
    41  				Maximum: ptrx.Float64(1000),
    42  			},
    43  		},
    44  		{
    45  			"04", "@double[1,1000]", rtFloat64,
    46  			&validator.Float{
    47  				MaxDigits: 15,
    48  				Minimum:   ptrx.Float64(1),
    49  				Maximum:   ptrx.Float64(1000),
    50  			},
    51  		},
    52  		{
    53  			"05", "@float64[1,1000]", rtFloat64,
    54  			&validator.Float{
    55  				MaxDigits: 15,
    56  				Minimum:   ptrx.Float64(1),
    57  				Maximum:   ptrx.Float64(1000),
    58  			},
    59  		},
    60  		{
    61  			"06", "@float(1,1000]", rtFloat64,
    62  			&validator.Float{
    63  				Minimum:          ptrx.Float64(1),
    64  				ExclusiveMinimum: true,
    65  				Maximum:          ptrx.Float64(1000),
    66  			},
    67  		},
    68  		{
    69  			"07", "@float[.1,]", rtFloat64,
    70  			&validator.Float{
    71  				Minimum: ptrx.Float64(.1),
    72  			},
    73  		},
    74  		{
    75  			"08", "@float[,-1]", rtFloat64,
    76  			&validator.Float{
    77  				Maximum: ptrx.Float64(-1),
    78  			},
    79  		},
    80  		{
    81  			"09", "@float[-1]", rtFloat64,
    82  			&validator.Float{
    83  				Minimum: ptrx.Float64(-1),
    84  				Maximum: ptrx.Float64(-1),
    85  			},
    86  		},
    87  		{
    88  			"10", "@float{1,2}", rtFloat64,
    89  			&validator.Float{
    90  				Enums: map[float64]string{
    91  					1: "1",
    92  					2: "2",
    93  				},
    94  			},
    95  		},
    96  		{
    97  			"11", "@float{%2.2}", rtFloat64,
    98  			&validator.Float{
    99  				MultipleOf: 2.2,
   100  			},
   101  		},
   102  		{
   103  			"12", "@float<10,3>[1.333,2.333]", rtFloat64,
   104  			&validator.Float{
   105  				MaxDigits:     10,
   106  				DecimalDigits: ptrx.Uint(3),
   107  				Minimum:       ptrx.Float64(1.333),
   108  				Maximum:       ptrx.Float64(2.333),
   109  			},
   110  		},
   111  	}
   112  
   113  	for _, c := range cases {
   114  		c.expect.SetDefault()
   115  		name := fmt.Sprintf("%s_%s%s|%s", c.name, c.typ, c.rule, c.expect.String())
   116  		t.Run(name, func(t *testing.T) {
   117  			ctx := validator.ContextWithFactory(
   118  				bg, validator.DefaultFactory,
   119  			)
   120  			r, err := validator.ParseRuleByType(
   121  				[]byte(c.rule),
   122  				typesx.FromReflectType(c.typ),
   123  			)
   124  			NewWithT(t).Expect(err).To(BeNil())
   125  			v, err := c.expect.New(ctx, r)
   126  			NewWithT(t).Expect(err).To(BeNil())
   127  			NewWithT(t).Expect(v).To(Equal(c.expect))
   128  		})
   129  	}
   130  }
   131  
   132  func TestFloat_Failed(t *testing.T) {
   133  	cases := []struct {
   134  		typ  reflect.Type
   135  		rule string
   136  	}{
   137  		{rtInt, `@float64`},
   138  		{rtFloat32, `@float64`},
   139  		{rtFloat32, `@double`},
   140  		{rtFloat32, `@float<9>`},
   141  		{rtFloat64, "@float<11,22,33>"},
   142  		{rtFloat64, "@float<32,2123>"},
   143  		{rtFloat64, "@float<@string>"},
   144  		{rtFloat64, "@float<66>"},
   145  		{rtFloat64, "@float<7,7>"},
   146  		{rtFloat64, "@float[1,0]"},
   147  		{rtFloat64, "@float[1,-2]"},
   148  		{rtFloat64, "@float<7,2>[1.333,2]"},
   149  		{rtFloat64, "@float<7,2>[111111.33,]"},
   150  		{rtFloat64, "@float[a,]"},
   151  		{rtFloat64, "@float[,a]"},
   152  		{rtFloat64, "@float[a]"},
   153  		{rtFloat64, `@float{%a}`},
   154  		{rtFloat64, `@float{A,B,C}`},
   155  	}
   156  
   157  	for i, c := range cases {
   158  		rule, err := validator.ParseRuleByType(
   159  			[]byte(c.rule),
   160  			typesx.FromReflectType(c.typ),
   161  		)
   162  		NewWithT(t).Expect(err).To(BeNil())
   163  
   164  		t.Run(
   165  			fmt.Sprintf("%02d|%s|%s", i+1, c.typ, rule.Bytes()),
   166  			func(t *testing.T) {
   167  				ctx := validator.ContextWithFactory(
   168  					bg, validator.DefaultFactory,
   169  				)
   170  				v := &validator.Float{}
   171  				_, err := v.New(ctx, rule)
   172  				NewWithT(t).Expect(err).NotTo(BeNil())
   173  				// t.Logf("\n%v", err)
   174  			},
   175  		)
   176  	}
   177  }
   178  
   179  func TestFloat_Validate(t *testing.T) {
   180  	cases := []struct {
   181  		values    []interface{}
   182  		validator *validator.Float
   183  		desc      string
   184  	}{
   185  		{
   186  			[]interface{}{reflect.ValueOf(float64(1)), float64(2), float64(3)},
   187  			&validator.Float{
   188  				Enums: map[float64]string{
   189  					1: "1",
   190  					2: "2",
   191  					3: "3",
   192  				},
   193  			},
   194  			"InEnum",
   195  		},
   196  		{
   197  			[]interface{}{float64(2), float64(3), float64(4)},
   198  			&validator.Float{
   199  				Minimum: ptrx.Float64(2),
   200  				Maximum: ptrx.Float64(4),
   201  			},
   202  			"InRange",
   203  		},
   204  		{
   205  			[]interface{}{float64(2), float64(3), float64(4), float64(4)},
   206  			&validator.Float{
   207  				Minimum: ptrx.Float64(2),
   208  				Maximum: ptrx.Float64(4),
   209  			},
   210  			"IntTypes",
   211  		},
   212  		{
   213  			[]interface{}{float32(2), float32(3), float32(4)},
   214  			&validator.Float{
   215  				Minimum: ptrx.Float64(2),
   216  				Maximum: ptrx.Float64(4),
   217  			},
   218  			"InRange",
   219  		},
   220  		{
   221  			[]interface{}{-2.2, 4.4, -6.6},
   222  			&validator.Float{
   223  				MultipleOf: 2.2,
   224  			},
   225  			"MultipleOf",
   226  		},
   227  	}
   228  	for ci := range cases {
   229  		c := cases[ci]
   230  		c.validator.SetDefault()
   231  		for vi, v := range c.values {
   232  			name := fmt.Sprintf(
   233  				"%02d_%02d_%s|%s|%v",
   234  				ci+1, vi+1, c.desc, c.validator, v,
   235  			)
   236  			t.Run(name, func(t *testing.T) {
   237  				NewWithT(t).Expect(c.validator.Validate(v)).To(BeNil())
   238  			})
   239  		}
   240  	}
   241  }
   242  
   243  func TestFloat_ValidateFailed(t *testing.T) {
   244  	cases := []struct {
   245  		values    []interface{}
   246  		validator *validator.Float
   247  		desc      string
   248  	}{
   249  		{[]interface{}{
   250  			uint(2),
   251  			"string",
   252  			reflect.ValueOf("1"),
   253  		}, &validator.Float{}, "unsupported type"},
   254  		{[]interface{}{1.11, 1.22, float64(111111), float64(222221), 222.33}, &validator.Float{
   255  			MaxDigits:     5,
   256  			DecimalDigits: ptrx.Uint(1),
   257  		}, "digits out out range range"},
   258  		{[]interface{}{float64(4), float64(5), float64(6)}, &validator.Float{
   259  			Enums: map[float64]string{
   260  				1: "1",
   261  				2: "2",
   262  				3: "3",
   263  			},
   264  		}, "not in enum"},
   265  		{[]interface{}{float64(1), float64(4), float64(5)}, &validator.Float{
   266  			Minimum:          ptrx.Float64(2),
   267  			Maximum:          ptrx.Float64(4),
   268  			ExclusiveMaximum: true,
   269  		}, "not in range"},
   270  		{[]interface{}{1.1, 1.2, 1.3}, &validator.Float{
   271  			MultipleOf: 2,
   272  		}, "not multiple of"},
   273  	}
   274  
   275  	for ci, c := range cases {
   276  		c.validator.SetDefault()
   277  		for vi, v := range c.values {
   278  			t.Run(
   279  				fmt.Sprintf(
   280  					"%02d_%02d_%s|%s|%v",
   281  					ci+1, vi+1, c.desc, c.validator, v,
   282  				),
   283  				func(t *testing.T) {
   284  					err := c.validator.Validate(v)
   285  					NewWithT(t).Expect(err).NotTo(BeNil())
   286  					// t.Logf("\n%v", err)
   287  				},
   288  			)
   289  		}
   290  	}
   291  }
   292  
   293  func TestFloat(t *testing.T) {
   294  	floats := [][]float64{
   295  		{99999.99999, 10, 5},
   296  		{-0.19999999999999998, 17, 17},
   297  		{9223372036854775808, 19, 0},
   298  		{340282346638528859811704183484516925440, 39, 0},
   299  		{math.MaxFloat64, 309, 0},
   300  		{math.SmallestNonzeroFloat64, 324, 324},
   301  	}
   302  
   303  	for i := range floats {
   304  		v := floats[i][0]
   305  		n, d := validator.FloatLengthOfDigit(v)
   306  		NewWithT(t).Expect(float64(n)).To(Equal(floats[i][1]))
   307  		NewWithT(t).Expect(float64(d)).To(Equal(floats[i][2]))
   308  	}
   309  }