github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/uint_test.go (about)

     1  package types
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  	"math/rand"
     7  	"strconv"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestUintPanics(t *testing.T) {
    14  	// Max Uint = 1.15e+77
    15  	// Min Uint = 0
    16  	u1 := NewUint(0)
    17  	u2 := OneUint()
    18  
    19  	require.Equal(t, uint64(0), u1.Uint64())
    20  	require.Equal(t, uint64(1), u2.Uint64())
    21  
    22  	require.Panics(t, func() { NewUintFromBigInt(big.NewInt(-5)) })
    23  	require.Panics(t, func() { NewUintFromString("-1") })
    24  	require.NotPanics(t, func() {
    25  		require.True(t, NewUintFromString("0").Equal(ZeroUint()))
    26  		require.True(t, NewUintFromString("5").Equal(NewUint(5)))
    27  	})
    28  
    29  	// Overflow check
    30  	require.True(t, u1.Add(u1).Equal(ZeroUint()))
    31  	require.True(t, u1.Add(OneUint()).Equal(OneUint()))
    32  	require.Equal(t, uint64(0), u1.Uint64())
    33  	require.Equal(t, uint64(1), OneUint().Uint64())
    34  	require.Panics(t, func() { u1.SubUint64(2) })
    35  	require.True(t, u1.SubUint64(0).Equal(ZeroUint()))
    36  	require.True(t, u2.Add(OneUint()).Sub(OneUint()).Equal(OneUint()))    // i2 == 1
    37  	require.True(t, u2.Add(OneUint()).Mul(NewUint(5)).Equal(NewUint(10))) // i2 == 10
    38  	require.True(t, NewUint(7).Quo(NewUint(2)).Equal(NewUint(3)))
    39  	require.True(t, NewUint(0).Quo(NewUint(2)).Equal(ZeroUint()))
    40  	require.True(t, NewUint(5).MulUint64(4).Equal(NewUint(20)))
    41  	require.True(t, NewUint(5).MulUint64(0).Equal(ZeroUint()))
    42  
    43  	uintmax := NewUintFromBigInt(new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1)))
    44  	uintmin := ZeroUint()
    45  
    46  	// divs by zero
    47  	require.Panics(t, func() { OneUint().Mul(ZeroUint().SubUint64(uint64(1))) })
    48  	require.Panics(t, func() { OneUint().QuoUint64(0) })
    49  	require.Panics(t, func() { OneUint().Quo(ZeroUint()) })
    50  	require.Panics(t, func() { ZeroUint().QuoUint64(0) })
    51  	require.Panics(t, func() { OneUint().Quo(ZeroUint().Sub(OneUint())) })
    52  	require.Panics(t, func() { uintmax.Add(OneUint()) })
    53  	require.Panics(t, func() { uintmax.Incr() })
    54  	require.Panics(t, func() { uintmin.Sub(OneUint()) })
    55  	require.Panics(t, func() { uintmin.Decr() })
    56  
    57  	require.Equal(t, uint64(0), MinUint(ZeroUint(), OneUint()).Uint64())
    58  	require.Equal(t, uint64(1), MaxUint(ZeroUint(), OneUint()).Uint64())
    59  
    60  	// comparison ops
    61  	require.True(t,
    62  		OneUint().GT(ZeroUint()),
    63  	)
    64  	require.False(t,
    65  		OneUint().LT(ZeroUint()),
    66  	)
    67  	require.True(t,
    68  		OneUint().GTE(ZeroUint()),
    69  	)
    70  	require.False(t,
    71  		OneUint().LTE(ZeroUint()),
    72  	)
    73  
    74  	require.False(t, ZeroUint().GT(OneUint()))
    75  	require.True(t, ZeroUint().LT(OneUint()))
    76  	require.False(t, ZeroUint().GTE(OneUint()))
    77  	require.True(t, ZeroUint().LTE(OneUint()))
    78  }
    79  
    80  func TestIdentUint(t *testing.T) {
    81  	for d := 0; d < 1000; d++ {
    82  		n := rand.Uint64()
    83  		i := NewUint(n)
    84  
    85  		ifromstr := NewUintFromString(strconv.FormatUint(n, 10))
    86  
    87  		cases := []uint64{
    88  			i.Uint64(),
    89  			i.BigInt().Uint64(),
    90  			i.i.Uint64(),
    91  			ifromstr.Uint64(),
    92  			NewUintFromBigInt(new(big.Int).SetUint64(n)).Uint64(),
    93  		}
    94  
    95  		for tcnum, tc := range cases {
    96  			require.Equal(t, n, tc, "Uint is modified during conversion. tc #%d", tcnum)
    97  		}
    98  	}
    99  }
   100  
   101  func TestArithUint(t *testing.T) {
   102  	for d := 0; d < 1000; d++ {
   103  		n1 := uint64(rand.Uint32())
   104  		u1 := NewUint(n1)
   105  		n2 := uint64(rand.Uint32())
   106  		u2 := NewUint(n2)
   107  
   108  		cases := []struct {
   109  			ures Uint
   110  			nres uint64
   111  		}{
   112  			{u1.Add(u2), n1 + n2},
   113  			{u1.Mul(u2), n1 * n2},
   114  			{u1.Quo(u2), n1 / n2},
   115  			{u1.AddUint64(n2), n1 + n2},
   116  			{u1.MulUint64(n2), n1 * n2},
   117  			{u1.QuoUint64(n2), n1 / n2},
   118  			{MinUint(u1, u2), minuint(n1, n2)},
   119  			{MaxUint(u1, u2), maxuint(n1, n2)},
   120  			{u1.Incr(), n1 + 1},
   121  		}
   122  
   123  		for tcnum, tc := range cases {
   124  			require.Equal(t, tc.nres, tc.ures.Uint64(), "Uint arithmetic operation does not match with uint64 operation. tc #%d", tcnum)
   125  		}
   126  
   127  		if n2 > n1 {
   128  			n1, n2 = n2, n1
   129  			u1, u2 = NewUint(n1), NewUint(n2)
   130  		}
   131  
   132  		subs := []struct {
   133  			ures Uint
   134  			nres uint64
   135  		}{
   136  			{u1.Sub(u2), n1 - n2},
   137  			{u1.SubUint64(n2), n1 - n2},
   138  			{u1.Decr(), n1 - 1},
   139  		}
   140  
   141  		for tcnum, tc := range subs {
   142  			require.Equal(t, tc.nres, tc.ures.Uint64(), "Uint subtraction does not match with uint64 operation. tc #%d", tcnum)
   143  		}
   144  	}
   145  }
   146  
   147  func TestCompUint(t *testing.T) {
   148  	for d := 0; d < 10000; d++ {
   149  		n1 := rand.Uint64()
   150  		i1 := NewUint(n1)
   151  		n2 := rand.Uint64()
   152  		i2 := NewUint(n2)
   153  
   154  		cases := []struct {
   155  			ires bool
   156  			nres bool
   157  		}{
   158  			{i1.Equal(i2), n1 == n2},
   159  			{i1.GT(i2), n1 > n2},
   160  			{i1.LT(i2), n1 < n2},
   161  			{i1.GTE(i2), !i1.LT(i2)},
   162  			{!i1.GTE(i2), i1.LT(i2)},
   163  			{i1.LTE(i2), n1 <= n2},
   164  			{i2.LTE(i1), n2 <= n1},
   165  		}
   166  
   167  		for tcnum, tc := range cases {
   168  			require.Equal(t, tc.nres, tc.ires, "Uint comparison operation does not match with uint64 operation. tc #%d", tcnum)
   169  		}
   170  	}
   171  }
   172  
   173  func TestImmutabilityAllUint(t *testing.T) {
   174  	ops := []func(*Uint){
   175  		func(i *Uint) { _ = i.Add(NewUint(rand.Uint64())) },
   176  		func(i *Uint) { _ = i.Sub(NewUint(rand.Uint64() % i.Uint64())) },
   177  		func(i *Uint) { _ = i.Mul(randuint()) },
   178  		func(i *Uint) { _ = i.Quo(randuint()) },
   179  		func(i *Uint) { _ = i.AddUint64(rand.Uint64()) },
   180  		func(i *Uint) { _ = i.SubUint64(rand.Uint64() % i.Uint64()) },
   181  		func(i *Uint) { _ = i.MulUint64(rand.Uint64()) },
   182  		func(i *Uint) { _ = i.QuoUint64(rand.Uint64()) },
   183  		func(i *Uint) { _ = i.IsZero() },
   184  		func(i *Uint) { _ = i.Equal(randuint()) },
   185  		func(i *Uint) { _ = i.GT(randuint()) },
   186  		func(i *Uint) { _ = i.GTE(randuint()) },
   187  		func(i *Uint) { _ = i.LT(randuint()) },
   188  		func(i *Uint) { _ = i.LTE(randuint()) },
   189  		func(i *Uint) { _ = i.String() },
   190  		func(i *Uint) { _ = i.Incr() },
   191  		func(i *Uint) {
   192  			if i.IsZero() {
   193  				return
   194  			}
   195  
   196  			_ = i.Decr()
   197  		},
   198  	}
   199  
   200  	for i := 0; i < 1000; i++ {
   201  		n := rand.Uint64()
   202  		ni := NewUint(n)
   203  
   204  		for opnum, op := range ops {
   205  			op(&ni)
   206  
   207  			require.Equal(t, n, ni.Uint64(), "Uint is modified by operation. #%d", opnum)
   208  			require.Equal(t, NewUint(n), ni, "Uint is modified by operation. #%d", opnum)
   209  		}
   210  	}
   211  }
   212  
   213  func TestSafeSub(t *testing.T) {
   214  	testCases := []struct {
   215  		x, y     Uint
   216  		expected uint64
   217  		panic    bool
   218  	}{
   219  		{NewUint(0), NewUint(0), 0, false},
   220  		{NewUint(10), NewUint(5), 5, false},
   221  		{NewUint(5), NewUint(10), 5, true},
   222  		{NewUint(math.MaxUint64), NewUint(0), math.MaxUint64, false},
   223  	}
   224  
   225  	for i, tc := range testCases {
   226  		tc := tc
   227  		if tc.panic {
   228  			require.Panics(t, func() { tc.x.Sub(tc.y) })
   229  			continue
   230  		}
   231  		require.Equal(
   232  			t, tc.expected, tc.x.Sub(tc.y).Uint64(),
   233  			"invalid subtraction result; x: %s, y: %s, tc: #%d", tc.x, tc.y, i,
   234  		)
   235  	}
   236  }
   237  
   238  func TestParseUint(t *testing.T) {
   239  	type args struct {
   240  		s string
   241  	}
   242  	tests := []struct {
   243  		name    string
   244  		args    args
   245  		want    Uint
   246  		wantErr bool
   247  	}{
   248  		{"malformed", args{"malformed"}, Uint{}, true},
   249  		{"empty", args{""}, Uint{}, true},
   250  		{"positive", args{"50"}, NewUint(uint64(50)), false},
   251  		{"negative", args{"-1"}, Uint{}, true},
   252  		{"zero", args{"0"}, ZeroUint(), false},
   253  	}
   254  	for _, tt := range tests {
   255  		tt := tt
   256  		t.Run(tt.name, func(t *testing.T) {
   257  			got, err := ParseUint(tt.args.s)
   258  			if tt.wantErr {
   259  				require.Error(t, err)
   260  				return
   261  			}
   262  			require.NoError(t, err)
   263  			require.True(t, got.Equal(tt.want))
   264  		})
   265  	}
   266  }
   267  
   268  func randuint() Uint {
   269  	return NewUint(rand.Uint64())
   270  }
   271  
   272  func TestRelativePow(t *testing.T) {
   273  	tests := []struct {
   274  		args []Uint
   275  		want Uint
   276  	}{
   277  		{[]Uint{ZeroUint(), ZeroUint(), OneUint()}, OneUint()},
   278  		{[]Uint{ZeroUint(), ZeroUint(), NewUint(10)}, NewUint(10)},
   279  		{[]Uint{ZeroUint(), OneUint(), NewUint(10)}, ZeroUint()},
   280  		{[]Uint{NewUint(10), NewUint(2), OneUint()}, NewUint(100)},
   281  		{[]Uint{NewUint(210), NewUint(2), NewUint(100)}, NewUint(441)},
   282  		{[]Uint{NewUint(2100), NewUint(2), NewUint(1000)}, NewUint(4410)},
   283  		{[]Uint{NewUint(1000000001547125958), NewUint(600), NewUint(1000000000000000000)}, NewUint(1000000928276004850)},
   284  	}
   285  	for i, tc := range tests {
   286  		res := RelativePow(tc.args[0], tc.args[1], tc.args[2])
   287  		require.Equal(t, tc.want, res, "unexpected result for test case %d, input: %v, got: %v", i, tc.args, res)
   288  	}
   289  }