2018-07-16 18:25:15 -07:00
|
|
|
package simulation
|
2018-07-06 13:19:11 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-04-12 15:52:16 -07:00
|
|
|
"io"
|
2018-07-06 13:19:11 -07:00
|
|
|
"math/rand"
|
2018-08-29 23:02:15 -07:00
|
|
|
"os"
|
2018-09-08 01:29:24 -07:00
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
2018-07-06 13:19:11 -07:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2018-08-16 08:36:15 -07:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
|
|
|
2018-07-16 18:15:50 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
2018-07-17 15:04:10 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-03-23 04:55:44 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/simulation"
|
2019-08-15 08:35:25 -07:00
|
|
|
)
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2020-04-21 11:28:43 -07:00
|
|
|
const AverageBlockTime = 6 * time.Second
|
|
|
|
|
2018-11-07 20:26:02 -08:00
|
|
|
// initialize the chain for the simulation
|
2019-01-17 08:15:13 -08:00
|
|
|
func initChain(
|
2020-03-23 04:55:44 -07:00
|
|
|
r *rand.Rand, params Params, accounts []simulation.Account, app *baseapp.BaseApp,
|
|
|
|
appStateFn simulation.AppStateFn, config simulation.Config,
|
|
|
|
) (mockValidators, time.Time, []simulation.Account, string) {
|
2019-01-29 14:53:42 -08:00
|
|
|
|
2019-08-15 08:35:25 -07:00
|
|
|
appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts, config)
|
2018-11-07 20:26:02 -08:00
|
|
|
|
2020-04-21 11:28:43 -07:00
|
|
|
consensusParams := RandomConsensusParams(r, appState)
|
|
|
|
|
2018-11-07 20:26:02 -08:00
|
|
|
req := abci.RequestInitChain{
|
2020-04-21 11:28:43 -07:00
|
|
|
AppStateBytes: appState,
|
|
|
|
ChainId: chainID,
|
|
|
|
ConsensusParams: consensusParams,
|
2018-08-29 23:02:15 -07:00
|
|
|
}
|
2018-11-07 20:26:02 -08:00
|
|
|
res := app.InitChain(req)
|
2018-11-07 22:57:37 -08:00
|
|
|
validators := newMockValidators(r, res.Validators, params)
|
2018-08-29 23:02:15 -07:00
|
|
|
|
2019-10-23 02:14:45 -07:00
|
|
|
return validators, genesisTimestamp, accounts, chainID
|
2018-08-29 23:02:15 -07:00
|
|
|
}
|
|
|
|
|
2018-07-17 11:33:53 -07:00
|
|
|
// SimulateFromSeed tests an application by running the provided
|
2019-08-15 08:35:25 -07:00
|
|
|
// operations, testing the provided invariants, but using the provided config.Seed.
|
2019-07-19 09:59:04 -07:00
|
|
|
// TODO: split this monster function up
|
2019-04-12 15:52:16 -07:00
|
|
|
func SimulateFromSeed(
|
|
|
|
tb testing.TB, w io.Writer, app *baseapp.BaseApp,
|
2020-03-23 04:55:44 -07:00
|
|
|
appStateFn simulation.AppStateFn, ops WeightedOperations,
|
|
|
|
blackListedAccs map[string]bool, config simulation.Config,
|
2019-07-19 09:59:04 -07:00
|
|
|
) (stopEarly bool, exportedParams Params, err error) {
|
2018-09-12 21:53:55 -07:00
|
|
|
|
2018-09-11 02:18:58 -07:00
|
|
|
// in case we have to end early, don't os.Exit so that we can run cleanup code.
|
2018-09-01 12:32:24 -07:00
|
|
|
testingMode, t, b := getTestingMode(tb)
|
2019-10-23 02:14:45 -07:00
|
|
|
fmt.Fprintf(w, "Starting SimulateFromSeed with randomness created with seed %d\n", int(config.Seed))
|
2018-11-07 21:12:51 -08:00
|
|
|
|
2019-08-15 08:35:25 -07:00
|
|
|
r := rand.New(rand.NewSource(config.Seed))
|
2019-06-08 13:55:47 -07:00
|
|
|
params := RandomParams(r)
|
|
|
|
fmt.Fprintf(w, "Randomized simulation params: \n%s\n", mustMarshalJSONIndent(params))
|
2018-11-07 21:12:51 -08:00
|
|
|
|
2018-08-26 18:04:52 -07:00
|
|
|
timeDiff := maxTimePerBlock - minTimePerBlock
|
2020-03-23 04:55:44 -07:00
|
|
|
accs := simulation.RandomAccounts(r, params.NumKeys())
|
2019-07-26 13:09:15 -07:00
|
|
|
eventStats := NewEventStats()
|
2018-11-07 09:19:58 -08:00
|
|
|
|
2018-11-07 21:54:12 -08:00
|
|
|
// Second variable to keep pending validator set (delayed one block since
|
|
|
|
// TM 0.24) Initially this is the same as the initial validator set
|
2019-10-23 02:14:45 -07:00
|
|
|
validators, genesisTimestamp, accs, chainID := initChain(r, params, accs, app, appStateFn, config)
|
2019-01-29 14:53:42 -08:00
|
|
|
if len(accs) == 0 {
|
2019-07-19 09:59:04 -07:00
|
|
|
return true, params, fmt.Errorf("must have greater than zero genesis accounts")
|
2019-01-29 14:53:42 -08:00
|
|
|
}
|
|
|
|
|
2019-10-23 02:14:45 -07:00
|
|
|
config.ChainID = chainID
|
|
|
|
|
2019-07-19 14:46:06 -07:00
|
|
|
fmt.Printf(
|
|
|
|
"Starting the simulation from time %v (unixtime %v)\n",
|
|
|
|
genesisTimestamp.UTC().Format(time.UnixDate), genesisTimestamp.Unix(),
|
|
|
|
)
|
|
|
|
|
2019-07-18 05:43:56 -07:00
|
|
|
// remove module account address if they exist in accs
|
2020-03-23 04:55:44 -07:00
|
|
|
var tmpAccs []simulation.Account
|
2019-07-18 05:43:56 -07:00
|
|
|
for _, acc := range accs {
|
|
|
|
if !blackListedAccs[acc.Address.String()] {
|
|
|
|
tmpAccs = append(tmpAccs, acc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
accs = tmpAccs
|
|
|
|
|
2018-11-07 22:57:37 -08:00
|
|
|
nextValidators := validators
|
2018-07-06 13:19:11 -07:00
|
|
|
|
2018-11-07 09:19:58 -08:00
|
|
|
header := abci.Header{
|
2019-10-23 02:14:45 -07:00
|
|
|
ChainID: config.ChainID,
|
2018-11-07 09:19:58 -08:00
|
|
|
Height: 1,
|
2019-01-17 08:15:13 -08:00
|
|
|
Time: genesisTimestamp,
|
2018-11-07 22:57:37 -08:00
|
|
|
ProposerAddress: validators.randomProposer(r),
|
2018-11-07 09:19:58 -08:00
|
|
|
}
|
2018-08-16 08:36:15 -07:00
|
|
|
opCount := 0
|
|
|
|
|
2018-09-08 01:29:24 -07:00
|
|
|
// Setup code to catch SIGTERM's
|
|
|
|
c := make(chan os.Signal)
|
2018-09-11 02:18:58 -07:00
|
|
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
|
2018-09-08 01:29:24 -07:00
|
|
|
go func() {
|
2018-09-11 02:18:58 -07:00
|
|
|
receivedSignal := <-c
|
2019-04-12 15:52:16 -07:00
|
|
|
fmt.Fprintf(w, "\nExiting early due to %s, on block %d, operation %d\n", receivedSignal, header.Height, opCount)
|
2019-08-19 09:06:27 -07:00
|
|
|
err = fmt.Errorf("exited due to %s", receivedSignal)
|
2018-09-11 02:18:58 -07:00
|
|
|
stopEarly = true
|
2018-09-08 01:29:24 -07:00
|
|
|
}()
|
|
|
|
|
2018-09-01 12:32:24 -07:00
|
|
|
var pastTimes []time.Time
|
2018-10-03 08:48:23 -07:00
|
|
|
var pastVoteInfos [][]abci.VoteInfo
|
2018-08-31 17:01:23 -07:00
|
|
|
|
2018-11-07 09:19:58 -08:00
|
|
|
request := RandomRequestBeginBlock(r, params,
|
2019-07-26 13:09:15 -07:00
|
|
|
validators, pastTimes, pastVoteInfos, eventStats.Tally, header)
|
2018-11-07 07:28:18 -08:00
|
|
|
|
2018-08-27 14:27:00 -07:00
|
|
|
// These are operations which have been queued by previous operations
|
2019-07-26 13:09:15 -07:00
|
|
|
operationQueue := NewOperationQueue()
|
2020-04-21 11:28:43 -07:00
|
|
|
var timeOperationQueue []simulation.FutureOperation
|
2018-07-06 13:19:11 -07:00
|
|
|
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter := NewLogWriter(testingMode)
|
|
|
|
|
2018-11-07 07:28:18 -08:00
|
|
|
blockSimulator := createBlockSimulator(
|
2019-09-06 11:23:40 -07:00
|
|
|
testingMode, tb, t, w, params, eventStats.Tally,
|
2019-08-15 08:35:25 -07:00
|
|
|
ops, operationQueue, timeOperationQueue, logWriter, config)
|
2018-11-07 07:28:18 -08:00
|
|
|
|
2018-09-11 02:18:58 -07:00
|
|
|
if !testingMode {
|
|
|
|
b.ResetTimer()
|
|
|
|
} else {
|
2019-08-07 09:54:13 -07:00
|
|
|
// recover logs in case of panic
|
2018-09-11 02:18:58 -07:00
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
2019-10-23 02:14:45 -07:00
|
|
|
_, _ = fmt.Fprintf(w, "simulation halted due to panic on block %d\n", header.Height)
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter.PrintLogs()
|
2019-08-07 09:54:13 -07:00
|
|
|
panic(r)
|
2018-09-11 02:18:58 -07:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2018-08-30 00:13:31 -07:00
|
|
|
|
2019-07-19 09:59:04 -07:00
|
|
|
// set exported params to the initial state
|
2019-08-15 08:35:25 -07:00
|
|
|
if config.ExportParamsPath != "" && config.ExportParamsHeight == 0 {
|
2019-08-02 08:28:50 -07:00
|
|
|
exportedParams = params
|
|
|
|
}
|
2019-07-19 09:59:04 -07:00
|
|
|
|
|
|
|
// TODO: split up the contents of this for loop into new functions
|
2019-08-15 08:35:25 -07:00
|
|
|
for height := config.InitialBlockHeight; height < config.NumBlocks+config.InitialBlockHeight && !stopEarly; height++ {
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-09-01 12:32:24 -07:00
|
|
|
// Log the header time for future lookup
|
|
|
|
pastTimes = append(pastTimes, header.Time)
|
2018-10-03 08:48:23 -07:00
|
|
|
pastVoteInfos = append(pastVoteInfos, request.LastCommitInfo.Votes)
|
2018-09-01 12:32:24 -07:00
|
|
|
|
2018-08-16 08:36:15 -07:00
|
|
|
// Run the BeginBlock handler
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter.AddEntry(BeginBlockEntry(int64(height)))
|
2018-08-16 08:36:15 -07:00
|
|
|
app.BeginBlock(request)
|
|
|
|
|
2018-07-06 13:19:11 -07:00
|
|
|
ctx := app.NewContext(false, header)
|
2018-08-29 23:02:15 -07:00
|
|
|
|
2018-08-27 14:27:00 -07:00
|
|
|
// Run queued operations. Ignores blocksize if blocksize is too small
|
2018-11-07 07:28:18 -08:00
|
|
|
numQueuedOpsRan := runQueuedOperations(
|
2019-10-23 02:14:45 -07:00
|
|
|
operationQueue, int(header.Height), tb, r, app, ctx, accs, logWriter,
|
|
|
|
eventStats.Tally, config.Lean, config.ChainID,
|
|
|
|
)
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-11-07 07:28:18 -08:00
|
|
|
numQueuedTimeOpsRan := runQueuedTimeOperations(
|
2019-03-14 11:13:15 -07:00
|
|
|
timeOperationQueue, int(header.Height), header.Time,
|
2019-10-23 02:14:45 -07:00
|
|
|
tb, r, app, ctx, accs, logWriter, eventStats.Tally,
|
|
|
|
config.Lean, config.ChainID,
|
|
|
|
)
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2019-03-14 11:13:15 -07:00
|
|
|
// run standard operations
|
|
|
|
operations := blockSimulator(r, app, ctx, accs, header)
|
2018-09-18 19:47:54 -07:00
|
|
|
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan
|
2018-07-06 13:19:11 -07:00
|
|
|
|
2018-08-16 08:36:15 -07:00
|
|
|
res := app.EndBlock(abci.RequestEndBlock{})
|
2018-07-06 13:19:11 -07:00
|
|
|
header.Height++
|
2018-11-07 07:28:18 -08:00
|
|
|
header.Time = header.Time.Add(
|
|
|
|
time.Duration(minTimePerBlock) * time.Second)
|
|
|
|
header.Time = header.Time.Add(
|
|
|
|
time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second)
|
2018-11-07 22:57:37 -08:00
|
|
|
header.ProposerAddress = validators.randomProposer(r)
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter.AddEntry(EndBlockEntry(int64(height)))
|
2018-08-16 08:36:15 -07:00
|
|
|
|
2019-08-15 08:35:25 -07:00
|
|
|
if config.Commit {
|
2018-08-17 07:19:33 -07:00
|
|
|
app.Commit()
|
|
|
|
}
|
2018-10-22 20:55:49 -07:00
|
|
|
|
|
|
|
if header.ProposerAddress == nil {
|
2019-04-12 15:52:16 -07:00
|
|
|
fmt.Fprintf(w, "\nSimulation stopped early as all validators have been unbonded; nobody left to propose a block!\n")
|
2018-10-22 20:55:49 -07:00
|
|
|
stopEarly = true
|
|
|
|
break
|
|
|
|
}
|
2018-08-17 07:19:33 -07:00
|
|
|
|
2018-11-07 21:54:12 -08:00
|
|
|
// Generate a random RequestBeginBlock with the current validator set
|
|
|
|
// for the next block
|
2018-11-07 09:19:58 -08:00
|
|
|
request = RandomRequestBeginBlock(r, params, validators,
|
2019-07-26 13:09:15 -07:00
|
|
|
pastTimes, pastVoteInfos, eventStats.Tally, header)
|
2018-08-16 08:36:15 -07:00
|
|
|
|
2018-11-07 21:54:12 -08:00
|
|
|
// Update the validator set, which will be reflected in the application
|
|
|
|
// on the next block
|
2018-10-04 09:22:51 -07:00
|
|
|
validators = nextValidators
|
2018-11-07 09:19:58 -08:00
|
|
|
nextValidators = updateValidators(tb, r, params,
|
2019-07-26 13:09:15 -07:00
|
|
|
validators, res.ValidatorUpdates, eventStats.Tally)
|
2019-07-19 09:59:04 -07:00
|
|
|
|
|
|
|
// update the exported params
|
2019-08-15 08:35:25 -07:00
|
|
|
if config.ExportParamsPath != "" && config.ExportParamsHeight == height {
|
2019-07-19 09:59:04 -07:00
|
|
|
exportedParams = params
|
|
|
|
}
|
2018-07-06 13:19:11 -07:00
|
|
|
}
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-09-11 02:18:58 -07:00
|
|
|
if stopEarly {
|
2019-08-15 08:35:25 -07:00
|
|
|
if config.ExportStatsPath != "" {
|
2019-07-26 13:09:15 -07:00
|
|
|
fmt.Println("Exporting simulation statistics...")
|
2019-08-15 08:35:25 -07:00
|
|
|
eventStats.ExportJSON(config.ExportStatsPath)
|
2019-07-26 13:09:15 -07:00
|
|
|
} else {
|
|
|
|
eventStats.Print(w)
|
|
|
|
}
|
|
|
|
|
2019-07-19 09:59:04 -07:00
|
|
|
return true, exportedParams, err
|
2018-09-11 02:18:58 -07:00
|
|
|
}
|
2018-11-07 08:00:24 -08:00
|
|
|
|
2019-04-12 15:52:16 -07:00
|
|
|
fmt.Fprintf(
|
|
|
|
w,
|
|
|
|
"\nSimulation complete; Final height (blocks): %d, final time (seconds): %v, operations ran: %d\n",
|
|
|
|
header.Height, header.Time, opCount,
|
|
|
|
)
|
|
|
|
|
2019-08-15 08:35:25 -07:00
|
|
|
if config.ExportStatsPath != "" {
|
2019-07-26 13:09:15 -07:00
|
|
|
fmt.Println("Exporting simulation statistics...")
|
2019-08-15 08:35:25 -07:00
|
|
|
eventStats.ExportJSON(config.ExportStatsPath)
|
2019-07-26 13:09:15 -07:00
|
|
|
} else {
|
|
|
|
eventStats.Print(w)
|
|
|
|
}
|
2019-07-19 09:59:04 -07:00
|
|
|
|
|
|
|
return false, exportedParams, nil
|
2018-08-30 11:43:56 -07:00
|
|
|
}
|
|
|
|
|
2018-11-07 08:00:24 -08:00
|
|
|
//______________________________________________________________________________
|
|
|
|
|
2018-11-07 07:28:18 -08:00
|
|
|
type blockSimFn func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
2020-03-23 04:55:44 -07:00
|
|
|
accounts []simulation.Account, header abci.Header) (opCount int)
|
2018-10-31 10:11:41 -07:00
|
|
|
|
2018-11-07 20:26:02 -08:00
|
|
|
// Returns a function to simulate blocks. Written like this to avoid constant
|
2018-11-07 21:12:51 -08:00
|
|
|
// parameters being passed everytime, to minimize memory overhead.
|
2019-04-12 15:52:16 -07:00
|
|
|
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, w io.Writer, params Params,
|
2019-09-06 11:23:40 -07:00
|
|
|
event func(route, op, evResult string), ops WeightedOperations,
|
2020-03-23 04:55:44 -07:00
|
|
|
operationQueue OperationQueue, timeOperationQueue []simulation.FutureOperation,
|
|
|
|
logWriter LogWriter, config simulation.Config) blockSimFn {
|
2018-10-31 09:37:50 -07:00
|
|
|
|
2019-08-07 09:54:13 -07:00
|
|
|
lastBlockSizeState := 0 // state for [4 * uniform distribution]
|
2019-03-14 11:13:15 -07:00
|
|
|
blocksize := 0
|
2018-11-07 20:26:02 -08:00
|
|
|
selectOp := ops.getSelectOpFn()
|
2018-10-28 21:37:19 -07:00
|
|
|
|
2019-08-07 09:54:13 -07:00
|
|
|
return func(
|
2020-03-23 04:55:44 -07:00
|
|
|
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account, header abci.Header,
|
2019-08-07 09:54:13 -07:00
|
|
|
) (opCount int) {
|
2018-11-07 07:28:18 -08:00
|
|
|
|
2019-08-07 09:54:13 -07:00
|
|
|
_, _ = fmt.Fprintf(
|
|
|
|
w, "\rSimulating... block %d/%d, operation %d/%d.",
|
2019-08-15 08:35:25 -07:00
|
|
|
header.Height, config.NumBlocks, opCount, blocksize,
|
2019-08-07 09:54:13 -07:00
|
|
|
)
|
2019-08-15 08:35:25 -07:00
|
|
|
lastBlockSizeState, blocksize = getBlockSize(r, params, lastBlockSizeState, config.BlockSize)
|
2018-11-07 07:28:18 -08:00
|
|
|
|
2018-11-27 00:14:22 -08:00
|
|
|
type opAndR struct {
|
2020-03-23 04:55:44 -07:00
|
|
|
op simulation.Operation
|
2018-11-27 00:14:22 -08:00
|
|
|
rand *rand.Rand
|
|
|
|
}
|
2019-08-07 09:54:13 -07:00
|
|
|
|
2018-11-27 00:14:22 -08:00
|
|
|
opAndRz := make([]opAndR, 0, blocksize)
|
2019-08-07 09:54:13 -07:00
|
|
|
|
2018-11-27 00:14:22 -08:00
|
|
|
// Predetermine the blocksize slice so that we can do things like block
|
|
|
|
// out certain operations without changing the ops that follow.
|
2018-11-07 21:54:12 -08:00
|
|
|
for i := 0; i < blocksize; i++ {
|
2018-11-27 00:14:22 -08:00
|
|
|
opAndRz = append(opAndRz, opAndR{
|
|
|
|
op: selectOp(r),
|
2020-03-23 04:55:44 -07:00
|
|
|
rand: simulation.DeriveRand(r),
|
2018-11-27 00:14:22 -08:00
|
|
|
})
|
|
|
|
}
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-11-27 00:14:22 -08:00
|
|
|
for i := 0; i < blocksize; i++ {
|
|
|
|
// NOTE: the Rand 'r' should not be used here.
|
|
|
|
opAndR := opAndRz[i]
|
|
|
|
op, r2 := opAndR.op, opAndR.rand
|
2019-10-23 02:14:45 -07:00
|
|
|
opMsg, futureOps, err := op(r2, app, ctx, accounts, config.ChainID)
|
2019-03-14 11:13:15 -07:00
|
|
|
opMsg.LogEvent(event)
|
2019-09-06 11:23:40 -07:00
|
|
|
|
2019-08-15 08:35:25 -07:00
|
|
|
if !config.Lean || opMsg.OK {
|
2019-07-26 13:09:15 -07:00
|
|
|
logWriter.AddEntry(MsgEntry(header.Height, int64(i), opMsg))
|
2019-03-14 11:13:15 -07:00
|
|
|
}
|
2019-09-06 11:23:40 -07:00
|
|
|
|
2018-08-30 11:43:56 -07:00
|
|
|
if err != nil {
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter.PrintLogs()
|
2019-10-23 02:14:45 -07:00
|
|
|
tb.Fatalf(`error on block %d/%d, operation (%d/%d) from x/%s:
|
|
|
|
%v
|
|
|
|
Comment: %s`,
|
|
|
|
header.Height, config.NumBlocks, opCount, blocksize, opMsg.Route, err, opMsg.Comment)
|
2018-08-30 11:43:56 -07:00
|
|
|
}
|
|
|
|
|
2018-09-18 19:47:54 -07:00
|
|
|
queueOperations(operationQueue, timeOperationQueue, futureOps)
|
2019-09-06 11:23:40 -07:00
|
|
|
|
|
|
|
if testingMode && opCount%50 == 0 {
|
|
|
|
fmt.Fprintf(w, "\rSimulating... block %d/%d, operation %d/%d. ",
|
|
|
|
header.Height, config.NumBlocks, opCount, blocksize)
|
2018-08-30 11:43:56 -07:00
|
|
|
}
|
2019-09-06 11:23:40 -07:00
|
|
|
|
2018-08-30 11:43:56 -07:00
|
|
|
opCount++
|
|
|
|
}
|
2018-09-09 08:34:09 -07:00
|
|
|
return opCount
|
2018-08-30 11:43:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 09:47:24 -07:00
|
|
|
// nolint: errcheck
|
2020-03-23 04:55:44 -07:00
|
|
|
func runQueuedOperations(queueOps map[int][]simulation.Operation,
|
2018-11-07 21:54:12 -08:00
|
|
|
height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp,
|
2020-03-23 04:55:44 -07:00
|
|
|
ctx sdk.Context, accounts []simulation.Account, logWriter LogWriter,
|
2019-10-23 02:14:45 -07:00
|
|
|
event func(route, op, evResult string), lean bool, chainID string) (numOpsRan int) {
|
2018-11-07 07:28:18 -08:00
|
|
|
|
2018-11-07 09:19:58 -08:00
|
|
|
queuedOp, ok := queueOps[height]
|
|
|
|
if !ok {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2018-11-07 20:55:48 -08:00
|
|
|
numOpsRan = len(queuedOp)
|
|
|
|
for i := 0; i < numOpsRan; i++ {
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-11-07 09:19:58 -08:00
|
|
|
// For now, queued operations cannot queue more operations.
|
|
|
|
// If a need arises for us to support queued messages to queue more messages, this can
|
|
|
|
// be changed.
|
2019-10-23 02:14:45 -07:00
|
|
|
opMsg, _, err := queuedOp[i](r, app, ctx, accounts, chainID)
|
2019-07-26 13:09:15 -07:00
|
|
|
opMsg.LogEvent(event)
|
2019-03-14 11:13:15 -07:00
|
|
|
if !lean || opMsg.OK {
|
|
|
|
logWriter.AddEntry((QueuedMsgEntry(int64(height), opMsg)))
|
|
|
|
}
|
2018-11-07 09:19:58 -08:00
|
|
|
if err != nil {
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter.PrintLogs()
|
2018-11-07 09:19:58 -08:00
|
|
|
tb.FailNow()
|
2018-08-27 14:27:00 -07:00
|
|
|
}
|
|
|
|
}
|
2018-11-07 09:19:58 -08:00
|
|
|
delete(queueOps, height)
|
2018-11-07 20:55:48 -08:00
|
|
|
return numOpsRan
|
2018-08-27 14:27:00 -07:00
|
|
|
}
|
|
|
|
|
2020-03-23 04:55:44 -07:00
|
|
|
func runQueuedTimeOperations(queueOps []simulation.FutureOperation,
|
2019-03-14 11:13:15 -07:00
|
|
|
height int, currentTime time.Time, tb testing.TB, r *rand.Rand,
|
2020-03-23 04:55:44 -07:00
|
|
|
app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account,
|
2019-10-23 02:14:45 -07:00
|
|
|
logWriter LogWriter, event func(route, op, evResult string),
|
|
|
|
lean bool, chainID string) (numOpsRan int) {
|
2018-09-18 19:47:54 -07:00
|
|
|
|
|
|
|
numOpsRan = 0
|
2018-11-07 09:00:13 -08:00
|
|
|
for len(queueOps) > 0 && currentTime.After(queueOps[0].BlockTime) {
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-09-18 19:47:54 -07:00
|
|
|
// For now, queued operations cannot queue more operations.
|
|
|
|
// If a need arises for us to support queued messages to queue more messages, this can
|
|
|
|
// be changed.
|
2019-10-23 02:14:45 -07:00
|
|
|
opMsg, _, err := queueOps[0].Op(r, app, ctx, accounts, chainID)
|
2019-07-26 13:09:15 -07:00
|
|
|
opMsg.LogEvent(event)
|
2019-03-14 11:13:15 -07:00
|
|
|
if !lean || opMsg.OK {
|
|
|
|
logWriter.AddEntry(QueuedMsgEntry(int64(height), opMsg))
|
|
|
|
}
|
2018-09-18 19:47:54 -07:00
|
|
|
if err != nil {
|
2019-03-14 11:13:15 -07:00
|
|
|
logWriter.PrintLogs()
|
2018-09-18 19:47:54 -07:00
|
|
|
tb.FailNow()
|
|
|
|
}
|
2018-11-07 21:54:12 -08:00
|
|
|
|
2018-11-07 09:00:13 -08:00
|
|
|
queueOps = queueOps[1:]
|
2018-09-18 19:47:54 -07:00
|
|
|
numOpsRan++
|
|
|
|
}
|
|
|
|
return numOpsRan
|
|
|
|
}
|