Fix coins.IsLT() impl (#2686)

* Fix coins.IsLT() impl
* Fix coin.IsLT() impl
* Coins.IsLT -> Coins.IsAllLT etc
This commit is contained in:
Jae Kwon
2018-11-07 00:14:48 -08:00
committed by GitHub
parent 2779f4dba3
commit 2a3d1f1e87
7 changed files with 110 additions and 21 deletions
+43 -13
View File
@@ -49,7 +49,7 @@ func (coin Coin) IsGTE(other Coin) bool {
// IsLT returns true if they are the same type and the receiver is
// a smaller value
func (coin Coin) IsLT(other Coin) bool {
return !coin.IsGTE(other)
return coin.SameDenomAs(other) && coin.Amount.LT(other.Amount)
}
// IsEqual returns true if the two sets of Coins have the same value
@@ -142,7 +142,11 @@ func (coins Coins) Plus(coinsB Coins) Coins {
coinA, coinB := coins[indexA], coinsB[indexB]
switch strings.Compare(coinA.Denom, coinB.Denom) {
case -1:
sum = append(sum, coinA)
if coinA.IsZero() {
// ignore 0 sum coin type
} else {
sum = append(sum, coinA)
}
indexA++
case 0:
if coinA.Amount.Add(coinB.Amount).IsZero() {
@@ -153,7 +157,11 @@ func (coins Coins) Plus(coinsB Coins) Coins {
indexA++
indexB++
case 1:
sum = append(sum, coinB)
if coinB.IsZero() {
// ignore 0 sum coin type
} else {
sum = append(sum, coinB)
}
indexB++
}
}
@@ -176,10 +184,19 @@ func (coins Coins) Minus(coinsB Coins) Coins {
return coins.Plus(coinsB.Negative())
}
// IsGTE returns True iff coins is NonNegative(), and for every
// currency in coinsB, the currency is present at an equal or greater
// amount in coinsB
func (coins Coins) IsGTE(coinsB Coins) bool {
// IsAllGT returns True iff for every denom in coins, the denom is present at a
// greater amount in coinsB.
func (coins Coins) IsAllGT(coinsB Coins) bool {
diff := coins.Minus(coinsB)
if len(diff) == 0 {
return false
}
return diff.IsPositive()
}
// IsAllGTE returns True iff for every denom in coins, the denom is present at an
// equal or greater amount in coinsB.
func (coins Coins) IsAllGTE(coinsB Coins) bool {
diff := coins.Minus(coinsB)
if len(diff) == 0 {
return true
@@ -187,14 +204,27 @@ func (coins Coins) IsGTE(coinsB Coins) bool {
return diff.IsNotNegative()
}
// IsLT returns True iff every currency in coins, the currency is
// present at a smaller amount in coins
func (coins Coins) IsLT(coinsB Coins) bool {
return !coins.IsGTE(coinsB)
// IsAllLT returns True iff for every denom in coins, the denom is present at
// a smaller amount in coinsB.
func (coins Coins) IsAllLT(coinsB Coins) bool {
diff := coinsB.Minus(coins)
if len(diff) == 0 {
return false
}
return diff.IsPositive()
}
// IsZero returns true if there are no coins
// or all coins are zero.
// IsAllLTE returns True iff for every denom in coins, the denom is present at
// a smaller or equal amount in coinsB.
func (coins Coins) IsAllLTE(coinsB Coins) bool {
diff := coinsB.Minus(coins)
if len(diff) == 0 {
return true
}
return diff.IsNotNegative()
}
// IsZero returns true if there are no coins or all coins are zero.
func (coins Coins) IsZero() bool {
for _, coin := range coins {
if !coin.IsZero() {
+61 -4
View File
@@ -86,7 +86,10 @@ func TestIsLTCoin(t *testing.T) {
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), false},
{NewInt64Coin("A", 2), NewInt64Coin("A", 1), false},
{NewInt64Coin("A", -1), NewInt64Coin("A", 5), true},
{NewInt64Coin("a", 0), NewInt64Coin("b", 1), true},
{NewInt64Coin("a", 0), NewInt64Coin("b", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("a", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("a", 2), true},
}
for tcIndex, tc := range cases {
@@ -245,9 +248,9 @@ func TestCoins(t *testing.T) {
assert.True(t, good.IsValid(), "Coins are valid")
assert.True(t, good.IsPositive(), "Expected coins to be positive: %v", good)
assert.False(t, null.IsPositive(), "Expected coins to not be positive: %v", null)
assert.True(t, good.IsGTE(empty), "Expected %v to be >= %v", good, empty)
assert.False(t, good.IsLT(empty), "Expected %v to be < %v", good, empty)
assert.True(t, empty.IsLT(good), "Expected %v to be < %v", empty, good)
assert.True(t, good.IsAllGTE(empty), "Expected %v to be >= %v", good, empty)
assert.False(t, good.IsAllLT(empty), "Expected %v to be < %v", good, empty)
assert.True(t, empty.IsAllLT(good), "Expected %v to be < %v", empty, good)
assert.False(t, neg.IsPositive(), "Expected neg coins to not be positive: %v", neg)
assert.Zero(t, len(sum), "Expected 0 coins")
assert.False(t, badSort1.IsValid(), "Coins are not sorted")
@@ -257,6 +260,60 @@ func TestCoins(t *testing.T) {
}
func TestCoinsGT(t *testing.T) {
one := NewInt(1)
two := NewInt(2)
assert.False(t, Coins{}.IsAllGT(Coins{}))
assert.True(t, Coins{{"A", one}}.IsAllGT(Coins{}))
assert.False(t, Coins{{"A", one}}.IsAllGT(Coins{{"A", one}}))
assert.False(t, Coins{{"A", one}}.IsAllGT(Coins{{"B", one}}))
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllGT(Coins{{"B", one}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllGT(Coins{{"B", two}}))
}
func TestCoinsGTE(t *testing.T) {
one := NewInt(1)
two := NewInt(2)
assert.True(t, Coins{}.IsAllGTE(Coins{}))
assert.True(t, Coins{{"A", one}}.IsAllGTE(Coins{}))
assert.True(t, Coins{{"A", one}}.IsAllGTE(Coins{{"A", one}}))
assert.False(t, Coins{{"A", one}}.IsAllGTE(Coins{{"B", one}}))
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllGTE(Coins{{"B", one}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllGTE(Coins{{"B", two}}))
}
func TestCoinsLT(t *testing.T) {
one := NewInt(1)
two := NewInt(2)
assert.False(t, Coins{}.IsAllLT(Coins{}))
assert.False(t, Coins{{"A", one}}.IsAllLT(Coins{}))
assert.False(t, Coins{{"A", one}}.IsAllLT(Coins{{"A", one}}))
assert.False(t, Coins{{"A", one}}.IsAllLT(Coins{{"B", one}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"B", one}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"B", two}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"A", one}, {"B", one}}))
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllLT(Coins{{"A", one}, {"B", two}}))
assert.True(t, Coins{}.IsAllLT(Coins{{"A", one}}))
}
func TestCoinsLTE(t *testing.T) {
one := NewInt(1)
two := NewInt(2)
assert.True(t, Coins{}.IsAllLTE(Coins{}))
assert.False(t, Coins{{"A", one}}.IsAllLTE(Coins{}))
assert.True(t, Coins{{"A", one}}.IsAllLTE(Coins{{"A", one}}))
assert.False(t, Coins{{"A", one}}.IsAllLTE(Coins{{"B", one}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"B", one}}))
assert.False(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"B", two}}))
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"A", one}, {"B", one}}))
assert.True(t, Coins{{"A", one}, {"B", one}}.IsAllLTE(Coins{{"A", one}, {"B", two}}))
assert.True(t, Coins{}.IsAllLTE(Coins{{"A", one}}))
}
func TestPlusCoins(t *testing.T) {
one := NewInt(1)
zero := NewInt(0)