github.com/Finschia/finschia-sdk@v0.48.1/types/int_test.go (about) 1 package types_test 2 3 import ( 4 "fmt" 5 "math/big" 6 "math/rand" 7 "strconv" 8 "testing" 9 10 "github.com/stretchr/testify/suite" 11 12 sdk "github.com/Finschia/finschia-sdk/types" 13 ) 14 15 type intTestSuite struct { 16 suite.Suite 17 } 18 19 func TestIntTestSuite(t *testing.T) { 20 suite.Run(t, new(intTestSuite)) 21 } 22 23 func (s *intTestSuite) SetupSuite() { 24 s.T().Parallel() 25 } 26 27 func (s *intTestSuite) TestFromInt64() { 28 for n := 0; n < 20; n++ { 29 r := rand.Int63() 30 s.Require().Equal(r, sdk.NewInt(r).Int64()) 31 } 32 } 33 34 func (s *intTestSuite) TestFromUint64() { 35 for n := 0; n < 20; n++ { 36 r := rand.Uint64() 37 s.Require().True(sdk.NewIntFromUint64(r).IsUint64()) 38 s.Require().Equal(r, sdk.NewIntFromUint64(r).Uint64()) 39 } 40 } 41 42 func (s *intTestSuite) TestIntPanic() { 43 // Max Int = 2^256-1 = 1.1579209e+77 44 // Min Int = -(2^256-1) = -1.1579209e+77 45 s.Require().NotPanics(func() { sdk.NewIntWithDecimal(4, 76) }) 46 i1 := sdk.NewIntWithDecimal(4, 76) 47 s.Require().NotPanics(func() { sdk.NewIntWithDecimal(5, 76) }) 48 i2 := sdk.NewIntWithDecimal(5, 76) 49 s.Require().NotPanics(func() { sdk.NewIntWithDecimal(6, 76) }) 50 i3 := sdk.NewIntWithDecimal(6, 76) 51 52 s.Require().Panics(func() { sdk.NewIntWithDecimal(2, 77) }) 53 s.Require().Panics(func() { sdk.NewIntWithDecimal(9, 80) }) 54 55 // Overflow check 56 s.Require().NotPanics(func() { i1.Add(i1) }) 57 s.Require().NotPanics(func() { i2.Add(i2) }) 58 s.Require().Panics(func() { i3.Add(i3) }) 59 60 s.Require().NotPanics(func() { i1.Sub(i1.Neg()) }) 61 s.Require().NotPanics(func() { i2.Sub(i2.Neg()) }) 62 s.Require().Panics(func() { i3.Sub(i3.Neg()) }) 63 64 s.Require().Panics(func() { i1.Mul(i1) }) 65 s.Require().Panics(func() { i2.Mul(i2) }) 66 s.Require().Panics(func() { i3.Mul(i3) }) 67 68 s.Require().Panics(func() { i1.Neg().Mul(i1.Neg()) }) 69 s.Require().Panics(func() { i2.Neg().Mul(i2.Neg()) }) 70 s.Require().Panics(func() { i3.Neg().Mul(i3.Neg()) }) 71 72 // // Underflow check 73 i3n := i3.Neg() 74 s.Require().NotPanics(func() { i3n.Sub(i1) }) 75 s.Require().NotPanics(func() { i3n.Sub(i2) }) 76 s.Require().Panics(func() { i3n.Sub(i3) }) 77 78 s.Require().NotPanics(func() { i3n.Add(i1.Neg()) }) 79 s.Require().NotPanics(func() { i3n.Add(i2.Neg()) }) 80 s.Require().Panics(func() { i3n.Add(i3.Neg()) }) 81 82 s.Require().Panics(func() { i1.Mul(i1.Neg()) }) 83 s.Require().Panics(func() { i2.Mul(i2.Neg()) }) 84 s.Require().Panics(func() { i3.Mul(i3.Neg()) }) 85 86 // Bound check 87 intmax := sdk.NewIntFromBigInt(new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1))) 88 intmin := intmax.Neg() 89 s.Require().NotPanics(func() { intmax.Add(sdk.ZeroInt()) }) 90 s.Require().NotPanics(func() { intmin.Sub(sdk.ZeroInt()) }) 91 s.Require().Panics(func() { intmax.Add(sdk.OneInt()) }) 92 s.Require().Panics(func() { intmin.Sub(sdk.OneInt()) }) 93 94 s.Require().NotPanics(func() { sdk.NewIntFromBigInt(nil) }) 95 s.Require().True(sdk.NewIntFromBigInt(nil).IsNil()) 96 97 // Division-by-zero check 98 s.Require().Panics(func() { i1.Quo(sdk.NewInt(0)) }) 99 100 s.Require().NotPanics(func() { sdk.Int{}.BigInt() }) 101 } 102 103 // Tests below uses randomness 104 // Since we are using *big.Int as underlying value 105 // and (U/)Int is immutable value(see TestImmutability(U/)Int) 106 // it is safe to use randomness in the tests 107 func (s *intTestSuite) TestIdentInt() { 108 for d := 0; d < 1000; d++ { 109 n := rand.Int63() 110 i := sdk.NewInt(n) 111 112 ifromstr, ok := sdk.NewIntFromString(strconv.FormatInt(n, 10)) 113 s.Require().True(ok) 114 115 cases := []int64{ 116 i.Int64(), 117 i.BigInt().Int64(), 118 ifromstr.Int64(), 119 sdk.NewIntFromBigInt(big.NewInt(n)).Int64(), 120 sdk.NewIntWithDecimal(n, 0).Int64(), 121 } 122 123 for tcnum, tc := range cases { 124 s.Require().Equal(n, tc, "Int is modified during conversion. tc #%d", tcnum) 125 } 126 } 127 } 128 129 func minint(i1, i2 int64) int64 { 130 if i1 < i2 { 131 return i1 132 } 133 return i2 134 } 135 136 func maxint(i1, i2 int64) int64 { 137 if i1 > i2 { 138 return i1 139 } 140 return i2 141 } 142 143 func (s *intTestSuite) TestArithInt() { 144 for d := 0; d < 1000; d++ { 145 n1 := int64(rand.Int31()) 146 i1 := sdk.NewInt(n1) 147 n2 := int64(rand.Int31()) 148 i2 := sdk.NewInt(n2) 149 150 cases := []struct { 151 ires sdk.Int 152 nres int64 153 }{ 154 {i1.Add(i2), n1 + n2}, 155 {i1.Sub(i2), n1 - n2}, 156 {i1.Mul(i2), n1 * n2}, 157 {i1.Quo(i2), n1 / n2}, 158 {i1.AddRaw(n2), n1 + n2}, 159 {i1.SubRaw(n2), n1 - n2}, 160 {i1.MulRaw(n2), n1 * n2}, 161 {i1.QuoRaw(n2), n1 / n2}, 162 {sdk.MinInt(i1, i2), minint(n1, n2)}, 163 {sdk.MaxInt(i1, i2), maxint(n1, n2)}, 164 {i1.Neg(), -n1}, 165 {i1.Abs(), n1}, 166 {i1.Neg().Abs(), n1}, 167 } 168 169 for tcnum, tc := range cases { 170 s.Require().Equal(tc.nres, tc.ires.Int64(), "Int arithmetic operation does not match with int64 operation. tc #%d", tcnum) 171 } 172 } 173 } 174 175 func (s *intTestSuite) TestCompInt() { 176 for d := 0; d < 1000; d++ { 177 n1 := int64(rand.Int31()) 178 i1 := sdk.NewInt(n1) 179 n2 := int64(rand.Int31()) 180 i2 := sdk.NewInt(n2) 181 182 cases := []struct { 183 ires bool 184 nres bool 185 }{ 186 {i1.Equal(i2), n1 == n2}, 187 {i1.GT(i2), n1 > n2}, 188 {i1.LT(i2), n1 < n2}, 189 {i1.LTE(i2), n1 <= n2}, 190 } 191 192 for tcnum, tc := range cases { 193 s.Require().Equal(tc.nres, tc.ires, "Int comparison operation does not match with int64 operation. tc #%d", tcnum) 194 } 195 } 196 } 197 198 func randint() sdk.Int { 199 return sdk.NewInt(rand.Int63()) 200 } 201 202 func (s *intTestSuite) TestImmutabilityAllInt() { 203 ops := []func(*sdk.Int){ 204 func(i *sdk.Int) { _ = i.Add(randint()) }, 205 func(i *sdk.Int) { _ = i.Sub(randint()) }, 206 func(i *sdk.Int) { _ = i.Mul(randint()) }, 207 func(i *sdk.Int) { _ = i.Quo(randint()) }, 208 func(i *sdk.Int) { _ = i.AddRaw(rand.Int63()) }, 209 func(i *sdk.Int) { _ = i.SubRaw(rand.Int63()) }, 210 func(i *sdk.Int) { _ = i.MulRaw(rand.Int63()) }, 211 func(i *sdk.Int) { _ = i.QuoRaw(rand.Int63()) }, 212 func(i *sdk.Int) { _ = i.Neg() }, 213 func(i *sdk.Int) { _ = i.Abs() }, 214 func(i *sdk.Int) { _ = i.IsZero() }, 215 func(i *sdk.Int) { _ = i.Sign() }, 216 func(i *sdk.Int) { _ = i.Equal(randint()) }, 217 func(i *sdk.Int) { _ = i.GT(randint()) }, 218 func(i *sdk.Int) { _ = i.LT(randint()) }, 219 func(i *sdk.Int) { _ = i.String() }, 220 } 221 222 for i := 0; i < 1000; i++ { 223 n := rand.Int63() 224 ni := sdk.NewInt(n) 225 226 for opnum, op := range ops { 227 op(&ni) 228 229 s.Require().Equal(n, ni.Int64(), "Int is modified by operation. tc #%d", opnum) 230 s.Require().Equal(sdk.NewInt(n), ni, "Int is modified by operation. tc #%d", opnum) 231 } 232 } 233 } 234 235 func (s *intTestSuite) TestEncodingTableInt() { 236 var i sdk.Int 237 238 cases := []struct { 239 i sdk.Int 240 jsonBz []byte 241 rawBz []byte 242 }{ 243 { 244 sdk.NewInt(0), 245 []byte("\"0\""), 246 []byte{0x30}, 247 }, 248 { 249 sdk.NewInt(100), 250 []byte("\"100\""), 251 []byte{0x31, 0x30, 0x30}, 252 }, 253 { 254 sdk.NewInt(-100), 255 []byte("\"-100\""), 256 []byte{0x2d, 0x31, 0x30, 0x30}, 257 }, 258 { 259 sdk.NewInt(51842), 260 []byte("\"51842\""), 261 []byte{0x35, 0x31, 0x38, 0x34, 0x32}, 262 }, 263 { 264 sdk.NewInt(-51842), 265 []byte("\"-51842\""), 266 []byte{0x2d, 0x35, 0x31, 0x38, 0x34, 0x32}, 267 }, 268 { 269 sdk.NewInt(19513368), 270 []byte("\"19513368\""), 271 []byte{0x31, 0x39, 0x35, 0x31, 0x33, 0x33, 0x36, 0x38}, 272 }, 273 { 274 sdk.NewInt(-19513368), 275 []byte("\"-19513368\""), 276 []byte{0x2d, 0x31, 0x39, 0x35, 0x31, 0x33, 0x33, 0x36, 0x38}, 277 }, 278 { 279 sdk.NewInt(999999999999), 280 []byte("\"999999999999\""), 281 []byte{0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39}, 282 }, 283 { 284 sdk.NewInt(-999999999999), 285 []byte("\"-999999999999\""), 286 []byte{0x2d, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39}, 287 }, 288 } 289 290 for tcnum, tc := range cases { 291 bz, err := tc.i.MarshalJSON() 292 s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err) 293 s.Require().Equal(tc.jsonBz, bz, "Marshaled value is different from exported. tc #%d", tcnum) 294 295 err = (&i).UnmarshalJSON(bz) 296 s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err) 297 s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum) 298 299 bz, err = tc.i.Marshal() 300 s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err) 301 s.Require().Equal(tc.rawBz, bz, "Marshaled value is different from exported. tc #%d", tcnum) 302 303 err = (&i).Unmarshal(bz) 304 s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err) 305 s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum) 306 } 307 } 308 309 func (s *intTestSuite) TestEncodingTableUint() { 310 var i sdk.Uint 311 312 cases := []struct { 313 i sdk.Uint 314 jsonBz []byte 315 rawBz []byte 316 }{ 317 { 318 sdk.NewUint(0), 319 []byte("\"0\""), 320 []byte{0x30}, 321 }, 322 { 323 sdk.NewUint(100), 324 []byte("\"100\""), 325 []byte{0x31, 0x30, 0x30}, 326 }, 327 { 328 sdk.NewUint(51842), 329 []byte("\"51842\""), 330 []byte{0x35, 0x31, 0x38, 0x34, 0x32}, 331 }, 332 { 333 sdk.NewUint(19513368), 334 []byte("\"19513368\""), 335 []byte{0x31, 0x39, 0x35, 0x31, 0x33, 0x33, 0x36, 0x38}, 336 }, 337 { 338 sdk.NewUint(999999999999), 339 []byte("\"999999999999\""), 340 []byte{0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39}, 341 }, 342 } 343 344 for tcnum, tc := range cases { 345 bz, err := tc.i.MarshalJSON() 346 s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err) 347 s.Require().Equal(tc.jsonBz, bz, "Marshaled value is different from exported. tc #%d", tcnum) 348 349 err = (&i).UnmarshalJSON(bz) 350 s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err) 351 s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum) 352 353 bz, err = tc.i.Marshal() 354 s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err) 355 s.Require().Equal(tc.rawBz, bz, "Marshaled value is different from exported. tc #%d", tcnum) 356 357 err = (&i).Unmarshal(bz) 358 s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err) 359 s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum) 360 } 361 } 362 363 func (s *intTestSuite) TestIntMod() { 364 tests := []struct { 365 name string 366 x int64 367 y int64 368 ret int64 369 wantPanic bool 370 }{ 371 {"3 % 10", 3, 10, 3, false}, 372 {"10 % 3", 10, 3, 1, false}, 373 {"4 % 2", 4, 2, 0, false}, 374 {"2 % 0", 2, 0, 0, true}, 375 } 376 377 for _, tt := range tests { 378 if tt.wantPanic { 379 s.Require().Panics(func() { sdk.NewInt(tt.x).Mod(sdk.NewInt(tt.y)) }) 380 s.Require().Panics(func() { sdk.NewInt(tt.x).ModRaw(tt.y) }) 381 return 382 } 383 s.Require().True(sdk.NewInt(tt.x).Mod(sdk.NewInt(tt.y)).Equal(sdk.NewInt(tt.ret))) 384 s.Require().True(sdk.NewInt(tt.x).ModRaw(tt.y).Equal(sdk.NewInt(tt.ret))) 385 } 386 } 387 388 func (s *intTestSuite) TestIntEq() { 389 _, resp, _, _, _ := sdk.IntEq(s.T(), sdk.ZeroInt(), sdk.ZeroInt()) 390 s.Require().True(resp) 391 _, resp, _, _, _ = sdk.IntEq(s.T(), sdk.OneInt(), sdk.ZeroInt()) 392 s.Require().False(resp) 393 } 394 395 func TestRoundTripMarshalToInt(t *testing.T) { 396 values := []int64{ 397 0, 398 1, 399 1 << 10, 400 1<<10 - 3, 401 1<<63 - 1, 402 1<<32 - 7, 403 1<<22 - 8, 404 } 405 406 for _, value := range values { 407 value := value 408 t.Run(fmt.Sprintf("%d", value), func(t *testing.T) { 409 t.Parallel() 410 411 var scratch [20]byte 412 iv := sdk.NewInt(value) 413 n, err := iv.MarshalTo(scratch[:]) 414 if err != nil { 415 t.Fatal(err) 416 } 417 rt := new(sdk.Int) 418 if err := rt.Unmarshal(scratch[:n]); err != nil { 419 t.Fatal(err) 420 } 421 if !rt.Equal(iv) { 422 t.Fatalf("roundtrip=%q != original=%q", rt, iv) 423 } 424 }) 425 } 426 }