github.com/Finschia/finschia-sdk@v0.48.1/x/distribution/simulation/operations_test.go (about) 1 package simulation_test 2 3 import ( 4 "math/rand" 5 "testing" 6 7 "github.com/stretchr/testify/suite" 8 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 9 10 ocabci "github.com/Finschia/ostracon/abci/types" 11 12 "github.com/Finschia/finschia-sdk/simapp" 13 simappparams "github.com/Finschia/finschia-sdk/simapp/params" 14 sdk "github.com/Finschia/finschia-sdk/types" 15 simtypes "github.com/Finschia/finschia-sdk/types/simulation" 16 "github.com/Finschia/finschia-sdk/x/distribution/simulation" 17 "github.com/Finschia/finschia-sdk/x/distribution/types" 18 distrtypes "github.com/Finschia/finschia-sdk/x/distribution/types" 19 stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" 20 ) 21 22 // TestWeightedOperations tests the weights of the operations. 23 func (suite *SimTestSuite) TestWeightedOperations() { 24 cdc := suite.app.AppCodec() 25 appParams := make(simtypes.AppParams) 26 27 weightesOps := simulation.WeightedOperations(appParams, cdc, suite.app.AccountKeeper, 28 suite.app.BankKeeper, suite.app.DistrKeeper, suite.app.StakingKeeper, 29 ) 30 31 // setup 3 accounts 32 s := rand.NewSource(1) 33 r := rand.New(s) 34 accs := suite.getTestingAccounts(r, 3) 35 36 expected := []struct { 37 weight int 38 opMsgRoute string 39 opMsgName string 40 }{ 41 {simappparams.DefaultWeightMsgSetWithdrawAddress, types.ModuleName, types.TypeMsgSetWithdrawAddress}, 42 {simappparams.DefaultWeightMsgWithdrawDelegationReward, types.ModuleName, types.TypeMsgWithdrawDelegatorReward}, 43 {simappparams.DefaultWeightMsgWithdrawValidatorCommission, types.ModuleName, types.TypeMsgWithdrawValidatorCommission}, 44 {simappparams.DefaultWeightMsgFundCommunityPool, types.ModuleName, types.TypeMsgFundCommunityPool}, 45 } 46 47 for i, w := range weightesOps { 48 operationMsg, _, _ := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") 49 // the following checks are very much dependent from the ordering of the output given 50 // by WeightedOperations. if the ordering in WeightedOperations changes some tests 51 // will fail 52 suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") 53 suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") 54 suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") 55 } 56 } 57 58 // TestSimulateMsgSetWithdrawAddress tests the normal scenario of a valid message of type TypeMsgSetWithdrawAddress. 59 // Abonormal scenarios, where the message is created by an errors, are not tested here. 60 func (suite *SimTestSuite) TestSimulateMsgSetWithdrawAddress() { 61 // setup 3 accounts 62 s := rand.NewSource(1) 63 r := rand.New(s) 64 accounts := suite.getTestingAccounts(r, 3) 65 66 // begin a new block 67 suite.app.BeginBlock(ocabci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) 68 69 // execute operation 70 op := simulation.SimulateMsgSetWithdrawAddress(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.DistrKeeper) 71 operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") 72 suite.Require().NoError(err) 73 74 var msg types.MsgSetWithdrawAddress 75 types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) 76 77 suite.Require().True(operationMsg.OK) 78 suite.Require().Equal("link1ghekyjucln7y67ntx7cf27m9dpuxxemnqk82wt", msg.DelegatorAddress) 79 suite.Require().Equal("link1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7fmx8x8", msg.WithdrawAddress) 80 suite.Require().Equal(types.TypeMsgSetWithdrawAddress, msg.Type()) 81 suite.Require().Equal(types.ModuleName, msg.Route()) 82 suite.Require().Len(futureOperations, 0) 83 } 84 85 // TestSimulateMsgWithdrawDelegatorReward tests the normal scenario of a valid message 86 // of type TypeMsgWithdrawDelegatorReward. 87 // Abonormal scenarios, where the message is created by an errors, are not tested here. 88 func (suite *SimTestSuite) TestSimulateMsgWithdrawDelegatorReward() { 89 // setup 3 accounts 90 s := rand.NewSource(4) 91 r := rand.New(s) 92 accounts := suite.getTestingAccounts(r, 3) 93 94 // setup accounts[0] as validator 95 validator0 := suite.getTestingValidator0(accounts) 96 97 // setup delegation 98 delTokens := suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 2) 99 validator0, issuedShares := validator0.AddTokensFromDel(delTokens) 100 delegator := accounts[1] 101 delegation := stakingtypes.NewDelegation(delegator.Address, validator0.GetOperator(), issuedShares) 102 suite.app.StakingKeeper.SetDelegation(suite.ctx, delegation) 103 suite.app.DistrKeeper.SetDelegatorStartingInfo(suite.ctx, validator0.GetOperator(), delegator.Address, distrtypes.NewDelegatorStartingInfo(2, sdk.OneDec(), 200)) 104 105 suite.setupValidatorRewards(validator0.GetOperator()) 106 107 // begin a new block 108 suite.app.BeginBlock(ocabci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) 109 110 // execute operation 111 op := simulation.SimulateMsgWithdrawDelegatorReward(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.DistrKeeper, suite.app.StakingKeeper) 112 operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") 113 suite.Require().NoError(err) 114 115 var msg types.MsgWithdrawDelegatorReward 116 types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) 117 118 suite.Require().True(operationMsg.OK) 119 suite.Require().Equal("linkvaloper1l4s054098kk9hmr5753c6k3m2kw65h68cr83wt", msg.ValidatorAddress) 120 suite.Require().Equal("link1d6u7zhjwmsucs678d7qn95uqajd4ucl98kjf3j", msg.DelegatorAddress) 121 suite.Require().Equal(types.TypeMsgWithdrawDelegatorReward, msg.Type()) 122 suite.Require().Equal(types.ModuleName, msg.Route()) 123 suite.Require().Len(futureOperations, 0) 124 } 125 126 // TestSimulateMsgWithdrawValidatorCommission tests the normal scenario of a valid message 127 // of type TypeMsgWithdrawValidatorCommission. 128 // Abonormal scenarios, where the message is created by an errors, are not tested here. 129 func (suite *SimTestSuite) TestSimulateMsgWithdrawValidatorCommission() { 130 suite.testSimulateMsgWithdrawValidatorCommission("atoken") 131 suite.testSimulateMsgWithdrawValidatorCommission("tokenxxx") 132 } 133 134 // all the checks in this function should not fail if we change the tokenName 135 func (suite *SimTestSuite) testSimulateMsgWithdrawValidatorCommission(tokenName string) { 136 // setup 3 accounts 137 s := rand.NewSource(1) 138 r := rand.New(s) 139 accounts := suite.getTestingAccounts(r, 3) 140 141 // setup accounts[0] as validator 142 validator0 := suite.getTestingValidator0(accounts) 143 144 // set module account coins 145 distrAcc := suite.app.DistrKeeper.GetDistributionAccount(suite.ctx) 146 suite.Require().NoError(simapp.FundModuleAccount(suite.app, suite.ctx, distrAcc.GetName(), sdk.NewCoins( 147 sdk.NewCoin(tokenName, sdk.NewInt(10)), 148 sdk.NewCoin("stake", sdk.NewInt(5)), 149 ))) 150 suite.app.AccountKeeper.SetModuleAccount(suite.ctx, distrAcc) 151 152 // set outstanding rewards 153 valCommission := sdk.NewDecCoins( 154 sdk.NewDecCoinFromDec(tokenName, sdk.NewDec(5).Quo(sdk.NewDec(2))), 155 sdk.NewDecCoinFromDec("stake", sdk.NewDec(1).Quo(sdk.NewDec(1))), 156 ) 157 158 suite.app.DistrKeeper.SetValidatorOutstandingRewards(suite.ctx, validator0.GetOperator(), types.ValidatorOutstandingRewards{Rewards: valCommission}) 159 160 // setup validator accumulated commission 161 suite.app.DistrKeeper.SetValidatorAccumulatedCommission(suite.ctx, validator0.GetOperator(), types.ValidatorAccumulatedCommission{Commission: valCommission}) 162 163 // begin a new block 164 suite.app.BeginBlock(ocabci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) 165 166 // execute operation 167 op := simulation.SimulateMsgWithdrawValidatorCommission(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.DistrKeeper, suite.app.StakingKeeper) 168 operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") 169 suite.Require().NoError(err) 170 171 var msg types.MsgWithdrawValidatorCommission 172 types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) 173 174 suite.Require().True(operationMsg.OK) 175 suite.Require().Equal("linkvaloper1tnh2q55v8wyygtt9srz5safamzdengsn8rx882", msg.ValidatorAddress) 176 suite.Require().Equal(types.TypeMsgWithdrawValidatorCommission, msg.Type()) 177 suite.Require().Equal(types.ModuleName, msg.Route()) 178 suite.Require().Len(futureOperations, 0) 179 } 180 181 // TestSimulateMsgFundCommunityPool tests the normal scenario of a valid message of type TypeMsgFundCommunityPool. 182 // Abonormal scenarios, where the message is created by an errors, are not tested here. 183 func (suite *SimTestSuite) TestSimulateMsgFundCommunityPool() { 184 // setup 3 accounts 185 s := rand.NewSource(1) 186 r := rand.New(s) 187 accounts := suite.getTestingAccounts(r, 3) 188 189 // begin a new block 190 suite.app.BeginBlock(ocabci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) 191 192 // execute operation 193 op := simulation.SimulateMsgFundCommunityPool(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.DistrKeeper, suite.app.StakingKeeper) 194 operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") 195 suite.Require().NoError(err) 196 197 var msg types.MsgFundCommunityPool 198 types.ModuleCdc.UnmarshalJSON(operationMsg.Msg, &msg) 199 200 suite.Require().True(operationMsg.OK) 201 suite.Require().Equal("4896096stake", msg.Amount.String()) 202 suite.Require().Equal("link1ghekyjucln7y67ntx7cf27m9dpuxxemnqk82wt", msg.Depositor) 203 suite.Require().Equal(types.TypeMsgFundCommunityPool, msg.Type()) 204 suite.Require().Equal(types.ModuleName, msg.Route()) 205 suite.Require().Len(futureOperations, 0) 206 } 207 208 type SimTestSuite struct { 209 suite.Suite 210 211 ctx sdk.Context 212 app *simapp.SimApp 213 } 214 215 func (suite *SimTestSuite) SetupTest() { 216 checkTx := false 217 app := simapp.Setup(checkTx) 218 suite.app = app 219 suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{}) 220 } 221 222 func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { 223 accounts := simtypes.RandomAccounts(r, n) 224 225 initAmt := suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 200) 226 initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) 227 228 // add coins to the accounts 229 for _, account := range accounts { 230 acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) 231 suite.app.AccountKeeper.SetAccount(suite.ctx, acc) 232 suite.Require().NoError(simapp.FundAccount(suite.app, suite.ctx, account.Address, initCoins)) 233 } 234 235 return accounts 236 } 237 238 func (suite *SimTestSuite) getTestingValidator0(accounts []simtypes.Account) stakingtypes.Validator { 239 commission0 := stakingtypes.NewCommission(sdk.ZeroDec(), sdk.OneDec(), sdk.OneDec()) 240 return suite.getTestingValidator(accounts, commission0, 0) 241 } 242 243 func (suite *SimTestSuite) getTestingValidator(accounts []simtypes.Account, commission stakingtypes.Commission, n int) stakingtypes.Validator { 244 require := suite.Require() 245 account := accounts[n] 246 valPubKey := account.PubKey 247 valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) 248 validator, err := stakingtypes.NewValidator(valAddr, valPubKey, stakingtypes.Description{}) 249 require.NoError(err) 250 validator, err = validator.SetInitialCommission(commission) 251 require.NoError(err) 252 validator.DelegatorShares = sdk.NewDec(100) 253 validator.Tokens = sdk.NewInt(1000000) 254 255 suite.app.StakingKeeper.SetValidator(suite.ctx, validator) 256 257 return validator 258 } 259 260 func (suite *SimTestSuite) setupValidatorRewards(valAddress sdk.ValAddress) { 261 decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.OneDec())} 262 historicalRewards := distrtypes.NewValidatorHistoricalRewards(decCoins, 2) 263 suite.app.DistrKeeper.SetValidatorHistoricalRewards(suite.ctx, valAddress, 2, historicalRewards) 264 // setup current revards 265 currentRewards := distrtypes.NewValidatorCurrentRewards(decCoins, 3) 266 suite.app.DistrKeeper.SetValidatorCurrentRewards(suite.ctx, valAddress, currentRewards) 267 } 268 269 func TestSimTestSuite(t *testing.T) { 270 suite.Run(t, new(SimTestSuite)) 271 }