Skip to content

Commit 89423f6

Browse files
committed
simulation: Switch the log method from a single string to string builders
This rapidly speeds up simulation in testing mode.
1 parent 1a70020 commit 89423f6

File tree

14 files changed

+176
-134
lines changed

14 files changed

+176
-134
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ test_sim_gaia_nondeterminism:
157157

158158
test_sim_gaia_fast:
159159
@echo "Running quick Gaia simulation. This may take several minutes..."
160-
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=150 -v -timeout 24h
160+
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -v -timeout 24h
161161

162162
test_sim_gaia_slow:
163163
@echo "Running full Gaia simulation. This may take awhile!"

PENDING.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ BREAKING CHANGES
4040
* [x/slashing] [#2122](https://github.com/cosmos/cosmos-sdk/pull/2122) - Implement slashing period
4141
* [types] [\#2119](https://github.com/cosmos/cosmos-sdk/issues/2119) Parsed error messages and ABCI log errors to make them more human readable.
4242
* [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153)
43+
* [simulation] Delete "log string" from the relevant types \#2282
4344
* [tools] Removed gocyclo [#2211](https://github.com/cosmos/cosmos-sdk/issues/2211)
4445
* [baseapp] Remove `SetTxDecoder` in favor of requiring the decoder be set in baseapp initialization. [#1441](https://github.com/cosmos/cosmos-sdk/issues/1441)
4546

@@ -103,6 +104,7 @@ IMPROVEMENTS
103104
* [store] Speedup IAVL iteration, and consequently everything that requires IAVL iteration. [#2143](https://github.com/cosmos/cosmos-sdk/issues/2143)
104105
* [store] \#1952 Update IAVL dependency to v0.10.0
105106
* [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153)
107+
* [simulation] Make logs not just pure strings, speeding it up by a large factor at greater block heights \#2282
106108

107109
* Tendermint
108110

cmd/gaia/app/sim_test.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
dbm "github.com/tendermint/tendermint/libs/db"
1515
"github.com/tendermint/tendermint/libs/log"
1616

17-
"github.com/cosmos/cosmos-sdk/baseapp"
1817
sdk "github.com/cosmos/cosmos-sdk/types"
1918
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
2019
"github.com/cosmos/cosmos-sdk/x/gov"
@@ -108,12 +107,10 @@ func testAndRunTxs(app *GaiaApp) []simulation.Operation {
108107

109108
func invariants(app *GaiaApp) []simulation.Invariant {
110109
return []simulation.Invariant{
111-
func(t *testing.T, baseapp *baseapp.BaseApp, log string) {
112-
banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log)
113-
govsim.AllInvariants()(t, baseapp, log)
114-
stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log)
115-
slashingsim.AllInvariants()(t, baseapp, log)
116-
},
110+
banksim.NonnegativeBalanceInvariant(app.accountMapper),
111+
govsim.AllInvariants(),
112+
stakesim.AllInvariants(app.bankKeeper, app.stakeKeeper, app.accountMapper),
113+
slashingsim.AllInvariants(),
117114
}
118115
}
119116

x/bank/simulation/invariants.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package simulation
22

33
import (
4+
"errors"
45
"fmt"
5-
"testing"
6-
7-
"github.com/stretchr/testify/require"
86

97
"github.com/cosmos/cosmos-sdk/baseapp"
108
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -16,25 +14,25 @@ import (
1614

1715
// NonnegativeBalanceInvariant checks that all accounts in the application have non-negative balances
1816
func NonnegativeBalanceInvariant(mapper auth.AccountMapper) simulation.Invariant {
19-
return func(t *testing.T, app *baseapp.BaseApp, log string) {
17+
return func(app *baseapp.BaseApp) error {
2018
ctx := app.NewContext(false, abci.Header{})
2119
accts := mock.GetAllAccounts(mapper, ctx)
2220
for _, acc := range accts {
2321
coins := acc.GetCoins()
24-
require.True(t, coins.IsNotNegative(),
25-
fmt.Sprintf("%s has a negative denomination of %s\n%s",
22+
if !coins.IsNotNegative() {
23+
return fmt.Errorf("%s has a negative denomination of %s\n",
2624
acc.GetAddress().String(),
27-
coins.String(),
28-
log),
29-
)
25+
coins.String())
26+
}
3027
}
28+
return nil
3129
}
3230
}
3331

3432
// TotalCoinsInvariant checks that the sum of the coins across all accounts
3533
// is what is expected
3634
func TotalCoinsInvariant(mapper auth.AccountMapper, totalSupplyFn func() sdk.Coins) simulation.Invariant {
37-
return func(t *testing.T, app *baseapp.BaseApp, log string) {
35+
return func(app *baseapp.BaseApp) error {
3836
ctx := app.NewContext(false, abci.Header{})
3937
totalCoins := sdk.Coins{}
4038

@@ -45,6 +43,9 @@ func TotalCoinsInvariant(mapper auth.AccountMapper, totalSupplyFn func() sdk.Coi
4543
}
4644

4745
mapper.IterateAccounts(ctx, chkAccount)
48-
require.Equal(t, totalSupplyFn(), totalCoins, log)
46+
if !totalSupplyFn().IsEqual(totalCoins) {
47+
return errors.New("total calculated coins doesn't equal expected coins")
48+
}
49+
return nil
4950
}
5051
}

x/bank/simulation/msgs.go

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77
"math/rand"
88
"testing"
99

10-
"github.com/stretchr/testify/require"
11-
1210
"github.com/cosmos/cosmos-sdk/baseapp"
1311
sdk "github.com/cosmos/cosmos-sdk/types"
1412
"github.com/cosmos/cosmos-sdk/x/auth"
@@ -21,7 +19,7 @@ import (
2119
// SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both
2220
// accounts already exist.
2321
func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation {
24-
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) {
22+
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
2523
fromKey := simulation.RandomKey(r, keys)
2624
fromAddr := sdk.AccAddress(fromKey.PubKey().Address())
2725
toKey := simulation.RandomKey(r, keys)
@@ -51,22 +49,24 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation
5149
initFromCoins[denomIndex].Denom,
5250
toAddr.String(),
5351
)
54-
log = fmt.Sprintf("%s\n%s", log, action)
5552

5653
coins := sdk.Coins{{initFromCoins[denomIndex].Denom, amt}}
5754
var msg = bank.MsgSend{
5855
Inputs: []bank.Input{bank.NewInput(fromAddr, coins)},
5956
Outputs: []bank.Output{bank.NewOutput(toAddr, coins)},
6057
}
61-
sendAndVerifyMsgSend(tb, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey})
58+
goErr = sendAndVerifyMsgSend(tb, app, mapper, msg, ctx, []crypto.PrivKey{fromKey})
59+
if goErr != nil {
60+
return "", nil, goErr
61+
}
6262
event("bank/sendAndVerifyMsgSend/ok")
6363

6464
return action, nil, nil
6565
}
6666
}
6767

6868
// Sends and verifies the transition of a msg send. This fails if there are repeated inputs or outputs
69-
func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) {
69+
func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, privkeys []crypto.PrivKey) error {
7070
initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs))
7171
initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs))
7272
AccountNumbers := make([]int64, len(msg.Inputs))
@@ -90,24 +90,22 @@ func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.Accou
9090
if !res.IsOK() {
9191
// TODO: Do this in a more 'canonical' way
9292
fmt.Println(res)
93-
fmt.Println(log)
9493
tb.FailNow()
9594
}
9695

9796
for i := 0; i < len(msg.Inputs); i++ {
9897
terminalInputCoins := mapper.GetAccount(ctx, msg.Inputs[i].Address).GetCoins()
99-
require.Equal(tb,
100-
initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins),
101-
terminalInputCoins,
102-
fmt.Sprintf("Input #%d had an incorrect amount of coins\n%s", i, log),
103-
)
98+
if !initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins).IsEqual(terminalInputCoins) {
99+
return fmt.Errorf("Input #%d had an incorrect amount of coins", i)
100+
}
104101
}
105102
for i := 0; i < len(msg.Outputs); i++ {
106103
terminalOutputCoins := mapper.GetAccount(ctx, msg.Outputs[i].Address).GetCoins()
107104
if !terminalOutputCoins.IsEqual(initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins)) {
108-
tb.Fatalf("Output #%d had an incorrect amount of coins\n%s", i, log)
105+
return fmt.Errorf("Output #%d had an incorrect amount of coins", i)
109106
}
110107
}
108+
return nil
111109
}
112110

113111
func randPositiveInt(r *rand.Rand, max sdk.Int) (sdk.Int, error) {

x/gov/simulation/invariants.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
package simulation
22

33
import (
4-
"testing"
5-
6-
"github.com/stretchr/testify/require"
7-
84
"github.com/cosmos/cosmos-sdk/baseapp"
95
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
106
)
117

128
// AllInvariants tests all governance invariants
139
func AllInvariants() simulation.Invariant {
14-
return func(t *testing.T, app *baseapp.BaseApp, log string) {
10+
return func(app *baseapp.BaseApp) error {
1511
// TODO Add some invariants!
1612
// Checking proposal queues, no passed-but-unexecuted proposals, etc.
17-
require.Nil(t, nil)
13+
return nil
1814
}
1915
}

x/gov/simulation/msgs.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,13 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
4545
})
4646
statePercentageArray := []float64{1, .9, .75, .4, .15, 0}
4747
curNumVotesState := 1
48-
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) {
48+
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
4949
// 1) submit proposal now
5050
sender := simulation.RandomKey(r, keys)
51-
msg := simulationCreateMsgSubmitProposal(tb, r, sender, log)
51+
msg, err := simulationCreateMsgSubmitProposal(tb, r, sender)
52+
if err != nil {
53+
return "", nil, err
54+
}
5255
action = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event)
5356
proposalID := k.GetLastProposalID(ctx)
5457
// 2) Schedule operations for votes
@@ -77,9 +80,12 @@ func SimulateSubmittingVotingAndSlashingForProposal(k gov.Keeper, sk stake.Keepe
7780
// Note: Currently doesn't ensure that the proposal txt is in JSON form
7881
func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation {
7982
handler := gov.NewHandler(k)
80-
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) {
83+
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOps []simulation.FutureOperation, err error) {
8184
sender := simulation.RandomKey(r, keys)
82-
msg := simulationCreateMsgSubmitProposal(tb, r, sender, log)
85+
msg, err := simulationCreateMsgSubmitProposal(tb, r, sender)
86+
if err != nil {
87+
return "", nil, err
88+
}
8389
action = simulateHandleMsgSubmitProposal(msg, sk, handler, ctx, event)
8490
return action, nil, nil
8591
}
@@ -100,25 +106,25 @@ func simulateHandleMsgSubmitProposal(msg gov.MsgSubmitProposal, sk stake.Keeper,
100106
return action
101107
}
102108

103-
func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, sender crypto.PrivKey, log string) gov.MsgSubmitProposal {
109+
func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, sender crypto.PrivKey) (msg gov.MsgSubmitProposal, err error) {
104110
addr := sdk.AccAddress(sender.PubKey().Address())
105111
deposit := randomDeposit(r)
106-
msg := gov.NewMsgSubmitProposal(
112+
msg = gov.NewMsgSubmitProposal(
107113
simulation.RandStringOfLength(r, 5),
108114
simulation.RandStringOfLength(r, 5),
109115
gov.ProposalTypeText,
110116
addr,
111117
deposit,
112118
)
113119
if msg.ValidateBasic() != nil {
114-
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
120+
err = fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
115121
}
116-
return msg
122+
return
117123
}
118124

119125
// SimulateMsgDeposit
120126
func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
121-
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
127+
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
122128
key := simulation.RandomKey(r, keys)
123129
addr := sdk.AccAddress(key.PubKey().Address())
124130
proposalID, ok := randomProposalID(r, k, ctx)
@@ -128,7 +134,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
128134
deposit := randomDeposit(r)
129135
msg := gov.NewMsgDeposit(addr, proposalID, deposit)
130136
if msg.ValidateBasic() != nil {
131-
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
137+
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
132138
}
133139
ctx, write := ctx.CacheContext()
134140
result := gov.NewHandler(k)(ctx, msg)
@@ -153,7 +159,7 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
153159

154160
// nolint: unparam
155161
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation {
156-
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
162+
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
157163
if key == nil {
158164
key = simulation.RandomKey(r, keys)
159165
}
@@ -168,7 +174,7 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey,
168174
option := randomVotingOption(r)
169175
msg := gov.NewMsgVote(addr, proposalID, option)
170176
if msg.ValidateBasic() != nil {
171-
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
177+
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
172178
}
173179
ctx, write := ctx.CacheContext()
174180
result := gov.NewHandler(k)(ctx, msg)

0 commit comments

Comments
 (0)