cosmos-sdk/simapp/v2/sim_test.go
mergify[bot] 5045abbf21
test: Add more sims test scenarios (backport #23278) (#23341)
Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>
Co-authored-by: Julien Robert <julien@rbrt.fr>
2025-01-13 11:45:37 +01:00

104 lines
2.9 KiB
Go

//go:build sims
package simapp
import (
"bytes"
"context"
"math/rand"
"sync"
"testing"
"time"
"github.com/stretchr/testify/require"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
genutil "github.com/cosmos/cosmos-sdk/x/genutil/v2"
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"
)
func init() {
simcli.GetSimulatorFlags()
}
func TestFullAppSimulation(t *testing.T) {
RunWithSeeds[Tx](t, NewSimApp[Tx], AppConfig, DefaultSeeds)
}
func TestAppStateDeterminism(t *testing.T) {
var seeds []int64
if s := simcli.NewConfigFromFlags().Seed; s != simcli.DefaultSeedValue {
// override defaults with user data
seeds = []int64{s, s, s} // run same simulation 3 times
} else {
seeds = []int64{ // some random seeds, tripled to ensure same app-hash on all runs
1, 1, 1,
3, 3, 3,
5, 5, 5,
}
}
var mx sync.Mutex
appHashResults := make(map[int64][]byte)
captureAndCheckHash := func(tb testing.TB, cs ChainState[Tx], ti TestInstance[Tx], _ []simtypes.Account) {
tb.Helper()
mx.Lock()
defer mx.Unlock()
otherHashes, ok := appHashResults[ti.Seed]
if !ok {
appHashResults[ti.Seed] = cs.AppHash
return
}
if !bytes.Equal(otherHashes, cs.AppHash) {
tb.Fatalf("non-determinism in seed %d", ti.Seed)
}
}
// run simulations
RunWithSeeds(t, NewSimApp[Tx], AppConfig, seeds, captureAndCheckHash)
}
// ExportableApp defines an interface for exporting application state and validator set.
type ExportableApp interface {
ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAddrs []string) (genutil.ExportedApp, error)
}
// Scenario:
//
// Start a fresh node and run n blocks, export state
// set up a new node instance, Init chain from exported genesis
// run new instance for n blocks
func TestAppSimulationAfterImport(t *testing.T) {
appFactory := NewSimApp[Tx]
cfg := simcli.NewConfigFromFlags()
cfg.ChainID = SimAppChainID
exportAndStartChainFromGenesisPostAction := func(tb testing.TB, cs ChainState[Tx], ti TestInstance[Tx], accs []simtypes.Account) {
tb.Helper()
tb.Log("exporting genesis...\n")
app, ok := ti.App.(ExportableApp)
require.True(tb, ok)
exported, err := app.ExportAppStateAndValidators(false, []string{})
require.NoError(tb, err)
genesisTimestamp := cs.BlockTime.Add(24 * time.Hour)
startHeight := uint64(exported.Height + 1)
chainID := SimAppChainID + "_2"
importGenesisChainStateFactory := func(ctx context.Context, r *rand.Rand) (TestInstance[Tx], ChainState[Tx], []simtypes.Account) {
testInstance := SetupTestInstance(tb, appFactory, AppConfig, ti.Seed)
newCs := testInstance.InitializeChain(
tb,
ctx,
chainID,
genesisTimestamp,
startHeight,
exported.AppState,
)
return testInstance, newCs, accs
}
// run sims with new app setup from exported genesis
RunWithSeedX[Tx](tb, cfg, importGenesisChainStateFactory, ti.Seed)
}
RunWithSeeds[Tx, *SimApp[Tx]](t, appFactory, AppConfig, DefaultSeeds, exportAndStartChainFromGenesisPostAction)
}