github.com/cosmos/cosmos-sdk@v0.50.10/x/group/client/cli/tx_test.go (about) 1 package cli_test 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "testing" 9 10 abci "github.com/cometbft/cometbft/abci/types" 11 rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" 12 "github.com/stretchr/testify/suite" 13 14 // without this import amino json encoding will fail when resolving any types 15 _ "cosmossdk.io/api/cosmos/group/v1" 16 sdkmath "cosmossdk.io/math" 17 18 "github.com/cosmos/cosmos-sdk/client" 19 "github.com/cosmos/cosmos-sdk/client/flags" 20 "github.com/cosmos/cosmos-sdk/codec/address" 21 "github.com/cosmos/cosmos-sdk/crypto/hd" 22 "github.com/cosmos/cosmos-sdk/crypto/keyring" 23 svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 24 "github.com/cosmos/cosmos-sdk/testutil" 25 clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" 26 sdk "github.com/cosmos/cosmos-sdk/types" 27 testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" 28 "github.com/cosmos/cosmos-sdk/x/group" 29 groupcli "github.com/cosmos/cosmos-sdk/x/group/client/cli" 30 groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" 31 ) 32 33 var validMetadata = "metadata" 34 35 type CLITestSuite struct { 36 suite.Suite 37 38 kr keyring.Keyring 39 encCfg testutilmod.TestEncodingConfig 40 baseCtx client.Context 41 clientCtx client.Context 42 group *group.GroupInfo 43 commonFlags []string 44 } 45 46 func TestCLITestSuite(t *testing.T) { 47 suite.Run(t, new(CLITestSuite)) 48 } 49 50 func (s *CLITestSuite) SetupSuite() { 51 s.encCfg = testutilmod.MakeTestEncodingConfig(groupmodule.AppModuleBasic{}) 52 s.kr = keyring.NewInMemory(s.encCfg.Codec) 53 s.baseCtx = client.Context{}. 54 WithKeyring(s.kr). 55 WithTxConfig(s.encCfg.TxConfig). 56 WithCodec(s.encCfg.Codec). 57 WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}). 58 WithAccountRetriever(client.MockAccountRetriever{}). 59 WithOutput(io.Discard). 60 WithChainID("test-chain") 61 62 s.commonFlags = []string{ 63 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 64 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 65 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 66 } 67 68 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 69 val := accounts[0] 70 71 ctxGen := func() client.Context { 72 bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) 73 c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ 74 Value: bz, 75 }) 76 return s.baseCtx.WithClient(c) 77 } 78 s.clientCtx = ctxGen() 79 80 // create a new account 81 info, _, err := s.clientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) 82 s.Require().NoError(err) 83 84 pk, err := info.GetPubKey() 85 s.Require().NoError(err) 86 87 account := sdk.AccAddress(pk.Address()) 88 _, err = clitestutil.MsgSendExec( 89 s.clientCtx, 90 val.Address, 91 account, 92 sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(2000))), address.NewBech32Codec("cosmos"), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 93 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), 94 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), 95 ) 96 s.Require().NoError(err) 97 98 // create a group 99 validMembers := fmt.Sprintf(` 100 { 101 "members": [ 102 { 103 "address": "%s", 104 "weight": "3", 105 "metadata": "%s" 106 } 107 ] 108 }`, val.Address.String(), validMetadata) 109 validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) 110 out, err := clitestutil.ExecTestCLICmd(s.clientCtx, groupcli.MsgCreateGroupCmd(), 111 append( 112 []string{ 113 val.Address.String(), 114 validMetadata, 115 validMembersFile.Name(), 116 }, 117 s.commonFlags..., 118 ), 119 ) 120 121 s.Require().NoError(err, out.String()) 122 txResp := sdk.TxResponse{} 123 s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) 124 s.Require().Equal(uint32(0), txResp.Code, out.String()) 125 126 s.group = &group.GroupInfo{Id: 1, Admin: val.Address.String(), Metadata: validMetadata, TotalWeight: "3", Version: 1} 127 } 128 129 func (s *CLITestSuite) TestTxCreateGroup() { 130 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 131 132 cmd := groupcli.MsgCreateGroupCmd() 133 cmd.SetOutput(io.Discard) 134 135 validMembers := fmt.Sprintf(`{"members": [{ 136 "address": "%s", 137 "weight": "1", 138 "metadata": "%s" 139 }]}`, accounts[0].Address.String(), validMetadata) 140 validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) 141 142 invalidMembersWeight := fmt.Sprintf(`{"members": [{ 143 "address": "%s", 144 "weight": "0" 145 }]}`, accounts[0].Address.String()) 146 invalidMembersWeightFile := testutil.WriteToNewTempFile(s.T(), invalidMembersWeight) 147 148 testCases := []struct { 149 name string 150 args []string 151 expCmdOutput string 152 expectErrMsg string 153 }{ 154 { 155 name: "correct data", 156 args: append( 157 []string{ 158 accounts[0].Address.String(), 159 "", 160 validMembersFile.Name(), 161 }, 162 s.commonFlags..., 163 ), 164 expCmdOutput: fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "", validMembersFile.Name()), 165 expectErrMsg: "", 166 }, 167 { 168 "with amino-json", 169 append( 170 []string{ 171 accounts[0].Address.String(), 172 "", 173 validMembersFile.Name(), 174 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 175 }, 176 s.commonFlags..., 177 ), 178 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "", validMembersFile.Name()), 179 "", 180 }, 181 { 182 "invalid members weight", 183 append( 184 []string{ 185 accounts[0].Address.String(), 186 "null", 187 invalidMembersWeightFile.Name(), 188 }, 189 s.commonFlags..., 190 ), 191 "", 192 "weight must be positive", 193 }, 194 { 195 "no member provided", 196 append( 197 []string{ 198 accounts[0].Address.String(), 199 "null", 200 "doesnotexist.json", 201 }, 202 s.commonFlags..., 203 ), 204 "", 205 "no such file or directory", 206 }, 207 } 208 209 for _, tc := range testCases { 210 tc := tc 211 212 s.Run(tc.name, func() { 213 ctx := svrcmd.CreateExecuteContext(context.Background()) 214 cmd.SetContext(ctx) 215 cmd.SetArgs(tc.args) 216 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 217 218 if len(tc.args) != 0 { 219 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 220 } 221 222 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 223 if tc.expectErrMsg != "" { 224 s.Require().Error(err) 225 s.Require().Contains(out.String(), tc.expectErrMsg) 226 } else { 227 s.Require().NoError(err) 228 msg := &sdk.TxResponse{} 229 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 230 } 231 }) 232 } 233 } 234 235 func (s *CLITestSuite) TestTxUpdateGroupAdmin() { 236 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 2) 237 238 cmd := groupcli.MsgUpdateGroupAdminCmd() 239 cmd.SetOutput(io.Discard) 240 241 ctx := svrcmd.CreateExecuteContext(context.Background()) 242 cmd.SetContext(ctx) 243 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 244 245 groupIDs := make([]string, 2) 246 for i := 0; i < 2; i++ { 247 validMembers := fmt.Sprintf(`{"members": [{ 248 "address": "%s", 249 "weight": "1", 250 "metadata": "%s" 251 }]}`, accounts[0].Address.String(), validMetadata) 252 validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) 253 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, groupcli.MsgCreateGroupCmd(), 254 append( 255 []string{ 256 accounts[0].Address.String(), 257 validMetadata, 258 validMembersFile.Name(), 259 }, 260 s.commonFlags..., 261 ), 262 ) 263 s.Require().NoError(err, out.String()) 264 groupIDs[i] = fmt.Sprintf("%d", i+1) 265 } 266 267 testCases := []struct { 268 name string 269 ctxGen func() client.Context 270 args []string 271 expCmdOutput string 272 expectErrMsg string 273 }{ 274 { 275 "correct data", 276 func() client.Context { 277 bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) 278 c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ 279 Value: bz, 280 }) 281 return s.baseCtx.WithClient(c) 282 }, 283 append( 284 []string{ 285 accounts[0].Address.String(), 286 groupIDs[0], 287 accounts[1].Address.String(), 288 }, 289 s.commonFlags..., 290 ), 291 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), groupIDs[0], accounts[1].Address.String()), 292 "", 293 }, 294 { 295 "with amino-json", 296 func() client.Context { 297 bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) 298 c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ 299 Value: bz, 300 }) 301 return s.baseCtx.WithClient(c) 302 }, 303 append( 304 []string{ 305 accounts[0].Address.String(), 306 groupIDs[1], 307 accounts[1].Address.String(), 308 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 309 }, 310 s.commonFlags..., 311 ), 312 fmt.Sprintf("%s %s %s --%s=%s", accounts[0].Address.String(), groupIDs[1], accounts[1].Address.String(), flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 313 "", 314 }, 315 { 316 "group id invalid", 317 func() client.Context { 318 bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) 319 c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ 320 Value: bz, 321 }) 322 return s.baseCtx.WithClient(c) 323 }, 324 append( 325 []string{ 326 accounts[0].Address.String(), 327 "", 328 accounts[1].Address.String(), 329 }, 330 s.commonFlags..., 331 ), 332 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "", accounts[1].Address.String()), 333 "strconv.ParseUint: parsing \"\": invalid syntax", 334 }, 335 } 336 337 for _, tc := range testCases { 338 tc := tc 339 340 s.Run(tc.name, func() { 341 ctx := svrcmd.CreateExecuteContext(context.Background()) 342 343 cmd.SetContext(ctx) 344 cmd.SetArgs(tc.args) 345 346 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 347 348 if len(tc.args) != 0 { 349 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 350 } 351 352 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 353 if tc.expectErrMsg != "" { 354 s.Require().Error(err) 355 s.Require().Contains(out.String(), tc.expectErrMsg) 356 } else { 357 s.Require().NoError(err) 358 msg := &sdk.TxResponse{} 359 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 360 } 361 }) 362 } 363 } 364 365 func (s *CLITestSuite) TestTxUpdateGroupMetadata() { 366 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 367 368 cmd := groupcli.MsgUpdateGroupMetadataCmd() 369 cmd.SetOutput(io.Discard) 370 371 testCases := []struct { 372 name string 373 args []string 374 expCmdOutput string 375 expectErrMsg string 376 }{ 377 { 378 "correct data", 379 append( 380 []string{ 381 accounts[0].Address.String(), 382 "1", 383 validMetadata, 384 }, 385 s.commonFlags..., 386 ), 387 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "1", validMetadata), 388 "", 389 }, 390 { 391 "with amino-json", 392 append( 393 []string{ 394 accounts[0].Address.String(), 395 "1", 396 validMetadata, 397 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 398 }, 399 s.commonFlags..., 400 ), 401 fmt.Sprintf("%s %s %s --%s=%s", accounts[0].Address.String(), "1", validMetadata, flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 402 "", 403 }, 404 { 405 "invalid group id", 406 append( 407 []string{ 408 accounts[0].Address.String(), 409 "abc", 410 validMetadata, 411 }, 412 s.commonFlags..., 413 ), 414 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "abc", validMetadata), 415 "Error: strconv.ParseUint: parsing \"abc\"", 416 }, 417 { 418 "empty group id", 419 append( 420 []string{ 421 accounts[0].Address.String(), 422 "0", 423 validMetadata, 424 }, 425 s.commonFlags..., 426 ), 427 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "0", validMetadata), 428 "group id cannot be 0", 429 }, 430 } 431 432 for _, tc := range testCases { 433 tc := tc 434 435 s.Run(tc.name, func() { 436 ctx := svrcmd.CreateExecuteContext(context.Background()) 437 438 cmd.SetContext(ctx) 439 cmd.SetArgs(tc.args) 440 441 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 442 443 if len(tc.args) != 0 { 444 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 445 } 446 447 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 448 if tc.expectErrMsg != "" { 449 s.Require().Error(err) 450 s.Require().Contains(out.String(), tc.expectErrMsg) 451 } else { 452 s.Require().NoError(err) 453 msg := &sdk.TxResponse{} 454 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 455 } 456 }) 457 } 458 } 459 460 func (s *CLITestSuite) TestTxUpdateGroupMembers() { 461 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 3) 462 groupPolicyAddress := accounts[2] 463 464 cmd := groupcli.MsgUpdateGroupMembersCmd() 465 cmd.SetOutput(io.Discard) 466 467 groupID := "1" 468 469 validUpdatedMembersFileName := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf(`{"members": [{ 470 "address": "%s", 471 "weight": "0", 472 "metadata": "%s" 473 }, { 474 "address": "%s", 475 "weight": "1", 476 "metadata": "%s" 477 }]}`, accounts[1], validMetadata, groupPolicyAddress, validMetadata)).Name() 478 479 invalidMembersMetadata := fmt.Sprintf(`{"members": [{ 480 "address": "%s", 481 "weight": "-1", 482 "metadata": "foo" 483 }]}`, accounts[1]) 484 invalidMembersMetadataFileName := testutil.WriteToNewTempFile(s.T(), invalidMembersMetadata).Name() 485 486 testCases := []struct { 487 name string 488 args []string 489 expCmdOutput string 490 expectErrMsg string 491 }{ 492 { 493 "correct data", 494 append( 495 []string{ 496 accounts[0].Address.String(), 497 groupID, 498 validUpdatedMembersFileName, 499 }, 500 s.commonFlags..., 501 ), 502 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), groupID, validUpdatedMembersFileName), 503 "", 504 }, 505 { 506 "with amino-json", 507 append( 508 []string{ 509 accounts[0].Address.String(), 510 groupID, 511 validUpdatedMembersFileName, 512 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 513 }, 514 s.commonFlags..., 515 ), 516 fmt.Sprintf("%s %s %s --%s=%s", accounts[0].Address.String(), groupID, validUpdatedMembersFileName, flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 517 "", 518 }, 519 { 520 "group id invalid", 521 append( 522 []string{ 523 accounts[0].Address.String(), 524 "0", 525 validUpdatedMembersFileName, 526 }, 527 s.commonFlags..., 528 ), 529 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), "0", validUpdatedMembersFileName), 530 "group id cannot be 0", 531 }, 532 { 533 "group member weight invalid", 534 append( 535 []string{ 536 accounts[0].Address.String(), 537 groupID, 538 invalidMembersMetadataFileName, 539 }, 540 s.commonFlags..., 541 ), 542 fmt.Sprintf("%s %s %s", accounts[0].Address.String(), groupID, invalidMembersMetadataFileName), 543 "invalid weight -1", 544 }, 545 } 546 547 for _, tc := range testCases { 548 tc := tc 549 550 s.Run(tc.name, func() { 551 ctx := svrcmd.CreateExecuteContext(context.Background()) 552 553 cmd.SetContext(ctx) 554 cmd.SetArgs(tc.args) 555 556 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 557 558 if len(tc.args) != 0 { 559 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 560 } 561 562 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 563 if tc.expectErrMsg != "" { 564 s.Require().Error(err) 565 s.Require().Contains(out.String(), tc.expectErrMsg) 566 } else { 567 s.Require().NoError(err) 568 msg := &sdk.TxResponse{} 569 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 570 } 571 }) 572 } 573 } 574 575 func (s *CLITestSuite) TestTxCreateGroupWithPolicy() { 576 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 577 578 cmd := groupcli.MsgCreateGroupWithPolicyCmd() 579 cmd.SetOutput(io.Discard) 580 581 validMembers := fmt.Sprintf(`{"members": [{ 582 "address": "%s", 583 "weight": "1", 584 "metadata": "%s" 585 }]}`, accounts[0].Address.String(), validMetadata) 586 validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) 587 588 invalidMembersWeight := fmt.Sprintf(`{"members": [{ 589 "address": "%s", 590 "weight": "0" 591 }]}`, accounts[0].Address.String()) 592 invalidMembersWeightFile := testutil.WriteToNewTempFile(s.T(), invalidMembersWeight) 593 594 thresholdDecisionPolicyFile := testutil.WriteToNewTempFile(s.T(), `{"@type": "/cosmos.group.v1.ThresholdDecisionPolicy","threshold": "1","windows": {"voting_period":"1s"}}`) 595 596 testCases := []struct { 597 name string 598 args []string 599 expectErrMsg string 600 expCmdOutput string 601 }{ 602 { 603 "correct data", 604 append( 605 []string{ 606 accounts[0].Address.String(), 607 validMetadata, 608 validMetadata, 609 validMembersFile.Name(), 610 thresholdDecisionPolicyFile.Name(), 611 fmt.Sprintf("--%s=%v", groupcli.FlagGroupPolicyAsAdmin, false), 612 }, 613 s.commonFlags..., 614 ), 615 "", 616 fmt.Sprintf("%s %s %s %s %s --%s=%v", accounts[0].Address.String(), validMetadata, validMetadata, validMembersFile.Name(), thresholdDecisionPolicyFile.Name(), groupcli.FlagGroupPolicyAsAdmin, false), 617 }, 618 { 619 "group-policy-as-admin is true", 620 append( 621 []string{ 622 accounts[0].Address.String(), 623 validMetadata, 624 validMetadata, 625 validMembersFile.Name(), 626 thresholdDecisionPolicyFile.Name(), 627 fmt.Sprintf("--%s=%v", groupcli.FlagGroupPolicyAsAdmin, true), 628 }, 629 s.commonFlags..., 630 ), 631 "", 632 fmt.Sprintf("%s %s %s %s %s --%s=%v", accounts[0].Address.String(), validMetadata, validMetadata, validMembersFile.Name(), thresholdDecisionPolicyFile.Name(), groupcli.FlagGroupPolicyAsAdmin, true), 633 }, 634 { 635 "with amino-json", 636 append( 637 []string{ 638 accounts[0].Address.String(), 639 validMetadata, 640 validMetadata, 641 validMembersFile.Name(), 642 thresholdDecisionPolicyFile.Name(), 643 fmt.Sprintf("--%s=%v", groupcli.FlagGroupPolicyAsAdmin, false), 644 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 645 }, 646 s.commonFlags..., 647 ), 648 "", 649 fmt.Sprintf("%s %s %s %s %s --%s=%v --%s=%s", accounts[0].Address.String(), validMetadata, validMetadata, validMembersFile.Name(), thresholdDecisionPolicyFile.Name(), groupcli.FlagGroupPolicyAsAdmin, false, flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 650 }, 651 { 652 "invalid members weight", 653 append( 654 []string{ 655 accounts[0].Address.String(), 656 validMetadata, 657 validMetadata, 658 invalidMembersWeightFile.Name(), 659 thresholdDecisionPolicyFile.Name(), 660 fmt.Sprintf("--%s=%v", groupcli.FlagGroupPolicyAsAdmin, false), 661 }, 662 s.commonFlags..., 663 ), 664 "weight must be positive", 665 fmt.Sprintf("%s %s %s %s %s --%s=%v", accounts[0].Address.String(), validMetadata, validMetadata, invalidMembersWeightFile.Name(), thresholdDecisionPolicyFile.Name(), groupcli.FlagGroupPolicyAsAdmin, false), 666 }, 667 } 668 for _, tc := range testCases { 669 tc := tc 670 671 s.Run(tc.name, func() { 672 ctx := svrcmd.CreateExecuteContext(context.Background()) 673 674 cmd.SetContext(ctx) 675 cmd.SetArgs(tc.args) 676 677 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 678 679 if len(tc.args) != 0 { 680 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 681 } 682 683 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 684 if tc.expectErrMsg != "" { 685 s.Require().Error(err) 686 s.Require().Contains(out.String(), tc.expectErrMsg) 687 } else { 688 s.Require().NoError(err, out.String()) 689 msg := &sdk.TxResponse{} 690 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 691 } 692 }) 693 } 694 } 695 696 func (s *CLITestSuite) TestTxCreateGroupPolicy() { 697 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 2) 698 val := accounts[0] 699 700 groupID := s.group.Id 701 702 thresholdDecisionPolicyFile := testutil.WriteToNewTempFile(s.T(), `{"@type": "/cosmos.group.v1.ThresholdDecisionPolicy","threshold": "1","windows": {"voting_period":"1s"}}`) 703 704 percentageDecisionPolicyFile := testutil.WriteToNewTempFile(s.T(), `{"@type":"/cosmos.group.v1.PercentageDecisionPolicy", "percentage":"0.5", "windows":{"voting_period":"1s"}}`) 705 invalidNegativePercentageDecisionPolicyFile := testutil.WriteToNewTempFile(s.T(), `{"@type":"/cosmos.group.v1.PercentageDecisionPolicy", "percentage":"-0.5", "windows":{"voting_period":"1s"}}`) 706 invalidPercentageDecisionPolicyFile := testutil.WriteToNewTempFile(s.T(), `{"@type":"/cosmos.group.v1.PercentageDecisionPolicy", "percentage":"2", "windows":{"voting_period":"1s"}}`) 707 708 cmd := groupcli.MsgCreateGroupPolicyCmd() 709 cmd.SetOutput(io.Discard) 710 711 testCases := []struct { 712 name string 713 args []string 714 expectErrMsg string 715 expCmdOutput string 716 }{ 717 { 718 "correct data", 719 append( 720 []string{ 721 val.Address.String(), 722 fmt.Sprintf("%v", groupID), 723 validMetadata, 724 thresholdDecisionPolicyFile.Name(), 725 }, 726 s.commonFlags..., 727 ), 728 "", 729 fmt.Sprintf("%s %s %s %s", val.Address.String(), fmt.Sprintf("%v", groupID), validMetadata, thresholdDecisionPolicyFile.Name()), 730 }, 731 { 732 "correct data with percentage decision policy", 733 append( 734 []string{ 735 val.Address.String(), 736 fmt.Sprintf("%v", groupID), 737 validMetadata, 738 percentageDecisionPolicyFile.Name(), 739 }, 740 s.commonFlags..., 741 ), 742 "", 743 fmt.Sprintf("%s %s %s %s", val.Address.String(), fmt.Sprintf("%v", groupID), validMetadata, percentageDecisionPolicyFile.Name()), 744 }, 745 { 746 "with amino-json", 747 append( 748 []string{ 749 val.Address.String(), 750 fmt.Sprintf("%v", groupID), 751 validMetadata, 752 thresholdDecisionPolicyFile.Name(), 753 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 754 }, 755 s.commonFlags..., 756 ), 757 "", 758 fmt.Sprintf("%s %s %s %s --%s=%s", val.Address.String(), fmt.Sprintf("%v", groupID), validMetadata, thresholdDecisionPolicyFile.Name(), flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 759 }, 760 { 761 "wrong admin", 762 append( 763 []string{ 764 "wrongAdmin", 765 fmt.Sprintf("%v", groupID), 766 validMetadata, 767 thresholdDecisionPolicyFile.Name(), 768 }, 769 s.commonFlags..., 770 ), 771 "key not found", 772 fmt.Sprintf("%s %s %s %s", "wrongAdmin", fmt.Sprintf("%v", groupID), validMetadata, thresholdDecisionPolicyFile.Name()), 773 }, 774 { 775 "invalid percentage decision policy with negative value", 776 append( 777 []string{ 778 val.Address.String(), 779 fmt.Sprintf("%v", groupID), 780 validMetadata, 781 invalidNegativePercentageDecisionPolicyFile.Name(), 782 }, 783 s.commonFlags..., 784 ), 785 "expected a positive decimal", 786 fmt.Sprintf("%s %s %s %s", val.Address.String(), fmt.Sprintf("%v", groupID), validMetadata, invalidNegativePercentageDecisionPolicyFile.Name()), 787 }, 788 { 789 "invalid percentage decision policy with value greater than 1", 790 append( 791 []string{ 792 val.Address.String(), 793 fmt.Sprintf("%v", groupID), 794 validMetadata, 795 invalidPercentageDecisionPolicyFile.Name(), 796 }, 797 s.commonFlags..., 798 ), 799 "percentage must be > 0 and <= 1", 800 fmt.Sprintf("%s %s %s %s", val.Address.String(), fmt.Sprintf("%v", groupID), validMetadata, invalidPercentageDecisionPolicyFile.Name()), 801 }, 802 } 803 804 for _, tc := range testCases { 805 tc := tc 806 807 s.Run(tc.name, func() { 808 ctx := svrcmd.CreateExecuteContext(context.Background()) 809 810 cmd.SetContext(ctx) 811 cmd.SetArgs(tc.args) 812 813 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 814 815 if len(tc.args) != 0 { 816 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 817 } 818 819 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 820 if tc.expectErrMsg != "" { 821 s.Require().Error(err) 822 s.Require().Contains(out.String(), tc.expectErrMsg) 823 } else { 824 s.Require().NoError(err, out.String()) 825 msg := &sdk.TxResponse{} 826 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 827 } 828 }) 829 } 830 } 831 832 func (s *CLITestSuite) TestTxUpdateGroupPolicyAdmin() { 833 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 4) 834 newAdmin := accounts[0] 835 groupPolicyAdmin := accounts[1] 836 groupPolicyAddress := accounts[2] 837 838 commonFlags := s.commonFlags 839 commonFlags = append(commonFlags, fmt.Sprintf("--%s=%d", flags.FlagGas, 300000)) 840 841 cmd := groupcli.MsgUpdateGroupPolicyAdminCmd() 842 cmd.SetOutput(io.Discard) 843 844 testCases := []struct { 845 name string 846 args []string 847 expCmdOutput string 848 expectErrMsg string 849 }{ 850 { 851 "correct data", 852 append( 853 []string{ 854 groupPolicyAdmin.Address.String(), 855 groupPolicyAddress.Address.String(), 856 newAdmin.Address.String(), 857 }, 858 commonFlags..., 859 ), 860 fmt.Sprintf("%s %s %s", groupPolicyAdmin.Address.String(), groupPolicyAddress.Address.String(), newAdmin.Address.String()), 861 "", 862 }, 863 { 864 "with amino-json", 865 append( 866 []string{ 867 groupPolicyAdmin.Address.String(), 868 groupPolicyAddress.Address.String(), 869 newAdmin.Address.String(), 870 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 871 }, 872 commonFlags..., 873 ), 874 fmt.Sprintf("%s %s %s --%s=%s", groupPolicyAdmin.Address.String(), groupPolicyAddress.Address.String(), newAdmin.Address.String(), flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 875 "", 876 }, 877 { 878 "wrong admin", 879 append( 880 []string{ 881 "wrong admin", 882 groupPolicyAddress.Address.String(), 883 newAdmin.Address.String(), 884 }, 885 commonFlags..., 886 ), 887 fmt.Sprintf("%s %s %s", "wrong admin", groupPolicyAddress.Address.String(), newAdmin.Address.String()), 888 "key not found", 889 }, 890 { 891 "identical admin and new admin", 892 append( 893 []string{ 894 groupPolicyAdmin.Address.String(), 895 groupPolicyAddress.Address.String(), 896 groupPolicyAdmin.Address.String(), 897 }, 898 commonFlags..., 899 ), 900 fmt.Sprintf("%s %s %s", groupPolicyAdmin.Address.String(), groupPolicyAddress.Address.String(), groupPolicyAdmin.Address.String()), 901 "new admin cannot be the same as the current admin", 902 }, 903 } 904 905 for _, tc := range testCases { 906 tc := tc 907 908 s.Run(tc.name, func() { 909 ctx := svrcmd.CreateExecuteContext(context.Background()) 910 911 cmd.SetContext(ctx) 912 cmd.SetArgs(tc.args) 913 914 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 915 916 if len(tc.args) != 0 { 917 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 918 } 919 920 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 921 if tc.expectErrMsg != "" { 922 s.Require().Error(err) 923 s.Require().Contains(out.String(), tc.expectErrMsg) 924 } else { 925 s.Require().NoError(err) 926 msg := &sdk.TxResponse{} 927 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 928 } 929 }) 930 } 931 } 932 933 func (s *CLITestSuite) TestTxUpdateGroupPolicyDecisionPolicy() { 934 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 3) 935 newAdmin := accounts[0] 936 groupPolicyAdmin := accounts[1] 937 groupPolicyAddress := accounts[2] 938 939 commonFlags := s.commonFlags 940 commonFlags = append(commonFlags, fmt.Sprintf("--%s=%d", flags.FlagGas, 300000)) 941 942 thresholdDecisionPolicy := testutil.WriteToNewTempFile(s.T(), `{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"1", "windows":{"voting_period":"40000s"}}`) 943 percentageDecisionPolicy := testutil.WriteToNewTempFile(s.T(), `{"@type":"/cosmos.group.v1.PercentageDecisionPolicy", "percentage":"0.5", "windows":{"voting_period":"40000s"}}`) 944 945 cmd := groupcli.MsgUpdateGroupPolicyDecisionPolicyCmd(address.NewBech32Codec("cosmos")) 946 cmd.SetOutput(io.Discard) 947 948 testCases := []struct { 949 name string 950 args []string 951 expCmdOutput string 952 expectErrMsg string 953 }{ 954 { 955 "correct data", 956 append( 957 []string{ 958 groupPolicyAdmin.Address.String(), 959 groupPolicyAddress.Address.String(), 960 thresholdDecisionPolicy.Name(), 961 }, 962 commonFlags..., 963 ), 964 fmt.Sprintf("%s %s %s", groupPolicyAdmin.Address.String(), groupPolicyAddress.Address.String(), thresholdDecisionPolicy.Name()), 965 "", 966 }, 967 { 968 "correct data with percentage decision policy", 969 append( 970 []string{ 971 groupPolicyAdmin.Address.String(), 972 groupPolicyAddress.Address.String(), 973 percentageDecisionPolicy.Name(), 974 }, 975 commonFlags..., 976 ), 977 fmt.Sprintf("%s %s %s", groupPolicyAdmin.Address.String(), groupPolicyAddress.Address.String(), percentageDecisionPolicy.Name()), 978 "", 979 }, 980 { 981 "with amino-json", 982 append( 983 []string{ 984 groupPolicyAdmin.Address.String(), 985 groupPolicyAddress.Address.String(), 986 thresholdDecisionPolicy.Name(), 987 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 988 }, 989 commonFlags..., 990 ), 991 fmt.Sprintf("%s %s %s --%s=%s", groupPolicyAdmin.Address.String(), groupPolicyAddress.Address.String(), thresholdDecisionPolicy.Name(), flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 992 "", 993 }, 994 { 995 "wrong admin", 996 append( 997 []string{ 998 newAdmin.Address.String(), 999 "invalid", 1000 thresholdDecisionPolicy.Name(), 1001 }, 1002 commonFlags..., 1003 ), 1004 fmt.Sprintf("%s %s %s", newAdmin.Address.String(), "invalid", thresholdDecisionPolicy.Name()), 1005 "decoding bech32 failed", 1006 }, 1007 } 1008 1009 for _, tc := range testCases { 1010 tc := tc 1011 1012 s.Run(tc.name, func() { 1013 ctx := svrcmd.CreateExecuteContext(context.Background()) 1014 1015 cmd.SetContext(ctx) 1016 cmd.SetArgs(tc.args) 1017 1018 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 1019 1020 if len(tc.args) != 0 { 1021 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 1022 } 1023 1024 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 1025 if tc.expectErrMsg != "" { 1026 s.Require().Error(err) 1027 s.Require().Contains(out.String(), tc.expectErrMsg) 1028 } else { 1029 s.Require().NoError(err) 1030 msg := &sdk.TxResponse{} 1031 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 1032 } 1033 }) 1034 } 1035 } 1036 1037 func (s *CLITestSuite) TestTxUpdateGroupPolicyMetadata() { 1038 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 2) 1039 groupPolicyAdmin := accounts[0].Address 1040 groupPolicyAddress := accounts[1].Address 1041 1042 commonFlags := s.commonFlags 1043 commonFlags = append(commonFlags, fmt.Sprintf("--%s=%d", flags.FlagGas, 300000)) 1044 1045 cmd := groupcli.MsgUpdateGroupPolicyMetadataCmd() 1046 cmd.SetOutput(io.Discard) 1047 1048 testCases := []struct { 1049 name string 1050 args []string 1051 expCmdOutput string 1052 expectErrMsg string 1053 }{ 1054 { 1055 "correct data", 1056 append( 1057 []string{ 1058 groupPolicyAdmin.String(), 1059 groupPolicyAddress.String(), 1060 validMetadata, 1061 }, 1062 commonFlags..., 1063 ), 1064 fmt.Sprintf("%s %s %s", groupPolicyAdmin.String(), groupPolicyAddress.String(), validMetadata), 1065 "", 1066 }, 1067 { 1068 "with amino-json", 1069 append( 1070 []string{ 1071 groupPolicyAdmin.String(), 1072 groupPolicyAddress.String(), 1073 validMetadata, 1074 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 1075 }, 1076 commonFlags..., 1077 ), 1078 fmt.Sprintf("%s %s %s --%s=%s", groupPolicyAdmin.String(), groupPolicyAddress.String(), validMetadata, flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 1079 "", 1080 }, 1081 { 1082 "wrong admin", 1083 append( 1084 []string{ 1085 "wrong admin", 1086 groupPolicyAddress.String(), 1087 validMetadata, 1088 }, 1089 commonFlags..., 1090 ), 1091 fmt.Sprintf("%s %s %s", "wrong admin", groupPolicyAddress.String(), validMetadata), 1092 "key not found", 1093 }, 1094 } 1095 1096 for _, tc := range testCases { 1097 tc := tc 1098 1099 s.Run(tc.name, func() { 1100 ctx := svrcmd.CreateExecuteContext(context.Background()) 1101 1102 cmd.SetContext(ctx) 1103 cmd.SetArgs(tc.args) 1104 1105 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 1106 1107 if len(tc.args) != 0 { 1108 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 1109 } 1110 1111 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 1112 if tc.expectErrMsg != "" { 1113 s.Require().Error(err) 1114 s.Require().Contains(out.String(), tc.expectErrMsg) 1115 } else { 1116 s.Require().NoError(err) 1117 msg := &sdk.TxResponse{} 1118 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 1119 } 1120 }) 1121 } 1122 } 1123 1124 func (s *CLITestSuite) TestTxSubmitProposal() { 1125 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 2) 1126 groupPolicyAddress := accounts[1].Address 1127 1128 p := groupcli.Proposal{ 1129 GroupPolicyAddress: groupPolicyAddress.String(), 1130 Messages: []json.RawMessage{}, 1131 Metadata: validMetadata, 1132 Proposers: []string{accounts[0].Address.String()}, 1133 } 1134 bz, err := json.Marshal(&p) 1135 s.Require().NoError(err) 1136 proposalFile := testutil.WriteToNewTempFile(s.T(), string(bz)) 1137 1138 cmd := groupcli.MsgSubmitProposalCmd() 1139 cmd.SetOutput(io.Discard) 1140 1141 testCases := []struct { 1142 name string 1143 args []string 1144 expCmdOutput string 1145 expectErrMsg string 1146 }{ 1147 { 1148 "correct data", 1149 append( 1150 []string{ 1151 proposalFile.Name(), 1152 }, 1153 s.commonFlags..., 1154 ), 1155 proposalFile.Name(), 1156 "", 1157 }, 1158 { 1159 "with try exec", 1160 append( 1161 []string{ 1162 proposalFile.Name(), 1163 fmt.Sprintf("--%s=try", groupcli.FlagExec), 1164 }, 1165 s.commonFlags..., 1166 ), 1167 fmt.Sprintf("%s --%s=try", proposalFile.Name(), groupcli.FlagExec), 1168 "", 1169 }, 1170 { 1171 "with try exec, not enough yes votes for proposal to pass", 1172 append( 1173 []string{ 1174 proposalFile.Name(), 1175 fmt.Sprintf("--%s=try", groupcli.FlagExec), 1176 }, 1177 s.commonFlags..., 1178 ), 1179 fmt.Sprintf("%s --%s=try", proposalFile.Name(), groupcli.FlagExec), 1180 "", 1181 }, 1182 { 1183 "with amino-json", 1184 append( 1185 []string{ 1186 proposalFile.Name(), 1187 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 1188 }, 1189 s.commonFlags..., 1190 ), 1191 fmt.Sprintf("%s --%s=%s", proposalFile.Name(), flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 1192 "", 1193 }, 1194 } 1195 1196 for _, tc := range testCases { 1197 tc := tc 1198 1199 s.Run(tc.name, func() { 1200 ctx := svrcmd.CreateExecuteContext(context.Background()) 1201 1202 cmd.SetContext(ctx) 1203 cmd.SetArgs(tc.args) 1204 1205 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 1206 1207 if len(tc.args) != 0 { 1208 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 1209 } 1210 1211 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 1212 if tc.expectErrMsg != "" { 1213 s.Require().Error(err) 1214 s.Require().Contains(out.String(), tc.expectErrMsg) 1215 } else { 1216 s.Require().NoError(err) 1217 msg := &sdk.TxResponse{} 1218 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 1219 } 1220 }) 1221 } 1222 } 1223 1224 func (s *CLITestSuite) TestTxVote() { 1225 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 4) 1226 1227 cmd := groupcli.MsgVoteCmd() 1228 cmd.SetOutput(io.Discard) 1229 1230 ids := make([]string, 4) 1231 for i := 0; i < len(ids); i++ { 1232 ids[i] = fmt.Sprint(i + 1) 1233 } 1234 1235 testCases := []struct { 1236 name string 1237 args []string 1238 expCmdOutput string 1239 expectErrMsg string 1240 }{ 1241 { 1242 "invalid vote", 1243 append( 1244 []string{ 1245 ids[0], 1246 accounts[0].Address.String(), 1247 "AYE", 1248 "", 1249 }, 1250 s.commonFlags..., 1251 ), 1252 fmt.Sprintf("%s %s %s", ids[0], accounts[0].Address.String(), "AYE"), 1253 "Error: 'AYE' is not a valid vote option", 1254 }, 1255 { 1256 "correct data", 1257 append( 1258 []string{ 1259 ids[0], 1260 accounts[0].Address.String(), 1261 "VOTE_OPTION_YES", 1262 "", 1263 }, 1264 s.commonFlags..., 1265 ), 1266 fmt.Sprintf("%s %s %s", ids[0], accounts[0].Address.String(), "VOTE_OPTION_YES"), 1267 "", 1268 }, 1269 { 1270 "with try exec", 1271 append( 1272 []string{ 1273 ids[1], 1274 accounts[0].Address.String(), 1275 "VOTE_OPTION_YES", 1276 "", 1277 fmt.Sprintf("--%s=try", groupcli.FlagExec), 1278 }, 1279 s.commonFlags..., 1280 ), 1281 fmt.Sprintf("%s %s %s %s --%s=try", ids[1], accounts[0].Address.String(), "VOTE_OPTION_YES", "", groupcli.FlagExec), 1282 "", 1283 }, 1284 { 1285 "with amino-json", 1286 append( 1287 []string{ 1288 ids[3], 1289 accounts[0].Address.String(), 1290 "VOTE_OPTION_YES", 1291 "", 1292 fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 1293 }, 1294 s.commonFlags..., 1295 ), 1296 fmt.Sprintf("%s %s %s %s --%s=%s", ids[3], accounts[0].Address.String(), "VOTE_OPTION_YES", "", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), 1297 "", 1298 }, 1299 } 1300 1301 for _, tc := range testCases { 1302 tc := tc 1303 1304 s.Run(tc.name, func() { 1305 ctx := svrcmd.CreateExecuteContext(context.Background()) 1306 1307 cmd.SetContext(ctx) 1308 cmd.SetArgs(tc.args) 1309 1310 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 1311 1312 if len(tc.args) != 0 { 1313 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 1314 } 1315 1316 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 1317 if tc.expectErrMsg != "" { 1318 s.Require().Error(err) 1319 s.Require().Contains(out.String(), tc.expectErrMsg) 1320 } else { 1321 s.Require().NoError(err) 1322 msg := &sdk.TxResponse{} 1323 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 1324 } 1325 }) 1326 } 1327 } 1328 1329 func (s *CLITestSuite) TestTxWithdrawProposal() { 1330 accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) 1331 1332 cmd := groupcli.MsgWithdrawProposalCmd() 1333 cmd.SetOutput(io.Discard) 1334 1335 ids := make([]string, 2) 1336 ids[0] = "1" 1337 ids[1] = "2" 1338 1339 testCases := []struct { 1340 name string 1341 args []string 1342 expCmdOutput string 1343 expectErrMsg string 1344 }{ 1345 { 1346 "correct data", 1347 append( 1348 []string{ 1349 ids[0], 1350 accounts[0].Address.String(), 1351 }, 1352 s.commonFlags..., 1353 ), 1354 fmt.Sprintf("%s %s", ids[0], accounts[0].Address.String()), 1355 "", 1356 }, 1357 { 1358 "wrong admin", 1359 append( 1360 []string{ 1361 ids[1], 1362 "wrongAdmin", 1363 }, 1364 s.commonFlags..., 1365 ), 1366 fmt.Sprintf("%s %s", ids[1], "wrongAdmin"), 1367 "key not found", 1368 }, 1369 { 1370 "wrong proposal id", 1371 append( 1372 []string{ 1373 "abc", 1374 accounts[0].Address.String(), 1375 }, 1376 s.commonFlags..., 1377 ), 1378 fmt.Sprintf("%s %s", "abc", accounts[0].Address.String()), 1379 "Error: strconv.ParseUint: parsing \"abc\"", 1380 }, 1381 } 1382 1383 for _, tc := range testCases { 1384 tc := tc 1385 1386 s.Run(tc.name, func() { 1387 ctx := svrcmd.CreateExecuteContext(context.Background()) 1388 1389 cmd.SetContext(ctx) 1390 cmd.SetArgs(tc.args) 1391 1392 s.Require().NoError(client.SetCmdClientContextHandler(s.baseCtx, cmd)) 1393 1394 if len(tc.args) != 0 { 1395 s.Require().Contains(fmt.Sprint(cmd), tc.expCmdOutput) 1396 } 1397 1398 out, err := clitestutil.ExecTestCLICmd(s.baseCtx, cmd, tc.args) 1399 if tc.expectErrMsg != "" { 1400 s.Require().Error(err) 1401 s.Require().Contains(out.String(), tc.expectErrMsg) 1402 } else { 1403 s.Require().NoError(err) 1404 msg := &sdk.TxResponse{} 1405 s.Require().NoError(s.baseCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) 1406 } 1407 }) 1408 } 1409 }