github.com/nebulouslabs/sia@v1.3.7/types/currency_test.go (about) 1 package types 2 3 import ( 4 "math" 5 "math/big" 6 "testing" 7 ) 8 9 // TestNewCurrency initializes a standard new currency. 10 func TestNewCurrency(t *testing.T) { 11 b := big.NewInt(481) 12 c := NewCurrency(b) 13 if b.String() != c.String() { 14 t.Error("NewCurrency does't seem to work properly") 15 } 16 } 17 18 // TestCurrencyAdd probes the addition function of the currency type. 19 func TestCurrencyAdd(t *testing.T) { 20 c7 := NewCurrency64(7) 21 c12 := NewCurrency64(12) 22 c19 := NewCurrency64(19) 23 24 if c7.Add(c12).Cmp(c19) != 0 { 25 t.Error("Add doesn't seem to work right") 26 } 27 } 28 29 // TestCurrencyToBig tests the Big method for the currency type 30 func TestCurrencyToBig(t *testing.T) { 31 c := NewCurrency64(125) 32 cb := c.Big() 33 b := big.NewInt(125) 34 35 if b.Cmp(cb) != 0 { 36 t.Error("currency to big has failed") 37 } 38 } 39 40 // TestCurrencyCmp tests the Cmp method for the currency type 41 func TestCurrencyCmp(t *testing.T) { 42 tests := []struct { 43 x, y Currency 44 exp int 45 }{ 46 {NewCurrency64(0), NewCurrency64(0), 0}, 47 {NewCurrency64(0), NewCurrency64(1), -1}, 48 {NewCurrency64(1), NewCurrency64(0), 1}, 49 {NewCurrency64(100), NewCurrency64(7), 1}, 50 {NewCurrency64(777), NewCurrency(big.NewInt(777)), 0}, 51 {NewCurrency(big.NewInt(7)), NewCurrency(big.NewInt(8)), -1}, 52 } 53 54 for _, test := range tests { 55 if c := test.x.Cmp(test.y); c != test.exp { 56 t.Errorf("expected %v.Cmp(%v) == %v, got %v", test.x, test.y, test.exp, c) 57 } else if bc := test.x.Big().Cmp(test.y.Big()); c != bc { 58 t.Errorf("Currency.Cmp (%v) does not match big.Int.Cmp (%v) for %v.Cmp(%v)", c, bc, test.x, test.y) 59 } 60 } 61 } 62 63 // TestCurrencyCmp64 tests the Cmp64 method for the currency type 64 func TestCurrencyCmp64(t *testing.T) { 65 tests := []struct { 66 x Currency 67 y uint64 68 exp int 69 }{ 70 {NewCurrency64(0), 0, 0}, 71 {NewCurrency64(0), 1, -1}, 72 {NewCurrency64(1), 0, 1}, 73 {NewCurrency64(100), 7, 1}, 74 {NewCurrency64(777), 777, 0}, 75 {NewCurrency(big.NewInt(7)), 8, -1}, 76 } 77 78 for _, test := range tests { 79 if c := test.x.Cmp64(test.y); c != test.exp { 80 t.Errorf("expected %v.Cmp64(%v) == %v, got %v", test.x, test.y, test.exp, c) 81 } else if bc := test.x.Big().Cmp(big.NewInt(int64(test.y))); c != bc { 82 t.Errorf("Currency.Cmp64 (%v) does not match big.Int.Cmp (%v) for %v.Cmp64(%v)", c, bc, test.x, test.y) 83 } 84 } 85 } 86 87 // TestCurrencyDiv checks that the div function has been correctly implemented. 88 func TestCurrencyDiv(t *testing.T) { 89 c9 := NewCurrency64(9) 90 c10 := NewCurrency64(10) 91 c90 := NewCurrency64(90) 92 c97 := NewCurrency64(97) 93 94 c90D10 := c90.Div(c10) 95 if c90D10.Cmp(c9) != 0 { 96 t.Error("Dividing 90 by 10 should produce 9") 97 } 98 c97D10 := c97.Div(c10) 99 if c97D10.Cmp(c9) != 0 { 100 t.Error("Dividing 97 by 10 should produce 9") 101 } 102 } 103 104 // TestCurrencyDiv64 checks that the Div64 function has been correctly implemented. 105 func TestCurrencyDiv64(t *testing.T) { 106 c9 := NewCurrency64(9) 107 u10 := uint64(10) 108 c90 := NewCurrency64(90) 109 c97 := NewCurrency64(97) 110 111 c90D10 := c90.Div64(u10) 112 if c90D10.Cmp(c9) != 0 { 113 t.Error("Dividing 90 by 10 should produce 9") 114 } 115 c97D10 := c97.Div64(u10) 116 if c97D10.Cmp(c9) != 0 { 117 t.Error("Dividing 97 by 10 should produce 9") 118 } 119 } 120 121 // TestCurrencyEquals tests the Equals method for the currency type 122 func TestCurrencyEquals(t *testing.T) { 123 tests := []struct { 124 x, y Currency 125 exp bool 126 }{ 127 {NewCurrency64(0), NewCurrency64(0), true}, 128 {NewCurrency64(0), NewCurrency64(1), false}, 129 {NewCurrency64(1), NewCurrency64(0), false}, 130 {NewCurrency64(100), NewCurrency64(7), false}, 131 {NewCurrency64(777), NewCurrency(big.NewInt(777)), true}, 132 {NewCurrency(big.NewInt(7)), NewCurrency(big.NewInt(8)), false}, 133 } 134 135 for _, test := range tests { 136 if eq := test.x.Equals(test.y); eq != test.exp { 137 t.Errorf("expected %v.Equals(%v) == %v, got %v", test.x, test.y, test.exp, eq) 138 } else if bc := test.x.Big().Cmp(test.y.Big()); (bc == 0) != eq { 139 t.Errorf("Currency.Equals (%v) does not match big.Int.Cmp (%v) for %v.Equals(%v)", eq, bc, test.x, test.y) 140 } 141 } 142 } 143 144 // TestCurrencyEquals64 tests the Equals64 method for the currency type 145 func TestCurrencyEquals64(t *testing.T) { 146 tests := []struct { 147 x Currency 148 y uint64 149 exp bool 150 }{ 151 {NewCurrency64(0), 0, true}, 152 {NewCurrency64(0), 1, false}, 153 {NewCurrency64(1), 0, false}, 154 {NewCurrency64(100), 7, false}, 155 {NewCurrency64(777), 777, true}, 156 {NewCurrency(big.NewInt(7)), 8, false}, 157 } 158 159 for _, test := range tests { 160 if eq := test.x.Equals64(test.y); eq != test.exp { 161 t.Errorf("expected %v.Equals64(%v) == %v, got %v", test.x, test.y, test.exp, eq) 162 } else if bc := test.x.Big().Cmp(big.NewInt(int64(test.y))); (bc == 0) != eq { 163 t.Errorf("Currency.Equals64 (%v) does not match big.Int.Cmp (%v) for %v.Equals64(%v)", eq, bc, test.x, test.y) 164 } 165 } 166 } 167 168 // TestCurrencyMul probes the Mul function of the currency type. 169 func TestCurrencyMul(t *testing.T) { 170 c5 := NewCurrency64(5) 171 c6 := NewCurrency64(6) 172 c30 := NewCurrency64(30) 173 if c5.Mul(c6).Cmp(c30) != 0 { 174 t.Error("Multiplying 5 by 6 should equal 30") 175 } 176 } 177 178 // TestCurrencyMul64 probes the Mul64 function of the currency type. 179 func TestCurrencyMul64(t *testing.T) { 180 c5 := NewCurrency64(5) 181 u6 := uint64(6) 182 c30 := NewCurrency64(30) 183 if c5.Mul64(u6).Cmp(c30) != 0 { 184 t.Error("Multiplying 5 by 6 should equal 30") 185 } 186 } 187 188 // TestCurrencyMulRat probes the MulRat function of the currency type. 189 func TestCurrencyMulRat(t *testing.T) { 190 c5 := NewCurrency64(5) 191 c7 := NewCurrency64(7) 192 c10 := NewCurrency64(10) 193 if c5.MulRat(big.NewRat(2, 1)).Cmp(c10) != 0 { 194 t.Error("Multiplying 5 by 2 should return 10") 195 } 196 if c5.MulRat(big.NewRat(3, 2)).Cmp(c7) != 0 { 197 t.Error("Multiplying 5 by 1.5 should return 7") 198 } 199 } 200 201 // TestCurrencyRoundDown probes the RoundDown function of the currency type. 202 func TestCurrencyRoundDown(t *testing.T) { 203 // 10,000 is chosen because that's how many siafunds there usually are. 204 c40000 := NewCurrency64(40000) 205 c45000 := NewCurrency64(45000) 206 if c45000.RoundDown(NewCurrency64(10000)).Cmp(c40000) != 0 { 207 t.Error("rounding down 45000 to the nearest 10000 didn't work") 208 } 209 } 210 211 // TestCurrencyIsZero probes the IsZero function of the currency type. 212 func TestCurrencyIsZero(t *testing.T) { 213 c0 := NewCurrency64(0) 214 c1 := NewCurrency64(1) 215 if !c0.IsZero() { 216 t.Error("IsZero returns wrong value for 0") 217 } 218 if c1.IsZero() { 219 t.Error("IsZero returns wrong value for 1") 220 } 221 } 222 223 // TestCurrencySqrt probes the Sqrt function of the currency type. 224 func TestCurrencySqrt(t *testing.T) { 225 c8 := NewCurrency64(8) 226 c64 := NewCurrency64(64) 227 c80 := NewCurrency64(80) 228 sqrt64 := c64.Sqrt() 229 sqrt80 := c80.Sqrt() 230 231 if c8.Cmp(sqrt64) != 0 { 232 t.Error("square root of 64 should be 8") 233 } 234 if c8.Cmp(sqrt80) != 0 { 235 t.Error("square root of 80 should be 8") 236 } 237 } 238 239 // TestCurrencySub probes the Sub function of the currency type. 240 func TestCurrencySub(t *testing.T) { 241 c3 := NewCurrency64(3) 242 c13 := NewCurrency64(13) 243 c16 := NewCurrency64(16) 244 if c16.Sub(c3).Cmp(c13) != 0 { 245 t.Error("16 minus 3 should equal 13") 246 } 247 } 248 249 // TestNegativeCurrencyMulRat checks that negative numbers are rejected when 250 // calling MulRat on the currency type. 251 func TestNegativeCurrencyMulRat(t *testing.T) { 252 // In debug mode, attempting to get a negative currency results in a panic. 253 defer func() { 254 r := recover() 255 if r == nil { 256 t.Error("no panic occurred when trying to create a negative currency") 257 } 258 }() 259 260 c := NewCurrency64(12) 261 _ = c.MulRat(big.NewRat(-1, 1)) 262 } 263 264 // TestNegativeCurrencySub checks that negative numbers are prevented when 265 // using subtraction on the currency type. 266 func TestNegativeCurrencySub(t *testing.T) { 267 // In debug mode, attempting to get a negative currency results in a panic. 268 defer func() { 269 r := recover() 270 if r == nil { 271 t.Error("no panic occurred when trying to create a negative currency") 272 } 273 }() 274 275 c1 := NewCurrency64(1) 276 c2 := NewCurrency64(2) 277 _ = c1.Sub(c2) 278 } 279 280 // TestNegativeCurrencies tries an array of ways to produce a negative currency. 281 func TestNegativeNewCurrency(t *testing.T) { 282 // In debug mode, attempting to get a negative currency results in a panic. 283 defer func() { 284 r := recover() 285 if r == nil { 286 t.Error("no panic occurred when trying to create a negative currency") 287 } 288 }() 289 290 // Try to create a new currency from a negative number. 291 negBig := big.NewInt(-1) 292 _ = NewCurrency(negBig) 293 } 294 295 // TestCurrencyUint64 tests that a currency is correctly converted to a uint64. 296 func TestCurrencyUint64(t *testing.T) { 297 // Try a set of valid values. 298 values := []uint64{0, 1, 2, 3, 4, 25e3, math.MaxUint64 - 1e6, math.MaxUint64} 299 for _, value := range values { 300 c := NewCurrency64(value) 301 result, err := c.Uint64() 302 if err != nil { 303 t.Error(err) 304 } 305 if value != result { 306 t.Error("uint64 conversion failed") 307 } 308 } 309 310 // Try an overflow. 311 c := NewCurrency64(math.MaxUint64) 312 c = c.Mul(NewCurrency64(2)) 313 result, err := c.Uint64() 314 if err != ErrUint64Overflow { 315 t.Error(err) 316 } 317 if result != 0 { 318 t.Error("result is not being zeroed in the event of an error") 319 } 320 }