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 }