github.com/Finschia/finschia-sdk@v0.48.1/x/staking/client/testutil/suite.go (about)

     1  package testutil
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/gogo/protobuf/proto"
    10  	"github.com/stretchr/testify/suite"
    11  	"github.com/tendermint/tendermint/proto/tendermint/crypto"
    12  
    13  	ostcli "github.com/Finschia/ostracon/libs/cli"
    14  	"github.com/Finschia/ostracon/rpc/client/http"
    15  
    16  	"github.com/Finschia/finschia-sdk/client/flags"
    17  	"github.com/Finschia/finschia-sdk/crypto/hd"
    18  	"github.com/Finschia/finschia-sdk/crypto/keyring"
    19  	"github.com/Finschia/finschia-sdk/crypto/keys/ed25519"
    20  	clitestutil "github.com/Finschia/finschia-sdk/testutil/cli"
    21  	"github.com/Finschia/finschia-sdk/testutil/network"
    22  	sdk "github.com/Finschia/finschia-sdk/types"
    23  	"github.com/Finschia/finschia-sdk/types/query"
    24  	banktestutil "github.com/Finschia/finschia-sdk/x/bank/client/testutil"
    25  	"github.com/Finschia/finschia-sdk/x/staking/client/cli"
    26  	"github.com/Finschia/finschia-sdk/x/staking/types"
    27  )
    28  
    29  type IntegrationTestSuite struct {
    30  	suite.Suite
    31  
    32  	cfg     network.Config
    33  	network *network.Network
    34  }
    35  
    36  func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {
    37  	return &IntegrationTestSuite{cfg: cfg}
    38  }
    39  
    40  func (s *IntegrationTestSuite) SetupSuite() {
    41  	s.T().Log("setting up integration test suite")
    42  
    43  	if testing.Short() {
    44  		s.T().Skip("skipping test in unit-tests mode.")
    45  	}
    46  
    47  	s.network = network.New(s.T(), s.cfg)
    48  
    49  	_, err := s.network.WaitForHeight(1)
    50  	s.Require().NoError(err)
    51  
    52  	unbond, err := sdk.ParseCoinNormalized("10stake")
    53  	s.Require().NoError(err)
    54  
    55  	val := s.network.Validators[0]
    56  	val2 := s.network.Validators[1]
    57  
    58  	// redelegate
    59  	_, err = MsgRedelegateExec(
    60  		val.ClientCtx,
    61  		val.Address,
    62  		val.ValAddress,
    63  		val2.ValAddress,
    64  		unbond,
    65  		fmt.Sprintf("--%s=%d", flags.FlagGas, 300000),
    66  	)
    67  	s.Require().NoError(err)
    68  	_, err = s.network.WaitForHeight(1)
    69  	s.Require().NoError(err)
    70  	// unbonding
    71  	_, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond)
    72  	s.Require().NoError(err)
    73  	_, err = s.network.WaitForHeight(1)
    74  	s.Require().NoError(err)
    75  }
    76  
    77  func (s *IntegrationTestSuite) TearDownSuite() {
    78  	s.T().Log("tearing down integration test suite")
    79  	s.network.Cleanup()
    80  }
    81  
    82  func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() {
    83  	require := s.Require()
    84  	val := s.network.Validators[0]
    85  
    86  	consPrivKey := ed25519.GenPrivKey()
    87  	consPubKeyBz, err := s.cfg.Codec.MarshalInterfaceJSON(consPrivKey.PubKey())
    88  	require.NoError(err)
    89  	require.NotNil(consPubKeyBz)
    90  
    91  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
    92  	require.NoError(err)
    93  
    94  	newAddr := sdk.AccAddress(info.GetPubKey().Address())
    95  	_, err = banktestutil.MsgSendExec(
    96  		val.ClientCtx,
    97  		val.Address,
    98  		newAddr,
    99  		sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   100  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   101  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   102  	)
   103  	require.NoError(err)
   104  
   105  	testCases := []struct {
   106  		name         string
   107  		args         []string
   108  		expectErr    bool
   109  		expectedCode uint32
   110  		respType     proto.Message
   111  	}{
   112  		{
   113  			"invalid transaction (missing amount)",
   114  			[]string{
   115  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   116  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   117  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   118  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   119  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   120  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   121  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   122  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   123  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   124  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   125  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   126  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   127  			},
   128  			true, 0, nil,
   129  		},
   130  		{
   131  			"invalid transaction (missing pubkey)",
   132  			[]string{
   133  				fmt.Sprintf("--%s=%dstake", cli.FlagAmount, 100),
   134  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   135  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   136  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   137  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   138  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   139  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   140  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   141  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   142  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   143  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   144  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   145  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   146  			},
   147  			true, 0, nil,
   148  		},
   149  		{
   150  			"invalid transaction (missing moniker)",
   151  			[]string{
   152  				fmt.Sprintf("--%s=%s", cli.FlagPubKey, consPubKeyBz),
   153  				fmt.Sprintf("--%s=%dstake", cli.FlagAmount, 100),
   154  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   155  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   156  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   157  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   158  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   159  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   160  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   161  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   162  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   163  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   164  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   165  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   166  			},
   167  			true, 0, nil,
   168  		},
   169  		{
   170  			"valid transaction",
   171  			[]string{
   172  				fmt.Sprintf("--%s=%s", cli.FlagPubKey, consPubKeyBz),
   173  				fmt.Sprintf("--%s=%dstake", cli.FlagAmount, 100),
   174  				fmt.Sprintf("--%s=NewValidator", cli.FlagMoniker),
   175  				fmt.Sprintf("--%s=AFAF00C4", cli.FlagIdentity),
   176  				fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
   177  				fmt.Sprintf("--%s=contact@newvalidator.io", cli.FlagSecurityContact),
   178  				fmt.Sprintf("--%s='Hey, I am a new validator. Please delegate!'", cli.FlagDetails),
   179  				fmt.Sprintf("--%s=0.5", cli.FlagCommissionRate),
   180  				fmt.Sprintf("--%s=1.0", cli.FlagCommissionMaxRate),
   181  				fmt.Sprintf("--%s=0.1", cli.FlagCommissionMaxChangeRate),
   182  				fmt.Sprintf("--%s=1", cli.FlagMinSelfDelegation),
   183  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr),
   184  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   185  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   186  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   187  			},
   188  			false, 0, &sdk.TxResponse{},
   189  		},
   190  	}
   191  
   192  	for _, tc := range testCases {
   193  		tc := tc
   194  
   195  		s.Run(tc.name, func() {
   196  			cmd := cli.NewCreateValidatorCmd()
   197  			clientCtx := val.ClientCtx
   198  
   199  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   200  			if tc.expectErr {
   201  				require.Error(err)
   202  			} else {
   203  				require.NoError(err, "test: %s\noutput: %s", tc.name, out.String())
   204  				err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType)
   205  				require.NoError(err, out.String(), "test: %s, output\n:", tc.name, out.String())
   206  
   207  				txResp := tc.respType.(*sdk.TxResponse)
   208  				require.Equal(tc.expectedCode, txResp.Code,
   209  					"test: %s, output\n:", tc.name, out.String())
   210  
   211  				events := txResp.Logs[0].GetEvents()
   212  				for i := 0; i < len(events); i++ {
   213  					if events[i].GetType() == "create_validator" {
   214  						attributes := events[i].GetAttributes()
   215  						require.Equal(attributes[1].Value, "100stake")
   216  						break
   217  					}
   218  				}
   219  			}
   220  		})
   221  	}
   222  }
   223  
   224  func (s *IntegrationTestSuite) TestGetCmdQueryValidator() {
   225  	val := s.network.Validators[0]
   226  	testCases := []struct {
   227  		name      string
   228  		args      []string
   229  		expectErr bool
   230  	}{
   231  		{
   232  			"with invalid address ",
   233  			[]string{"somethinginvalidaddress", fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   234  			true,
   235  		},
   236  		{
   237  			"with valid and not existing address",
   238  			[]string{"linkvaloper1mqn4snc20sxt6lrecjclmdglfdmtql4408kwvl", fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   239  			true,
   240  		},
   241  		{
   242  			"happy case",
   243  			[]string{val.ValAddress.String(), fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   244  			false,
   245  		},
   246  	}
   247  	for _, tc := range testCases {
   248  		tc := tc
   249  		s.Run(tc.name, func() {
   250  			cmd := cli.GetCmdQueryValidator()
   251  			clientCtx := val.ClientCtx
   252  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   253  			if tc.expectErr {
   254  				s.Require().Error(err)
   255  				s.Require().NotEqual("internal", err.Error())
   256  			} else {
   257  				var result types.Validator
   258  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result))
   259  				s.Require().Equal(val.ValAddress.String(), result.OperatorAddress)
   260  			}
   261  		})
   262  	}
   263  }
   264  
   265  func (s *IntegrationTestSuite) TestGetCmdQueryValidators() {
   266  	val := s.network.Validators[0]
   267  
   268  	testCases := []struct {
   269  		name              string
   270  		args              []string
   271  		minValidatorCount int
   272  	}{
   273  		{
   274  			"one validator case",
   275  			[]string{
   276  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   277  				fmt.Sprintf("--%s=1", flags.FlagLimit),
   278  			},
   279  			1,
   280  		},
   281  		{
   282  			"multi validator case",
   283  			[]string{fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   284  			len(s.network.Validators),
   285  		},
   286  	}
   287  
   288  	for _, tc := range testCases {
   289  		tc := tc
   290  
   291  		s.Run(tc.name, func() {
   292  			cmd := cli.GetCmdQueryValidators()
   293  			clientCtx := val.ClientCtx
   294  
   295  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   296  			s.Require().NoError(err)
   297  
   298  			var result types.QueryValidatorsResponse
   299  			s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result))
   300  			s.Require().Equal(tc.minValidatorCount, len(result.Validators))
   301  		})
   302  	}
   303  }
   304  
   305  func (s *IntegrationTestSuite) TestGetCmdQueryDelegation() {
   306  	val := s.network.Validators[0]
   307  	val2 := s.network.Validators[1]
   308  
   309  	testCases := []struct {
   310  		name     string
   311  		args     []string
   312  		expErr   bool
   313  		respType proto.Message
   314  		expected proto.Message
   315  	}{
   316  		{
   317  			"with wrong delegator address",
   318  			[]string{
   319  				"wrongDelAddr",
   320  				val2.ValAddress.String(),
   321  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   322  			},
   323  			true, nil, nil,
   324  		},
   325  		{
   326  			"with wrong validator address",
   327  			[]string{
   328  				val.Address.String(),
   329  				"wrongValAddr",
   330  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   331  			},
   332  			true, nil, nil,
   333  		},
   334  		{
   335  			"with json output",
   336  			[]string{
   337  				val.Address.String(),
   338  				val2.ValAddress.String(),
   339  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   340  			},
   341  			false,
   342  			&types.DelegationResponse{},
   343  			&types.DelegationResponse{
   344  				Delegation: types.Delegation{
   345  					DelegatorAddress: val.Address.String(),
   346  					ValidatorAddress: val2.ValAddress.String(),
   347  					Shares:           sdk.NewDec(10),
   348  				},
   349  				Balance: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)),
   350  			},
   351  		},
   352  	}
   353  
   354  	for _, tc := range testCases {
   355  		tc := tc
   356  		s.Run(tc.name, func() {
   357  			cmd := cli.GetCmdQueryDelegation()
   358  			clientCtx := val.ClientCtx
   359  
   360  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   361  			if tc.expErr {
   362  				s.Require().Error(err)
   363  			} else {
   364  				s.Require().NoError(err)
   365  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   366  				s.Require().Equal(tc.expected.String(), tc.respType.String())
   367  			}
   368  		})
   369  	}
   370  }
   371  
   372  func (s *IntegrationTestSuite) TestGetCmdQueryDelegations() {
   373  	val := s.network.Validators[0]
   374  
   375  	testCases := []struct {
   376  		name     string
   377  		args     []string
   378  		expErr   bool
   379  		respType proto.Message
   380  		expected proto.Message
   381  	}{
   382  		{
   383  			"with no delegator address",
   384  			[]string{},
   385  			true, nil, nil,
   386  		},
   387  		{
   388  			"with wrong delegator address",
   389  			[]string{"wrongDelAddr"},
   390  			true, nil, nil,
   391  		},
   392  		{
   393  			"valid request (height specific)",
   394  			[]string{
   395  				val.Address.String(),
   396  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   397  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   398  			},
   399  			false,
   400  			&types.QueryDelegatorDelegationsResponse{},
   401  			&types.QueryDelegatorDelegationsResponse{
   402  				DelegationResponses: types.DelegationResponses{
   403  					types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
   404  				},
   405  				Pagination: &query.PageResponse{},
   406  			},
   407  		},
   408  	}
   409  
   410  	for _, tc := range testCases {
   411  		tc := tc
   412  		s.Run(tc.name, func() {
   413  			cmd := cli.GetCmdQueryDelegations()
   414  			clientCtx := val.ClientCtx
   415  
   416  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   417  			if tc.expErr {
   418  				s.Require().Error(err)
   419  			} else {
   420  				s.Require().NoError(err)
   421  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   422  				s.Require().Equal(tc.expected.String(), tc.respType.String())
   423  			}
   424  		})
   425  	}
   426  }
   427  
   428  func (s *IntegrationTestSuite) TestGetCmdQueryValidatorDelegations() {
   429  	val := s.network.Validators[0]
   430  
   431  	testCases := []struct {
   432  		name     string
   433  		args     []string
   434  		expErr   bool
   435  		respType proto.Message
   436  		expected proto.Message
   437  	}{
   438  		{
   439  			"with no validator address",
   440  			[]string{},
   441  			true, nil, nil,
   442  		},
   443  		{
   444  			"wrong validator address",
   445  			[]string{"wrongValAddr"},
   446  			true, nil, nil,
   447  		},
   448  		{
   449  			"valid request(height specific)",
   450  			[]string{
   451  				val.Address.String(),
   452  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   453  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   454  			},
   455  			false,
   456  			&types.QueryValidatorDelegationsResponse{},
   457  			&types.QueryValidatorDelegationsResponse{
   458  				DelegationResponses: types.DelegationResponses{
   459  					types.NewDelegationResp(val.Address, val.ValAddress, sdk.NewDecFromInt(cli.DefaultTokens), sdk.NewCoin(sdk.DefaultBondDenom, cli.DefaultTokens)),
   460  				},
   461  				Pagination: &query.PageResponse{},
   462  			},
   463  		},
   464  	}
   465  
   466  	for _, tc := range testCases {
   467  		tc := tc
   468  		s.Run(tc.name, func() {
   469  			cmd := cli.GetCmdQueryDelegations()
   470  			clientCtx := val.ClientCtx
   471  
   472  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   473  			if tc.expErr {
   474  				s.Require().Error(err)
   475  			} else {
   476  				s.Require().NoError(err)
   477  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
   478  				s.Require().Equal(tc.expected.String(), tc.respType.String())
   479  			}
   480  		})
   481  	}
   482  }
   483  
   484  func (s *IntegrationTestSuite) TestGetCmdQueryUnbondingDelegations() {
   485  	val := s.network.Validators[0]
   486  
   487  	testCases := []struct {
   488  		name   string
   489  		args   []string
   490  		expErr bool
   491  	}{
   492  		{
   493  			"wrong delegator address",
   494  			[]string{
   495  				"wrongDelAddr",
   496  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   497  			},
   498  			true,
   499  		},
   500  		{
   501  			"valid request",
   502  			[]string{
   503  				val.Address.String(),
   504  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   505  			},
   506  			false,
   507  		},
   508  	}
   509  
   510  	for _, tc := range testCases {
   511  		tc := tc
   512  		s.Run(tc.name, func() {
   513  			cmd := cli.GetCmdQueryUnbondingDelegations()
   514  			clientCtx := val.ClientCtx
   515  
   516  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   517  
   518  			if tc.expErr {
   519  				s.Require().Error(err)
   520  			} else {
   521  				var ubds types.QueryDelegatorUnbondingDelegationsResponse
   522  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &ubds)
   523  
   524  				s.Require().NoError(err)
   525  				s.Require().Len(ubds.UnbondingResponses, 1)
   526  				s.Require().Equal(ubds.UnbondingResponses[0].DelegatorAddress, val.Address.String())
   527  			}
   528  		})
   529  	}
   530  }
   531  
   532  func (s *IntegrationTestSuite) TestGetCmdQueryUnbondingDelegation() {
   533  	val := s.network.Validators[0]
   534  
   535  	testCases := []struct {
   536  		name   string
   537  		args   []string
   538  		expErr bool
   539  	}{
   540  		{
   541  			"wrong delegator address",
   542  			[]string{
   543  				"wrongDelAddr",
   544  				val.ValAddress.String(),
   545  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   546  			},
   547  			true,
   548  		},
   549  		{
   550  			"wrong validator address",
   551  			[]string{
   552  				val.Address.String(),
   553  				"wrongValAddr",
   554  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   555  			},
   556  			true,
   557  		},
   558  		{
   559  			"valid request",
   560  			[]string{
   561  				val.Address.String(),
   562  				val.ValAddress.String(),
   563  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   564  			},
   565  			false,
   566  		},
   567  	}
   568  
   569  	for _, tc := range testCases {
   570  		tc := tc
   571  		s.Run(tc.name, func() {
   572  			cmd := cli.GetCmdQueryUnbondingDelegation()
   573  			clientCtx := val.ClientCtx
   574  
   575  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   576  
   577  			if tc.expErr {
   578  				s.Require().Error(err)
   579  			} else {
   580  				var ubd types.UnbondingDelegation
   581  
   582  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &ubd)
   583  				s.Require().NoError(err)
   584  				s.Require().Equal(ubd.DelegatorAddress, val.Address.String())
   585  				s.Require().Equal(ubd.ValidatorAddress, val.ValAddress.String())
   586  				s.Require().Len(ubd.Entries, 1)
   587  			}
   588  		})
   589  	}
   590  }
   591  
   592  func (s *IntegrationTestSuite) TestGetCmdQueryValidatorUnbondingDelegations() {
   593  	val := s.network.Validators[0]
   594  
   595  	testCases := []struct {
   596  		name   string
   597  		args   []string
   598  		expErr bool
   599  	}{
   600  		{
   601  			"wrong validator address",
   602  			[]string{
   603  				"wrongValAddr",
   604  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   605  			},
   606  			true,
   607  		},
   608  		{
   609  			"valid request",
   610  			[]string{
   611  				val.ValAddress.String(),
   612  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   613  			},
   614  			false,
   615  		},
   616  	}
   617  
   618  	for _, tc := range testCases {
   619  		tc := tc
   620  		s.Run(tc.name, func() {
   621  			cmd := cli.GetCmdQueryValidatorUnbondingDelegations()
   622  			clientCtx := val.ClientCtx
   623  
   624  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   625  
   626  			if tc.expErr {
   627  				s.Require().Error(err)
   628  			} else {
   629  				var ubds types.QueryValidatorUnbondingDelegationsResponse
   630  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &ubds)
   631  
   632  				s.Require().NoError(err)
   633  				s.Require().Len(ubds.UnbondingResponses, 1)
   634  				s.Require().Equal(ubds.UnbondingResponses[0].DelegatorAddress, val.Address.String())
   635  			}
   636  		})
   637  	}
   638  }
   639  
   640  func (s *IntegrationTestSuite) TestGetCmdQueryRedelegations() {
   641  	val := s.network.Validators[0]
   642  	val2 := s.network.Validators[1]
   643  
   644  	testCases := []struct {
   645  		name   string
   646  		args   []string
   647  		expErr bool
   648  	}{
   649  		{
   650  			"wrong delegator address",
   651  			[]string{
   652  				"wrongdeladdr",
   653  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   654  			},
   655  			true,
   656  		},
   657  		{
   658  			"valid request",
   659  			[]string{
   660  				val.Address.String(),
   661  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   662  			},
   663  			false,
   664  		},
   665  	}
   666  
   667  	for _, tc := range testCases {
   668  		tc := tc
   669  		s.Run(tc.name, func() {
   670  			cmd := cli.GetCmdQueryRedelegations()
   671  			clientCtx := val.ClientCtx
   672  
   673  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   674  
   675  			if tc.expErr {
   676  				s.Require().Error(err)
   677  			} else {
   678  				var redelegations types.QueryRedelegationsResponse
   679  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &redelegations)
   680  
   681  				s.Require().NoError(err)
   682  
   683  				s.Require().Len(redelegations.RedelegationResponses, 1)
   684  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.DelegatorAddress, val.Address.String())
   685  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorSrcAddress, val.ValAddress.String())
   686  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorDstAddress, val2.ValAddress.String())
   687  			}
   688  		})
   689  	}
   690  }
   691  
   692  func (s *IntegrationTestSuite) TestGetCmdQueryRedelegation() {
   693  	val := s.network.Validators[0]
   694  	val2 := s.network.Validators[1]
   695  
   696  	testCases := []struct {
   697  		name   string
   698  		args   []string
   699  		expErr bool
   700  	}{
   701  		{
   702  			"wrong delegator address",
   703  			[]string{
   704  				"wrongdeladdr",
   705  				val.ValAddress.String(),
   706  				val2.ValAddress.String(),
   707  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   708  			},
   709  			true,
   710  		},
   711  		{
   712  			"wrong source validator address address",
   713  			[]string{
   714  				val.Address.String(),
   715  				"wrongSrcValAddress",
   716  				val2.ValAddress.String(),
   717  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   718  			},
   719  			true,
   720  		},
   721  		{
   722  			"wrong destination validator address address",
   723  			[]string{
   724  				val.Address.String(),
   725  				val.ValAddress.String(),
   726  				"wrongDestValAddress",
   727  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   728  			},
   729  			true,
   730  		},
   731  		{
   732  			"valid request",
   733  			[]string{
   734  				val.Address.String(),
   735  				val.ValAddress.String(),
   736  				val2.ValAddress.String(),
   737  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   738  			},
   739  			false,
   740  		},
   741  	}
   742  
   743  	for _, tc := range testCases {
   744  		tc := tc
   745  		s.Run(tc.name, func() {
   746  			cmd := cli.GetCmdQueryRedelegation()
   747  			clientCtx := val.ClientCtx
   748  
   749  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   750  
   751  			if tc.expErr {
   752  				s.Require().Error(err)
   753  			} else {
   754  				var redelegations types.QueryRedelegationsResponse
   755  
   756  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &redelegations)
   757  				s.Require().NoError(err)
   758  
   759  				s.Require().Len(redelegations.RedelegationResponses, 1)
   760  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.DelegatorAddress, val.Address.String())
   761  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorSrcAddress, val.ValAddress.String())
   762  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorDstAddress, val2.ValAddress.String())
   763  			}
   764  		})
   765  	}
   766  }
   767  
   768  func (s *IntegrationTestSuite) TestGetCmdQueryValidatorRedelegations() {
   769  	val := s.network.Validators[0]
   770  	val2 := s.network.Validators[1]
   771  
   772  	testCases := []struct {
   773  		name   string
   774  		args   []string
   775  		expErr bool
   776  	}{
   777  		{
   778  			"wrong validator address",
   779  			[]string{
   780  				"wrongValAddr",
   781  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   782  			},
   783  			true,
   784  		},
   785  		{
   786  			"valid request",
   787  			[]string{
   788  				val.ValAddress.String(),
   789  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   790  			},
   791  			false,
   792  		},
   793  	}
   794  
   795  	for _, tc := range testCases {
   796  		tc := tc
   797  		s.Run(tc.name, func() {
   798  			cmd := cli.GetCmdQueryValidatorRedelegations()
   799  			clientCtx := val.ClientCtx
   800  
   801  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   802  
   803  			if tc.expErr {
   804  				s.Require().Error(err)
   805  			} else {
   806  				var redelegations types.QueryRedelegationsResponse
   807  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &redelegations)
   808  
   809  				s.Require().NoError(err)
   810  
   811  				s.Require().Len(redelegations.RedelegationResponses, 1)
   812  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.DelegatorAddress, val.Address.String())
   813  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorSrcAddress, val.ValAddress.String())
   814  				s.Require().Equal(redelegations.RedelegationResponses[0].Redelegation.ValidatorDstAddress, val2.ValAddress.String())
   815  			}
   816  		})
   817  	}
   818  }
   819  
   820  func (s *IntegrationTestSuite) TestGetCmdQueryHistoricalInfo() {
   821  	val := s.network.Validators[0]
   822  
   823  	testCases := []struct {
   824  		name  string
   825  		args  []string
   826  		error bool
   827  	}{
   828  		{
   829  			"wrong height",
   830  			[]string{
   831  				"-1",
   832  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   833  			},
   834  			true,
   835  		},
   836  		{
   837  			"valid request",
   838  			[]string{
   839  				"1",
   840  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   841  			},
   842  			false,
   843  		},
   844  	}
   845  
   846  	for _, tc := range testCases {
   847  		tc := tc
   848  		s.Run(tc.name, func() {
   849  			cmd := cli.GetCmdQueryHistoricalInfo()
   850  			clientCtx := val.ClientCtx
   851  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   852  
   853  			if tc.error {
   854  				s.Require().Error(err)
   855  			} else {
   856  				var historicalInfo types.HistoricalInfo
   857  
   858  				err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &historicalInfo)
   859  				s.Require().NoError(err)
   860  				s.Require().NotNil(historicalInfo)
   861  			}
   862  		})
   863  	}
   864  }
   865  
   866  func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
   867  	val := s.network.Validators[0]
   868  	testCases := []struct {
   869  		name           string
   870  		args           []string
   871  		expectedOutput string
   872  	}{
   873  		{
   874  			"with text output",
   875  			[]string{fmt.Sprintf("--%s=text", ostcli.OutputFlag)},
   876  			`bond_denom: stake
   877  historical_entries: 10000
   878  max_entries: 7
   879  max_validators: 100
   880  unbonding_time: 1814400s`,
   881  		},
   882  		{
   883  			"with json output",
   884  			[]string{fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
   885  			`{"unbonding_time":"1814400s","max_validators":100,"max_entries":7,"historical_entries":10000,"bond_denom":"stake"}`,
   886  		},
   887  	}
   888  	for _, tc := range testCases {
   889  		tc := tc
   890  		s.Run(tc.name, func() {
   891  			cmd := cli.GetCmdQueryParams()
   892  			clientCtx := val.ClientCtx
   893  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   894  			s.Require().NoError(err)
   895  			s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String()))
   896  		})
   897  	}
   898  }
   899  
   900  func (s *IntegrationTestSuite) TestGetCmdQueryPool() {
   901  	val := s.network.Validators[0]
   902  	testCases := []struct {
   903  		name           string
   904  		args           []string
   905  		expectedOutput string
   906  	}{
   907  		{
   908  			"with text",
   909  			[]string{
   910  				fmt.Sprintf("--%s=text", ostcli.OutputFlag),
   911  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   912  			},
   913  			fmt.Sprintf(`bonded_tokens: "%s"
   914  not_bonded_tokens: "0"`, cli.DefaultTokens.Mul(sdk.NewInt(2)).String()),
   915  		},
   916  		{
   917  			"with json",
   918  			[]string{
   919  				fmt.Sprintf("--%s=json", ostcli.OutputFlag),
   920  				fmt.Sprintf("--%s=1", flags.FlagHeight),
   921  			},
   922  			fmt.Sprintf(`{"not_bonded_tokens":"0","bonded_tokens":"%s"}`, cli.DefaultTokens.Mul(sdk.NewInt(2)).String()),
   923  		},
   924  	}
   925  	for _, tc := range testCases {
   926  		tc := tc
   927  		s.Run(tc.name, func() {
   928  			cmd := cli.GetCmdQueryPool()
   929  			clientCtx := val.ClientCtx
   930  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
   931  			s.Require().NoError(err)
   932  			s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String()))
   933  		})
   934  	}
   935  }
   936  
   937  func (s *IntegrationTestSuite) TestNewEditValidatorCmd() {
   938  	val := s.network.Validators[0]
   939  
   940  	details := "bio"
   941  	identity := "test identity"
   942  	securityContact := "test contact"
   943  	website := "https://test.com"
   944  
   945  	testCases := []struct {
   946  		name         string
   947  		args         []string
   948  		expectErr    bool
   949  		expectedCode uint32
   950  		respType     proto.Message
   951  	}{
   952  		{
   953  			"with no edit flag (since all are optional)",
   954  			[]string{
   955  				fmt.Sprintf("--%s=%s", flags.FlagFrom, "with wrong from address"),
   956  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   957  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   958  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   959  			},
   960  			true, 0, nil,
   961  		},
   962  		{
   963  			"with no edit flag (since all are optional)",
   964  			[]string{
   965  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   966  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   967  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   968  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   969  			},
   970  			false, 0, &sdk.TxResponse{},
   971  		},
   972  		{
   973  			"edit validator details",
   974  			[]string{
   975  				fmt.Sprintf("--details=%s", details),
   976  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   977  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   978  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   979  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   980  			},
   981  			false, 0, &sdk.TxResponse{},
   982  		},
   983  		{
   984  			"edit validator identity",
   985  			[]string{
   986  				fmt.Sprintf("--identity=%s", identity),
   987  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   988  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   989  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
   990  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
   991  			},
   992  			false, 0, &sdk.TxResponse{},
   993  		},
   994  		{
   995  			"edit validator security-contact",
   996  			[]string{
   997  				fmt.Sprintf("--security-contact=%s", securityContact),
   998  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
   999  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1000  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1001  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1002  			},
  1003  			false, 0, &sdk.TxResponse{},
  1004  		},
  1005  		{
  1006  			"edit validator website",
  1007  			[]string{
  1008  				fmt.Sprintf("--website=%s", website),
  1009  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1010  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1011  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1012  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1013  			},
  1014  			false, 0, &sdk.TxResponse{},
  1015  		},
  1016  		{
  1017  			"with all edit flags",
  1018  			[]string{
  1019  				fmt.Sprintf("--details=%s", details),
  1020  				fmt.Sprintf("--identity=%s", identity),
  1021  				fmt.Sprintf("--security-contact=%s", securityContact),
  1022  				fmt.Sprintf("--website=%s", website),
  1023  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1024  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1025  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1026  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1027  			},
  1028  			false, 0, &sdk.TxResponse{},
  1029  		},
  1030  	}
  1031  
  1032  	for _, tc := range testCases {
  1033  		tc := tc
  1034  
  1035  		s.Run(tc.name, func() {
  1036  			cmd := cli.NewEditValidatorCmd()
  1037  			clientCtx := val.ClientCtx
  1038  
  1039  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1040  			if tc.expectErr {
  1041  				s.Require().Error(err)
  1042  			} else {
  1043  				s.Require().NoError(err, out.String())
  1044  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1045  
  1046  				txResp := tc.respType.(*sdk.TxResponse)
  1047  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1048  			}
  1049  		})
  1050  	}
  1051  }
  1052  
  1053  func (s *IntegrationTestSuite) TestNewDelegateCmd() {
  1054  	val := s.network.Validators[0]
  1055  
  1056  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
  1057  	s.Require().NoError(err)
  1058  
  1059  	newAddr := sdk.AccAddress(info.GetPubKey().Address())
  1060  
  1061  	_, err = banktestutil.MsgSendExec(
  1062  		val.ClientCtx,
  1063  		val.Address,
  1064  		newAddr,
  1065  		sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1066  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1067  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1068  	)
  1069  	s.Require().NoError(err)
  1070  
  1071  	testCases := []struct {
  1072  		name         string
  1073  		args         []string
  1074  		expectErr    bool
  1075  		expectedCode uint32
  1076  		respType     proto.Message
  1077  	}{
  1078  		{
  1079  			"without delegate amount",
  1080  			[]string{
  1081  				val.ValAddress.String(),
  1082  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1083  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1084  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1085  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1086  			},
  1087  			true, 0, nil,
  1088  		},
  1089  		{
  1090  			"without validator address",
  1091  			[]string{
  1092  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1093  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1094  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1095  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1096  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1097  			},
  1098  			true, 0, nil,
  1099  		},
  1100  		{
  1101  			"valid transaction of delegate",
  1102  			[]string{
  1103  				val.ValAddress.String(),
  1104  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1105  				fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1106  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1107  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1108  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1109  			},
  1110  			false, 0, &sdk.TxResponse{},
  1111  		},
  1112  	}
  1113  
  1114  	for _, tc := range testCases {
  1115  		tc := tc
  1116  
  1117  		s.Run(tc.name, func() {
  1118  			cmd := cli.NewDelegateCmd()
  1119  			clientCtx := val.ClientCtx
  1120  
  1121  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1122  			if tc.expectErr {
  1123  				s.Require().Error(err)
  1124  			} else {
  1125  				s.Require().NoError(err, out.String())
  1126  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1127  
  1128  				txResp := tc.respType.(*sdk.TxResponse)
  1129  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1130  			}
  1131  		})
  1132  	}
  1133  }
  1134  
  1135  func (s *IntegrationTestSuite) TestNewRedelegateCmd() {
  1136  	val := s.network.Validators[0]
  1137  	val2 := s.network.Validators[1]
  1138  
  1139  	testCases := []struct {
  1140  		name         string
  1141  		args         []string
  1142  		expectErr    bool
  1143  		expectedCode uint32
  1144  		respType     proto.Message
  1145  	}{
  1146  		{
  1147  			"without amount",
  1148  			[]string{
  1149  				val.ValAddress.String(),  // src-validator-addr
  1150  				val2.ValAddress.String(), // dst-validator-addr
  1151  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1152  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1153  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1154  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1155  			},
  1156  			true, 0, nil,
  1157  		},
  1158  		{
  1159  			"with wrong source validator address",
  1160  			[]string{
  1161  				`linkvaloper120yvjfy7m2gnu9mvusrs40cxxhpt8nr3jr36d2`,   // src-validator-addr
  1162  				val2.ValAddress.String(),                               // dst-validator-addr
  1163  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(), // amount
  1164  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1165  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1166  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1167  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1168  			},
  1169  			false, 3, &sdk.TxResponse{},
  1170  		},
  1171  		{
  1172  			"with wrong destination validator address",
  1173  			[]string{
  1174  				val.ValAddress.String(),                                // dst-validator-addr
  1175  				`linkvaloper120yvjfy7m2gnu9mvusrs40cxxhpt8nr3jr36d2`,   // src-validator-addr
  1176  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(), // amount
  1177  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1178  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1179  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1180  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1181  			},
  1182  			false, 31, &sdk.TxResponse{},
  1183  		},
  1184  		{
  1185  			"valid transaction of delegate",
  1186  			[]string{
  1187  				val.ValAddress.String(),                                // src-validator-addr
  1188  				val2.ValAddress.String(),                               // dst-validator-addr
  1189  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(), // amount
  1190  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1191  				fmt.Sprintf("--%s=%s", flags.FlagGas, "auto"),
  1192  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1193  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1194  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1195  			},
  1196  			false, 0, &sdk.TxResponse{},
  1197  		},
  1198  	}
  1199  
  1200  	for _, tc := range testCases {
  1201  		tc := tc
  1202  
  1203  		s.Run(tc.name, func() {
  1204  			cmd := cli.NewRedelegateCmd()
  1205  			clientCtx := val.ClientCtx
  1206  
  1207  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1208  			if tc.expectErr {
  1209  				s.Require().Error(err)
  1210  			} else {
  1211  				s.Require().NoError(err, out.String())
  1212  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1213  
  1214  				txResp := tc.respType.(*sdk.TxResponse)
  1215  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1216  			}
  1217  		})
  1218  	}
  1219  }
  1220  
  1221  func (s *IntegrationTestSuite) TestNewUnbondCmd() {
  1222  	val := s.network.Validators[0]
  1223  
  1224  	testCases := []struct {
  1225  		name         string
  1226  		args         []string
  1227  		expectErr    bool
  1228  		expectedCode uint32
  1229  		respType     proto.Message
  1230  	}{
  1231  		{
  1232  			"Without unbond amount",
  1233  			[]string{
  1234  				val.ValAddress.String(),
  1235  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1236  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1237  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1238  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1239  			},
  1240  			true, 0, nil,
  1241  		},
  1242  		{
  1243  			"Without validator address",
  1244  			[]string{
  1245  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1246  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1247  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1248  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1249  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1250  			},
  1251  			true, 0, nil,
  1252  		},
  1253  		{
  1254  			"valid transaction of unbond",
  1255  			[]string{
  1256  				val.ValAddress.String(),
  1257  				sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1258  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1259  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1260  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1261  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1262  			},
  1263  			false, 0, &sdk.TxResponse{},
  1264  		},
  1265  	}
  1266  
  1267  	for _, tc := range testCases {
  1268  		tc := tc
  1269  
  1270  		s.Run(tc.name, func() {
  1271  			cmd := cli.NewUnbondCmd()
  1272  			clientCtx := val.ClientCtx
  1273  
  1274  			out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
  1275  			if tc.expectErr {
  1276  				s.Require().Error(err)
  1277  			} else {
  1278  				s.Require().NoError(err, out.String())
  1279  				s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
  1280  
  1281  				txResp := tc.respType.(*sdk.TxResponse)
  1282  				s.Require().Equal(tc.expectedCode, txResp.Code, out.String())
  1283  			}
  1284  		})
  1285  	}
  1286  }
  1287  
  1288  // TestBlockResults tests that the validator updates correctly show when
  1289  // calling the /block_results RPC endpoint.
  1290  // ref: https://github.com/cosmos/cosmos-sdk/issues/7401.
  1291  func (s *IntegrationTestSuite) TestBlockResults() {
  1292  	require := s.Require()
  1293  	val := s.network.Validators[0]
  1294  
  1295  	// Create new account in the keyring.
  1296  	info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
  1297  	require.NoError(err)
  1298  	newAddr := sdk.AccAddress(info.GetPubKey().Address())
  1299  
  1300  	// Send some funds to the new account.
  1301  	_, err = banktestutil.MsgSendExec(
  1302  		val.ClientCtx,
  1303  		val.Address,
  1304  		newAddr,
  1305  		sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1306  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1307  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1308  	)
  1309  	require.NoError(err)
  1310  
  1311  	// Use CLI to create a delegation from the new account to validator `val`.
  1312  	delHeight, err := s.network.LatestHeight()
  1313  	require.NoError(err)
  1314  	cmd := cli.NewDelegateCmd()
  1315  	_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, []string{
  1316  		val.ValAddress.String(),
  1317  		sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(150)).String(),
  1318  		fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr.String()),
  1319  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1320  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1321  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1322  	})
  1323  	require.NoError(err)
  1324  
  1325  	// Create a HTTP rpc client.
  1326  	rpcClient, err := http.New(val.RPCAddress, "/websocket")
  1327  	require.NoError(err)
  1328  
  1329  	// Loop until we find a block result with the correct validator updates.
  1330  	// By experience, it happens around 2 blocks after `delHeight`.
  1331  	for {
  1332  		latestHeight, err := s.network.LatestHeight()
  1333  		require.NoError(err)
  1334  
  1335  		// Wait maximum 10 blocks, or else fail test.
  1336  		if latestHeight > delHeight+10 {
  1337  			s.Fail("timeout reached")
  1338  		}
  1339  
  1340  		res, err := rpcClient.BlockResults(context.Background(), &latestHeight)
  1341  		require.NoError(err)
  1342  
  1343  		if len(res.ValidatorUpdates) > 0 {
  1344  			valUpdate := res.ValidatorUpdates[0]
  1345  			require.Equal(
  1346  				valUpdate.GetPubKey().Sum.(*crypto.PublicKey_Ed25519).Ed25519,
  1347  				val.PubKey.Bytes(),
  1348  			)
  1349  
  1350  			// We got our validator update, test passed.
  1351  			break
  1352  		}
  1353  
  1354  		s.network.WaitForNextBlock()
  1355  	}
  1356  }
  1357  
  1358  // https://github.com/cosmos/cosmos-sdk/issues/10660
  1359  func (s *IntegrationTestSuite) TestEditValidatorMoniker() {
  1360  	val := s.network.Validators[0]
  1361  	require := s.Require()
  1362  
  1363  	txCmd := cli.NewEditValidatorCmd()
  1364  	moniker := "testing"
  1365  	_, err := clitestutil.ExecTestCLICmd(val.ClientCtx, txCmd, []string{
  1366  		val.ValAddress.String(),
  1367  		fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1368  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1369  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1370  		fmt.Sprintf("--%s=%s", cli.FlagEditMoniker, moniker),
  1371  		fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
  1372  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1373  	})
  1374  	require.NoError(err)
  1375  
  1376  	queryCmd := cli.GetCmdQueryValidator()
  1377  	res, err := clitestutil.ExecTestCLICmd(
  1378  		val.ClientCtx, queryCmd,
  1379  		[]string{val.ValAddress.String(), fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
  1380  	)
  1381  	require.NoError(err)
  1382  	var result types.Validator
  1383  	require.NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &result))
  1384  	require.Equal(result.GetMoniker(), moniker)
  1385  
  1386  	_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, txCmd, []string{
  1387  		val.ValAddress.String(),
  1388  		fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
  1389  		fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
  1390  		fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
  1391  		fmt.Sprintf("--%s=https://newvalidator.io", cli.FlagWebsite),
  1392  		fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
  1393  	})
  1394  	require.NoError(err)
  1395  
  1396  	res, err = clitestutil.ExecTestCLICmd(
  1397  		val.ClientCtx, queryCmd,
  1398  		[]string{val.ValAddress.String(), fmt.Sprintf("--%s=json", ostcli.OutputFlag)},
  1399  	)
  1400  	require.NoError(err)
  1401  
  1402  	require.NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &result))
  1403  	require.Equal(result.GetMoniker(), moniker)
  1404  }