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