github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/gov/keeper/querier_test.go (about) 1 package keeper 2 3 import ( 4 "math/rand" 5 "strings" 6 "testing" 7 "time" 8 9 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 10 "github.com/stretchr/testify/require" 11 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 13 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 14 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/types" 15 ) 16 17 const custom = "custom" 18 19 func getQueriedParams(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier) (types.DepositParams, types.VotingParams, types.TallyParams) { 20 query := abci.RequestQuery{ 21 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryParams, types.ParamDeposit}, "/"), 22 Data: []byte{}, 23 } 24 25 bz, err := querier(ctx, []string{types.QueryParams, types.ParamDeposit}, query) 26 require.NoError(t, err) 27 require.NotNil(t, bz) 28 29 var depositParams types.DepositParams 30 require.NoError(t, cdc.UnmarshalJSON(bz, &depositParams)) 31 32 query = abci.RequestQuery{ 33 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryParams, types.ParamVoting}, "/"), 34 Data: []byte{}, 35 } 36 37 bz, err = querier(ctx, []string{types.QueryParams, types.ParamVoting}, query) 38 require.NoError(t, err) 39 require.NotNil(t, bz) 40 41 var votingParams types.VotingParams 42 require.NoError(t, cdc.UnmarshalJSON(bz, &votingParams)) 43 44 query = abci.RequestQuery{ 45 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryParams, types.ParamTallying}, "/"), 46 Data: []byte{}, 47 } 48 49 bz, err = querier(ctx, []string{types.QueryParams, types.ParamTallying}, query) 50 require.NoError(t, err) 51 require.NotNil(t, bz) 52 53 var tallyParams types.TallyParams 54 require.NoError(t, cdc.UnmarshalJSON(bz, &tallyParams)) 55 56 return depositParams, votingParams, tallyParams 57 } 58 59 func getQueriedProposals( 60 t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, 61 depositor, voter sdk.AccAddress, status types.ProposalStatus, page, limit int, 62 ) []types.Proposal { 63 64 query := abci.RequestQuery{ 65 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryProposals}, "/"), 66 Data: cdc.MustMarshalJSON(types.NewQueryProposalsParams(page, limit, status, voter, depositor)), 67 } 68 69 bz, err := querier(ctx, []string{types.QueryProposals}, query) 70 require.NoError(t, err) 71 require.NotNil(t, bz) 72 73 var proposals types.Proposals 74 require.NoError(t, cdc.UnmarshalJSON(bz, &proposals)) 75 76 return proposals 77 } 78 79 func getQueriedDeposit(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64, depositor sdk.AccAddress) types.Deposit { 80 query := abci.RequestQuery{ 81 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryDeposit}, "/"), 82 Data: cdc.MustMarshalJSON(types.NewQueryDepositParams(proposalID, depositor)), 83 } 84 85 bz, err := querier(ctx, []string{types.QueryDeposit}, query) 86 require.NoError(t, err) 87 require.NotNil(t, bz) 88 89 var deposit types.Deposit 90 require.NoError(t, cdc.UnmarshalJSON(bz, &deposit)) 91 92 return deposit 93 } 94 95 func getQueriedDeposits(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64) []types.Deposit { 96 query := abci.RequestQuery{ 97 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryDeposits}, "/"), 98 Data: cdc.MustMarshalJSON(types.NewQueryProposalParams(proposalID)), 99 } 100 101 bz, err := querier(ctx, []string{types.QueryDeposits}, query) 102 require.NoError(t, err) 103 require.NotNil(t, bz) 104 105 var deposits []types.Deposit 106 require.NoError(t, cdc.UnmarshalJSON(bz, &deposits)) 107 108 return deposits 109 } 110 111 func getQueriedVote(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64, voter sdk.AccAddress) types.Vote { 112 query := abci.RequestQuery{ 113 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryVote}, "/"), 114 Data: cdc.MustMarshalJSON(types.NewQueryVoteParams(proposalID, voter)), 115 } 116 117 bz, err := querier(ctx, []string{types.QueryVote}, query) 118 require.NoError(t, err) 119 require.NotNil(t, bz) 120 121 var vote types.Vote 122 require.NoError(t, cdc.UnmarshalJSON(bz, &vote)) 123 124 return vote 125 } 126 127 func getQueriedVotes(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, 128 proposalID uint64, page, limit int) []types.Vote { 129 query := abci.RequestQuery{ 130 Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryVote}, "/"), 131 Data: cdc.MustMarshalJSON(types.NewQueryProposalVotesParams(proposalID, page, limit)), 132 } 133 134 bz, err := querier(ctx, []string{types.QueryVotes}, query) 135 require.NoError(t, err) 136 require.NotNil(t, bz) 137 138 var votes []types.Vote 139 require.NoError(t, cdc.UnmarshalJSON(bz, &votes)) 140 141 return votes 142 } 143 144 func TestQueries(t *testing.T) { 145 ctx, _, keeper, _, _ := createTestInput(t, false, 1000) 146 querier := NewQuerier(keeper) 147 148 oneCoins := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1)) 149 consCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))) 150 151 tp := TestProposal 152 153 depositParams, _, _ := getQueriedParams(t, ctx, keeper.cdc, querier) 154 155 // TestAddrs[0] proposes (and deposits) proposals #1 and #2 156 proposal1, err := keeper.SubmitProposal(ctx, tp) 157 require.NoError(t, err) 158 deposit1 := types.NewDeposit(proposal1.ProposalID, TestAddrs[0], oneCoins) 159 _, err = keeper.AddDeposit(ctx, deposit1.ProposalID, deposit1.Depositor, deposit1.Amount) 160 require.NoError(t, err) 161 162 proposal1.TotalDeposit = proposal1.TotalDeposit.Add(deposit1.Amount...) 163 164 proposal2, err := keeper.SubmitProposal(ctx, tp) 165 require.NoError(t, err) 166 deposit2 := types.NewDeposit(proposal2.ProposalID, TestAddrs[0], consCoins) 167 _, err = keeper.AddDeposit(ctx, deposit2.ProposalID, deposit2.Depositor, deposit2.Amount) 168 require.NoError(t, err) 169 170 proposal2.TotalDeposit = proposal2.TotalDeposit.Add(deposit2.Amount...) 171 172 // TestAddrs[1] proposes (and deposits) on proposal #3 173 proposal3, err := keeper.SubmitProposal(ctx, tp) 174 require.NoError(t, err) 175 deposit3 := types.NewDeposit(proposal3.ProposalID, TestAddrs[1], oneCoins) 176 _, err = keeper.AddDeposit(ctx, deposit3.ProposalID, deposit3.Depositor, deposit3.Amount) 177 require.NoError(t, err) 178 179 proposal3.TotalDeposit = proposal3.TotalDeposit.Add(deposit3.Amount...) 180 181 // TestAddrs[1] deposits on proposals #2 & #3 182 deposit4 := types.NewDeposit(proposal2.ProposalID, TestAddrs[1], depositParams.MinDeposit) 183 _, err = keeper.AddDeposit(ctx, deposit4.ProposalID, deposit4.Depositor, deposit4.Amount) 184 require.NoError(t, err) 185 186 proposal2.TotalDeposit = proposal2.TotalDeposit.Add(deposit4.Amount...) 187 proposal2.Status = types.StatusVotingPeriod 188 proposal2.VotingEndTime = proposal2.VotingEndTime.Add(types.DefaultPeriod) 189 190 deposit5 := types.NewDeposit(proposal3.ProposalID, TestAddrs[1], depositParams.MinDeposit) 191 _, err = keeper.AddDeposit(ctx, deposit5.ProposalID, deposit5.Depositor, deposit5.Amount) 192 require.NoError(t, err) 193 194 proposal3.TotalDeposit = proposal3.TotalDeposit.Add(deposit5.Amount...) 195 proposal3.Status = types.StatusVotingPeriod 196 proposal3.VotingEndTime = proposal3.VotingEndTime.Add(types.DefaultPeriod) 197 // total deposit of TestAddrs[1] on proposal #3 is worth the proposal deposit + individual deposit 198 deposit5.Amount = deposit5.Amount.Add(deposit3.Amount...) 199 200 // check deposits on proposal1 match individual deposits 201 deposits := getQueriedDeposits(t, ctx, keeper.cdc, querier, proposal1.ProposalID) 202 require.Len(t, deposits, 1) 203 require.Equal(t, deposit1, deposits[0]) 204 205 deposit := getQueriedDeposit(t, ctx, keeper.cdc, querier, proposal1.ProposalID, TestAddrs[0]) 206 require.Equal(t, deposit1, deposit) 207 208 // check deposits on proposal2 match individual deposits 209 deposits = getQueriedDeposits(t, ctx, keeper.cdc, querier, proposal2.ProposalID) 210 require.Len(t, deposits, 2) 211 // NOTE order of deposits is determined by the addresses 212 require.Equal(t, deposit2, deposits[0]) 213 require.Equal(t, deposit4, deposits[1]) 214 215 // check deposits on proposal3 match individual deposits 216 deposits = getQueriedDeposits(t, ctx, keeper.cdc, querier, proposal3.ProposalID) 217 require.Len(t, deposits, 1) 218 require.Equal(t, deposit5, deposits[0]) 219 220 deposit = getQueriedDeposit(t, ctx, keeper.cdc, querier, proposal3.ProposalID, TestAddrs[1]) 221 require.Equal(t, deposit5, deposit) 222 223 // Only proposal #1 should be in types.Deposit Period 224 proposals := getQueriedProposals(t, ctx, keeper.cdc, querier, nil, nil, types.StatusDepositPeriod, 1, 0) 225 require.Len(t, proposals, 1) 226 require.Equal(t, proposal1, proposals[0]) 227 228 // Only proposals #2 and #3 should be in Voting Period 229 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, nil, nil, types.StatusVotingPeriod, 1, 0) 230 require.Len(t, proposals, 2) 231 require.Equal(t, proposal2, proposals[0]) 232 require.Equal(t, proposal3, proposals[1]) 233 234 // Addrs[0] votes on proposals #2 & #3 235 vote1 := types.NewVote(proposal2.ProposalID, TestAddrs[0], types.OptionYes) 236 vote2 := types.NewVote(proposal3.ProposalID, TestAddrs[0], types.OptionYes) 237 keeper.SetVote(ctx, vote1) 238 keeper.SetVote(ctx, vote2) 239 240 // Addrs[1] votes on proposal #3 241 vote3 := types.NewVote(proposal3.ProposalID, TestAddrs[1], types.OptionYes) 242 keeper.SetVote(ctx, vote3) 243 244 // Test query voted by TestAddrs[0] 245 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, nil, TestAddrs[0], types.StatusNil, 1, 0) 246 require.Equal(t, proposal2, proposals[0]) 247 require.Equal(t, proposal3, proposals[1]) 248 249 // Test query votes on types.Proposal 2 250 votes := getQueriedVotes(t, ctx, keeper.cdc, querier, proposal2.ProposalID, 1, 0) 251 require.Len(t, votes, 1) 252 require.Equal(t, vote1, votes[0]) 253 254 vote := getQueriedVote(t, ctx, keeper.cdc, querier, proposal2.ProposalID, TestAddrs[0]) 255 require.Equal(t, vote1, vote) 256 257 // Test query votes on types.Proposal 3 258 votes = getQueriedVotes(t, ctx, keeper.cdc, querier, proposal3.ProposalID, 1, 0) 259 require.Len(t, votes, 2) 260 require.Equal(t, vote2, votes[0]) 261 require.Equal(t, vote3, votes[1]) 262 263 // Test query all proposals 264 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, nil, nil, types.StatusNil, 1, 0) 265 require.Equal(t, proposal1, proposals[0]) 266 require.Equal(t, proposal2, proposals[1]) 267 require.Equal(t, proposal3, proposals[2]) 268 269 // Test query voted by TestAddrs[1] 270 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, nil, TestAddrs[1], types.StatusNil, 1, 0) 271 require.Equal(t, proposal3.ProposalID, proposals[0].ProposalID) 272 273 // Test query deposited by TestAddrs[0] 274 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, TestAddrs[0], nil, types.StatusNil, 1, 0) 275 require.Equal(t, proposal1.ProposalID, proposals[0].ProposalID) 276 277 // Test query deposited by addr2 278 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, TestAddrs[1], nil, types.StatusNil, 1, 0) 279 require.Equal(t, proposal2.ProposalID, proposals[0].ProposalID) 280 require.Equal(t, proposal3.ProposalID, proposals[1].ProposalID) 281 282 // Test query voted AND deposited by addr1 283 proposals = getQueriedProposals(t, ctx, keeper.cdc, querier, TestAddrs[0], TestAddrs[0], types.StatusNil, 1, 0) 284 require.Equal(t, proposal2.ProposalID, proposals[0].ProposalID) 285 } 286 287 func TestPaginatedVotesQuery(t *testing.T) { 288 ctx, _, keeper, _, _ := createTestInput(t, false, 1000) 289 290 proposal := types.Proposal{ 291 ProposalID: 100, 292 Status: types.StatusVotingPeriod, 293 } 294 keeper.SetProposal(ctx, proposal) 295 296 votes := make([]types.Vote, 20) 297 rand := rand.New(rand.NewSource(time.Now().UnixNano())) 298 addr := make(sdk.AccAddress, 20) 299 for i := range votes { 300 rand.Read(addr) 301 vote := types.Vote{ 302 ProposalID: proposal.ProposalID, 303 Voter: addr, 304 Option: types.OptionYes, 305 } 306 votes[i] = vote 307 keeper.SetVote(ctx, vote) 308 } 309 310 querier := NewQuerier(keeper) 311 312 // keeper preserves consistent order for each query, but this is not the insertion order 313 all := getQueriedVotes(t, ctx, keeper.cdc, querier, proposal.ProposalID, 1, 0) 314 require.Equal(t, len(all), len(votes)) 315 316 type testCase struct { 317 description string 318 page int 319 limit int 320 votes []types.Vote 321 } 322 for _, tc := range []testCase{ 323 { 324 description: "SkipAll", 325 page: 2, 326 limit: len(all), 327 }, 328 { 329 description: "GetFirstChunk", 330 page: 1, 331 limit: 10, 332 votes: all[:10], 333 }, 334 { 335 description: "GetSecondsChunk", 336 page: 2, 337 limit: 10, 338 votes: all[10:], 339 }, 340 { 341 description: "InvalidPage", 342 page: -1, 343 }, 344 } { 345 tc := tc 346 t.Run(tc.description, func(t *testing.T) { 347 votes := getQueriedVotes(t, ctx, keeper.cdc, querier, proposal.ProposalID, tc.page, tc.limit) 348 require.Equal(t, len(tc.votes), len(votes)) 349 for i := range votes { 350 require.Equal(t, tc.votes[i], votes[i]) 351 } 352 }) 353 } 354 }