From 621c03f74952eedc00f376208984e49b3fcf6442 Mon Sep 17 00:00:00 2001 From: 170210 <85928898+170210@users.noreply.github.com> Date: Fri, 24 May 2024 14:31:08 +0900 Subject: [PATCH] test: add cli_test for fswap module (#1391) * test: add cli_test for query Signed-off-by: 170210 * test: add cli_test for tx Signed-off-by: 170210 * chore: lint fix Signed-off-by: 170210 * chore: update CHANGLOG.md Signed-off-by: 170210 * chore: lint fix Signed-off-by: 170210 * test: add grpc query test Signed-off-by: 170210 * fix: change fromDenom & toDenom Signed-off-by: 170210 * fix: fix for comment Signed-off-by: 170210 --------- Signed-off-by: 170210 --- CHANGELOG.md | 1 + x/fswap/client/testutil/cli_test.go | 18 ++ x/fswap/client/testutil/grpc.go | 226 +++++++++++++++++++++ x/fswap/client/testutil/query.go | 246 +++++++++++++++++++++++ x/fswap/client/testutil/suite.go | 96 +++++++++ x/fswap/client/testutil/tx.go | 297 ++++++++++++++++++++++++++++ 6 files changed, 884 insertions(+) create mode 100644 x/fswap/client/testutil/cli_test.go create mode 100644 x/fswap/client/testutil/grpc.go create mode 100644 x/fswap/client/testutil/query.go create mode 100644 x/fswap/client/testutil/suite.go create mode 100644 x/fswap/client/testutil/tx.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 38b67292ea..491e929a71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/fswap) [\#1387](https://github.com/Finschia/finschia-sdk/pull/1387) add new Swap query to get a single swap * (x/fswap) [\#1382](https://github.com/Finschia/finschia-sdk/pull/1382) add validation & unit tests in fswap module * (x/fswap) [\#1396](https://github.com/Finschia/finschia-sdk/pull/1396) refactor to use snake_case in proto +* (x/fswap) [\#1391](https://github.com/Finschia/finschia-sdk/pull/1391) add cli_test for fswap module ### Bug Fixes * chore(deps) [\#1141](https://github.com/Finschia/finschia-sdk/pull/1141) Bump github.com/cosmos/ledger-cosmos-go from 0.12.2 to 0.13.2 to fix ledger signing issue diff --git a/x/fswap/client/testutil/cli_test.go b/x/fswap/client/testutil/cli_test.go new file mode 100644 index 0000000000..15c377bbb9 --- /dev/null +++ b/x/fswap/client/testutil/cli_test.go @@ -0,0 +1,18 @@ +//go:build norace +// +build norace + +package testutil + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/Finschia/finschia-sdk/testutil/network" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/fswap/client/testutil/grpc.go b/x/fswap/client/testutil/grpc.go new file mode 100644 index 0000000000..74e81b200a --- /dev/null +++ b/x/fswap/client/testutil/grpc.go @@ -0,0 +1,226 @@ +package testutil + +import ( + "fmt" + + "github.com/gogo/protobuf/proto" + + "github.com/Finschia/finschia-sdk/testutil" + "github.com/Finschia/finschia-sdk/testutil/rest" + sdk "github.com/Finschia/finschia-sdk/types" + grpctypes "github.com/Finschia/finschia-sdk/types/grpc" + "github.com/Finschia/finschia-sdk/types/query" + fswaptypes "github.com/Finschia/finschia-sdk/x/fswap/types" +) + +func (s *IntegrationTestSuite) TestGRPCQuerySwap() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + testCases := []struct { + name string + url string + expectedErr bool + expected proto.Message + }{ + { + "test query swap with valid query string", + fmt.Sprintf("%s/lbm/fswap/v1/swap?from_denom=stake&to_denom=dummy", baseURL), + false, + &fswaptypes.QuerySwapResponse{ + Swap: s.dummySwap, + }, + }, + { + "test query swap with not existed swap pairs", + fmt.Sprintf("%s/lbm/fswap/v1/swap?from_denom=fake&to_denom=dummy", baseURL), + true, + &fswaptypes.QuerySwapResponse{}, + }, + { + "test query swap with nil to_denom", + fmt.Sprintf("%s/lbm/fswap/v1/swap?from_denom=stake", baseURL), + true, + &fswaptypes.QuerySwapResponse{}, + }, + { + "test query swap with nil from_denom", + fmt.Sprintf("%s/lbm/fswap/v1/swap?to_denom=dummy", baseURL), + true, + &fswaptypes.QuerySwapResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, err := rest.GetRequest(tc.url) + s.Require().NoError(err) + var valRes fswaptypes.QuerySwapResponse + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &valRes) + + if tc.expectedErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Equal(tc.expected.String(), valRes.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestGRPCQuerySwaps() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + testCases := []struct { + name string + url string + expectedErr bool + expected proto.Message + }{ + { + "test query swaps", + fmt.Sprintf("%s/lbm/fswap/v1/swaps", baseURL), + false, + &fswaptypes.QuerySwapsResponse{ + Swaps: []fswaptypes.Swap{s.dummySwap}, + Pagination: &query.PageResponse{Total: 1}, + }, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, err := rest.GetRequest(tc.url) + s.Require().NoError(err) + var valRes fswaptypes.QuerySwapsResponse + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &valRes) + + if tc.expectedErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Equal(tc.expected.String(), valRes.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestGRPCQuerySwapped() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + testCases := []struct { + name string + url string + expectedErr bool + expected proto.Message + }{ + { + "test query swapped with valid query string", + fmt.Sprintf("%s/lbm/fswap/v1/swapped?from_denom=stake&to_denom=dummy", baseURL), + false, + &fswaptypes.QuerySwappedResponse{ + FromCoinAmount: sdk.NewCoin("stake", sdk.ZeroInt()), + ToCoinAmount: sdk.NewCoin("dummy", sdk.ZeroInt()), + }, + }, + { + "test query swapped with not existed swap pairs", + fmt.Sprintf("%s/lbm/fswap/v1/swapped?from_denom=fake&to_denom=dummy", baseURL), + true, + &fswaptypes.QuerySwappedResponse{}, + }, + { + "test query swapped with nil to_denom", + fmt.Sprintf("%s/lbm/fswap/v1/swapped?from_denom=stake", baseURL), + true, + &fswaptypes.QuerySwappedResponse{}, + }, + { + "test query swapped with nil from_denom", + fmt.Sprintf("%s/lbm/fswap/v1/swapped?to_denom=dummy", baseURL), + true, + &fswaptypes.QuerySwappedResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, err := testutil.GetRequestWithHeaders(tc.url, map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }) + s.Require().NoError(err) + var valRes fswaptypes.QuerySwappedResponse + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &valRes) + + if tc.expectedErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Equal(tc.expected.String(), valRes.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestGRPCQueryTotalSwappableAmount() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + testCases := []struct { + name string + url string + expectedErr bool + expected proto.Message + }{ + { + "test query total_swappable_to_coin_amount with valid query string", + fmt.Sprintf("%s/lbm/fswap/v1/total_swappable_to_coin_amount?from_denom=stake&to_denom=dummy", baseURL), + false, + &fswaptypes.QueryTotalSwappableToCoinAmountResponse{ + SwappableAmount: sdk.NewCoin("dummy", s.dummySwap.AmountCapForToDenom), + }, + }, + { + "test query total_swappable_to_coin_amount with not existed swap pairs", + fmt.Sprintf("%s/lbm/fswap/v1/total_swappable_to_coin_amount?from_denom=fake&to_denom=dummy", baseURL), + true, + &fswaptypes.QueryTotalSwappableToCoinAmountResponse{}, + }, + { + "test query total_swappable_to_coin_amount with nil to_denom", + fmt.Sprintf("%s/lbm/fswap/v1/total_swappable_to_coin_amount?from_denom=stake", baseURL), + true, + &fswaptypes.QueryTotalSwappableToCoinAmountResponse{}, + }, + { + "test query total_swappable_to_coin_amount with nil from_denom", + fmt.Sprintf("%s/lbm/fswap/v1/total_swappable_to_coin_amount?to_denom=dummy", baseURL), + true, + &fswaptypes.QueryTotalSwappableToCoinAmountResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, err := testutil.GetRequestWithHeaders(tc.url, map[string]string{ + grpctypes.GRPCBlockHeightHeader: "1", + }) + s.Require().NoError(err) + var valRes fswaptypes.QueryTotalSwappableToCoinAmountResponse + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &valRes) + + if tc.expectedErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Equal(tc.expected.String(), valRes.String()) + } + }) + } +} diff --git a/x/fswap/client/testutil/query.go b/x/fswap/client/testutil/query.go new file mode 100644 index 0000000000..4e4004f8b5 --- /dev/null +++ b/x/fswap/client/testutil/query.go @@ -0,0 +1,246 @@ +package testutil + +import ( + "github.com/gogo/protobuf/proto" + + clitestutil "github.com/Finschia/finschia-sdk/testutil/cli" + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/types/query" + "github.com/Finschia/finschia-sdk/x/fswap/client/cli" + fswaptypes "github.com/Finschia/finschia-sdk/x/fswap/types" +) + +func (s *IntegrationTestSuite) TestCmdQuerySwapped() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + + fromDenom := s.cfg.BondDenom + toDenom := s.toDenom.Base + + testCases := []struct { + name string + args []string + expectErr bool + expected proto.Message + }{ + { + "valid query", + []string{fromDenom, toDenom}, + false, + &fswaptypes.QuerySwappedResponse{ + FromCoinAmount: sdk.NewCoin(fromDenom, sdk.ZeroInt()), + ToCoinAmount: sdk.NewCoin(toDenom, sdk.ZeroInt()), + }, + }, + { + "wrong number of args", + []string{fromDenom, toDenom, "extra"}, + true, + nil, + }, + { + "invalid fromDenom", + []string{"", toDenom}, + true, + nil, + }, + { + "invalid toDenom", + []string{fromDenom, ""}, + true, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdQuerySwapped() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + var actual fswaptypes.QuerySwappedResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &actual)) + s.Require().Equal(tc.expected, &actual) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQueryTotalSwappableAmount() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + + fromDenom := s.cfg.BondDenom + toDenom := s.toDenom.Base + + testCases := []struct { + name string + args []string + expectErr bool + expected proto.Message + }{ + { + "valid query", + []string{fromDenom, toDenom}, + false, + &fswaptypes.QueryTotalSwappableToCoinAmountResponse{ + SwappableAmount: sdk.NewCoin(toDenom, s.dummySwap.AmountCapForToDenom), + }, + }, + { + "wrong number of args", + []string{fromDenom, toDenom, "extra"}, + true, + nil, + }, + { + "invalid fromDenom", + []string{"", toDenom}, + true, + nil, + }, + { + "invalid toDenom", + []string{fromDenom, ""}, + true, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdQueryTotalSwappableAmount() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + var actual fswaptypes.QueryTotalSwappableToCoinAmountResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &actual)) + s.Require().Equal(tc.expected, &actual) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQuerySwap() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + + fromDenom := s.cfg.BondDenom + toDenom := s.toDenom.Base + + testCases := []struct { + name string + args []string + expectErr bool + expected proto.Message + }{ + { + "valid query", + []string{fromDenom, toDenom}, + false, + &fswaptypes.QuerySwapResponse{ + Swap: s.dummySwap, + }, + }, + { + "wrong number of args", + []string{fromDenom, toDenom, "extra"}, + true, + nil, + }, + { + "invalid fromDenom", + []string{"", toDenom}, + true, + nil, + }, + { + "invalid toDenom", + []string{fromDenom, ""}, + true, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdQuerySwap() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + var actual fswaptypes.QuerySwapResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &actual)) + s.Require().Equal(tc.expected, &actual) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdQuerySwaps() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + + testCases := []struct { + name string + args []string + expectErr bool + expected proto.Message + }{ + { + "valid query (default pagination)", + []string{}, + false, + &fswaptypes.QuerySwapsResponse{ + Swaps: []fswaptypes.Swap{s.dummySwap}, + Pagination: &query.PageResponse{Total: 1}, + }, + }, + { + "invalid query", + []string{"extra"}, + true, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdQuerySwaps() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + var actual fswaptypes.QuerySwapsResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &actual)) + s.Require().Equal(tc.expected, &actual) + } + }) + } +} diff --git a/x/fswap/client/testutil/suite.go b/x/fswap/client/testutil/suite.go new file mode 100644 index 0000000000..e3f3aab2c0 --- /dev/null +++ b/x/fswap/client/testutil/suite.go @@ -0,0 +1,96 @@ +package testutil + +import ( + "github.com/stretchr/testify/suite" + + "github.com/Finschia/finschia-sdk/testutil/network" + sdk "github.com/Finschia/finschia-sdk/types" + banktypes "github.com/Finschia/finschia-sdk/x/bank/types" + fswaptypes "github.com/Finschia/finschia-sdk/x/fswap/types" +) + +const jsonOutputFormat string = "JSON" + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + + authority sdk.AccAddress + toDenom banktypes.Metadata + dummySwap fswaptypes.Swap +} + +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + genesisState := s.cfg.GenesisState + var bankGenesis banktypes.GenesisState + s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[banktypes.ModuleName], &bankGenesis)) + s.toDenom = banktypes.Metadata{ + Name: "Dummy Coin", + Symbol: "Dummy", + Description: "The native token of Dummy chain", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "dummy", + Exponent: 0, + Aliases: []string{}, + }, + }, + Base: "dummy", + Display: "dummy", + } + bankGenesis.DenomMetadata = []banktypes.Metadata{s.toDenom} + bankDataBz, err := s.cfg.Codec.MarshalJSON(&bankGenesis) + s.Require().NoError(err) + genesisState[banktypes.ModuleName] = bankDataBz + + bondDenom := s.cfg.BondDenom + toDenom := s.toDenom.Base + + var fswapData fswaptypes.GenesisState + s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[fswaptypes.ModuleName], &fswapData)) + fswapData.SwapStats.SwapCount = 1 + s.dummySwap = fswaptypes.Swap{ + FromDenom: bondDenom, + ToDenom: toDenom, + AmountCapForToDenom: sdk.NewInt(12340000000000), + SwapRate: sdk.MustNewDecFromStr("1234"), + } + + fswapData.Swaps = []fswaptypes.Swap{s.dummySwap} + fswapData.Swappeds = []fswaptypes.Swapped{ + { + FromCoinAmount: sdk.Coin{ + Denom: bondDenom, + Amount: sdk.ZeroInt(), + }, + ToCoinAmount: sdk.Coin{ + Denom: toDenom, + Amount: sdk.ZeroInt(), + }, + }, + } + + fswapDataBz, err := s.cfg.Codec.MarshalJSON(&fswapData) + s.Require().NoError(err) + genesisState[fswaptypes.ModuleName] = fswapDataBz + s.cfg.GenesisState = genesisState + + s.network = network.New(s.T(), s.cfg) + s.authority = fswaptypes.DefaultAuthority() + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} diff --git a/x/fswap/client/testutil/tx.go b/x/fswap/client/testutil/tx.go new file mode 100644 index 0000000000..31fd363446 --- /dev/null +++ b/x/fswap/client/testutil/tx.go @@ -0,0 +1,297 @@ +package testutil + +import ( + "encoding/json" + "fmt" + + "github.com/gogo/protobuf/proto" + + "github.com/Finschia/finschia-sdk/client/flags" + clitestutil "github.com/Finschia/finschia-sdk/testutil/cli" + sdk "github.com/Finschia/finschia-sdk/types" + banktypes "github.com/Finschia/finschia-sdk/x/bank/types" + "github.com/Finschia/finschia-sdk/x/fswap/client/cli" +) + +func (s *IntegrationTestSuite) TestCmdTxMsgSwap() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + commonArgs := []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + }{ + { + "valid transaction", + []string{ + val.Address.String(), + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), + s.toDenom.Base, + }, + false, + &sdk.TxResponse{}, + }, + { + "invalid request (wrong number of args)", + []string{ + val.Address.String(), + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), + s.toDenom.Base, + "extra", + }, + true, + nil, + }, + { + "invalid request (invalid from address)", + []string{ + "invalidAddress", + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), + s.toDenom.Base, + }, + true, + nil, + }, + { + "invalid request (invalid from coin amount)", + []string{ + val.Address.String(), + "", + s.toDenom.Base, + }, + true, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdTxMsgSwap() + bz, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, append(tc.args, commonArgs...)) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(bz.Bytes(), tc.respType), bz.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdTxMsgSwapAll() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + commonArgs := []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + }{ + { + "valid transaction", + []string{ + val.Address.String(), + s.cfg.BondDenom, + s.toDenom.Base, + }, + false, + &sdk.TxResponse{}, + }, + { + "invalid request (wrong number of args)", + []string{ + val.Address.String(), + s.cfg.BondDenom, + s.toDenom.Base, + "extra", + }, + true, + nil, + }, + { + "invalid request (invalid from address)", + []string{ + "invalidAddress", + s.cfg.BondDenom, + s.toDenom.Base, + }, + true, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdTxMsgSwapAll() + bz, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, append(tc.args, commonArgs...)) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(bz.Bytes(), tc.respType), bz.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestMsgSetSwap() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = jsonOutputFormat + + denomMeta := struct { + Metadata banktypes.Metadata `json:"metadata"` + }{ + Metadata: s.toDenom, + } + jsonBytes, err := json.Marshal(denomMeta) + s.Require().NoError(err) + denomMetaString := string(jsonBytes) + + commonArgs := []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + + args []string + expectErr bool + }{ + { + "valid transaction (generateOnly)", + []string{ + s.authority.String(), + denomMetaString, + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, s.dummySwap.AmountCapForToDenom), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, s.dummySwap.SwapRate), + }, + false, + }, + { + "invalid transaction (without generateOnly)", + []string{ + s.authority.String(), + denomMetaString, + fmt.Sprintf("--%s=false", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, s.dummySwap.AmountCapForToDenom), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, s.dummySwap.SwapRate), + }, + true, + }, + { + "extra args", + []string{ + s.authority.String(), + denomMetaString, + "extra", + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, s.dummySwap.AmountCapForToDenom), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, s.dummySwap.SwapRate), + }, + true, + }, + { + "invalid authority", + []string{ + "invalid authority", + denomMetaString, + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, s.dummySwap.AmountCapForToDenom), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, s.dummySwap.SwapRate), + }, + true, + }, + { + "invalid json", + []string{ + s.authority.String(), + "invalid json", + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, s.dummySwap.AmountCapForToDenom), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, s.dummySwap.SwapRate), + }, + true, + }, + { + "invalid amountCapForToDenom", + []string{ + s.authority.String(), + denomMetaString, + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, "123.456"), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, s.dummySwap.SwapRate), + }, + true, + }, + { + "invalid swapRate", + []string{ + s.authority.String(), + denomMetaString, + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", cli.FlagFromDenom, s.dummySwap.FromDenom), + fmt.Sprintf("--%s=%s", cli.FlagToDenom, s.dummySwap.ToDenom), + fmt.Sprintf("--%s=%s", cli.FlagAmountCapForToDenom, s.dummySwap.AmountCapForToDenom), + fmt.Sprintf("--%s=%s", cli.FlagSwapRate, "abc.123"), + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.CmdMsgSetSwap() + bz, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, append(tc.args, commonArgs...)) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + _, err := s.cfg.TxConfig.TxJSONDecoder()(bz.Bytes()) + s.Require().NoError(err) + } + }) + } +}