diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 1fd07b330..6568f124b 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "flag" "math/rand" + "os" "testing" "github.com/stretchr/testify/require" @@ -23,11 +24,12 @@ import ( ) var ( - seed int64 - numBlocks int - blockSize int - enabled bool - verbose bool + seed int64 + numBlocks int + blockSize int + enabled bool + verbose bool + usegoleveldb bool ) func init() { @@ -36,6 +38,7 @@ func init() { flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") + flag.BoolVar(&usegoleveldb, "SimulationGoLevelDB", false, "Use GoLevelDB instead of memdb") } func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { @@ -118,7 +121,11 @@ func BenchmarkFullGaiaSimulation(b *testing.B) { // Setup Gaia application var logger log.Logger logger = log.NewNopLogger() - db := dbm.NewMemDB() + var db dbm.DB + db = dbm.NewMemDB() + if usegoleveldb { + db, _ = dbm.NewGoLevelDB("Simulation", os.TempDir()) + } app := NewGaiaApp(logger, db, nil) // Run randomized simulation diff --git a/server/export_test.go b/server/export_test.go index 358f72cf6..488c55bbf 100644 --- a/server/export_test.go +++ b/server/export_test.go @@ -1,16 +1,16 @@ package server import ( - "testing" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/wire" - "github.com/tendermint/tendermint/libs/log" - tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" - "os" "bytes" + "github.com/cosmos/cosmos-sdk/server/mock" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/stretchr/testify/require" + tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + "github.com/tendermint/tendermint/libs/log" "io" - "github.com/cosmos/cosmos-sdk/server/mock" - ) + "os" + "testing" +) func TestEmptyState(t *testing.T) { defer setupViper(t)() diff --git a/server/mock/app.go b/server/mock/app.go index eb2dfc3cc..3c6ad3ec2 100644 --- a/server/mock/app.go +++ b/server/mock/app.go @@ -129,7 +129,7 @@ func AppGenStateEmpty(_ *wire.Codec, _ []json.RawMessage) (appState json.RawMess // Return a validator, not much else func AppGenTx(_ *wire.Codec, pk crypto.PubKey, genTxConfig gc.GenTx) ( - appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { + appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { validator = tmtypes.GenesisValidator{ PubKey: pk, diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e0ab9ba58..42a616331 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -54,15 +54,7 @@ func SimulateFromSeed( tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { - var t *testing.T - var b *testing.B - testingmode := false - if _t, ok := tb.(*testing.T); ok { - t = _t - testingmode = true - } else { - b = tb.(*testing.B) - } + testingmode, t, b := getTestingMode(tb) log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) r := rand.New(rand.NewSource(seed)) timestamp := randTimestamp(r) @@ -93,6 +85,7 @@ func SimulateFromSeed( if !testingmode { b.ResetTimer() } + blockSimulator := createBlockSimulator(testingmode, tb, t, event, invariants, ops, operationQueue, numBlocks) for i := 0; i < numBlocks; i++ { // Run the BeginBlock handler @@ -111,24 +104,8 @@ func SimulateFromSeed( log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, log, event) opCount += numQueuedOpsRan thisBlockSize -= numQueuedOpsRan - for j := 0; j < thisBlockSize; j++ { - logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) - log = updateLog(testingmode, log, logUpdate) - if err != nil { - tb.Fatalf("error on operation %d, %v, log %s", opCount, err, log) - } - - queueOperations(operationQueue, futureOps) - if testingmode { - if onOperation { - AssertAllInvariants(t, app, invariants, log) - } - if opCount%200 == 0 { - fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) - } - } - opCount++ - } + log, operations := blockSimulator(thisBlockSize, r, app, ctx, keys, log, header) + opCount += operations res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ @@ -151,14 +128,49 @@ func SimulateFromSeed( validators = updateValidators(tb, r, validators, res.ValidatorUpdates, event) } - if testingmode { - fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) - } else { - fmt.Printf("%d operations ran\n", opCount) - } + fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds), : %v, operations ran %d\n", header.Height, header.Time, opCount) DisplayEvents(events) } +// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize +// memory overhead +func createBlockSimulator(testingmode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []Operation, operationQueue map[int][]Operation, totalNumBlocks int) func( + blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { + return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + keys []crypto.PrivKey, log string, header abci.Header) (updatedLog string, opCount int) { + for j := 0; j < blocksize; j++ { + logUpdate, futureOps, err := ops[r.Intn(len(ops))](tb, r, app, ctx, keys, log, event) + log = updateLog(testingmode, log, logUpdate) + if err != nil { + tb.Fatalf("error on operation %d within block %d, %v, log %s", header.Height, opCount, err, log) + } + + queueOperations(operationQueue, futureOps) + if testingmode { + if onOperation { + AssertAllInvariants(t, app, invariants, log) + } + if opCount%50 == 0 { + fmt.Printf("\rSimulating... block %d/%d, operation %d/%d.", header.Height, totalNumBlocks, opCount, blocksize) + } + } + opCount++ + } + return log, opCount + } +} + +func getTestingMode(tb testing.TB) (testingmode bool, t *testing.T, b *testing.B) { + testingmode = false + if _t, ok := tb.(*testing.T); ok { + t = _t + testingmode = true + } else { + b = tb.(*testing.B) + } + return +} + func updateLog(testingmode bool, log string, update string, args ...interface{}) (updatedLog string) { if testingmode { update = fmt.Sprintf(update, args...)