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/suite.go b/x/fswap/client/testutil/suite.go new file mode 100644 index 0000000000..60f4c71929 --- /dev/null +++ b/x/fswap/client/testutil/suite.go @@ -0,0 +1,294 @@ +package testutil + +import ( + clitestutil "github.com/Finschia/finschia-sdk/testutil/cli" + "github.com/Finschia/finschia-sdk/testutil/network" + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/types/query" + banktypes "github.com/Finschia/finschia-sdk/x/bank/types" + "github.com/Finschia/finschia-sdk/x/fswap/client/cli" + fswaptypes "github.com/Finschia/finschia-sdk/x/fswap/types" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + + 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) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestCmdQuerySwapped() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + // avoid printing as yaml from CLI command + clientCtx.OutputFormat = "JSON" + + 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()), + }, + }, + { + "invalid query", + []string{}, + 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 = "JSON" + + 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), + }, + }, + { + "invalid query", + []string{}, + 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 = "JSON" + + 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, + }, + }, + { + "invalid query (no params)", + []string{}, + 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 = "JSON" + + 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) + } + }) + } +}