github.com/cosmos/cosmos-sdk@v0.50.10/x/distribution/client/cli/tx_test.go (about) 1 package cli_test 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "testing" 8 9 abci "github.com/cometbft/cometbft/abci/types" 10 rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" 11 "github.com/cosmos/gogoproto/proto" 12 "github.com/stretchr/testify/suite" 13 14 sdkmath "cosmossdk.io/math" 15 16 "github.com/cosmos/cosmos-sdk/client" 17 "github.com/cosmos/cosmos-sdk/client/flags" 18 "github.com/cosmos/cosmos-sdk/codec/address" 19 "github.com/cosmos/cosmos-sdk/crypto/keyring" 20 svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 21 "github.com/cosmos/cosmos-sdk/testutil" 22 clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" 23 "github.com/cosmos/cosmos-sdk/testutil/network" 24 sdk "github.com/cosmos/cosmos-sdk/types" 25 testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" 26 "github.com/cosmos/cosmos-sdk/x/bank" 27 "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" 28 distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil" 29 "github.com/cosmos/cosmos-sdk/x/gov" 30 minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" 31 ) 32 33 type CLITestSuite struct { 34 suite.Suite 35 36 kr keyring.Keyring 37 encCfg testutilmod.TestEncodingConfig 38 baseCtx client.Context 39 clientCtx client.Context 40 } 41 42 func TestCLITestSuite(t *testing.T) { 43 suite.Run(t, new(CLITestSuite)) 44 } 45 46 func (s *CLITestSuite) SetupSuite() { 47 s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{}, bank.AppModuleBasic{}) 48 s.kr = keyring.NewInMemory(s.encCfg.Codec) 49 s.baseCtx = client.Context{}. 50 WithKeyring(s.kr). 51 WithTxConfig(s.encCfg.TxConfig). 52 WithCodec(s.encCfg.Codec). 53 WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}). 54 WithAccountRetriever(client.MockAccountRetriever{}). 55 WithOutput(io.Discard). 56 WithChainID("test-chain") 57 58 ctxGen := func() client.Context { 59 bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) 60 c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ 61 Value: bz, 62 }) 63 return s.baseCtx.WithClient(c) 64 } 65 s.clientCtx = ctxGen() 66 67 cfg, err := network.DefaultConfigWithAppConfig(distrtestutil.AppConfig) 68 s.Require().NoError(err) 69 70 genesisState := cfg.GenesisState 71 var mintData minttypes.GenesisState 72 s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) 73 74 inflation := sdkmath.LegacyMustNewDecFromStr("1.0") 75 mintData.Minter.Inflation = inflation 76 mintData.Params.InflationMin = inflation 77 mintData.Params.InflationMax = inflation 78 79 mintDataBz, err := cfg.Codec.MarshalJSON(&mintData) 80 s.Require().NoError(err) 81 genesisState[minttypes.ModuleName] = mintDataBz 82 cfg.GenesisState = genesisState 83 } 84 85 func (s *CLITestSuite) TestTxWithdrawRewardsCmd() { 86 val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 87 88 testCases := []struct { 89 name string 90 valAddr fmt.Stringer 91 args []string 92 expectErrMsg string 93 }{ 94 { 95 "invalid validator address", 96 val[0].Address, 97 []string{ 98 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 99 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 100 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 101 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 102 }, 103 "hrp does not match bech32 prefix", 104 }, 105 { 106 "valid transaction", 107 sdk.ValAddress(val[0].Address), 108 []string{ 109 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 110 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 111 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 112 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 113 }, 114 "", 115 }, 116 { 117 "valid transaction (with commission)", 118 sdk.ValAddress(val[0].Address), 119 []string{ 120 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 121 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 122 fmt.Sprintf("--%s=true", cli.FlagCommission), 123 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 124 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 125 }, 126 "", 127 }, 128 } 129 130 for _, tc := range testCases { 131 tc := tc 132 133 s.Run(tc.name, func() { 134 args := append([]string{tc.valAddr.String()}, tc.args...) 135 136 ctx := svrcmd.CreateExecuteContext(context.Background()) 137 cmd := cli.NewWithdrawRewardsCmd(address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) 138 cmd.SetContext(ctx) 139 cmd.SetArgs(args) 140 s.Require().NoError(client.SetCmdClientContextHandler(s.clientCtx, cmd)) 141 142 out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args) 143 if tc.expectErrMsg != "" { 144 s.Require().Error(err) 145 s.Require().Contains(err.Error(), tc.expectErrMsg) 146 } else { 147 s.Require().NoError(err) 148 msg := &sdk.TxResponse{} 149 s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 150 } 151 }) 152 } 153 } 154 155 func (s *CLITestSuite) TestTxWithdrawAllRewardsCmd() { 156 val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 157 158 testCases := []struct { 159 name string 160 args []string 161 expectErrMsg string 162 }{ 163 { 164 "invalid transaction (offline)", 165 []string{ 166 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 167 fmt.Sprintf("--%s=true", flags.FlagOffline), 168 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 169 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 170 }, 171 "cannot generate tx in offline mode", 172 }, 173 { 174 "valid transaction", 175 []string{ 176 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 177 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 178 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 179 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 180 }, 181 "", 182 }, 183 } 184 185 for _, tc := range testCases { 186 tc := tc 187 188 s.Run(tc.name, func() { 189 cmd := cli.NewWithdrawAllRewardsCmd(address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) 190 191 out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) 192 if tc.expectErrMsg != "" { 193 s.Require().Error(err) 194 s.Require().Contains(err.Error(), tc.expectErrMsg) 195 } else { 196 s.Require().NoError(err) 197 msg := &sdk.TxResponse{} 198 s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 199 } 200 }) 201 } 202 } 203 204 func (s *CLITestSuite) TestTxSetWithdrawAddrCmd() { 205 val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 206 207 testCases := []struct { 208 name string 209 args []string 210 expectErr bool 211 respType proto.Message 212 }{ 213 { 214 "invalid withdraw address", 215 []string{ 216 "foo", 217 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 218 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 219 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 220 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 221 }, 222 true, nil, 223 }, 224 { 225 "valid transaction", 226 []string{ 227 val[0].Address.String(), 228 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 229 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 230 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 231 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 232 }, 233 false, &sdk.TxResponse{}, 234 }, 235 } 236 237 for _, tc := range testCases { 238 tc := tc 239 240 s.Run(tc.name, func() { 241 cmd := cli.NewSetWithdrawAddrCmd(address.NewBech32Codec("cosmos")) 242 243 out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) 244 if tc.expectErr { 245 s.Require().Error(err) 246 } else { 247 s.Require().NoError(err) 248 s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) 249 } 250 }) 251 } 252 } 253 254 func (s *CLITestSuite) TestTxFundCommunityPoolCmd() { 255 val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 256 257 testCases := []struct { 258 name string 259 args []string 260 expectErr bool 261 respType proto.Message 262 }{ 263 { 264 "invalid funding amount", 265 []string{ 266 "-43foocoin", 267 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 268 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 269 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 270 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 271 }, 272 true, nil, 273 }, 274 { 275 "valid transaction", 276 []string{ 277 sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(5431))).String(), 278 fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()), 279 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 280 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 281 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 282 }, 283 false, &sdk.TxResponse{}, 284 }, 285 } 286 287 for _, tc := range testCases { 288 tc := tc 289 290 s.Run(tc.name, func() { 291 cmd := cli.NewFundCommunityPoolCmd(address.NewBech32Codec("cosmos")) 292 293 out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) 294 if tc.expectErr { 295 s.Require().Error(err) 296 } else { 297 s.Require().NoError(err) 298 s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) 299 } 300 }) 301 } 302 }