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