-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make stakeibc/cli unit tests fast and add more tests
Instead of starting a new test chain, we just need to create a clientCtx and pass it to the command line functions. That's because the test chain waits for all the API server to start, which takes about 17s: - https://github.com/cosmos/cosmos-sdk/blob/d1b5b0c5a/testutil/network/util.go#L90-L94 - https://github.com/cosmos/cosmos-sdk/blob/d1b5b0c5a/server/grpc/server.go#L76-L83 - https://github.com/cosmos/cosmos-sdk/blob/d1b5b0c5a/server/grpc/grpc_web.go#L40-L45
- Loading branch information
Showing
2 changed files
with
88 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,22 @@ | ||
package cli_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
tmcli "github.com/cometbft/cometbft/libs/cli" | ||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/spf13/cobra" | ||
"github.com/stretchr/testify/suite" | ||
|
||
"github.com/Stride-Labs/stride/v22/app" | ||
cmdcfg "github.com/Stride-Labs/stride/v22/cmd/strided/config" | ||
strideclitestutil "github.com/Stride-Labs/stride/v22/testutil/cli" | ||
"github.com/Stride-Labs/stride/v22/testutil/network" | ||
) | ||
|
||
var HostChainId = "chain-1" | ||
|
||
type ClientTestSuite struct { | ||
suite.Suite | ||
|
||
cfg network.Config | ||
network *network.Network | ||
val *network.Validator | ||
} | ||
|
||
func TestClientTestSuite(t *testing.T) { | ||
suite.Run(t, new(ClientTestSuite)) | ||
} | ||
|
||
func (s *ClientTestSuite) SetupSuite() { | ||
s.T().Log("setting up client test suite") | ||
|
||
s.cfg = network.DefaultConfig() | ||
|
||
genState := app.ModuleBasics.DefaultGenesis(s.cfg.Codec) | ||
|
||
s.cfg.GenesisState = genState | ||
s.network = network.New(s.T(), s.cfg) | ||
"github.com/stretchr/testify/require" | ||
|
||
_, err := s.network.WaitForHeight(1) | ||
s.Require().NoError(err) | ||
|
||
s.val = s.network.Validators[0] | ||
|
||
cmdcfg.RegisterDenoms() | ||
} | ||
|
||
func (s *ClientTestSuite) ExecuteTxAndCheckSuccessful(cmd *cobra.Command, args []string) { | ||
defaultFlags := []string{ | ||
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.val.Address.String()), | ||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), | ||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), | ||
fmt.Sprintf("--%s=json", tmcli.OutputFlag), | ||
strideclitestutil.DefaultFeeString(s.cfg), | ||
} | ||
args = append(args, defaultFlags...) | ||
|
||
clientCtx := s.val.ClientCtx | ||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) | ||
s.Require().NoError(err) | ||
|
||
var response sdk.TxResponse | ||
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response)) | ||
} | ||
"github.com/cosmos/cosmos-sdk/client" | ||
) | ||
|
||
func (s *ClientTestSuite) ExecuteCLIExpectError(cmd *cobra.Command, args []string, errorString string) { | ||
defaultFlags := []string{ | ||
fmt.Sprintf("--%s=%s", flags.FlagFrom, s.val.Address.String()), | ||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), | ||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), | ||
fmt.Sprintf("--%s=json", tmcli.OutputFlag), | ||
strideclitestutil.DefaultFeeString(s.cfg), | ||
} | ||
args = append(args, defaultFlags...) | ||
func ExecuteCLIExpectError(t *testing.T, cmd *cobra.Command, args []string, errorString string) { | ||
sdk.GetConfig().SetBech32PrefixForAccount("stride", "stridepub") | ||
|
||
clientCtx := s.val.ClientCtx | ||
_, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) | ||
s.Require().ErrorContains(err, errorString) | ||
} | ||
clientCtx := client.Context{}.WithFromAddress(sdk.MustAccAddressFromBech32("stride10p3xzmnpdeshqctsv9ukzcm0vdhkuat52aucqd")) | ||
|
||
func (s *ClientTestSuite) ExecuteQueryAndCheckSuccessful(cmd *cobra.Command, args []string) { | ||
clientCtx := s.val.ClientCtx | ||
_, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) | ||
s.Require().NoError(err) | ||
require.ErrorContains(t, err, errorString) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,197 +1,225 @@ | ||
package cli_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/Stride-Labs/stride/v22/x/stakeibc/client/cli" | ||
) | ||
|
||
func (s *ClientTestSuite) TestCmdLiquidStake() { | ||
func TestCmdLiquidStake(t *testing.T) { | ||
args := []string{ | ||
"banana", | ||
"[lsm-token-denom]", | ||
} | ||
|
||
cmd := cli.CmdLiquidStake() | ||
s.ExecuteCLIExpectError(cmd, args, "can not convert string to int") | ||
ExecuteCLIExpectError(t, cmd, args, "can not convert string to int") | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdLSMLiquidStake() { | ||
func TestCmdLSMLiquidStake(t *testing.T) { | ||
args := []string{ | ||
"banana", | ||
"[lsm-token-denom]", | ||
} | ||
|
||
cmd := cli.CmdLSMLiquidStake() | ||
s.ExecuteCLIExpectError(cmd, args, "can not convert string to int") | ||
ExecuteCLIExpectError(t, cmd, args, "can not convert string to int") | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdRegisterHostZone() { | ||
s.T().Run("unbonding-period not a number", func(t *testing.T) { | ||
func TestCmdRegisterHostZone(t *testing.T) { | ||
t.Run("unbonding-period not a number", func(t *testing.T) { | ||
args := []string{ | ||
"[connection-id]", "[host-denom]", "[bech32prefix]", "[ibc-denom]", "[channel-id]", "banana", "1", | ||
"[connection-id]", "[host-denom]", "[bech32prefix]", "[ibc-denom]", "[channel-id]", "[unbonding-period]", "1", | ||
} | ||
|
||
cmd := cli.CmdRegisterHostZone() | ||
s.ExecuteCLIExpectError(cmd, args, `strconv.ParseUint: parsing "banana": invalid syntax`) | ||
ExecuteCLIExpectError(t, cmd, args, `strconv.ParseUint: parsing "[unbonding-period]": invalid syntax`) | ||
}) | ||
|
||
s.T().Run("lsm-enabled not a boolean", func(t *testing.T) { | ||
t.Run("lsm-enabled not a boolean", func(t *testing.T) { | ||
args := []string{ | ||
"[connection-id]", "[host-denom]", "[bech32prefix]", "[ibc-denom]", "[channel-id]", "0", "2", | ||
} | ||
|
||
cmd := cli.CmdRegisterHostZone() | ||
s.ExecuteCLIExpectError(cmd, args, `strconv.ParseBool: parsing "2": invalid syntax`) | ||
ExecuteCLIExpectError(t, cmd, args, `strconv.ParseBool: parsing "2": invalid syntax`) | ||
}) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdRedeemStake() { | ||
func TestCmdRedeemStake(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
"[amount]", "[hostZoneID]", "[receiver]", | ||
} | ||
|
||
cmd := cli.CmdRedeemStake() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdClaimUndelegatedTokens() { | ||
func TestCmdClaimUndelegatedTokens(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
"[host-zone]", "[epoch]", "[receiver]", | ||
} | ||
|
||
cmd := cli.CmdClaimUndelegatedTokens() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `unable to cast "[epoch]" of type string to uint64`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdRebalanceValidators() { | ||
func TestCmdRebalanceValidators(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
"[host-zone]", "[num-to-rebalance]", | ||
} | ||
|
||
cmd := cli.CmdRebalanceValidators() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `strconv.ParseUint: parsing "[num-to-rebalance]": invalid syntax`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdAddValidators() { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
func TestCmdAddValidators(t *testing.T) { | ||
t.Run("no file", func(t *testing.T) { | ||
args := []string{ | ||
"[host-zone]", "[validator-list-file]", | ||
} | ||
|
||
cmd := cli.CmdAddValidators() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
cmd := cli.CmdAddValidators() | ||
ExecuteCLIExpectError(t, cmd, args, `open [validator-list-file]: no such file or directory`) | ||
}) | ||
t.Run("empty file", func(t *testing.T) { | ||
// pass an temp file | ||
f, err := os.CreateTemp("", "") | ||
require.NoError(t, err) | ||
defer f.Close() | ||
|
||
args := []string{ | ||
"[host-zone]", f.Name(), | ||
} | ||
|
||
cmd := cli.CmdAddValidators() | ||
ExecuteCLIExpectError(t, cmd, args, `unexpected end of JSON input`) | ||
}) | ||
t.Run("non-JSON file", func(t *testing.T) { | ||
// pass a temp file with non-JSON content | ||
f, err := os.CreateTemp("", "") | ||
require.NoError(t, err) | ||
defer f.Close() | ||
_, err = f.WriteString("This is not JSON") | ||
require.NoError(t, err) | ||
|
||
args := []string{ | ||
"[host-zone]", f.Name(), | ||
} | ||
|
||
cmd := cli.CmdAddValidators() | ||
ExecuteCLIExpectError(t, cmd, args, `invalid character 'T' looking for beginning of value`) | ||
}) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdChangeValidatorWeight() { | ||
func TestCmdChangeValidatorWeight(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
"[host-zone]", "[address]", "[weight]", | ||
} | ||
|
||
cmd := cli.CmdChangeValidatorWeight() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `unable to cast "[weight]" of type string to uint64`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdChangeMultipleValidatorWeight() { | ||
func TestCmdChangeMultipleValidatorWeight(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdChangeMultipleValidatorWeight() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdDeleteValidator() { | ||
func TestCmdDeleteValidator(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdDeleteValidator() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdRestoreInterchainAccount() { | ||
func TestCmdRestoreInterchainAccount(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdRestoreInterchainAccount() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdUpdateValidatorSharesExchRate() { | ||
func TestCmdUpdateValidatorSharesExchRate(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdUpdateValidatorSharesExchRate() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdCalibrateDelegation() { | ||
func TestCmdCalibrateDelegation(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdCalibrateDelegation() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdClearBalance() { | ||
func TestCmdClearBalance(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdClearBalance() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdUpdateInnerRedemptionRateBounds() { | ||
func TestCmdUpdateInnerRedemptionRateBounds(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdUpdateInnerRedemptionRateBounds() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdResumeHostZone() { | ||
func TestCmdResumeHostZone(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdResumeHostZone() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdSetCommunityPoolRebate() { | ||
func TestCmdSetCommunityPoolRebate(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdSetCommunityPoolRebate() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} | ||
|
||
func (s *ClientTestSuite) TestCmdToggleTradeController() { | ||
func TestCmdToggleTradeController(t *testing.T) { | ||
args := []string{ | ||
"1", | ||
"utia", | ||
} | ||
|
||
cmd := cli.CmdToggleTradeController() | ||
s.ExecuteTxAndCheckSuccessful(cmd, args) | ||
ExecuteCLIExpectError(t, cmd, args, `can not convert string to int: invalid type`) | ||
} |