refactor!: extract simulation helpers out of simapp (#13402)

This commit is contained in:
Julien Robert
2022-09-27 21:19:44 +02:00
committed by GitHub
parent 9bae8a817f
commit 91d66f30e1
22 changed files with 179 additions and 195 deletions
-3
View File
@@ -89,9 +89,6 @@ import (
)
var (
// App is deprecated, use runtime.AppI instead
App runtime.AppI
// DefaultNodeHome default home directories for the application daemon
DefaultNodeHome string
-3
View File
@@ -100,9 +100,6 @@ import (
const appName = "SimApp"
var (
// App is deprecated, use runtime.AppI instead
App runtime.AppI
// DefaultNodeHome default home directories for the application daemon
DefaultNodeHome string
-78
View File
@@ -1,78 +0,0 @@
package simapp
import (
"flag"
"github.com/cosmos/cosmos-sdk/types/simulation"
)
// List of available flags for the simulator
var (
FlagGenesisFileValue string
FlagParamsFileValue string
FlagExportParamsPathValue string
FlagExportParamsHeightValue int
FlagExportStatePathValue string
FlagExportStatsPathValue string
FlagSeedValue int64
FlagInitialBlockHeightValue int
FlagNumBlocksValue int
FlagBlockSizeValue int
FlagLeanValue bool
FlagCommitValue bool
FlagOnOperationValue bool // TODO: Remove in favor of binary search for invariant violation
FlagAllInvariantsValue bool
FlagDBBackendValue string
FlagEnabledValue bool
FlagVerboseValue bool
FlagPeriodValue uint
FlagGenesisTimeValue int64
)
// GetSimulatorFlags gets the values of all the available simulation flags
func GetSimulatorFlags() {
// config fields
flag.StringVar(&FlagGenesisFileValue, "Genesis", "", "custom simulation genesis file; cannot be used with params file")
flag.StringVar(&FlagParamsFileValue, "Params", "", "custom simulation params file which overrides any random params; cannot be used with genesis")
flag.StringVar(&FlagExportParamsPathValue, "ExportParamsPath", "", "custom file path to save the exported params JSON")
flag.IntVar(&FlagExportParamsHeightValue, "ExportParamsHeight", 0, "height to which export the randomly generated params")
flag.StringVar(&FlagExportStatePathValue, "ExportStatePath", "", "custom file path to save the exported app state JSON")
flag.StringVar(&FlagExportStatsPathValue, "ExportStatsPath", "", "custom file path to save the exported simulation statistics JSON")
flag.Int64Var(&FlagSeedValue, "Seed", 42, "simulation random seed")
flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", 1, "initial block to start the simulation")
flag.IntVar(&FlagNumBlocksValue, "NumBlocks", 500, "number of new blocks to simulate from the initial block height")
flag.IntVar(&FlagBlockSizeValue, "BlockSize", 200, "operations per block")
flag.BoolVar(&FlagLeanValue, "Lean", false, "lean simulation log output")
flag.BoolVar(&FlagCommitValue, "Commit", false, "have the simulation commit")
flag.BoolVar(&FlagOnOperationValue, "SimulateEveryOperation", false, "run slow invariants every operation")
flag.BoolVar(&FlagAllInvariantsValue, "PrintAllInvariants", false, "print all invariants if a broken invariant is found")
flag.StringVar(&FlagDBBackendValue, "DBBackend", "goleveldb", "custom db backend type")
// simulation flags
flag.BoolVar(&FlagEnabledValue, "Enabled", false, "enable the simulation")
flag.BoolVar(&FlagVerboseValue, "Verbose", false, "verbose log output")
flag.UintVar(&FlagPeriodValue, "Period", 0, "run slow invariants only once every period assertions")
flag.Int64Var(&FlagGenesisTimeValue, "GenesisTime", 0, "override genesis UNIX time instead of using a random UNIX time")
}
// NewConfigFromFlags creates a simulation from the retrieved values of the flags.
func NewConfigFromFlags() simulation.Config {
return simulation.Config{
GenesisFile: FlagGenesisFileValue,
ParamsFile: FlagParamsFileValue,
ExportParamsPath: FlagExportParamsPathValue,
ExportParamsHeight: FlagExportParamsHeightValue,
ExportStatePath: FlagExportStatePathValue,
ExportStatsPath: FlagExportStatsPathValue,
Seed: FlagSeedValue,
InitialBlockHeight: FlagInitialBlockHeightValue,
NumBlocks: FlagNumBlocksValue,
BlockSize: FlagBlockSizeValue,
Lean: FlagLeanValue,
Commit: FlagCommitValue,
OnOperation: FlagOnOperationValue,
AllInvariants: FlagAllInvariantsValue,
DBBackend: FlagDBBackendValue,
}
}
+19 -10
View File
@@ -13,13 +13,18 @@ import (
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/simulation"
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
)
// Profile with:
// /usr/local/go/bin/go test -benchmem -run=^$ cosmossdk.io/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out
func BenchmarkFullAppSimulation(b *testing.B) {
b.ReportAllocs()
config, db, dir, logger, skip, err := SetupSimulation("goleveldb-app-sim", "Simulation")
config := simcli.NewConfigFromFlags()
config.ChainID = SimAppChainID
db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "goleveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if err != nil {
b.Fatalf("simulation setup failed: %s", err.Error())
}
@@ -35,7 +40,7 @@ func BenchmarkFullAppSimulation(b *testing.B) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = DefaultNodeHome
appOptions[server.FlagInvCheckPeriod] = FlagPeriodValue
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue
app := NewSimApp(logger, db, nil, true, appOptions, interBlockCacheOpt())
@@ -46,14 +51,14 @@ func BenchmarkFullAppSimulation(b *testing.B) {
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(app, app.AppCodec(), config),
simtestutil.SimulationOperations(app, app.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
)
// export state and simParams before the simulation error is checked
if err = CheckExportSimulation(app, config, simParams); err != nil {
if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil {
b.Fatal(err)
}
@@ -62,13 +67,17 @@ func BenchmarkFullAppSimulation(b *testing.B) {
}
if config.Commit {
PrintStats(db)
simtestutil.PrintStats(db)
}
}
func BenchmarkInvariants(b *testing.B) {
b.ReportAllocs()
config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-invariant-bench", "Simulation")
config := simcli.NewConfigFromFlags()
config.ChainID = SimAppChainID
db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "leveldb-app-invariant-bench", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if err != nil {
b.Fatalf("simulation setup failed: %s", err.Error())
}
@@ -86,7 +95,7 @@ func BenchmarkInvariants(b *testing.B) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = DefaultNodeHome
appOptions[server.FlagInvCheckPeriod] = FlagPeriodValue
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue
app := NewSimApp(logger, db, nil, true, appOptions, interBlockCacheOpt())
@@ -97,14 +106,14 @@ func BenchmarkInvariants(b *testing.B) {
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(app, app.AppCodec(), config),
simtestutil.SimulationOperations(app, app.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
)
// export state and simParams before the simulation error is checked
if err = CheckExportSimulation(app, config, simParams); err != nil {
if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil {
b.Fatal(err)
}
@@ -113,7 +122,7 @@ func BenchmarkInvariants(b *testing.B) {
}
if config.Commit {
PrintStats(db)
simtestutil.PrintStats(db)
}
ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight() + 1})
+40 -27
View File
@@ -34,13 +34,17 @@ import (
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
// SimAppChainID hardcoded chainID for simulation
const SimAppChainID = "simulation-app"
// Get flags every time the simulator is run
func init() {
GetSimulatorFlags()
simcli.GetSimulatorFlags()
}
type StoreKeysPrefixes struct {
@@ -62,7 +66,10 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) {
}
func TestFullAppSimulation(t *testing.T) {
config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-sim", "Simulation")
config := simcli.NewConfigFromFlags()
config.ChainID = SimAppChainID
db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "leveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if skip {
t.Skip("skipping application simulation")
}
@@ -75,7 +82,7 @@ func TestFullAppSimulation(t *testing.T) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = DefaultNodeHome
appOptions[server.FlagInvCheckPeriod] = FlagPeriodValue
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue
app := NewSimApp(logger, db, nil, true, appOptions, fauxMerkleModeOpt)
require.Equal(t, "SimApp", app.Name())
@@ -87,24 +94,27 @@ func TestFullAppSimulation(t *testing.T) {
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(app, app.AppCodec(), config),
simtestutil.SimulationOperations(app, app.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
)
// export state and simParams before the simulation error is checked
err = CheckExportSimulation(app, config, simParams)
err = simtestutil.CheckExportSimulation(app, config, simParams)
require.NoError(t, err)
require.NoError(t, simErr)
if config.Commit {
PrintStats(db)
simtestutil.PrintStats(db)
}
}
func TestAppImportExport(t *testing.T) {
config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-sim", "Simulation")
config := simcli.NewConfigFromFlags()
config.ChainID = SimAppChainID
db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "leveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if skip {
t.Skip("skipping application import/export simulation")
}
@@ -117,7 +127,7 @@ func TestAppImportExport(t *testing.T) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = DefaultNodeHome
appOptions[server.FlagInvCheckPeriod] = FlagPeriodValue
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue
app := NewSimApp(logger, db, nil, true, appOptions, fauxMerkleModeOpt)
require.Equal(t, "SimApp", app.Name())
@@ -129,19 +139,19 @@ func TestAppImportExport(t *testing.T) {
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(app, app.AppCodec(), config),
simtestutil.SimulationOperations(app, app.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
)
// export state and simParams before the simulation error is checked
err = CheckExportSimulation(app, config, simParams)
err = simtestutil.CheckExportSimulation(app, config, simParams)
require.NoError(t, err)
require.NoError(t, simErr)
if config.Commit {
PrintStats(db)
simtestutil.PrintStats(db)
}
fmt.Printf("exporting genesis...\n")
@@ -151,7 +161,7 @@ func TestAppImportExport(t *testing.T) {
fmt.Printf("importing genesis...\n")
_, newDB, newDir, _, _, err := SetupSimulation("leveldb-app-sim-2", "Simulation-2")
newDB, newDir, _, _, err := simtestutil.SetupSimulation(config, "leveldb-app-sim-2", "Simulation-2", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
require.NoError(t, err, "simulation setup failed")
defer func() {
@@ -212,12 +222,15 @@ func TestAppImportExport(t *testing.T) {
require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare")
fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B)
require.Equal(t, 0, len(failedKVAs), GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs))
require.Equal(t, 0, len(failedKVAs), simtestutil.GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs))
}
}
func TestAppSimulationAfterImport(t *testing.T) {
config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-sim", "Simulation")
config := simcli.NewConfigFromFlags()
config.ChainID = SimAppChainID
db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "leveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if skip {
t.Skip("skipping application simulation after import")
}
@@ -230,7 +243,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = DefaultNodeHome
appOptions[server.FlagInvCheckPeriod] = FlagPeriodValue
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue
app := NewSimApp(logger, db, nil, true, appOptions, fauxMerkleModeOpt)
require.Equal(t, "SimApp", app.Name())
@@ -242,19 +255,19 @@ func TestAppSimulationAfterImport(t *testing.T) {
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(app, app.AppCodec(), config),
simtestutil.SimulationOperations(app, app.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
)
// export state and simParams before the simulation error is checked
err = CheckExportSimulation(app, config, simParams)
err = simtestutil.CheckExportSimulation(app, config, simParams)
require.NoError(t, err)
require.NoError(t, simErr)
if config.Commit {
PrintStats(db)
simtestutil.PrintStats(db)
}
if stopEarly {
@@ -269,7 +282,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
fmt.Printf("importing genesis...\n")
_, newDB, newDir, _, _, err := SetupSimulation("leveldb-app-sim-2", "Simulation-2")
newDB, newDir, _, _, err := simtestutil.SetupSimulation(config, "leveldb-app-sim-2", "Simulation-2", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
require.NoError(t, err, "simulation setup failed")
defer func() {
@@ -290,7 +303,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
newApp.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(newApp, newApp.AppCodec(), config),
simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
@@ -301,16 +314,16 @@ func TestAppSimulationAfterImport(t *testing.T) {
// TODO: Make another test for the fuzzer itself, which just has noOp txs
// and doesn't depend on the application.
func TestAppStateDeterminism(t *testing.T) {
if !FlagEnabledValue {
if !simcli.FlagEnabledValue {
t.Skip("skipping application simulation")
}
config := NewConfigFromFlags()
config := simcli.NewConfigFromFlags()
config.InitialBlockHeight = 1
config.ExportParamsPath = ""
config.OnOperation = false
config.AllInvariants = false
config.ChainID = simtestutil.SimAppChainID
config.ChainID = SimAppChainID
numSeeds := 3
numTimesToRunPerSeed := 5
@@ -318,14 +331,14 @@ func TestAppStateDeterminism(t *testing.T) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = DefaultNodeHome
appOptions[server.FlagInvCheckPeriod] = FlagPeriodValue
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue
for i := 0; i < numSeeds; i++ {
config.Seed = rand.Int63()
for j := 0; j < numTimesToRunPerSeed; j++ {
var logger log.Logger
if FlagVerboseValue {
if simcli.FlagVerboseValue {
logger = log.TestingLogger()
} else {
logger = log.NewNopLogger()
@@ -345,7 +358,7 @@ func TestAppStateDeterminism(t *testing.T) {
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
SimulationOperations(app, app.AppCodec(), config),
simtestutil.SimulationOperations(app, app.AppCodec(), config),
ModuleAccountAddrs(),
config,
app.AppCodec(),
@@ -353,7 +366,7 @@ func TestAppStateDeterminism(t *testing.T) {
require.NoError(t, err)
if config.Commit {
PrintStats(db)
simtestutil.PrintStats(db)
}
appHash := app.LastCommitID().Hash
+4 -3
View File
@@ -20,6 +20,7 @@ import (
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
@@ -29,10 +30,10 @@ import (
func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
if FlagGenesisTimeValue == 0 {
if simcli.FlagGenesisTimeValue == 0 {
genesisTimestamp = simtypes.RandTimestamp(r)
} else {
genesisTimestamp = time.Unix(FlagGenesisTimeValue, 0)
genesisTimestamp = time.Unix(simcli.FlagGenesisTimeValue, 0)
}
chainID = config.ChainID
@@ -44,7 +45,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
// override the default chain-id from simapp to set it later to the config
genesisDoc, accounts := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile)
if FlagGenesisTimeValue == 0 {
if simcli.FlagGenesisTimeValue == 0 {
// use genesis timestamp if no custom timestamp is provided (i.e no random timestamp)
genesisTimestamp = genesisDoc.GenesisTime
}
-131
View File
@@ -1,131 +0,0 @@
package simapp
import (
"encoding/json"
"fmt"
"os"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/runtime"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
)
// SetupSimulation creates the config, db (levelDB), temporary directory and logger for
// the simulation tests. If `FlagEnabledValue` is false it skips the current test.
// Returns error on an invalid db intantiation or temp dir creation.
func SetupSimulation(dirPrefix, dbName string) (simtypes.Config, dbm.DB, string, log.Logger, bool, error) {
if !FlagEnabledValue {
return simtypes.Config{}, nil, "", nil, true, nil
}
config := NewConfigFromFlags()
config.ChainID = simtestutil.SimAppChainID
var logger log.Logger
if FlagVerboseValue {
logger = log.TestingLogger()
} else {
logger = log.NewNopLogger()
}
dir, err := os.MkdirTemp("", dirPrefix)
if err != nil {
return simtypes.Config{}, nil, "", nil, false, err
}
db, err := dbm.NewDB(dbName, dbm.BackendType(config.DBBackend), dir)
if err != nil {
return simtypes.Config{}, nil, "", nil, false, err
}
return config, db, dir, logger, false, nil
}
// SimulationOperations retrieves the simulation params from the provided file path
// and returns all the modules weighted operations
func SimulationOperations(app runtime.AppI, cdc codec.JSONCodec, config simtypes.Config) []simtypes.WeightedOperation {
simState := module.SimulationState{
AppParams: make(simtypes.AppParams),
Cdc: cdc,
}
if config.ParamsFile != "" {
bz, err := os.ReadFile(config.ParamsFile)
if err != nil {
panic(err)
}
err = json.Unmarshal(bz, &simState.AppParams)
if err != nil {
panic(err)
}
}
simState.Contents = app.SimulationManager().GetProposalContents(simState)
return app.SimulationManager().WeightedOperations(simState)
}
// CheckExportSimulation exports the app state and simulation parameters to JSON
// if the export paths are defined.
func CheckExportSimulation(
app runtime.AppI, config simtypes.Config, params simtypes.Params,
) error {
if config.ExportStatePath != "" {
fmt.Println("exporting app state...")
exported, err := app.ExportAppStateAndValidators(false, nil)
if err != nil {
return err
}
if err := os.WriteFile(config.ExportStatePath, []byte(exported.AppState), 0o600); err != nil {
return err
}
}
if config.ExportParamsPath != "" {
fmt.Println("exporting simulation params...")
paramsBz, err := json.MarshalIndent(params, "", " ")
if err != nil {
return err
}
if err := os.WriteFile(config.ExportParamsPath, paramsBz, 0o600); err != nil {
return err
}
}
return nil
}
// PrintStats prints the corresponding statistics from the app DB.
func PrintStats(db dbm.DB) {
fmt.Println("\nLevelDB Stats")
fmt.Println(db.Stats()["leveldb.stats"])
fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
// GetSimulationLog unmarshals the KVPair's Value to the corresponding type based on the
// each's module store key and the prefix bytes of the KVPair's key.
func GetSimulationLog(storeName string, sdr sdk.StoreDecoderRegistry, kvAs, kvBs []kv.Pair) (log string) {
for i := 0; i < len(kvAs); i++ {
if len(kvAs[i].Value) == 0 && len(kvBs[i].Value) == 0 {
// skip if the value doesn't have any bytes
continue
}
decoder, ok := sdr[storeName]
if ok {
log += decoder(kvAs[i], kvBs[i])
} else {
log += fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", kvAs[i].Key, kvAs[i].Value, kvBs[i].Key, kvBs[i].Value)
}
}
return log
}
-60
View File
@@ -1,60 +0,0 @@
package simapp
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/std"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
"github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)
func makeCodec(bm module.BasicManager) *codec.LegacyAmino {
cdc := codec.NewLegacyAmino()
bm.RegisterLegacyAminoCodec(cdc)
std.RegisterLegacyAminoCodec(cdc)
return cdc
}
func TestGetSimulationLog(t *testing.T) {
cdc := makeCodec(ModuleBasics)
decoders := make(sdk.StoreDecoderRegistry)
decoders[authtypes.StoreKey] = func(kvAs, kvBs kv.Pair) string { return "10" }
tests := []struct {
store string
kvPairs []kv.Pair
expectedLog string
}{
{
"Empty",
[]kv.Pair{{}},
"",
},
{
authtypes.StoreKey,
[]kv.Pair{{Key: authtypes.GlobalAccountNumberKey, Value: cdc.MustMarshal(uint64(10))}},
"10",
},
{
"OtherStore",
[]kv.Pair{{Key: []byte("key"), Value: []byte("value")}},
fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", []byte("key"), []byte("value"), []byte("key"), []byte("value")),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.store, func(t *testing.T) {
require.Equal(t, tt.expectedLog, GetSimulationLog(tt.store, decoders, tt.kvPairs, tt.kvPairs), tt.store)
})
}
}