Use require.Equal instead of assert.Equal, add diagnostic messages
This commit is contained in:
parent
765e065e50
commit
ff0fefa558
|
@ -1,10 +1,12 @@
|
||||||
package stake
|
package stake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
|
@ -198,34 +200,39 @@ func randomSetup(r *rand.Rand) (Pool, Candidates, int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// operation that transforms staking state
|
// operation that transforms staking state
|
||||||
type Operation func(p Pool, c Candidates, t int64) (Pool, Candidates, int64)
|
type Operation func(p Pool, c Candidates, t int64) (Pool, Candidates, int64, string)
|
||||||
|
|
||||||
// pick a random staking operation
|
// pick a random staking operation
|
||||||
func randomOperation(r *rand.Rand) Operation {
|
func randomOperation(r *rand.Rand) Operation {
|
||||||
operations := []Operation{
|
operations := []Operation{
|
||||||
// bond/unbond
|
// bond/unbond
|
||||||
func(p Pool, c Candidates, t int64) (Pool, Candidates, int64) {
|
func(p Pool, c Candidates, t int64) (Pool, Candidates, int64, string) {
|
||||||
index := int(r.Int31n(int32(len(c))))
|
index := int(r.Int31n(int32(len(c))))
|
||||||
cand := c[index]
|
cand := c[index]
|
||||||
|
var msg string
|
||||||
if cand.Status == Bonded {
|
if cand.Status == Bonded {
|
||||||
p, cand = p.bondedToUnbondedPool(cand)
|
p, cand = p.bondedToUnbondedPool(cand)
|
||||||
|
msg = fmt.Sprintf("Unbonded candidate %s", cand.PubKey)
|
||||||
cand.Status = Unbonded
|
cand.Status = Unbonded
|
||||||
} else {
|
} else {
|
||||||
p, cand = p.unbondedToBondedPool(cand)
|
p, cand = p.unbondedToBondedPool(cand)
|
||||||
|
msg = fmt.Sprintf("Bonded candidate %s", cand.PubKey)
|
||||||
cand.Status = Bonded
|
cand.Status = Bonded
|
||||||
}
|
}
|
||||||
c[index] = cand
|
c[index] = cand
|
||||||
return p, c, t
|
return p, c, t, msg
|
||||||
},
|
},
|
||||||
// add some tokens to a candidate
|
// add some tokens to a candidate
|
||||||
func(p Pool, c Candidates, t int64) (Pool, Candidates, int64) {
|
func(p Pool, c Candidates, t int64) (Pool, Candidates, int64, string) {
|
||||||
tokens := int64(r.Int31n(1000))
|
tokens := int64(r.Int31n(1000))
|
||||||
index := int(r.Int31n(int32(len(c))))
|
index := int(r.Int31n(int32(len(c))))
|
||||||
cand := c[index]
|
cand := c[index]
|
||||||
|
msg := fmt.Sprintf("candidate with %d assets, %d liabilities, and %d delegatorShareExRate", cand.Assets.Evaluate(), cand.Liabilities.Evaluate(), cand.delegatorShareExRate().Evaluate())
|
||||||
p, cand, _ = p.candidateAddTokens(cand, tokens)
|
p, cand, _ = p.candidateAddTokens(cand, tokens)
|
||||||
c[index] = cand
|
c[index] = cand
|
||||||
t -= tokens
|
t -= tokens
|
||||||
return p, c, t
|
msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg)
|
||||||
|
return p, c, t, msg
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
// remove some shares from a candidate
|
// remove some shares from a candidate
|
||||||
|
@ -247,20 +254,23 @@ func randomOperation(r *rand.Rand) Operation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure invariants that should always be true are true
|
// ensure invariants that should always be true are true
|
||||||
func assertInvariants(t *testing.T, pA Pool, cA Candidates, tA int64, pB Pool, cB Candidates, tB int64) {
|
func assertInvariants(t *testing.T, pA Pool, cA Candidates, tA int64, pB Pool, cB Candidates, tB int64, msg string) {
|
||||||
// total tokens conserved
|
// total tokens conserved
|
||||||
assert.Equal(t, pA.UnbondedPool+pA.BondedPool+tA, pB.UnbondedPool+pB.BondedPool+tB)
|
require.Equal(t, pA.UnbondedPool+pA.BondedPool+tA, pB.UnbondedPool+pB.BondedPool+tB)
|
||||||
// nonnegative shares
|
// nonnegative shares
|
||||||
assert.Equal(t, pB.BondedShares.LT(sdk.ZeroRat), false)
|
require.Equal(t, pB.BondedShares.LT(sdk.ZeroRat), false)
|
||||||
assert.Equal(t, pB.UnbondedShares.LT(sdk.ZeroRat), false)
|
require.Equal(t, pB.UnbondedShares.LT(sdk.ZeroRat), false)
|
||||||
|
// nonnegative ex rates
|
||||||
|
require.Equal(t, pB.bondedShareExRate().LT(sdk.ZeroRat), false, "Applying operation \"%s\" resulted in negative bondedShareExRate: %d", msg, pB.bondedShareExRate().Evaluate())
|
||||||
|
require.Equal(t, pB.unbondedShareExRate().LT(sdk.ZeroRat), false, "Applying operation \"%s\" resulted in negative unbondedShareExRate: %d", msg, pB.unbondedShareExRate().Evaluate())
|
||||||
bondedSharesHeld := sdk.ZeroRat
|
bondedSharesHeld := sdk.ZeroRat
|
||||||
unbondedSharesHeld := sdk.ZeroRat
|
unbondedSharesHeld := sdk.ZeroRat
|
||||||
for _, candidate := range cA {
|
for _, candidate := range cA {
|
||||||
// nonnegative ex rate
|
// nonnegative ex rate
|
||||||
assert.Equal(t, false, candidate.delegatorShareExRate().LT(sdk.ZeroRat))
|
require.Equal(t, false, candidate.delegatorShareExRate().LT(sdk.ZeroRat))
|
||||||
// nonnegative assets / liabilities
|
// nonnegative assets / liabilities
|
||||||
assert.Equal(t, false, candidate.Assets.LT(sdk.ZeroRat))
|
require.Equal(t, false, candidate.Assets.LT(sdk.ZeroRat), "Applying operation \"%s\" resulted in negative candidate.Assets: %d", msg, candidate.Assets.Evaluate())
|
||||||
assert.Equal(t, false, candidate.Liabilities.LT(sdk.ZeroRat))
|
require.Equal(t, false, candidate.Liabilities.LT(sdk.ZeroRat), "Applying operation \"%s\" resulted in negative candidate.Liabilities: %d", msg, candidate.Liabilities.Evaluate())
|
||||||
if candidate.Status == Bonded {
|
if candidate.Status == Bonded {
|
||||||
bondedSharesHeld = bondedSharesHeld.Add(candidate.Assets)
|
bondedSharesHeld = bondedSharesHeld.Add(candidate.Assets)
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,20 +278,21 @@ func assertInvariants(t *testing.T, pA Pool, cA Candidates, tA int64, pB Pool, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// shares outstanding = total shares held by candidates, both bonded and unbonded
|
// shares outstanding = total shares held by candidates, both bonded and unbonded
|
||||||
assert.Equal(t, bondedSharesHeld, pB.BondedShares)
|
require.Equal(t, bondedSharesHeld, pB.BondedShares)
|
||||||
assert.Equal(t, unbondedSharesHeld, pB.UnbondedShares)
|
require.Equal(t, unbondedSharesHeld, pB.UnbondedShares)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run random operations in a random order on a random state, assert invariants hold
|
// run random operations in a random order on a random state, assert invariants hold
|
||||||
func TestIntegrationInvariants(t *testing.T) {
|
func TestIntegrationInvariants(t *testing.T) {
|
||||||
r := rand.New(rand.NewSource(int64(42)))
|
r := rand.New(rand.NewSource(int64(42)))
|
||||||
|
var msg string
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
pool, candidates, tokens := randomSetup(r)
|
pool, candidates, tokens := randomSetup(r)
|
||||||
initialPool, initialCandidates, initialTokens := pool, candidates, tokens
|
initialPool, initialCandidates, initialTokens := pool, candidates, tokens
|
||||||
assertInvariants(t, initialPool, initialCandidates, initialTokens, pool, candidates, tokens)
|
assertInvariants(t, initialPool, initialCandidates, initialTokens, pool, candidates, tokens, "NOOP")
|
||||||
for j := 0; j < 100; j++ {
|
for j := 0; j < 100; j++ {
|
||||||
pool, candidates, tokens = randomOperation(r)(pool, candidates, tokens)
|
pool, candidates, tokens, msg = randomOperation(r)(pool, candidates, tokens)
|
||||||
assertInvariants(t, initialPool, initialCandidates, initialTokens, pool, candidates, tokens)
|
assertInvariants(t, initialPool, initialCandidates, initialTokens, pool, candidates, tokens, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue