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  }