github.com/Finschia/finschia-sdk@v0.48.1/x/gov/client/utils/query_test.go (about) 1 package utils_test 2 3 import ( 4 "context" 5 "regexp" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 10 "github.com/Finschia/ostracon/rpc/client/mock" 11 ctypes "github.com/Finschia/ostracon/rpc/core/types" 12 octypes "github.com/Finschia/ostracon/types" 13 14 "github.com/Finschia/finschia-sdk/client" 15 "github.com/Finschia/finschia-sdk/simapp" 16 sdk "github.com/Finschia/finschia-sdk/types" 17 "github.com/Finschia/finschia-sdk/x/auth/legacy/legacytx" 18 "github.com/Finschia/finschia-sdk/x/gov/client/utils" 19 "github.com/Finschia/finschia-sdk/x/gov/types" 20 ) 21 22 type TxSearchMock struct { 23 txConfig client.TxConfig 24 mock.Client 25 txs []octypes.Tx 26 } 27 28 func (mock TxSearchMock) TxSearch(ctx context.Context, query string, prove bool, page, perPage *int, orderBy string) (*ctypes.ResultTxSearch, error) { 29 if page == nil { 30 *page = 0 31 } 32 33 if perPage == nil { 34 *perPage = 0 35 } 36 37 // Get the `message.action` value from the query. 38 messageAction := regexp.MustCompile(`message\.action='(.*)' .*$`) 39 msgType := messageAction.FindStringSubmatch(query)[1] 40 41 // Filter only the txs that match the query 42 matchingTxs := make([]octypes.Tx, 0) 43 for _, tx := range mock.txs { 44 sdkTx, err := mock.txConfig.TxDecoder()(tx) 45 if err != nil { 46 return nil, err 47 } 48 for _, msg := range sdkTx.GetMsgs() { 49 if msg.(legacytx.LegacyMsg).Type() == msgType { 50 matchingTxs = append(matchingTxs, tx) 51 break 52 } 53 } 54 } 55 56 start, end := client.Paginate(len(mock.txs), *page, *perPage, 100) 57 if start < 0 || end < 0 { 58 // nil result with nil error crashes utils.QueryTxsByEvents 59 return &ctypes.ResultTxSearch{}, nil 60 } 61 if len(matchingTxs) < end { 62 return &ctypes.ResultTxSearch{}, nil 63 } 64 65 txs := matchingTxs[start:end] 66 rst := &ctypes.ResultTxSearch{Txs: make([]*ctypes.ResultTx, len(txs)), TotalCount: len(txs)} 67 for i := range txs { 68 rst.Txs[i] = &ctypes.ResultTx{Tx: txs[i]} 69 } 70 return rst, nil 71 } 72 73 func (mock TxSearchMock) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) { 74 // any non nil Block needs to be returned. used to get time value 75 return &ctypes.ResultBlock{Block: &octypes.Block{}}, nil 76 } 77 78 func TestGetPaginatedVotes(t *testing.T) { 79 encCfg := simapp.MakeTestEncodingConfig() 80 81 type testCase struct { 82 description string 83 page, limit int 84 msgs [][]sdk.Msg 85 votes []types.Vote 86 } 87 acc1 := make(sdk.AccAddress, 20) 88 acc1[0] = 1 89 acc2 := make(sdk.AccAddress, 20) 90 acc2[0] = 2 91 acc1Msgs := []sdk.Msg{ 92 types.NewMsgVote(acc1, 0, types.OptionYes), 93 types.NewMsgVote(acc1, 0, types.OptionYes), 94 } 95 acc2Msgs := []sdk.Msg{ 96 types.NewMsgVote(acc2, 0, types.OptionYes), 97 types.NewMsgVoteWeighted(acc2, 0, types.NewNonSplitVoteOption(types.OptionYes)), 98 } 99 for _, tc := range []testCase{ 100 { 101 description: "1MsgPerTxAll", 102 page: 1, 103 limit: 2, 104 msgs: [][]sdk.Msg{ 105 acc1Msgs[:1], 106 acc2Msgs[:1], 107 }, 108 votes: []types.Vote{ 109 types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes)), 110 types.NewVote(0, acc2, types.NewNonSplitVoteOption(types.OptionYes)), 111 }, 112 }, 113 { 114 description: "2MsgPerTx1Chunk", 115 page: 1, 116 limit: 2, 117 msgs: [][]sdk.Msg{ 118 acc1Msgs, 119 acc2Msgs, 120 }, 121 votes: []types.Vote{ 122 types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes)), 123 types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes)), 124 }, 125 }, 126 { 127 description: "2MsgPerTx2Chunk", 128 page: 2, 129 limit: 2, 130 msgs: [][]sdk.Msg{ 131 acc1Msgs, 132 acc2Msgs, 133 }, 134 votes: []types.Vote{ 135 types.NewVote(0, acc2, types.NewNonSplitVoteOption(types.OptionYes)), 136 types.NewVote(0, acc2, types.NewNonSplitVoteOption(types.OptionYes)), 137 }, 138 }, 139 { 140 description: "IncompleteSearchTx", 141 page: 1, 142 limit: 2, 143 msgs: [][]sdk.Msg{ 144 acc1Msgs[:1], 145 }, 146 votes: []types.Vote{types.NewVote(0, acc1, types.NewNonSplitVoteOption(types.OptionYes))}, 147 }, 148 { 149 description: "InvalidPage", 150 page: -1, 151 msgs: [][]sdk.Msg{ 152 acc1Msgs[:1], 153 }, 154 }, 155 { 156 description: "OutOfBounds", 157 page: 2, 158 limit: 10, 159 msgs: [][]sdk.Msg{ 160 acc1Msgs[:1], 161 }, 162 }, 163 } { 164 tc := tc 165 166 t.Run(tc.description, func(t *testing.T) { 167 marshalled := make([]octypes.Tx, len(tc.msgs)) 168 cli := TxSearchMock{txs: marshalled, txConfig: encCfg.TxConfig} 169 clientCtx := client.Context{}. 170 WithLegacyAmino(encCfg.Amino). 171 WithClient(cli). 172 WithTxConfig(encCfg.TxConfig) 173 174 for i := range tc.msgs { 175 txBuilder := clientCtx.TxConfig.NewTxBuilder() 176 err := txBuilder.SetMsgs(tc.msgs[i]...) 177 require.NoError(t, err) 178 179 tx, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) 180 require.NoError(t, err) 181 marshalled[i] = tx 182 } 183 184 params := types.NewQueryProposalVotesParams(0, tc.page, tc.limit) 185 votesData, err := utils.QueryVotesByTxQuery(clientCtx, params) 186 require.NoError(t, err) 187 votes := []types.Vote{} 188 require.NoError(t, clientCtx.LegacyAmino.UnmarshalJSON(votesData, &votes)) 189 require.Equal(t, len(tc.votes), len(votes)) 190 for i := range votes { 191 require.Equal(t, tc.votes[i], votes[i]) 192 } 193 }) 194 } 195 }