Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration Testing #5103

Merged
merged 10 commits into from
Sep 26, 2019
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ linters:
- errcheck
- scopelint
- varcheck
- godox

issues:
exclude-rules:
Expand Down
2 changes: 1 addition & 1 deletion server/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C
}

func isEmptyState(db dbm.DB) bool {
return db.Stats()["leveldb.sstables"] != ""
return db.Stats()["leveldb.sstables"] == ""
}
123 changes: 123 additions & 0 deletions simapp/sim_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package simapp

import (
"fmt"
"io/ioutil"
"os"
"testing"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/simulation"
)

// Profile with:
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out
func BenchmarkFullAppSimulation(b *testing.B) {
logger := log.NewNopLogger()
config := NewConfigFromFlags()

var db dbm.DB
dir, _ := ioutil.TempDir("", "goleveldb-app-sim")
db, _ = sdk.NewLevelDB("Simulation", dir)
defer func() {
db.Close()
os.RemoveAll(dir)
}()

app := NewSimApp(logger, db, nil, true, FlagPeriodValue, interBlockCacheOpt())

// Run randomized simulation
// TODO: parameterize numbers, save for a later PR
_, simParams, simErr := simulation.SimulateFromSeed(
b, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), app.ModuleAccountAddrs(), config,
)

// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
if err := ExportStateToJSON(app, config.ExportStatePath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if config.ExportParamsPath != "" {
if err := ExportParamsToJSON(simParams, config.ExportParamsPath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if simErr != nil {
fmt.Println(simErr)
b.FailNow()
}

if config.Commit {
fmt.Println("\nGoLevelDB Stats")
fmt.Println(db.Stats()["leveldb.stats"])
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
}

func BenchmarkInvariants(b *testing.B) {
logger := log.NewNopLogger()

config := NewConfigFromFlags()
config.AllInvariants = false

dir, _ := ioutil.TempDir("", "goleveldb-app-invariant-bench")
db, _ := sdk.NewLevelDB("simulation", dir)

defer func() {
db.Close()
os.RemoveAll(dir)
}()

app := NewSimApp(logger, db, nil, true, FlagPeriodValue, interBlockCacheOpt())

// 2. Run parameterized simulation (w/o invariants)
_, simParams, simErr := simulation.SimulateFromSeed(
b, ioutil.Discard, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), app.ModuleAccountAddrs(), config,
)

// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
if err := ExportStateToJSON(app, config.ExportStatePath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if config.ExportParamsPath != "" {
if err := ExportParamsToJSON(simParams, config.ExportParamsPath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if simErr != nil {
fmt.Println(simErr)
b.FailNow()
}

ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight() + 1})

// 3. Benchmark each invariant separately
//
// NOTE: We use the crisis keeper as it has all the invariants registered with
// their respective metadata which makes it useful for testing/benchmarking.
for _, cr := range app.CrisisKeeper.Routes() {
b.Run(fmt.Sprintf("%s/%s", cr.ModuleName, cr.Route), func(b *testing.B) {
if res, stop := cr.Invar(ctx); stop {
fmt.Printf("broken invariant at block %d of %d\n%s", ctx.BlockHeight()-1, config.NumBlocks, res)
b.FailNow()
}
})
}
}
109 changes: 0 additions & 109 deletions simapp/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"testing"

"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
Expand Down Expand Up @@ -292,56 +291,6 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) {
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
}

// Profile with:
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out
func BenchmarkFullAppSimulation(b *testing.B) {
logger := log.NewNopLogger()
config := NewConfigFromFlags()

var db dbm.DB
dir, _ := ioutil.TempDir("", "goleveldb-app-sim")
db, _ = sdk.NewLevelDB("Simulation", dir)
defer func() {
db.Close()
os.RemoveAll(dir)
}()

app := NewSimApp(logger, db, nil, true, FlagPeriodValue, interBlockCacheOpt())

// Run randomized simulation
// TODO: parameterize numbers, save for a later PR
_, simParams, simErr := simulation.SimulateFromSeed(
b, os.Stdout, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), app.ModuleAccountAddrs(), config,
)

// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
if err := ExportStateToJSON(app, config.ExportStatePath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if config.ExportParamsPath != "" {
if err := ExportParamsToJSON(simParams, config.ExportParamsPath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if simErr != nil {
fmt.Println(simErr)
b.FailNow()
}

if config.Commit {
fmt.Println("\nGoLevelDB Stats")
fmt.Println(db.Stats()["leveldb.stats"])
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
}

func TestFullAppSimulation(t *testing.T) {
if !FlagEnabledValue {
t.Skip("skipping application simulation")
Expand Down Expand Up @@ -652,61 +601,3 @@ func TestAppStateDeterminism(t *testing.T) {
}
}
}

func BenchmarkInvariants(b *testing.B) {
logger := log.NewNopLogger()

config := NewConfigFromFlags()
config.AllInvariants = false

dir, _ := ioutil.TempDir("", "goleveldb-app-invariant-bench")
db, _ := sdk.NewLevelDB("simulation", dir)

defer func() {
db.Close()
os.RemoveAll(dir)
}()

app := NewSimApp(logger, db, nil, true, FlagPeriodValue, interBlockCacheOpt())

// 2. Run parameterized simulation (w/o invariants)
_, simParams, simErr := simulation.SimulateFromSeed(
b, ioutil.Discard, app.BaseApp, AppStateFn(app.Codec(), app.sm),
testAndRunTxs(app, config), app.ModuleAccountAddrs(), config,
)

// export state and params before the simulation error is checked
if config.ExportStatePath != "" {
if err := ExportStateToJSON(app, config.ExportStatePath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if config.ExportParamsPath != "" {
if err := ExportParamsToJSON(simParams, config.ExportParamsPath); err != nil {
fmt.Println(err)
b.Fail()
}
}

if simErr != nil {
fmt.Println(simErr)
b.FailNow()
}

ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight() + 1})

// 3. Benchmark each invariant separately
//
// NOTE: We use the crisis keeper as it has all the invariants registered with
// their respective metadata which makes it useful for testing/benchmarking.
for _, cr := range app.CrisisKeeper.Routes() {
b.Run(fmt.Sprintf("%s/%s", cr.ModuleName, cr.Route), func(b *testing.B) {
if res, stop := cr.Invar(ctx); stop {
fmt.Printf("broken invariant at block %d of %d\n%s", ctx.BlockHeight()-1, config.NumBlocks, res)
b.FailNow()
}
})
}
}
28 changes: 21 additions & 7 deletions x/genutil/client/cli/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
// Ref: https://github.com/cosmos/cosmos-sdk/issues/5041
var migrationMap = extypes.MigrationMap{
"v0.36": v036.Migrate,
"v0.38": v038.Migrate,
"v0.38": v038.Migrate, // NOTE: v0.37 and v0.38 are genesis compatible
}

const (
Expand All @@ -42,6 +42,8 @@ $ %s migrate v0.36 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2
`, version.ServerName),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
var err error

target := args[0]
importGenesis := args[1]

Expand All @@ -51,14 +53,21 @@ $ %s migrate v0.36 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2
}

var initialState extypes.AppMap
cdc.MustUnmarshalJSON(genDoc.AppState, &initialState)
if err := cdc.UnmarshalJSON(genDoc.AppState, &initialState); err != nil {
return errors.Wrap(err, "failed to JSON unmarshal initial genesis state")
}

if migrationMap[target] == nil {
return fmt.Errorf("unknown migration function version: %s", target)
}

// TODO: handler error from migrationMap call
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
newGenState := migrationMap[target](initialState)
genDoc.AppState = cdc.MustMarshalJSON(newGenState)

alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
genDoc.AppState, err = cdc.MarshalJSON(newGenState)
if err != nil {
return errors.Wrap(err, "failed to JSON marshal migrated genesis state")
}

genesisTime := cmd.Flag(flagGenesisTime).Value.String()
if genesisTime != "" {
Expand All @@ -77,18 +86,23 @@ $ %s migrate v0.36 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2
genDoc.ChainID = chainID
}

out, err := cdc.MarshalJSONIndent(genDoc, "", " ")
bz, err := cdc.MarshalJSONIndent(genDoc, "", " ")
if err != nil {
return errors.Wrap(err, "failed to marshal genesis doc")
}

fmt.Println(string(sdk.MustSortJSON(out)))
sortedBz, err := sdk.SortJSON(bz)
if err != nil {
return errors.Wrap(err, "failed to sort JSON genesis doc")
}

fmt.Println(string(sortedBz))
return nil
},
}

cmd.Flags().String(flagGenesisTime, "", "Override genesis_time with this flag")
cmd.Flags().String(flagChainID, "", "Override chain_id with this flag")
cmd.Flags().String(flagGenesisTime, "", "override genesis_time with this flag")
cmd.Flags().String(flagChainID, "", "override chain_id with this flag")

return cmd
}
11 changes: 11 additions & 0 deletions x/genutil/legacy/v0_38/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v0_38"
v036genaccounts "github.com/cosmos/cosmos-sdk/x/genaccounts/legacy/v0_36"
"github.com/cosmos/cosmos-sdk/x/genutil"
v036staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_36"
v038staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_38"
)

// Migrate migrates exported state from v0.34 to a v0.36 genesis state.
Expand Down Expand Up @@ -35,5 +37,14 @@ func Migrate(appState genutil.AppMap) genutil.AppMap {
delete(appState, v036genaccounts.ModuleName)
}

// migrate staking state
if appState[v036staking.ModuleName] != nil {
var stakingGenState v036staking.GenesisState
v036Codec.MustUnmarshalJSON(appState[v036staking.ModuleName], &stakingGenState)

delete(appState, v036staking.ModuleName) // delete old key in case the name changed
appState[v038staking.ModuleName] = v038Codec.MustMarshalJSON(v038staking.Migrate(stakingGenState))
}

return appState
}
Loading