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