Commit 977975f6 authored by David Vorick's avatar David Vorick

polish currency.go

parent 288f1aea
package types
// currency.go defines the internal currency object. One design goal of the
// currency type is immutability: the currency type should be safe to pass
// directly to other objects and packages. The currency object should never
// have a negative value. The currency should never overflow. There is a
// maximum size value that can be encoded (around 10^10^20), however exceeding
// this value will not result in overflow.
import (
"errors"
"fmt"
......@@ -9,28 +16,23 @@ import (
"github.com/NebulousLabs/Sia/build"
)
type (
// A Currency represents a number of siacoins or siafunds. Internally, a
// Currency value is unbounded; however, Currency values sent over the wire
// protocol are subject to a maximum size of 255 bytes (approximately 10^614).
// Unlike the math/big library, whose methods modify their receiver, all
// arithmetic Currency methods return a new value. Currency cannot be negative.
Currency struct {
i big.Int
}
)
var (
ZeroCurrency = NewCurrency64(0)
ErrNegativeCurrency = errors.New("negative currency not allowed")
)
// currency.go defines the internal currency object. One design goal of the
// currency type is immutability: the currency type should be safe to pass
// directly to other objects and packages. The currency object should never
// have a negative value. The currency should never overflow. There is a
// maximum size value that can be encoded (around 10^10^20), however exceeding
// this value will not result in overflow.
// A Currency represents a number of siacoins or siafunds. Internally, a
// Currency value is unbounded; however, Currency values sent over the wire
// protocol are subject to a maximum size of 255 bytes (approximately 10^614).
// Unlike the math/big library, whose methods modify their receiver, all
// arithmetic Currency methods return a new value. Currency cannot be negative.
type Currency struct {
i big.Int
}
// NewCurrency creates a Currency value from a big.Int. Undefined behavior
// occurs if a negative input is used.
func NewCurrency(b *big.Int) (c Currency) {
......
......@@ -5,8 +5,30 @@ import (
"fmt"
"math/big"
"testing"
"github.com/NebulousLabs/Sia/encoding"
)
// TestNewCurrency initializes a standard new currency.
func TestNewCurrency(t *testing.T) {
b := big.NewInt(481)
c := NewCurrency(b)
if b.String() != c.String() {
t.Error("NewCurrency does't seem to work properly")
}
}
// TestCurrencyAdd probes the addition function of the currency type.
func TestCurrencyAdd(t *testing.T) {
c7 := NewCurrency64(7)
c12 := NewCurrency64(12)
c19 := NewCurrency64(19)
if c7.Add(c12).Cmp(c19) != 0 {
t.Error("Add doesn't seem to work right")
}
}
// TestCurrencyToBig tests the Big method for the currency type
func TestCurrencyToBig(t *testing.T) {
c := NewCurrency64(125)
......@@ -35,8 +57,52 @@ func TestCurrencyDiv(t *testing.T) {
}
}
// TestCurrencySqrt checks that the sqrt function of the currency type has been
// correctly implemented.
// TestCurrencyMul probes the Mul function of the currency type.
func TestCurrencyMul(t *testing.T) {
c5 := NewCurrency64(5)
c6 := NewCurrency64(6)
c30 := NewCurrency64(30)
if c5.Mul(c6).Cmp(c30) != 0 {
t.Error("Multiplying 5 by 6 should equal 30")
}
}
// TestCurrencyMulFloat probes the MulFloat function of the currency type.
func TestCurrencyMulFloat(t *testing.T) {
c5 := NewCurrency64(5)
c7 := NewCurrency64(7)
c10 := NewCurrency64(10)
if c5.MulFloat(2).Cmp(c10) != 0 {
t.Error("Multiplying 5 by 2 should return 10")
}
if c5.MulFloat(1.5).Cmp(c7) != 0 {
t.Error("Multiplying 5 by 1.5 should return 7")
}
}
// TestCurrencyRoundDown probes the RoundDown function of the currency type.
func TestCurrencyRoundDown(t *testing.T) {
// 10,000 is chosen because that's how many siafunds there usually are.
c40000 := NewCurrency64(40000)
c45000 := NewCurrency64(45000)
if c45000.RoundDown(10000).Cmp(c40000) != 0 {
t.Error("rounding down 45000 to the nearest 10000 didn't work")
}
}
// TestCurrencyIsZero probes the IsZero function of the currency type.
func TestCurrencyIsZero(t *testing.T) {
c0 := NewCurrency64(0)
c1 := NewCurrency64(1)
if !c0.IsZero() {
t.Error("IsZero returns wrong value for 0")
}
if c1.IsZero() {
t.Error("IsZero returns wrong value for 1")
}
}
// TestCurrencySqrt probes the Sqrt function of the currency type.
func TestCurrencySqrt(t *testing.T) {
c8 := NewCurrency64(8)
c64 := NewCurrency64(64)
......@@ -52,6 +118,16 @@ func TestCurrencySqrt(t *testing.T) {
}
}
// TestCurrencySub probes the Sub function of the currency type.
func TestCurrencySub(t *testing.T) {
c3 := NewCurrency64(3)
c13 := NewCurrency64(13)
c16 := NewCurrency64(16)
if c16.Sub(c3).Cmp(c13) != 0 {
t.Error("16 minus 3 should equal 13")
}
}
// TestCurrencyMarshalJSON probes the MarshalJSON and UnmarshalJSON functions
// of the currency type.
func TestCurrencyMarshalJSON(t *testing.T) {
......@@ -124,6 +200,21 @@ func TestCurrencyScan(t *testing.T) {
}
}
// TestCurrencyEncoding checks that a currency can encode and decode without
// error.
func TestCurrencyEncoding(t *testing.T) {
c := NewCurrency64(351)
cMar := encoding.Marshal(c)
var cUmar Currency
err := encoding.Unmarshal(cMar, &cUmar)
if err != nil {
t.Error("Error unmarshalling a currency:", err)
}
if cUmar.Cmp(c) != 0 {
t.Error("Marshalling and Unmarshalling a currency did not work correctly")
}
}
// TestNegativeCurrencyMulFloat checks that negative numbers are rejected when
// calling MulFloat on the currency type.
func TestNegativeCurrencyMulFloat(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment