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 }