github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/gov/abci_test.go (about) 1 package gov 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/require" 9 10 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 11 12 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 13 keep "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/keeper" 14 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking" 15 ) 16 17 func TestTickExpiredDepositPeriod(t *testing.T) { 18 input := getMockApp(t, 10, GenesisState{}, nil, ProposalHandler) 19 20 header := abci.Header{Height: input.mApp.LastBlockHeight() + 1} 21 input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) 22 23 ctx := input.mApp.BaseApp.NewContext(false, abci.Header{}) 24 govHandler := NewHandler(input.keeper) 25 26 inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 27 require.False(t, inactiveQueue.Valid()) 28 inactiveQueue.Close() 29 30 newProposalMsg := NewMsgSubmitProposal( 31 ContentFromProposalType("test", "test", ProposalTypeText), 32 sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, 33 input.addrs[0], 34 ) 35 36 res, err := govHandler(ctx, newProposalMsg) 37 require.NoError(t, err) 38 require.NotNil(t, res) 39 40 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 41 require.False(t, inactiveQueue.Valid()) 42 inactiveQueue.Close() 43 44 newHeader := ctx.BlockHeader() 45 newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) 46 ctx.SetBlockHeader(newHeader) 47 48 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 49 require.False(t, inactiveQueue.Valid()) 50 inactiveQueue.Close() 51 52 newHeader = ctx.BlockHeader() 53 newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod) 54 ctx.SetBlockHeader(newHeader) 55 56 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 57 require.True(t, inactiveQueue.Valid()) 58 inactiveQueue.Close() 59 60 EndBlocker(ctx, input.keeper) 61 62 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 63 require.False(t, inactiveQueue.Valid()) 64 inactiveQueue.Close() 65 } 66 67 func TestTickMultipleExpiredDepositPeriod(t *testing.T) { 68 input := getMockApp(t, 10, GenesisState{}, nil, ProposalHandler) 69 70 header := abci.Header{Height: input.mApp.LastBlockHeight() + 1} 71 input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) 72 73 ctx := input.mApp.BaseApp.NewContext(false, abci.Header{}) 74 govHandler := NewHandler(input.keeper) 75 76 inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 77 require.False(t, inactiveQueue.Valid()) 78 inactiveQueue.Close() 79 80 newProposalMsg := NewMsgSubmitProposal( 81 ContentFromProposalType("test", "test", ProposalTypeText), 82 sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, 83 input.addrs[0], 84 ) 85 86 res, err := govHandler(ctx, newProposalMsg) 87 require.NoError(t, err) 88 require.NotNil(t, res) 89 90 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 91 require.False(t, inactiveQueue.Valid()) 92 inactiveQueue.Close() 93 94 newHeader := ctx.BlockHeader() 95 newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(2) * time.Second) 96 ctx.SetBlockHeader(newHeader) 97 98 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 99 require.False(t, inactiveQueue.Valid()) 100 inactiveQueue.Close() 101 102 newProposalMsg2 := NewMsgSubmitProposal( 103 ContentFromProposalType("test2", "test2", ProposalTypeText), 104 sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, 105 input.addrs[0], 106 ) 107 108 res, err = govHandler(ctx, newProposalMsg2) 109 require.NoError(t, err) 110 require.NotNil(t, res) 111 112 newHeader = ctx.BlockHeader() 113 newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second) 114 ctx.SetBlockHeader(newHeader) 115 116 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 117 require.True(t, inactiveQueue.Valid()) 118 inactiveQueue.Close() 119 EndBlocker(ctx, input.keeper) 120 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 121 require.False(t, inactiveQueue.Valid()) 122 inactiveQueue.Close() 123 124 newHeader = ctx.BlockHeader() 125 newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(5) * time.Second) 126 ctx.SetBlockHeader(newHeader) 127 128 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 129 require.True(t, inactiveQueue.Valid()) 130 inactiveQueue.Close() 131 EndBlocker(ctx, input.keeper) 132 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 133 require.False(t, inactiveQueue.Valid()) 134 inactiveQueue.Close() 135 } 136 137 func TestTickPassedDepositPeriod(t *testing.T) { 138 input := getMockApp(t, 10, GenesisState{}, nil, ProposalHandler) 139 140 header := abci.Header{Height: input.mApp.LastBlockHeight() + 1} 141 input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) 142 143 ctx := input.mApp.BaseApp.NewContext(false, abci.Header{}) 144 govHandler := NewHandler(input.keeper) 145 146 inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 147 require.False(t, inactiveQueue.Valid()) 148 inactiveQueue.Close() 149 activeQueue := input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 150 require.False(t, activeQueue.Valid()) 151 activeQueue.Close() 152 153 newProposalMsg := NewMsgSubmitProposal( 154 ContentFromProposalType("test2", "test2", ProposalTypeText), 155 sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}, 156 input.addrs[0], 157 ) 158 159 res, err := govHandler(ctx, newProposalMsg) 160 require.NoError(t, err) 161 require.NotNil(t, res) 162 163 proposalID := GetProposalIDFromBytes(res.Data) 164 165 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 166 require.False(t, inactiveQueue.Valid()) 167 inactiveQueue.Close() 168 169 newHeader := ctx.BlockHeader() 170 newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) 171 ctx.SetBlockHeader(newHeader) 172 173 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 174 require.False(t, inactiveQueue.Valid()) 175 inactiveQueue.Close() 176 177 newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)}) 178 179 res, err = govHandler(ctx, newDepositMsg) 180 require.NoError(t, err) 181 require.NotNil(t, res) 182 183 activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 184 require.False(t, activeQueue.Valid()) 185 activeQueue.Close() 186 } 187 188 func TestTickPassedVotingPeriod(t *testing.T) { 189 input := getMockApp(t, 10, GenesisState{}, nil, ProposalHandler) 190 SortAddresses(input.addrs) 191 192 header := abci.Header{Height: input.mApp.LastBlockHeight() + 1} 193 input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) 194 195 ctx := input.mApp.BaseApp.NewContext(false, abci.Header{}) 196 govHandler := NewHandler(input.keeper) 197 198 inactiveQueue := input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 199 require.False(t, inactiveQueue.Valid()) 200 inactiveQueue.Close() 201 activeQueue := input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 202 require.False(t, activeQueue.Valid()) 203 activeQueue.Close() 204 205 proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(5))} 206 newProposalMsg := NewMsgSubmitProposal(keep.TestProposal, proposalCoins, input.addrs[0]) 207 208 res, err := govHandler(ctx, newProposalMsg) 209 require.NoError(t, err) 210 require.NotNil(t, res) 211 212 proposalID := GetProposalIDFromBytes(res.Data) 213 214 newHeader := ctx.BlockHeader() 215 newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second) 216 ctx.SetBlockHeader(newHeader) 217 218 newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, proposalCoins) 219 220 res, err = govHandler(ctx, newDepositMsg) 221 require.NoError(t, err) 222 require.NotNil(t, res) 223 224 newHeader = ctx.BlockHeader() 225 newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod) 226 ctx.SetBlockHeader(newHeader) 227 228 inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 229 require.False(t, inactiveQueue.Valid()) 230 inactiveQueue.Close() 231 232 activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 233 require.True(t, activeQueue.Valid()) 234 235 activeProposalID := GetProposalIDFromBytes(activeQueue.Value()) 236 proposal, ok := input.keeper.GetProposal(ctx, activeProposalID) 237 require.True(t, ok) 238 require.Equal(t, StatusVotingPeriod, proposal.Status) 239 240 activeQueue.Close() 241 242 EndBlocker(ctx, input.keeper) 243 244 activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) 245 require.False(t, activeQueue.Valid()) 246 activeQueue.Close() 247 } 248 249 func TestProposalPassedEndblocker(t *testing.T) { 250 input := getMockApp(t, 1, GenesisState{}, nil, ProposalHandler) 251 SortAddresses(input.addrs) 252 253 handler := NewHandler(input.keeper) 254 stakingHandler := staking.NewHandler(input.sk) 255 256 header := abci.Header{Height: input.mApp.LastBlockHeight() + 1} 257 input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) 258 ctx := input.mApp.BaseApp.NewContext(false, abci.Header{}) 259 260 valAddr := sdk.ValAddress(input.addrs[0]) 261 262 createValidators(t, stakingHandler, ctx, []sdk.ValAddress{valAddr}, []int64{10}) 263 staking.EndBlocker(ctx, input.sk) 264 265 macc := input.keeper.GetGovernanceAccount(ctx) 266 require.NotNil(t, macc) 267 initialModuleAccCoins := macc.GetCoins() 268 269 proposal, err := input.keeper.SubmitProposal(ctx, keep.TestProposal) 270 require.NoError(t, err) 271 272 proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))} 273 newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins) 274 275 res, err := handler(ctx, newDepositMsg) 276 require.NoError(t, err) 277 require.NotNil(t, res) 278 279 macc = input.keeper.GetGovernanceAccount(ctx) 280 require.NotNil(t, macc) 281 moduleAccCoins := macc.GetCoins() 282 283 deposits := initialModuleAccCoins.Add(proposal.TotalDeposit...).Add(proposalCoins...) 284 require.True(t, moduleAccCoins.IsEqual(deposits)) 285 286 err = input.keeper.AddVote(ctx, proposal.ProposalID, input.addrs[0], OptionYes) 287 require.NoError(t, err) 288 289 newHeader := ctx.BlockHeader() 290 newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod) 291 ctx.SetBlockHeader(newHeader) 292 293 EndBlocker(ctx, input.keeper) 294 295 macc = input.keeper.GetGovernanceAccount(ctx) 296 require.NotNil(t, macc) 297 require.True(t, macc.GetCoins().IsEqual(initialModuleAccCoins)) 298 } 299 300 func TestEndBlockerProposalHandlerFailed(t *testing.T) { 301 // hijack the router to one that will fail in a proposal's handler 302 input := getMockApp(t, 1, GenesisState{}, nil, badProposalHandler) 303 SortAddresses(input.addrs) 304 305 handler := NewHandler(input.keeper) 306 stakingHandler := staking.NewHandler(input.sk) 307 308 header := abci.Header{Height: input.mApp.LastBlockHeight() + 1} 309 input.mApp.BeginBlock(abci.RequestBeginBlock{Header: header}) 310 ctx := input.mApp.BaseApp.NewContext(false, abci.Header{}) 311 312 valAddr := sdk.ValAddress(input.addrs[0]) 313 314 createValidators(t, stakingHandler, ctx, []sdk.ValAddress{valAddr}, []int64{10}) 315 staking.EndBlocker(ctx, input.sk) 316 317 // Create a proposal where the handler will pass for the test proposal 318 // because the value of contextKeyBadProposal is true. 319 ctx.SetContext(context.WithValue(ctx.Context(), contextKeyBadProposal, true)) 320 proposal, err := input.keeper.SubmitProposal(ctx, keep.TestProposal) 321 require.NoError(t, err) 322 323 proposalCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))) 324 newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins) 325 326 res, err := handler(ctx, newDepositMsg) 327 require.NoError(t, err) 328 require.NotNil(t, res) 329 330 err = input.keeper.AddVote(ctx, proposal.ProposalID, input.addrs[0], OptionYes) 331 require.NoError(t, err) 332 333 newHeader := ctx.BlockHeader() 334 newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod) 335 ctx.SetBlockHeader(newHeader) 336 337 // Set the contextKeyBadProposal value to false so that the handler will fail 338 // during the processing of the proposal in the EndBlocker. 339 ctx.SetContext(context.WithValue(ctx.Context(), contextKeyBadProposal, false)) 340 341 // validate that the proposal fails/has been rejected 342 EndBlocker(ctx, input.keeper) 343 }