package simulation_test import ( "math/rand" "testing" "time" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/simapp" simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/slashing/simulation" "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // TestWeightedOperations tests the weights of the operations. func TestWeightedOperations(t *testing.T) { app, ctx := createTestApp(false) ctx.WithChainID("test-chain") cdc := app.LegacyAmino() appParams := make(simtypes.AppParams) s := rand.NewSource(1) r := rand.New(s) accs := simtypes.RandomAccounts(r, 3) expected := []struct { weight int opMsgRoute string opMsgName string }{{simappparams.DefaultWeightMsgUnjail, types.ModuleName, types.TypeMsgUnjail}} weightesOps := simulation.WeightedOperations(appParams, cdc, app.AccountKeeper, app.BankKeeper, app.SlashingKeeper, app.StakingKeeper) for i, w := range weightesOps { operationMsg, _, _ := w.Op()(r, app.BaseApp, ctx, accs, ctx.ChainID()) // the following checks are very much dependent from the ordering of the output given // by WeightedOperations. if the ordering in WeightedOperations changes some tests // will fail require.Equal(t, expected[i].weight, w.Weight(), "weight should be the same") require.Equal(t, expected[i].opMsgRoute, operationMsg.Route, "route should be the same") require.Equal(t, expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") } } // TestSimulateMsgUnjail tests the normal scenario of a valid message of type types.MsgUnjail. // Abonormal scenarios, where the message is created by an errors, are not tested here. func TestSimulateMsgUnjail(t *testing.T) { app, ctx := createTestApp(false) blockTime := time.Now().UTC() ctx = ctx.WithBlockTime(blockTime) // setup 3 accounts s := rand.NewSource(1) r := rand.New(s) accounts := getTestingAccounts(t, r, app, ctx, 3) // setup accounts[0] as validator0 validator0 := getTestingValidator0(t, app, ctx, accounts) // setup validator0 by consensus address app.StakingKeeper.SetValidatorByConsAddr(ctx, validator0) val0ConsAddress := sdk.ConsAddress(validator0.GetConsPubKey().Address()) info := types.NewValidatorSigningInfo(val0ConsAddress, int64(4), int64(3), time.Unix(2, 0), false, int64(10)) app.SlashingKeeper.SetValidatorSigningInfo(ctx, val0ConsAddress, info) // put validator0 in jail app.StakingKeeper.Jail(ctx, val0ConsAddress) // setup self delegation delTokens := sdk.TokensFromConsensusPower(2) validator0, issuedShares := validator0.AddTokensFromDel(delTokens) val0AccAddress := sdk.AccAddress(validator0.OperatorAddress.Bytes()) selfDelegation := stakingtypes.NewDelegation(val0AccAddress, validator0.OperatorAddress, issuedShares) app.StakingKeeper.SetDelegation(ctx, selfDelegation) app.DistrKeeper.SetDelegatorStartingInfo(ctx, validator0.OperatorAddress, val0AccAddress, distrtypes.NewDelegatorStartingInfo(2, sdk.OneDec(), 200)) // begin a new block app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash, Time: blockTime}}) // execute operation op := simulation.SimulateMsgUnjail(app.AccountKeeper, app.BankKeeper, app.SlashingKeeper, app.StakingKeeper) operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") require.NoError(t, err) var msg types.MsgUnjail types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) require.True(t, operationMsg.OK) require.Equal(t, types.TypeMsgUnjail, msg.Type()) require.Equal(t, "cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z", msg.GetValidatorAddr().String()) require.Len(t, futureOperations, 0) } // returns context and an app with updated mint keeper func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) { app := simapp.Setup(isCheckTx) ctx := app.BaseApp.NewContext(isCheckTx, abci.Header{}) app.MintKeeper.SetParams(ctx, minttypes.DefaultParams()) app.MintKeeper.SetMinter(ctx, minttypes.DefaultInitialMinter()) return app, ctx } func getTestingAccounts(t *testing.T, r *rand.Rand, app *simapp.SimApp, ctx sdk.Context, n int) []simtypes.Account { accounts := simtypes.RandomAccounts(r, n) initAmt := sdk.TokensFromConsensusPower(200) initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) // add coins to the accounts for _, account := range accounts { acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) app.AccountKeeper.SetAccount(ctx, acc) err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) require.NoError(t, err) } return accounts } func getTestingValidator0(t *testing.T, app *simapp.SimApp, ctx sdk.Context, accounts []simtypes.Account) stakingtypes.Validator { commission0 := stakingtypes.NewCommission(sdk.ZeroDec(), sdk.OneDec(), sdk.OneDec()) return getTestingValidator(t, app, ctx, accounts, commission0, 0) } func getTestingValidator(t *testing.T, app *simapp.SimApp, ctx sdk.Context, accounts []simtypes.Account, commission stakingtypes.Commission, n int) stakingtypes.Validator { account := accounts[n] valPubKey := account.PubKey valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) validator := stakingtypes.NewValidator(valAddr, valPubKey, stakingtypes.Description{}) validator, err := validator.SetInitialCommission(commission) require.NoError(t, err) validator.DelegatorShares = sdk.NewDec(100) validator.Tokens = sdk.NewInt(1000000) app.StakingKeeper.SetValidator(ctx, validator) return validator }