github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/client/utils/query_test.go (about)

     1  package utils_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/cometbft/cometbft/rpc/client/mock"
     8  	coretypes "github.com/cometbft/cometbft/rpc/core/types"
     9  	cmttypes "github.com/cometbft/cometbft/types"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	sdkmath "cosmossdk.io/math"
    13  
    14  	"github.com/cosmos/cosmos-sdk/client"
    15  	sdk "github.com/cosmos/cosmos-sdk/types"
    16  	moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
    17  	"github.com/cosmos/cosmos-sdk/x/gov"
    18  	"github.com/cosmos/cosmos-sdk/x/gov/client/utils"
    19  	v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
    20  )
    21  
    22  type TxSearchMock struct {
    23  	txConfig client.TxConfig
    24  	mock.Client
    25  	txs []cmttypes.Tx
    26  }
    27  
    28  func (mock TxSearchMock) TxSearch(ctx context.Context, query string, prove bool, page, perPage *int, orderBy string) (*coretypes.ResultTxSearch, error) {
    29  	if page == nil {
    30  		*page = 0
    31  	}
    32  
    33  	if perPage == nil {
    34  		*perPage = 0
    35  	}
    36  
    37  	start, end := client.Paginate(len(mock.txs), *page, *perPage, 100)
    38  	if start < 0 || end < 0 {
    39  		// nil result with nil error crashes utils.QueryTxsByEvents
    40  		return &coretypes.ResultTxSearch{}, nil
    41  	}
    42  
    43  	txs := mock.txs[start:end]
    44  	rst := &coretypes.ResultTxSearch{Txs: make([]*coretypes.ResultTx, len(txs)), TotalCount: len(txs)}
    45  	for i := range txs {
    46  		rst.Txs[i] = &coretypes.ResultTx{Tx: txs[i]}
    47  	}
    48  	return rst, nil
    49  }
    50  
    51  func (mock TxSearchMock) Block(ctx context.Context, height *int64) (*coretypes.ResultBlock, error) {
    52  	// any non nil Block needs to be returned. used to get time value
    53  	return &coretypes.ResultBlock{Block: &cmttypes.Block{}}, nil
    54  }
    55  
    56  func TestGetPaginatedVotes(t *testing.T) {
    57  	encCfg := moduletestutil.MakeTestEncodingConfig(gov.AppModuleBasic{})
    58  
    59  	type testCase struct {
    60  		description string
    61  		page, limit int
    62  		msgs        [][]sdk.Msg
    63  		votes       []v1.Vote
    64  	}
    65  	acc1 := make(sdk.AccAddress, 20)
    66  	acc1[0] = 1
    67  	acc2 := make(sdk.AccAddress, 20)
    68  	acc2[0] = 2
    69  	acc1Msgs := []sdk.Msg{
    70  		v1.NewMsgVote(acc1, 0, v1.OptionYes, ""),
    71  		v1.NewMsgVote(acc1, 0, v1.OptionYes, ""),
    72  		v1.NewMsgDeposit(acc1, 0, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10)))), // should be ignored
    73  	}
    74  	acc2Msgs := []sdk.Msg{
    75  		v1.NewMsgVote(acc2, 0, v1.OptionYes, ""),
    76  		v1.NewMsgVoteWeighted(acc2, 0, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
    77  	}
    78  	for _, tc := range []testCase{
    79  		{
    80  			description: "1MsgPerTxAll",
    81  			page:        1,
    82  			limit:       2,
    83  			msgs: [][]sdk.Msg{
    84  				acc1Msgs[:1],
    85  				acc2Msgs[:1],
    86  			},
    87  			votes: []v1.Vote{
    88  				v1.NewVote(0, acc1, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
    89  				v1.NewVote(0, acc2, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
    90  			},
    91  		},
    92  		{
    93  			description: "2MsgPerTx1Chunk",
    94  			page:        1,
    95  			limit:       2,
    96  			msgs: [][]sdk.Msg{
    97  				acc1Msgs,
    98  				acc2Msgs,
    99  			},
   100  			votes: []v1.Vote{
   101  				v1.NewVote(0, acc1, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
   102  				v1.NewVote(0, acc1, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
   103  			},
   104  		},
   105  		{
   106  			description: "2MsgPerTx2Chunk",
   107  			page:        2,
   108  			limit:       2,
   109  			msgs: [][]sdk.Msg{
   110  				acc1Msgs,
   111  				acc2Msgs,
   112  			},
   113  			votes: []v1.Vote{
   114  				v1.NewVote(0, acc2, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
   115  				v1.NewVote(0, acc2, v1.NewNonSplitVoteOption(v1.OptionYes), ""),
   116  			},
   117  		},
   118  		{
   119  			description: "IncompleteSearchTx",
   120  			page:        1,
   121  			limit:       2,
   122  			msgs: [][]sdk.Msg{
   123  				acc1Msgs[:1],
   124  			},
   125  			votes: []v1.Vote{v1.NewVote(0, acc1, v1.NewNonSplitVoteOption(v1.OptionYes), "")},
   126  		},
   127  		{
   128  			description: "InvalidPage",
   129  			page:        -1,
   130  			msgs: [][]sdk.Msg{
   131  				acc1Msgs[:1],
   132  			},
   133  		},
   134  		{
   135  			description: "OutOfBounds",
   136  			page:        2,
   137  			limit:       10,
   138  			msgs: [][]sdk.Msg{
   139  				acc1Msgs[:1],
   140  			},
   141  		},
   142  	} {
   143  		tc := tc
   144  
   145  		t.Run(tc.description, func(t *testing.T) {
   146  			marshaled := make([]cmttypes.Tx, len(tc.msgs))
   147  			cli := TxSearchMock{txs: marshaled, txConfig: encCfg.TxConfig}
   148  			clientCtx := client.Context{}.
   149  				WithLegacyAmino(encCfg.Amino).
   150  				WithClient(cli).
   151  				WithTxConfig(encCfg.TxConfig)
   152  
   153  			for i := range tc.msgs {
   154  				txBuilder := clientCtx.TxConfig.NewTxBuilder()
   155  				err := txBuilder.SetMsgs(tc.msgs[i]...)
   156  				require.NoError(t, err)
   157  
   158  				tx, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
   159  				require.NoError(t, err)
   160  				marshaled[i] = tx
   161  			}
   162  
   163  			params := v1.NewQueryProposalVotesParams(0, tc.page, tc.limit)
   164  			votesData, err := utils.QueryVotesByTxQuery(clientCtx, params)
   165  			require.NoError(t, err)
   166  			votes := []v1.Vote{}
   167  			require.NoError(t, clientCtx.LegacyAmino.UnmarshalJSON(votesData, &votes))
   168  			require.Equal(t, len(tc.votes), len(votes))
   169  			for i := range votes {
   170  				require.Equal(t, tc.votes[i], votes[i])
   171  			}
   172  		})
   173  	}
   174  }