From d2d6d0abd689d6214a104bd2b5733c4d8016464e Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 20 Apr 2023 21:12:25 +0200 Subject: [PATCH] test(sims): fix sim-import-export and improve sims (#15835) --- CHANGELOG.md | 4 +- simapp/app.go | 29 ++---- simapp/sim_test.go | 66 ++++++------- testutil/sims/simulation_helpers.go | 114 ++++++++++++++++------- testutil/sims/simulation_helpers_test.go | 41 +++++--- x/slashing/simulation/decoder.go | 12 +-- x/slashing/simulation/decoder_test.go | 9 +- 7 files changed, 156 insertions(+), 119 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6101c6478..660866500e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features +* (client) [#15597](https://github.com/cosmos/cosmos-sdk/pull/15597) Add status endpoint for clients. * (testutil/integration) [#15556](https://github.com/cosmos/cosmos-sdk/pull/15556) Introduce `testutil/integration` package for module integration testing. * (types) [#15735](https://github.com/cosmos/cosmos-sdk/pull/15735) Make `ValidateBasic() error` method of `Msg` interface optional. Modules should validate messages directly in their message handlers ([RFC 001](https://docs.cosmos.network/main/rfc/rfc-001-tx-validation)). * (x/genutil) [#15679](https://github.com/cosmos/cosmos-sdk/pull/15679) Allow applications to specify a custom genesis migration function for the `genesis migrate` command. @@ -108,6 +109,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* (client) [#15597](https://github.com/cosmos/cosmos-sdk/pull/15597) `RegisterNodeService` now requires a config parameter. * (x/*all*) [#15648](https://github.com/cosmos/cosmos-sdk/issues/15648) Make `SetParams` consistent across all modules and validate the params at the message handling instead of `SetParams` method. * (x/genutil) [#15679](https://github.com/cosmos/cosmos-sdk/pull/15679) `MigrateGenesisCmd` now takes a `MigrationMap` instead of having the SDK genesis migration hardcoded. * (client) [#15673](https://github.com/cosmos/cosmos-sdk/pull/15673) Move `client/keys.OutputFormatJSON` and `client/keys.OutputFormatText` to `client/flags` package. @@ -745,7 +747,6 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (upgrade) [#12603](https://github.com/cosmos/cosmos-sdk/pull/12603) feat: Move AppModule.BeginBlock and AppModule.EndBlock to extension interfaces * (telemetry) [#12405](https://github.com/cosmos/cosmos-sdk/pull/12405) Add *query* calls metric to telemetry. * (query) [#12253](https://github.com/cosmos/cosmos-sdk/pull/12253) Add `GenericFilteredPaginate` to the `query` package to improve UX. -* (client) [#15597](https://github.com/cosmos/cosmos-sdk/pull/15597) Add status endpoint for clients ### API Breaking Changes @@ -821,7 +822,6 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * [#11334](https://github.com/cosmos/cosmos-sdk/pull/11334) Move `x/gov/types/v1beta2` to `x/gov/types/v1`. * (x/auth/middleware) [#11413](https://github.com/cosmos/cosmos-sdk/pull/11413) Refactor tx middleware to be extensible on tx fee logic. Merged `MempoolFeeMiddleware` and `TxPriorityMiddleware` functionalities into `DeductFeeMiddleware`, make the logic extensible using the `TxFeeChecker` option, the current fee logic is preserved by the default `checkTxFeeWithValidatorMinGasPrices` implementation. Change `RejectExtensionOptionsMiddleware` to `NewExtensionOptionsMiddleware` which is extensible with the `ExtensionOptionChecker` option. Unpack the tx extension options `Any`s to interface `TxExtensionOptionI`. * (migrations) [#11556](https://github.com/cosmos/cosmos-sdk/pull/11556#issuecomment-1091385011) Remove migration code from 0.42 and below. To use previous migrations, checkout previous versions of the cosmos-sdk. -* (client) [#15597](https://github.com/cosmos/cosmos-sdk/pull/15597) `RegisterNodeService` now requires a config parameter ### Client Breaking Changes diff --git a/simapp/app.go b/simapp/app.go index e11defc2d9..68b796061c 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -165,9 +165,8 @@ type SimApp struct { interfaceRegistry types.InterfaceRegistry // keys to access the substores - keys map[string]*storetypes.KVStoreKey - tkeys map[string]*storetypes.TransientStoreKey - memKeys map[string]*storetypes.MemoryStoreKey + keys map[string]*storetypes.KVStoreKey + tkeys map[string]*storetypes.TransientStoreKey // keepers AccountKeeper authkeeper.AccountKeeper @@ -267,10 +266,6 @@ func NewSimApp( } tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey) - // NOTE: The testingkey is just mounted for testing purposes. Actual applications should - // not include this key. - memKeys := storetypes.NewMemoryStoreKeys("testingkey") - app := &SimApp{ BaseApp: bApp, legacyAmino: legacyAmino, @@ -279,7 +274,6 @@ func NewSimApp( interfaceRegistry: interfaceRegistry, keys: keys, tkeys: tkeys, - memKeys: memKeys, } app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) @@ -482,7 +476,6 @@ func NewSimApp( // initialize stores app.MountKVStores(keys) app.MountTransientStores(tkeys) - app.MountMemoryStores(memKeys) // initialize BaseApp app.SetInitChainer(app.InitChainer) @@ -645,18 +638,14 @@ func (app *SimApp) GetKey(storeKey string) *storetypes.KVStoreKey { return app.keys[storeKey] } -// GetTKey returns the TransientStoreKey for the provided store key. -// -// NOTE: This is solely to be used for testing purposes. -func (app *SimApp) GetTKey(storeKey string) *storetypes.TransientStoreKey { - return app.tkeys[storeKey] -} +// GetStoreKeys returns all the stored store keys. +func (app *SimApp) GetStoreKeys() []storetypes.StoreKey { + keys := make([]storetypes.StoreKey, len(app.keys)) + for _, key := range app.keys { + keys = append(keys, key) + } -// GetMemKey returns the MemStoreKey for the provided mem key. -// -// NOTE: This is solely used for testing purposes. -func (app *SimApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { - return app.memKeys[storeKey] + return keys } // GetSubspace returns a param subspace for a given module name. diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 53ba1b1ece..f151124b19 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -10,7 +10,6 @@ import ( "strings" "testing" - evidencetypes "cosmossdk.io/x/evidence/types" abci "github.com/cometbft/cometbft/abci/types" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" dbm "github.com/cosmos/cosmos-db" @@ -20,19 +19,14 @@ import ( "cosmossdk.io/log" "cosmossdk.io/store" storetypes "cosmossdk.io/store/types" + "cosmossdk.io/x/feegrant" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - 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" @@ -50,12 +44,6 @@ func init() { flag.BoolVar(&FlagEnableStreamingValue, "EnableStreaming", false, "Enable streaming service") } -type StoreKeysPrefixes struct { - A storetypes.StoreKey - B storetypes.StoreKey - Prefixes [][]byte -} - // fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of // an IAVLStore for faster simulation speed. func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { @@ -197,35 +185,39 @@ func TestAppImportExport(t *testing.T) { fmt.Printf("comparing stores...\n") - storeKeysPrefixes := []StoreKeysPrefixes{ - {app.GetKey(authtypes.StoreKey), newApp.GetKey(authtypes.StoreKey), [][]byte{}}, - { - app.GetKey(stakingtypes.StoreKey), newApp.GetKey(stakingtypes.StoreKey), - [][]byte{ - stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey, - stakingtypes.HistoricalInfoKey, stakingtypes.UnbondingIDKey, stakingtypes.UnbondingIndexKey, stakingtypes.UnbondingTypeKey, stakingtypes.ValidatorUpdatesKey, - }, - }, // ordering may change but it doesn't matter - {app.GetKey(slashingtypes.StoreKey), newApp.GetKey(slashingtypes.StoreKey), [][]byte{}}, - {app.GetKey(minttypes.StoreKey), newApp.GetKey(minttypes.StoreKey), [][]byte{}}, - {app.GetKey(distrtypes.StoreKey), newApp.GetKey(distrtypes.StoreKey), [][]byte{}}, - {app.GetKey(banktypes.StoreKey), newApp.GetKey(banktypes.StoreKey), [][]byte{banktypes.BalancesPrefix}}, - {app.GetKey(paramtypes.StoreKey), newApp.GetKey(paramtypes.StoreKey), [][]byte{}}, - {app.GetKey(govtypes.StoreKey), newApp.GetKey(govtypes.StoreKey), [][]byte{}}, - {app.GetKey(evidencetypes.StoreKey), newApp.GetKey(evidencetypes.StoreKey), [][]byte{}}, - {app.GetKey(authzkeeper.StoreKey), newApp.GetKey(authzkeeper.StoreKey), [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}}, + // skip certain prefixes + skipPrefixes := map[string][][]byte{ + stakingtypes.StoreKey: { + stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey, + stakingtypes.HistoricalInfoKey, stakingtypes.UnbondingIDKey, stakingtypes.UnbondingIndexKey, + stakingtypes.UnbondingTypeKey, stakingtypes.ValidatorUpdatesKey, + }, + authzkeeper.StoreKey: {authzkeeper.GrantQueuePrefix}, + feegrant.StoreKey: {feegrant.FeeAllowanceQueueKeyPrefix}, + slashingtypes.StoreKey: {slashingtypes.ValidatorMissedBlockBitmapKeyPrefix}, } - for _, skp := range storeKeysPrefixes { - storeA := ctxA.KVStore(skp.A) - storeB := ctxB.KVStore(skp.B) + storeKeys := app.GetStoreKeys() + require.NotEmpty(t, storeKeys) - failedKVAs, failedKVBs := simtestutil.DiffKVStores(storeA, storeB, skp.Prefixes) - require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare") + for _, appKeyA := range storeKeys { + // only compare kvstores + if _, ok := appKeyA.(*storetypes.KVStoreKey); !ok { + continue + } - fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B) + keyName := appKeyA.Name() + appKeyB := newApp.GetKey(keyName) - require.Equal(t, 0, len(failedKVAs), simtestutil.GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs)) + storeA := ctxA.KVStore(appKeyA) + storeB := ctxB.KVStore(appKeyB) + + failedKVAs, failedKVBs := simtestutil.DiffKVStores(storeA, storeB, skipPrefixes[keyName]) + require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare %s", keyName) + + fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), appKeyA, appKeyB) + + require.Equal(t, 0, len(failedKVAs), simtestutil.GetSimulationLog(keyName, app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs)) } } diff --git a/testutil/sims/simulation_helpers.go b/testutil/sims/simulation_helpers.go index 72bbde88a9..9e35ebb232 100644 --- a/testutil/sims/simulation_helpers.go +++ b/testutil/sims/simulation_helpers.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "os" + "sync" dbm "github.com/cosmos/cosmos-db" @@ -133,56 +134,103 @@ func GetSimulationLog(storeName string, sdr simtypes.StoreDecoderRegistry, kvAs, // DiffKVStores compares two KVstores and returns all the key/value pairs // that differ from one another. It also skips value comparison for a set of provided prefixes. -func DiffKVStores(a, b storetypes.KVStore, prefixesToSkip [][]byte) (kvAs, kvBs []kv.Pair) { +func DiffKVStores(a, b storetypes.KVStore, prefixesToSkip [][]byte) (diffA, diffB []kv.Pair) { iterA := a.Iterator(nil, nil) - defer iterA.Close() iterB := b.Iterator(nil, nil) - defer iterB.Close() - for { - if !iterA.Valid() && !iterB.Valid() { - return kvAs, kvBs + var wg sync.WaitGroup + + wg.Add(1) + kvAs := make([]kv.Pair, 0) + go func() { + defer wg.Done() + kvAs = getKVPairs(iterA, prefixesToSkip) + }() + + wg.Add(1) + kvBs := make([]kv.Pair, 0) + go func() { + defer wg.Done() + kvBs = getKVPairs(iterB, prefixesToSkip) + }() + + wg.Wait() + + if len(kvAs) != len(kvBs) { + fmt.Printf("KV stores are different: %d key/value pairs in store A and %d key/value pairs in store B\n", len(kvAs), len(kvBs)) + } + + return getDiffFromKVPair(kvAs, kvBs) +} + +// getDiffFromKVPair compares two KVstores and returns all the key/value pairs +func getDiffFromKVPair(kvAs, kvBs []kv.Pair) (diffA, diffB []kv.Pair) { + // we assume that kvBs is equal or larger than kvAs + // if not, we swap the two + if len(kvAs) > len(kvBs) { + kvAs, kvBs = kvBs, kvAs + // we need to swap the diffA and diffB as well + defer func() { + diffA, diffB = diffB, diffA + }() + } + + // in case kvAs is empty we can return early + // since there is nothing to compare + // if kvAs == kvBs, then diffA and diffB will be empty + if len(kvAs) == 0 { + return []kv.Pair{}, kvBs + } + + index := make(map[string][]byte, len(kvBs)) + for _, kv := range kvBs { + index[string(kv.Key)] = kv.Value + } + + for _, kvA := range kvAs { + if kvBValue, ok := index[string(kvA.Key)]; !ok { + diffA = append(diffA, kvA) + diffB = append(diffB, kv.Pair{Key: kvA.Key}) // the key is missing from kvB so we append a pair with an empty value + } else if !bytes.Equal(kvA.Value, kvBValue) { + diffA = append(diffA, kvA) + diffB = append(diffB, kv.Pair{Key: kvA.Key, Value: kvBValue}) + } else { + // values are equal, so we remove the key from the index + delete(index, string(kvA.Key)) } + } - var kvA, kvB kv.Pair - if iterA.Valid() { - kvA = kv.Pair{Key: iterA.Key(), Value: iterA.Value()} + // add the remaining keys from kvBs + for key, value := range index { + diffA = append(diffA, kv.Pair{Key: []byte(key)}) // the key is missing from kvA so we append a pair with an empty value + diffB = append(diffB, kv.Pair{Key: []byte(key), Value: value}) + } - iterA.Next() - } + return diffA, diffB +} - if iterB.Valid() { - kvB = kv.Pair{Key: iterB.Key(), Value: iterB.Value()} - } - - compareValue := true +func getKVPairs(iter dbm.Iterator, prefixesToSkip [][]byte) (kvs []kv.Pair) { + for iter.Valid() { + key, value := iter.Key(), iter.Value() + // do not add the KV pair if the key is prefixed to be skipped. + skip := false for _, prefix := range prefixesToSkip { - // Skip value comparison if we matched a prefix - if bytes.HasPrefix(kvA.Key, prefix) { - compareValue = false + if bytes.HasPrefix(key, prefix) { + skip = true break } } - if !compareValue { - // We're skipping this key due to an exclusion prefix. If it's present in B, iterate past it. If it's - // absent don't iterate. - if bytes.Equal(kvA.Key, kvB.Key) { - iterB.Next() - } - continue + if !skip { + kvs = append(kvs, kv.Pair{Key: key, Value: value}) } - // always iterate B when comparing - iterB.Next() - - if !bytes.Equal(kvA.Key, kvB.Key) || !bytes.Equal(kvA.Value, kvB.Value) { - kvAs = append(kvAs, kvA) - kvBs = append(kvBs, kvB) - } + iter.Next() } + + return kvs } diff --git a/testutil/sims/simulation_helpers_test.go b/testutil/sims/simulation_helpers_test.go index d60a720f2e..67eef0d1a0 100644 --- a/testutil/sims/simulation_helpers_test.go +++ b/testutil/sims/simulation_helpers_test.go @@ -4,17 +4,16 @@ import ( "fmt" "testing" - "cosmossdk.io/log" - "cosmossdk.io/store/metrics" - "cosmossdk.io/store/rootmulti" dbm "github.com/cosmos/cosmos-db" "github.com/stretchr/testify/require" "gotest.tools/v3/assert" - "github.com/cosmos/cosmos-sdk/codec" - + "cosmossdk.io/log" + "cosmossdk.io/store/metrics" + "cosmossdk.io/store/rootmulti" storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -62,24 +61,30 @@ func TestDiffKVStores(t *testing.T) { store1.Set(k1, v1) store2.Set(k1, v1) - checkDiffResults(t, store1, store2) + checkDiffResults(t, store1, store2, true, nil) // delete k1 from store2, which is now empty store2.Delete(k1) - checkDiffResults(t, store1, store2) + checkDiffResults(t, store1, store2, false, nil) // set k1 in store2, different value than what store1 holds for k1 v2 := []byte("v2") store2.Set(k1, v2) - checkDiffResults(t, store1, store2) + checkDiffResults(t, store1, store2, false, nil) // add k2 to store2 k2 := []byte("k2") store2.Set(k2, v2) - checkDiffResults(t, store1, store2) + checkDiffResults(t, store1, store2, false, nil) + + // add k3 to store1 + k3 := []byte("k3") + store1.Set(k3, v2) + checkDiffResults(t, store1, store2, false, nil) // Reset stores store1.Delete(k1) + store1.Delete(k3) store2.Delete(k1) store2.Delete(k2) @@ -88,14 +93,20 @@ func TestDiffKVStores(t *testing.T) { k1Prefixed := append(prefix, k1...) store1.Set(k1Prefixed, v1) store2.Set(k1Prefixed, v2) - checkDiffResults(t, store1, store2) + checkDiffResults(t, store1, store2, true, [][]byte{prefix}) } -func checkDiffResults(t *testing.T, store1, store2 storetypes.KVStore) { - kvAs1, kvBs1 := DiffKVStores(store1, store2, nil) - kvAs2, kvBs2 := DiffKVStores(store1, store2, nil) - assert.DeepEqual(t, kvAs1, kvAs2) - assert.DeepEqual(t, kvBs1, kvBs2) +func checkDiffResults(t *testing.T, store1, store2 storetypes.KVStore, noDiff bool, skipPrefixes [][]byte) { + t.Helper() + + kvAs1, kvBs1 := DiffKVStores(store1, store2, skipPrefixes) + + if noDiff { + assert.Assert(t, len(kvAs1) == 0) + assert.Assert(t, len(kvBs1) == 0) + } else { + assert.Assert(t, len(kvAs1) > 0 || len(kvBs1) > 0) + } } func initTestStores(t *testing.T) (storetypes.KVStore, storetypes.KVStore) { diff --git a/x/slashing/simulation/decoder.go b/x/slashing/simulation/decoder.go index 1e96739d66..754e2a9e97 100644 --- a/x/slashing/simulation/decoder.go +++ b/x/slashing/simulation/decoder.go @@ -4,10 +4,9 @@ import ( "bytes" "fmt" - gogotypes "github.com/cosmos/gogoproto/types" - "github.com/cosmos/cosmos-sdk/codec" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) @@ -24,11 +23,10 @@ func NewDecodeStore(cdc codec.BinaryCodec) func(kvA, kvB kv.Pair) string { return fmt.Sprintf("%v\n%v", infoA, infoB) case bytes.Equal(kvA.Key[:1], types.ValidatorMissedBlockBitmapKeyPrefix): - var missedA, missedB gogotypes.BoolValue - cdc.MustUnmarshal(kvA.Value, &missedA) - cdc.MustUnmarshal(kvB.Value, &missedB) - return fmt.Sprintf("missedA: %v\nmissedB: %v", missedA.Value, missedB.Value) - + addrBzLen := int(kvA.Key[1]) + addrBz := kvA.Key[2 : 2+addrBzLen] + addr := sdk.ConsAddress(addrBz) + return fmt.Sprintf("missedA: %v\nmissedB: %v\nfor %s\n", kvA.Value, kvB.Value, addr) case bytes.Equal(kvA.Key[:1], types.AddrPubkeyRelationKeyPrefix): var pubKeyA, pubKeyB cryptotypes.PubKey if err := cdc.UnmarshalInterface(kvA.Value, &pubKeyA); err != nil { diff --git a/x/slashing/simulation/decoder_test.go b/x/slashing/simulation/decoder_test.go index 85aa4fa460..c63dcbbd23 100644 --- a/x/slashing/simulation/decoder_test.go +++ b/x/slashing/simulation/decoder_test.go @@ -5,7 +5,6 @@ import ( "testing" "time" - gogotypes "github.com/cosmos/gogoproto/types" "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" @@ -29,14 +28,14 @@ func TestDecodeStore(t *testing.T) { dec := simulation.NewDecodeStore(cdc) info := types.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0) - missed := gogotypes.BoolValue{Value: true} + missed := []byte{1} // we want to display the bytes for simulation diffs bz, err := cdc.MarshalInterface(delPk1) require.NoError(t, err) kvPairs := kv.Pairs{ Pairs: []kv.Pair{ {Key: types.ValidatorSigningInfoKey(consAddr1), Value: cdc.MustMarshal(&info)}, - {Key: types.ValidatorMissedBlockBitmapKey(consAddr1, 6), Value: cdc.MustMarshal(&missed)}, + {Key: types.ValidatorMissedBlockBitmapKey(consAddr1, 6), Value: missed}, {Key: types.AddrPubkeyRelationKey(delAddr1), Value: bz}, {Key: []byte{0x99}, Value: []byte{0x99}}, // This test should panic }, @@ -48,7 +47,7 @@ func TestDecodeStore(t *testing.T) { panics bool }{ {"ValidatorSigningInfo", fmt.Sprintf("%v\n%v", info, info), false}, - {"ValidatorMissedBlockBitArray", fmt.Sprintf("missedA: %v\nmissedB: %v", missed.Value, missed.Value), false}, + {"ValidatorMissedBlockBitArray", fmt.Sprintf("missedA: %v\nmissedB: %v\n", missed, missed), false}, {"AddrPubkeyRelation", fmt.Sprintf("PubKeyA: %s\nPubKeyB: %s", delPk1, delPk1), false}, {"other", "", true}, } @@ -58,7 +57,7 @@ func TestDecodeStore(t *testing.T) { if tt.panics { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) } else { - require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + require.Contains(t, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.expectedLog, tt.name) } }) }