Merge PR #4906: Introduce Simulation Config

This commit is contained in:
Federico Kunze
2019-08-15 11:35:25 -04:00
committed by Alexander Bezobchuk
parent 7ffa95d675
commit 57cc5ae3a2
6 changed files with 362 additions and 292 deletions
+36 -40
View File
@@ -18,16 +18,17 @@ import (
)
// AppStateFn returns the app state json bytes, the genesis accounts, and the chain identifier
type AppStateFn func(
r *rand.Rand, accs []Account,
) (appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time)
type AppStateFn func(r *rand.Rand, accs []Account, config Config) (
appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time,
)
// initialize the chain for the simulation
func initChain(
r *rand.Rand, params Params, accounts []Account, app *baseapp.BaseApp, appStateFn AppStateFn,
r *rand.Rand, params Params, accounts []Account, app *baseapp.BaseApp,
appStateFn AppStateFn, config Config,
) (mockValidators, time.Time, []Account) {
appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts)
appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts, config)
req := abci.RequestInitChain{
AppStateBytes: appState,
@@ -40,23 +41,19 @@ func initChain(
}
// SimulateFromSeed tests an application by running the provided
// operations, testing the provided invariants, but using the provided seed.
// operations, testing the provided invariants, but using the provided config.Seed.
// TODO: split this monster function up
func SimulateFromSeed(
tb testing.TB, w io.Writer, app *baseapp.BaseApp,
appStateFn AppStateFn, seed int64,
ops WeightedOperations, invariants sdk.Invariants,
initialHeight, numBlocks, exportParamsHeight, blockSize int,
exportStatsPath string,
exportParams, commit, lean, onOperation, allInvariants bool,
blackListedAccs map[string]bool,
appStateFn AppStateFn, ops WeightedOperations, invariants sdk.Invariants,
blackListedAccs map[string]bool, config Config,
) (stopEarly bool, exportedParams Params, err error) {
// in case we have to end early, don't os.Exit so that we can run cleanup code.
testingMode, t, b := getTestingMode(tb)
fmt.Fprintf(w, "Starting SimulateFromSeed with randomness created with seed %d\n", int(seed))
fmt.Fprintf(w, "Starting SimulateFromSeed with randomness created with config.Seed %d\n", int(config.Seed))
r := rand.New(rand.NewSource(seed))
r := rand.New(rand.NewSource(config.Seed))
params := RandomParams(r)
fmt.Fprintf(w, "Randomized simulation params: \n%s\n", mustMarshalJSONIndent(params))
@@ -66,7 +63,7 @@ func SimulateFromSeed(
// Second variable to keep pending validator set (delayed one block since
// TM 0.24) Initially this is the same as the initial validator set
validators, genesisTimestamp, accs := initChain(r, params, accs, app, appStateFn)
validators, genesisTimestamp, accs := initChain(r, params, accs, app, appStateFn, config)
if len(accs) == 0 {
return true, params, fmt.Errorf("must have greater than zero genesis accounts")
}
@@ -119,8 +116,7 @@ func SimulateFromSeed(
blockSimulator := createBlockSimulator(
testingMode, tb, t, w, params, eventStats.Tally, invariants,
ops, operationQueue, timeOperationQueue,
numBlocks, blockSize, logWriter, lean, onOperation, allInvariants)
ops, operationQueue, timeOperationQueue, logWriter, config)
if !testingMode {
b.ResetTimer()
@@ -136,12 +132,12 @@ func SimulateFromSeed(
}
// set exported params to the initial state
if exportParams && exportParamsHeight == 0 {
if config.ExportParamsPath != "" && config.ExportParamsHeight == 0 {
exportedParams = params
}
// TODO: split up the contents of this for loop into new functions
for height := initialHeight; height < numBlocks+initialHeight && !stopEarly; height++ {
for height := config.InitialBlockHeight; height < config.NumBlocks+config.InitialBlockHeight && !stopEarly; height++ {
// Log the header time for future lookup
pastTimes = append(pastTimes, header.Time)
@@ -152,7 +148,7 @@ func SimulateFromSeed(
app.BeginBlock(request)
if testingMode {
assertAllInvariants(t, app, invariants, "BeginBlock", logWriter, allInvariants)
assertAllInvariants(t, app, invariants, "BeginBlock", logWriter, config.AllInvariants)
}
ctx := app.NewContext(false, header)
@@ -160,21 +156,21 @@ func SimulateFromSeed(
// Run queued operations. Ignores blocksize if blocksize is too small
numQueuedOpsRan := runQueuedOperations(
operationQueue, int(header.Height),
tb, r, app, ctx, accs, logWriter, eventStats.Tally, lean)
tb, r, app, ctx, accs, logWriter, eventStats.Tally, config.Lean)
numQueuedTimeOpsRan := runQueuedTimeOperations(
timeOperationQueue, int(header.Height), header.Time,
tb, r, app, ctx, accs, logWriter, eventStats.Tally, lean)
tb, r, app, ctx, accs, logWriter, eventStats.Tally, config.Lean)
if testingMode && onOperation {
assertAllInvariants(t, app, invariants, "QueuedOperations", logWriter, allInvariants)
if testingMode && config.OnOperation {
assertAllInvariants(t, app, invariants, "QueuedOperations", logWriter, config.AllInvariants)
}
// run standard operations
operations := blockSimulator(r, app, ctx, accs, header)
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan
if testingMode {
assertAllInvariants(t, app, invariants, "StandardOperations", logWriter, allInvariants)
assertAllInvariants(t, app, invariants, "StandardOperations", logWriter, config.AllInvariants)
}
res := app.EndBlock(abci.RequestEndBlock{})
@@ -187,9 +183,9 @@ func SimulateFromSeed(
logWriter.AddEntry(EndBlockEntry(int64(height)))
if testingMode {
assertAllInvariants(t, app, invariants, "EndBlock", logWriter, allInvariants)
assertAllInvariants(t, app, invariants, "EndBlock", logWriter, config.AllInvariants)
}
if commit {
if config.Commit {
app.Commit()
}
@@ -211,15 +207,15 @@ func SimulateFromSeed(
validators, res.ValidatorUpdates, eventStats.Tally)
// update the exported params
if exportParams && exportParamsHeight == height {
if config.ExportParamsPath != "" && config.ExportParamsHeight == height {
exportedParams = params
}
}
if stopEarly {
if exportStatsPath != "" {
if config.ExportStatsPath != "" {
fmt.Println("Exporting simulation statistics...")
eventStats.ExportJSON(exportStatsPath)
eventStats.ExportJSON(config.ExportStatsPath)
} else {
eventStats.Print(w)
}
@@ -233,9 +229,9 @@ func SimulateFromSeed(
header.Height, header.Time, opCount,
)
if exportStatsPath != "" {
if config.ExportStatsPath != "" {
fmt.Println("Exporting simulation statistics...")
eventStats.ExportJSON(exportStatsPath)
eventStats.ExportJSON(config.ExportStatsPath)
} else {
eventStats.Print(w)
}
@@ -253,7 +249,7 @@ type blockSimFn func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, w io.Writer, params Params,
event func(route, op, evResult string), invariants sdk.Invariants, ops WeightedOperations,
operationQueue OperationQueue, timeOperationQueue []FutureOperation,
totalNumBlocks, avgBlockSize int, logWriter LogWriter, lean, onOperation, allInvariants bool) blockSimFn {
logWriter LogWriter, config Config) blockSimFn {
lastBlockSizeState := 0 // state for [4 * uniform distribution]
blocksize := 0
@@ -265,9 +261,9 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, w io.Wr
_, _ = fmt.Fprintf(
w, "\rSimulating... block %d/%d, operation %d/%d.",
header.Height, totalNumBlocks, opCount, blocksize,
header.Height, config.NumBlocks, opCount, blocksize,
)
lastBlockSizeState, blocksize = getBlockSize(r, params, lastBlockSizeState, avgBlockSize)
lastBlockSizeState, blocksize = getBlockSize(r, params, lastBlockSizeState, config.BlockSize)
type opAndR struct {
op Operation
@@ -291,7 +287,7 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, w io.Wr
op, r2 := opAndR.op, opAndR.rand
opMsg, futureOps, err := op(r2, app, ctx, accounts)
opMsg.LogEvent(event)
if !lean || opMsg.OK {
if !config.Lean || opMsg.OK {
logWriter.AddEntry(MsgEntry(header.Height, int64(i), opMsg))
}
if err != nil {
@@ -302,14 +298,14 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, w io.Wr
queueOperations(operationQueue, timeOperationQueue, futureOps)
if testingMode {
if onOperation {
if config.OnOperation {
fmt.Fprintf(w, "\rSimulating... block %d/%d, operation %d/%d. ",
header.Height, totalNumBlocks, opCount, blocksize)
header.Height, config.NumBlocks, opCount, blocksize)
eventStr := fmt.Sprintf("operation: %v", opMsg.String())
assertAllInvariants(t, app, invariants, eventStr, logWriter, allInvariants)
assertAllInvariants(t, app, invariants, eventStr, logWriter, config.AllInvariants)
} else if opCount%50 == 0 {
fmt.Fprintf(w, "\rSimulating... block %d/%d, operation %d/%d. ",
header.Height, totalNumBlocks, opCount, blocksize)
header.Height, config.NumBlocks, opCount, blocksize)
}
}
opCount++