Skip to content

Commit

Permalink
Make stakeibc/cli unit tests fast and add more tests
Browse files Browse the repository at this point in the history
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
assafmo committed Jun 13, 2024
1 parent 1f9706f commit 90b4875
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 127 deletions.
81 changes: 7 additions & 74 deletions x/stakeibc/client/cli/cli_test.go
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)
}
134 changes: 81 additions & 53 deletions x/stakeibc/client/cli/tx_test.go
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`)
}

0 comments on commit 90b4875

Please sign in to comment.