2020-09-29 04:29:10 -07:00
|
|
|
package types_test
|
2018-06-15 14:16:45 -07:00
|
|
|
|
|
|
|
import (
|
types: use (*math/big.Int).BitLen() == 0 to check if value is 0 (#8580)
Instead of using len((*math/big.Int).Bytes()) == 0, which expensively
creates a byte slice and marshals a value, on the majority hot path,
instead use the cheaper method .BitLen() to check if 0.
Benchmarking results, just from types:
name old time/op new time/op delta
CoinsAdditionIntersect/sizes:_A_1,_B_1-8 132ns ± 2% 126ns ±13% -4.55% (p=0.050 n=10+10)
CoinsAdditionIntersect/sizes:_A_5,_B_5-8 1.41µs ± 3% 1.41µs ± 2% ~ (p=1.000 n=10+10)
CoinsAdditionIntersect/sizes:_A_5,_B_20-8 2.30µs ± 1% 2.27µs ± 3% ~ (p=0.066 n=10+10)
CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 30.9µs ± 3% 30.7µs ± 1% ~ (p=0.218 n=10+10)
CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 31.4µs ± 3% 30.8µs ± 2% -1.94% (p=0.015 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 116ns ± 1% 114ns ± 4% ~ (p=0.142 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 1.11µs ± 1% 1.08µs ± 3% -2.36% (p=0.003 n=8+10)
CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 1.85µs ± 2% 1.82µs ± 1% -1.38% (p=0.001 n=10+9)
CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 30.7µs ± 1% 30.6µs ± 3% ~ (p=0.393 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 31.1µs ± 1% 30.7µs ± 2% -1.32% (p=0.015 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 31.0µs ± 2% 30.7µs ± 2% ~ (p=0.190 n=10+10)
Bech32ifyPubKey-8 28.8µs ± 5% 28.8µs ± 3% ~ (p=0.965 n=10+8)
GetPubKeyFromBech32-8 38.8µs ± 3% 39.4µs ± 2% +1.70% (p=0.013 n=9+10)
ParseCoin-8 16.7µs ± 6% 15.8µs ± 4% -5.21% (p=0.001 n=10+10)
MarshalTo-8 521ns ± 5% 508ns ± 3% -2.56% (p=0.029 n=10+10)
UintMarshal-8 3.10µs ±17% 2.56µs ± 3% -17.45% (p=0.000 n=10+9)
IntMarshal-8 2.52µs ±10% 1.94µs ± 2% -23.10% (p=0.000 n=10+10)
name old alloc/op new alloc/op delta
Bech32ifyPubKey-8 4.02kB ± 0% 4.02kB ± 0% ~ (all equal)
GetPubKeyFromBech32-8 2.48kB ± 0% 2.48kB ± 0% ~ (all equal)
ParseCoin-8 2.21kB ± 0% 2.21kB ± 0% ~ (all equal)
MarshalTo-8 80.0B ± 0% 80.0B ± 0% ~ (all equal)
UintMarshal-8 440B ± 0% 392B ± 0% -10.91% (p=0.000 n=10+10)
IntMarshal-8 216B ± 0% 168B ± 0% -22.22% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
Bech32ifyPubKey-8 25.0 ± 0% 25.0 ± 0% ~ (all equal)
GetPubKeyFromBech32-8 85.0 ± 0% 85.0 ± 0% ~ (all equal)
ParseCoin-8 71.0 ± 0% 71.0 ± 0% ~ (all equal)
MarshalTo-8 2.00 ± 0% 2.00 ± 0% ~ (all equal)
UintMarshal-8 31.0 ± 0% 25.0 ± 0% -19.35% (p=0.000 n=10+10)
IntMarshal-8 24.0 ± 0% 18.0 ± 0% -25.00% (p=0.000 n=10+10)
name old speed new speed delta
UintMarshal-8 2.27MB/s ±15% 2.75MB/s ± 2% +20.87% (p=0.000 n=10+8)
IntMarshal-8 2.78MB/s ± 9% 3.60MB/s ± 2% +29.69% (p=0.000 n=10+10)
Fixes #8575
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2021-02-15 02:53:10 -08:00
|
|
|
"fmt"
|
2018-06-15 14:16:45 -07:00
|
|
|
"math/big"
|
|
|
|
"math/rand"
|
2018-08-06 12:00:49 -07:00
|
|
|
"strconv"
|
2018-06-15 14:16:45 -07:00
|
|
|
"testing"
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2018-06-15 14:16:45 -07:00
|
|
|
)
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
type intTestSuite struct {
|
|
|
|
suite.Suite
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIntTestSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(intTestSuite))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *intTestSuite) SetupSuite() {
|
|
|
|
s.T().Parallel()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *intTestSuite) TestFromInt64() {
|
2018-06-15 14:16:45 -07:00
|
|
|
for n := 0; n < 20; n++ {
|
|
|
|
r := rand.Int63()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Equal(r, sdk.NewInt(r).Int64())
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestFromUint64() {
|
2020-01-04 12:16:12 -08:00
|
|
|
for n := 0; n < 20; n++ {
|
|
|
|
r := rand.Uint64()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().True(sdk.NewIntFromUint64(r).IsUint64())
|
|
|
|
s.Require().Equal(r, sdk.NewIntFromUint64(r).Uint64())
|
2020-01-04 12:16:12 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestIntPanic() {
|
2021-06-16 07:18:02 -07:00
|
|
|
// Max Int = 2^256-1 = 1.1579209e+77
|
|
|
|
// Min Int = -(2^256-1) = -1.1579209e+77
|
|
|
|
s.Require().NotPanics(func() { sdk.NewIntWithDecimal(4, 76) })
|
|
|
|
i1 := sdk.NewIntWithDecimal(4, 76)
|
|
|
|
s.Require().NotPanics(func() { sdk.NewIntWithDecimal(5, 76) })
|
|
|
|
i2 := sdk.NewIntWithDecimal(5, 76)
|
|
|
|
s.Require().NotPanics(func() { sdk.NewIntWithDecimal(6, 76) })
|
|
|
|
i3 := sdk.NewIntWithDecimal(6, 76)
|
|
|
|
|
|
|
|
s.Require().Panics(func() { sdk.NewIntWithDecimal(2, 77) })
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Panics(func() { sdk.NewIntWithDecimal(9, 80) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
|
|
|
// Overflow check
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().NotPanics(func() { i1.Add(i1) })
|
|
|
|
s.Require().NotPanics(func() { i2.Add(i2) })
|
|
|
|
s.Require().Panics(func() { i3.Add(i3) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().NotPanics(func() { i1.Sub(i1.Neg()) })
|
|
|
|
s.Require().NotPanics(func() { i2.Sub(i2.Neg()) })
|
|
|
|
s.Require().Panics(func() { i3.Sub(i3.Neg()) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Panics(func() { i1.Mul(i1) })
|
|
|
|
s.Require().Panics(func() { i2.Mul(i2) })
|
|
|
|
s.Require().Panics(func() { i3.Mul(i3) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Panics(func() { i1.Neg().Mul(i1.Neg()) })
|
|
|
|
s.Require().Panics(func() { i2.Neg().Mul(i2.Neg()) })
|
|
|
|
s.Require().Panics(func() { i3.Neg().Mul(i3.Neg()) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2021-06-16 07:18:02 -07:00
|
|
|
// // Underflow check
|
2018-06-15 14:16:45 -07:00
|
|
|
i3n := i3.Neg()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().NotPanics(func() { i3n.Sub(i1) })
|
|
|
|
s.Require().NotPanics(func() { i3n.Sub(i2) })
|
|
|
|
s.Require().Panics(func() { i3n.Sub(i3) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().NotPanics(func() { i3n.Add(i1.Neg()) })
|
|
|
|
s.Require().NotPanics(func() { i3n.Add(i2.Neg()) })
|
|
|
|
s.Require().Panics(func() { i3n.Add(i3.Neg()) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Panics(func() { i1.Mul(i1.Neg()) })
|
|
|
|
s.Require().Panics(func() { i2.Mul(i2.Neg()) })
|
|
|
|
s.Require().Panics(func() { i3.Mul(i3.Neg()) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
|
|
|
// Bound check
|
2021-06-16 07:18:02 -07:00
|
|
|
intmax := sdk.NewIntFromBigInt(new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1)))
|
2018-06-15 14:16:45 -07:00
|
|
|
intmin := intmax.Neg()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().NotPanics(func() { intmax.Add(sdk.ZeroInt()) })
|
|
|
|
s.Require().NotPanics(func() { intmin.Sub(sdk.ZeroInt()) })
|
|
|
|
s.Require().Panics(func() { intmax.Add(sdk.OneInt()) })
|
|
|
|
s.Require().Panics(func() { intmin.Sub(sdk.OneInt()) })
|
2018-06-15 14:16:45 -07:00
|
|
|
|
|
|
|
// Division-by-zero check
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Panics(func() { i1.Quo(sdk.NewInt(0)) })
|
2020-08-18 06:16:23 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().NotPanics(func() { sdk.Int{}.BigInt() })
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2018-08-06 12:00:49 -07:00
|
|
|
// Tests below uses randomness
|
|
|
|
// Since we are using *big.Int as underlying value
|
|
|
|
// and (U/)Int is immutable value(see TestImmutability(U/)Int)
|
|
|
|
// it is safe to use randomness in the tests
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestIdentInt() {
|
2018-08-06 12:00:49 -07:00
|
|
|
for d := 0; d < 1000; d++ {
|
|
|
|
n := rand.Int63()
|
2020-09-29 04:29:10 -07:00
|
|
|
i := sdk.NewInt(n)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
ifromstr, ok := sdk.NewIntFromString(strconv.FormatInt(n, 10))
|
|
|
|
s.Require().True(ok)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
|
|
|
cases := []int64{
|
|
|
|
i.Int64(),
|
|
|
|
i.BigInt().Int64(),
|
|
|
|
ifromstr.Int64(),
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewIntFromBigInt(big.NewInt(n)).Int64(),
|
|
|
|
sdk.NewIntWithDecimal(n, 0).Int64(),
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for tcnum, tc := range cases {
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Equal(n, tc, "Int is modified during conversion. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func minint(i1, i2 int64) int64 {
|
|
|
|
if i1 < i2 {
|
|
|
|
return i1
|
|
|
|
}
|
|
|
|
return i2
|
|
|
|
}
|
|
|
|
|
2019-01-14 08:11:24 -08:00
|
|
|
func maxint(i1, i2 int64) int64 {
|
|
|
|
if i1 > i2 {
|
|
|
|
return i1
|
|
|
|
}
|
|
|
|
return i2
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestArithInt() {
|
2018-08-06 12:00:49 -07:00
|
|
|
for d := 0; d < 1000; d++ {
|
|
|
|
n1 := int64(rand.Int31())
|
2020-09-29 04:29:10 -07:00
|
|
|
i1 := sdk.NewInt(n1)
|
2018-08-06 12:00:49 -07:00
|
|
|
n2 := int64(rand.Int31())
|
2020-09-29 04:29:10 -07:00
|
|
|
i2 := sdk.NewInt(n2)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
|
|
|
cases := []struct {
|
2020-09-29 04:29:10 -07:00
|
|
|
ires sdk.Int
|
2018-08-06 12:00:49 -07:00
|
|
|
nres int64
|
|
|
|
}{
|
|
|
|
{i1.Add(i2), n1 + n2},
|
|
|
|
{i1.Sub(i2), n1 - n2},
|
|
|
|
{i1.Mul(i2), n1 * n2},
|
2019-02-21 09:35:55 -08:00
|
|
|
{i1.Quo(i2), n1 / n2},
|
2018-08-06 12:00:49 -07:00
|
|
|
{i1.AddRaw(n2), n1 + n2},
|
|
|
|
{i1.SubRaw(n2), n1 - n2},
|
|
|
|
{i1.MulRaw(n2), n1 * n2},
|
2019-02-21 09:35:55 -08:00
|
|
|
{i1.QuoRaw(n2), n1 / n2},
|
2020-09-29 04:29:10 -07:00
|
|
|
{sdk.MinInt(i1, i2), minint(n1, n2)},
|
|
|
|
{sdk.MaxInt(i1, i2), maxint(n1, n2)},
|
2018-08-06 12:00:49 -07:00
|
|
|
{i1.Neg(), -n1},
|
2021-03-24 09:33:55 -07:00
|
|
|
{i1.Abs(), n1},
|
|
|
|
{i1.Neg().Abs(), n1},
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for tcnum, tc := range cases {
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Equal(tc.nres, tc.ires.Int64(), "Int arithmetic operation does not match with int64 operation. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestCompInt() {
|
2018-08-06 12:00:49 -07:00
|
|
|
for d := 0; d < 1000; d++ {
|
|
|
|
n1 := int64(rand.Int31())
|
2020-09-29 04:29:10 -07:00
|
|
|
i1 := sdk.NewInt(n1)
|
2018-08-06 12:00:49 -07:00
|
|
|
n2 := int64(rand.Int31())
|
2020-09-29 04:29:10 -07:00
|
|
|
i2 := sdk.NewInt(n2)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
ires bool
|
|
|
|
nres bool
|
|
|
|
}{
|
|
|
|
{i1.Equal(i2), n1 == n2},
|
|
|
|
{i1.GT(i2), n1 > n2},
|
|
|
|
{i1.LT(i2), n1 < n2},
|
2020-03-04 09:49:59 -08:00
|
|
|
{i1.LTE(i2), n1 <= n2},
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for tcnum, tc := range cases {
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Equal(tc.nres, tc.ires, "Int comparison operation does not match with int64 operation. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func randint() sdk.Int {
|
|
|
|
return sdk.NewInt(rand.Int63())
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestImmutabilityAllInt() {
|
|
|
|
ops := []func(*sdk.Int){
|
|
|
|
func(i *sdk.Int) { _ = i.Add(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.Sub(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.Mul(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.Quo(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.AddRaw(rand.Int63()) },
|
|
|
|
func(i *sdk.Int) { _ = i.SubRaw(rand.Int63()) },
|
|
|
|
func(i *sdk.Int) { _ = i.MulRaw(rand.Int63()) },
|
|
|
|
func(i *sdk.Int) { _ = i.QuoRaw(rand.Int63()) },
|
|
|
|
func(i *sdk.Int) { _ = i.Neg() },
|
2021-03-24 09:33:55 -07:00
|
|
|
func(i *sdk.Int) { _ = i.Abs() },
|
2020-09-29 04:29:10 -07:00
|
|
|
func(i *sdk.Int) { _ = i.IsZero() },
|
|
|
|
func(i *sdk.Int) { _ = i.Sign() },
|
|
|
|
func(i *sdk.Int) { _ = i.Equal(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.GT(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.LT(randint()) },
|
|
|
|
func(i *sdk.Int) { _ = i.String() },
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < 1000; i++ {
|
|
|
|
n := rand.Int63()
|
2020-09-29 04:29:10 -07:00
|
|
|
ni := sdk.NewInt(n)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
|
|
|
for opnum, op := range ops {
|
|
|
|
op(&ni)
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Equal(n, ni.Int64(), "Int is modified by operation. tc #%d", opnum)
|
|
|
|
s.Require().Equal(sdk.NewInt(n), ni, "Int is modified by operation. tc #%d", opnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestEncodingTableInt() {
|
|
|
|
var i sdk.Int
|
2018-08-06 12:00:49 -07:00
|
|
|
|
|
|
|
cases := []struct {
|
2020-09-29 04:29:10 -07:00
|
|
|
i sdk.Int
|
2020-01-24 07:32:00 -08:00
|
|
|
jsonBz []byte
|
|
|
|
rawBz []byte
|
2018-08-06 12:00:49 -07:00
|
|
|
}{
|
2020-01-24 07:32:00 -08:00
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(0),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"0\""),
|
|
|
|
[]byte{0x30},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(100),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"100\""),
|
|
|
|
[]byte{0x31, 0x30, 0x30},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(-100),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"-100\""),
|
|
|
|
[]byte{0x2d, 0x31, 0x30, 0x30},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(51842),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"51842\""),
|
|
|
|
[]byte{0x35, 0x31, 0x38, 0x34, 0x32},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(-51842),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"-51842\""),
|
|
|
|
[]byte{0x2d, 0x35, 0x31, 0x38, 0x34, 0x32},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(19513368),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"19513368\""),
|
|
|
|
[]byte{0x31, 0x39, 0x35, 0x31, 0x33, 0x33, 0x36, 0x38},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(-19513368),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"-19513368\""),
|
|
|
|
[]byte{0x2d, 0x31, 0x39, 0x35, 0x31, 0x33, 0x33, 0x36, 0x38},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(999999999999),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"999999999999\""),
|
|
|
|
[]byte{0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewInt(-999999999999),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"-999999999999\""),
|
|
|
|
[]byte{0x2d, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39},
|
|
|
|
},
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for tcnum, tc := range cases {
|
|
|
|
bz, err := tc.i.MarshalJSON()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.jsonBz, bz, "Marshaled value is different from exported. tc #%d", tcnum)
|
2020-01-24 07:32:00 -08:00
|
|
|
|
2018-08-06 12:00:49 -07:00
|
|
|
err = (&i).UnmarshalJSON(bz)
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
bz, err = tc.i.Marshal()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.rawBz, bz, "Marshaled value is different from exported. tc #%d", tcnum)
|
2020-01-24 07:32:00 -08:00
|
|
|
|
|
|
|
err = (&i).Unmarshal(bz)
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestEncodingTableUint() {
|
|
|
|
var i sdk.Uint
|
2018-08-06 12:00:49 -07:00
|
|
|
|
|
|
|
cases := []struct {
|
2020-09-29 04:29:10 -07:00
|
|
|
i sdk.Uint
|
2020-01-24 07:32:00 -08:00
|
|
|
jsonBz []byte
|
|
|
|
rawBz []byte
|
2018-08-06 12:00:49 -07:00
|
|
|
}{
|
2020-01-24 07:32:00 -08:00
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewUint(0),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"0\""),
|
|
|
|
[]byte{0x30},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewUint(100),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"100\""),
|
|
|
|
[]byte{0x31, 0x30, 0x30},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewUint(51842),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"51842\""),
|
|
|
|
[]byte{0x35, 0x31, 0x38, 0x34, 0x32},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewUint(19513368),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"19513368\""),
|
|
|
|
[]byte{0x31, 0x39, 0x35, 0x31, 0x33, 0x33, 0x36, 0x38},
|
|
|
|
},
|
|
|
|
{
|
2020-09-29 04:29:10 -07:00
|
|
|
sdk.NewUint(999999999999),
|
2020-01-24 07:32:00 -08:00
|
|
|
[]byte("\"999999999999\""),
|
|
|
|
[]byte{0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39},
|
|
|
|
},
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for tcnum, tc := range cases {
|
|
|
|
bz, err := tc.i.MarshalJSON()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.jsonBz, bz, "Marshaled value is different from exported. tc #%d", tcnum)
|
2020-01-24 07:32:00 -08:00
|
|
|
|
2018-08-06 12:00:49 -07:00
|
|
|
err = (&i).UnmarshalJSON(bz)
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
bz, err = tc.i.Marshal()
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error marshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.rawBz, bz, "Marshaled value is different from exported. tc #%d", tcnum)
|
2020-01-24 07:32:00 -08:00
|
|
|
|
|
|
|
err = (&i).Unmarshal(bz)
|
2020-09-29 04:29:10 -07:00
|
|
|
s.Require().Nil(err, "Error unmarshaling Int. tc #%d, err %s", tcnum, err)
|
|
|
|
s.Require().Equal(tc.i, i, "Unmarshaled value is different from exported. tc #%d", tcnum)
|
2018-08-06 12:00:49 -07:00
|
|
|
}
|
|
|
|
}
|
2018-11-19 09:13:45 -08:00
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestIntMod() {
|
2020-03-04 09:49:59 -08:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
x int64
|
|
|
|
y int64
|
|
|
|
ret int64
|
|
|
|
wantPanic bool
|
|
|
|
}{
|
|
|
|
{"3 % 10", 3, 10, 3, false},
|
|
|
|
{"10 % 3", 10, 3, 1, false},
|
|
|
|
{"4 % 2", 4, 2, 0, false},
|
|
|
|
{"2 % 0", 2, 0, 0, true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
2020-09-29 04:29:10 -07:00
|
|
|
if tt.wantPanic {
|
|
|
|
s.Require().Panics(func() { sdk.NewInt(tt.x).Mod(sdk.NewInt(tt.y)) })
|
|
|
|
s.Require().Panics(func() { sdk.NewInt(tt.x).ModRaw(tt.y) })
|
|
|
|
return
|
|
|
|
}
|
|
|
|
s.Require().True(sdk.NewInt(tt.x).Mod(sdk.NewInt(tt.y)).Equal(sdk.NewInt(tt.ret)))
|
|
|
|
s.Require().True(sdk.NewInt(tt.x).ModRaw(tt.y).Equal(sdk.NewInt(tt.ret)))
|
2020-03-04 09:49:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:29:10 -07:00
|
|
|
func (s *intTestSuite) TestIntEq() {
|
|
|
|
_, resp, _, _, _ := sdk.IntEq(s.T(), sdk.ZeroInt(), sdk.ZeroInt())
|
|
|
|
s.Require().True(resp)
|
|
|
|
_, resp, _, _, _ = sdk.IntEq(s.T(), sdk.OneInt(), sdk.ZeroInt())
|
|
|
|
s.Require().False(resp)
|
2020-03-04 09:49:59 -08:00
|
|
|
}
|
types: use (*math/big.Int).BitLen() == 0 to check if value is 0 (#8580)
Instead of using len((*math/big.Int).Bytes()) == 0, which expensively
creates a byte slice and marshals a value, on the majority hot path,
instead use the cheaper method .BitLen() to check if 0.
Benchmarking results, just from types:
name old time/op new time/op delta
CoinsAdditionIntersect/sizes:_A_1,_B_1-8 132ns ± 2% 126ns ±13% -4.55% (p=0.050 n=10+10)
CoinsAdditionIntersect/sizes:_A_5,_B_5-8 1.41µs ± 3% 1.41µs ± 2% ~ (p=1.000 n=10+10)
CoinsAdditionIntersect/sizes:_A_5,_B_20-8 2.30µs ± 1% 2.27µs ± 3% ~ (p=0.066 n=10+10)
CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 30.9µs ± 3% 30.7µs ± 1% ~ (p=0.218 n=10+10)
CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 31.4µs ± 3% 30.8µs ± 2% -1.94% (p=0.015 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 116ns ± 1% 114ns ± 4% ~ (p=0.142 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 1.11µs ± 1% 1.08µs ± 3% -2.36% (p=0.003 n=8+10)
CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 1.85µs ± 2% 1.82µs ± 1% -1.38% (p=0.001 n=10+9)
CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 30.7µs ± 1% 30.6µs ± 3% ~ (p=0.393 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 31.1µs ± 1% 30.7µs ± 2% -1.32% (p=0.015 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 31.0µs ± 2% 30.7µs ± 2% ~ (p=0.190 n=10+10)
Bech32ifyPubKey-8 28.8µs ± 5% 28.8µs ± 3% ~ (p=0.965 n=10+8)
GetPubKeyFromBech32-8 38.8µs ± 3% 39.4µs ± 2% +1.70% (p=0.013 n=9+10)
ParseCoin-8 16.7µs ± 6% 15.8µs ± 4% -5.21% (p=0.001 n=10+10)
MarshalTo-8 521ns ± 5% 508ns ± 3% -2.56% (p=0.029 n=10+10)
UintMarshal-8 3.10µs ±17% 2.56µs ± 3% -17.45% (p=0.000 n=10+9)
IntMarshal-8 2.52µs ±10% 1.94µs ± 2% -23.10% (p=0.000 n=10+10)
name old alloc/op new alloc/op delta
Bech32ifyPubKey-8 4.02kB ± 0% 4.02kB ± 0% ~ (all equal)
GetPubKeyFromBech32-8 2.48kB ± 0% 2.48kB ± 0% ~ (all equal)
ParseCoin-8 2.21kB ± 0% 2.21kB ± 0% ~ (all equal)
MarshalTo-8 80.0B ± 0% 80.0B ± 0% ~ (all equal)
UintMarshal-8 440B ± 0% 392B ± 0% -10.91% (p=0.000 n=10+10)
IntMarshal-8 216B ± 0% 168B ± 0% -22.22% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
Bech32ifyPubKey-8 25.0 ± 0% 25.0 ± 0% ~ (all equal)
GetPubKeyFromBech32-8 85.0 ± 0% 85.0 ± 0% ~ (all equal)
ParseCoin-8 71.0 ± 0% 71.0 ± 0% ~ (all equal)
MarshalTo-8 2.00 ± 0% 2.00 ± 0% ~ (all equal)
UintMarshal-8 31.0 ± 0% 25.0 ± 0% -19.35% (p=0.000 n=10+10)
IntMarshal-8 24.0 ± 0% 18.0 ± 0% -25.00% (p=0.000 n=10+10)
name old speed new speed delta
UintMarshal-8 2.27MB/s ±15% 2.75MB/s ± 2% +20.87% (p=0.000 n=10+8)
IntMarshal-8 2.78MB/s ± 9% 3.60MB/s ± 2% +29.69% (p=0.000 n=10+10)
Fixes #8575
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2021-02-15 02:53:10 -08:00
|
|
|
|
|
|
|
func TestRoundTripMarshalToInt(t *testing.T) {
|
|
|
|
var values = []int64{
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
1 << 10,
|
|
|
|
1<<10 - 3,
|
|
|
|
1<<63 - 1,
|
|
|
|
1<<32 - 7,
|
|
|
|
1<<22 - 8,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, value := range values {
|
|
|
|
value := value
|
|
|
|
t.Run(fmt.Sprintf("%d", value), func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
var scratch [20]byte
|
|
|
|
iv := sdk.NewInt(value)
|
|
|
|
n, err := iv.MarshalTo(scratch[:])
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
rt := new(sdk.Int)
|
|
|
|
if err := rt.Unmarshal(scratch[:n]); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if !rt.Equal(iv) {
|
|
|
|
t.Fatalf("roundtrip=%q != original=%q", rt, iv)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|