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 }