github.com/Finschia/finschia-sdk@v0.48.1/types/uint_test.go (about)

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