From cc37bdba465878f12c46ead3e8ec5080276e2625 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:27:28 +0900 Subject: [PATCH] chore: add additional testcases for fswap (backport #1415) (#1420) * chore: add additional testcases for fswap (#1415) * chore: add more test for grpc_query * chore: add more test for config and msg validation * chore: add more test for genesis-related things * chore: add TestMsgSetSwap for msg server * chore: add more test for keeper * chore: fix for lint * chore: update changelog * chore: rename kai to kei * chore: introduce stubGenesisState func for DRY * chore: remove unnecessary code * chore: remove unnecessary code (cherry picked from commit 10726cfaffbbb4f786e0a7503dfe59aee8527812) # Conflicts: # CHANGELOG.md * chore: add additional testcases for fswap (#1415) * chore: add more test for grpc_query * chore: add more test for config and msg validation * chore: add more test for genesis-related things * chore: add TestMsgSetSwap for msg server * chore: add more test for keeper * chore: fix for lint * chore: update changelog * chore: rename kai to kei * chore: introduce stubGenesisState func for DRY * chore: remove unnecessary code * chore: remove unnecessary code --------- Co-authored-by: jaeseung-bae <119839167+jaeseung-bae@users.noreply.github.com> --- CHANGELOG.md | 3 +- x/fswap/keeper/genesis_test.go | 77 +++++++- x/fswap/keeper/grpc_query_test.go | 232 ++++++++++++++++++++--- x/fswap/keeper/keeper_test.go | 16 ++ x/fswap/keeper/msg_server_test.go | 125 +++++++++++++ x/fswap/types/config_test.go | 14 ++ x/fswap/types/genesis_test.go | 22 +++ x/fswap/types/msgs_test.go | 295 ++++++++++++++++++++++++++---- 8 files changed, 713 insertions(+), 71 deletions(-) create mode 100644 x/fswap/types/config_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index c52aebef7a..1ecb3c2a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features ### Improvements - +* (x/fswap) [\#1415](https://github.com/Finschia/finschia-sdk/pull/1415) add more testcases for fswap module + ### Bug Fixes ### Removed diff --git a/x/fswap/keeper/genesis_test.go b/x/fswap/keeper/genesis_test.go index 1df6f28c75..f9a8e415ed 100644 --- a/x/fswap/keeper/genesis_test.go +++ b/x/fswap/keeper/genesis_test.go @@ -2,15 +2,81 @@ package keeper_test import ( "fmt" + "testing" + "github.com/stretchr/testify/require" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/Finschia/finschia-sdk/simapp" + "github.com/Finschia/finschia-sdk/testutil/testdata" sdk "github.com/Finschia/finschia-sdk/types" "github.com/Finschia/finschia-sdk/x/fswap/types" ) func (s *KeeperTestSuite) TestInitAndExportGenesis() { ctx, _ := s.ctx.CacheContext() + testGenesis := stubGenesisState() + err := s.keeper.InitGenesis(ctx, testGenesis) + s.Require().NoError(err) + + exportGenesis := s.keeper.ExportGenesis(ctx) + fmt.Println(len(exportGenesis.GetSwaps())) + s.Require().Equal(testGenesis, exportGenesis) + s.Require().Equal(testGenesis.GetSwaps(), exportGenesis.GetSwaps()) + s.Require().Equal(testGenesis.GetSwapStats(), exportGenesis.GetSwapStats()) + s.Require().Equal(testGenesis.GetSwappeds(), exportGenesis.GetSwappeds()) +} + +func TestInitGenesis(t *testing.T) { + checkTx := false + app := simapp.Setup(checkTx) + testdata.RegisterInterfaces(app.InterfaceRegistry()) + testdata.RegisterMsgServer(app.MsgServiceRouter(), testdata.MsgServerImpl{}) + ctx := app.BaseApp.NewContext(checkTx, tmproto.Header{}) + keeper := app.FswapKeeper + + tests := []struct { + name string + genState *types.GenesisState + expectedError error + }{ + { + name: "valid", + genState: stubGenesisState(), + expectedError: nil, + }, + { + name: "invalid: swapCount", + genState: func() *types.GenesisState { + state := stubGenesisState() + state.SwapStats.SwapCount = -1 + return state + }(), + expectedError: types.ErrInvalidState, + }, + { + name: "invalid: swaps count exceeds limit", + genState: func() *types.GenesisState { + state := stubGenesisState() + state.Swaps = append(state.Swaps, state.Swaps[0]) + state.Swappeds = append(state.Swappeds, state.Swappeds[0]) + state.SwapStats.SwapCount = 2 + return state + }(), + expectedError: types.ErrCanNotHaveMoreSwap, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := keeper.InitGenesis(ctx, tc.genState) + require.ErrorIs(t, tc.expectedError, err) + }) + } +} + +func stubGenesisState() *types.GenesisState { testSwapRate, _ := sdk.NewDecFromStr("1234567890") - testGenesis := &types.GenesisState{ + return &types.GenesisState{ Swaps: []types.Swap{ { FromDenom: "aaa", @@ -35,13 +101,4 @@ func (s *KeeperTestSuite) TestInitAndExportGenesis() { }, }, } - err := s.keeper.InitGenesis(ctx, testGenesis) - s.Require().NoError(err) - - exportGenesis := s.keeper.ExportGenesis(ctx) - fmt.Println(len(exportGenesis.GetSwaps())) - s.Require().Equal(testGenesis, exportGenesis) - s.Require().Equal(testGenesis.GetSwaps(), exportGenesis.GetSwaps()) - s.Require().Equal(testGenesis.GetSwapStats(), exportGenesis.GetSwapStats()) - s.Require().Equal(testGenesis.GetSwappeds(), exportGenesis.GetSwappeds()) } diff --git a/x/fswap/keeper/grpc_query_test.go b/x/fswap/keeper/grpc_query_test.go index d947121578..f9499b1dc7 100644 --- a/x/fswap/keeper/grpc_query_test.go +++ b/x/fswap/keeper/grpc_query_test.go @@ -11,6 +11,7 @@ import ( "github.com/Finschia/finschia-sdk/baseapp" "github.com/Finschia/finschia-sdk/simapp" sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/types/query" bank "github.com/Finschia/finschia-sdk/x/bank/types" "github.com/Finschia/finschia-sdk/x/fswap/keeper" "github.com/Finschia/finschia-sdk/x/fswap/types" @@ -42,7 +43,7 @@ func (s *FSwapQueryTestSuite) SetupTest() { s.queryClient = types.NewQueryClient(queryHelper) s.keeper = s.app.FswapKeeper - pebSwapRateForCony, err := sdk.NewDecFromStr("148079656000000") + keiSwapRateForCony, err := sdk.NewDecFromStr("148079656000000") s.Require().NoError(err) swapCap := sdk.NewInt(1000) s.Require().NoError(err) @@ -52,7 +53,7 @@ func (s *FSwapQueryTestSuite) SetupTest() { FromDenom: s.fromDenom, ToDenom: s.toDenom, AmountCapForToDenom: swapCap, - SwapRate: pebSwapRateForCony, + SwapRate: keiSwapRateForCony, } s.toDenomMetadata = bank.Metadata{ Description: "This is metadata for to-coin", @@ -88,48 +89,227 @@ func (s *FSwapQueryTestSuite) SetupTest() { func (s *FSwapQueryTestSuite) TestQuerySwapRequest() { tests := []struct { name string - FromDenom string - ToDenom string - wantErr bool + request *types.QuerySwapRequest + expectedResponse *types.QuerySwapResponse expectedGrpcCode codes.Code }{ { - name: "valid", - FromDenom: s.fromDenom, - ToDenom: s.toDenom, - wantErr: false, + name: "valid", + request: &types.QuerySwapRequest{ + FromDenom: s.fromDenom, + ToDenom: s.toDenom, + }, + expectedResponse: &types.QuerySwapResponse{ + Swap: types.Swap{ + FromDenom: s.swap.FromDenom, + ToDenom: s.swap.ToDenom, + AmountCapForToDenom: s.swap.AmountCapForToDenom, + SwapRate: s.swap.SwapRate, + }, + }, expectedGrpcCode: codes.OK, }, { - name: "invalid: empty fromDenom", - FromDenom: "", - ToDenom: s.toDenom, - wantErr: true, + name: "invalid: empty fromDenom", + request: &types.QuerySwapRequest{ + FromDenom: "", + ToDenom: s.toDenom, + }, expectedGrpcCode: codes.InvalidArgument, }, { - name: "invalid: empty toDenom", - FromDenom: s.fromDenom, - ToDenom: "", - wantErr: true, + name: "invalid: empty toDenom", + request: &types.QuerySwapRequest{ + FromDenom: s.fromDenom, + ToDenom: "", + }, expectedGrpcCode: codes.InvalidArgument, }, { - name: "invalid: the same fromDenom and toDenom", - FromDenom: s.fromDenom, - ToDenom: s.fromDenom, - wantErr: true, + name: "invalid: the same fromDenom and toDenom", + request: &types.QuerySwapRequest{ + FromDenom: s.fromDenom, + ToDenom: s.fromDenom, + }, expectedGrpcCode: codes.InvalidArgument, }, + { + name: "invalid: unregistered swap", + request: &types.QuerySwapRequest{ + FromDenom: s.toDenom, + ToDenom: s.fromDenom, + }, + expectedGrpcCode: codes.NotFound, + }, + } + for _, tc := range tests { + s.Run(tc.name, func() { + response, err := s.queryClient.Swap(s.ctx.Context(), tc.request) + s.Require().Equal(tc.expectedResponse, response) + actualGrpcCode := status.Code(err) + s.Require().Equal(tc.expectedGrpcCode, actualGrpcCode, actualGrpcCode.String()) + }) + } +} + +func (s *FSwapQueryTestSuite) TestQuerySwappedRequest() { + tests := []struct { + name string + request *types.QuerySwappedRequest + expectedResponse *types.QuerySwappedResponse + expectedGrpcCode codes.Code + }{ + { + name: "valid", + request: &types.QuerySwappedRequest{ + FromDenom: s.fromDenom, + ToDenom: s.toDenom, + }, + expectedResponse: &types.QuerySwappedResponse{ + FromCoinAmount: sdk.NewCoin(s.fromDenom, sdk.ZeroInt()), + ToCoinAmount: sdk.NewCoin(s.toDenom, sdk.ZeroInt()), + }, + expectedGrpcCode: codes.OK, + }, + { + name: "invalid: empty fromDenom", + request: &types.QuerySwappedRequest{ + FromDenom: "", + ToDenom: s.toDenom, + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, + { + name: "invalid: empty toDenom", + request: &types.QuerySwappedRequest{ + FromDenom: s.fromDenom, + ToDenom: "", + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, + { + name: "invalid: unregistered swap", + request: &types.QuerySwappedRequest{ + FromDenom: s.toDenom, + ToDenom: s.fromDenom, + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, } for _, tc := range tests { s.Run(tc.name, func() { - m := &types.QuerySwapRequest{ - FromDenom: tc.FromDenom, - ToDenom: tc.ToDenom, - } + response, err := s.queryClient.Swapped(s.ctx.Context(), tc.request) + s.Require().Equal(tc.expectedResponse, response) + actualGrpcCode := status.Code(err) + s.Require().Equal(tc.expectedGrpcCode, actualGrpcCode, actualGrpcCode.String()) + }) + } +} - _, err := s.queryClient.Swap(s.ctx.Context(), m) +func (s *FSwapQueryTestSuite) TestQueryTotalSwappableToCoinAmountRequest() { + tests := []struct { + name string + request *types.QueryTotalSwappableToCoinAmountRequest + expectedResponse *types.QueryTotalSwappableToCoinAmountResponse + expectedGrpcCode codes.Code + }{ + { + name: "valid", + request: &types.QueryTotalSwappableToCoinAmountRequest{ + FromDenom: s.fromDenom, + ToDenom: s.toDenom, + }, + expectedResponse: &types.QueryTotalSwappableToCoinAmountResponse{ + SwappableAmount: sdk.NewCoin(s.toDenom, s.swap.AmountCapForToDenom), + }, + expectedGrpcCode: codes.OK, + }, + { + name: "invalid: empty fromDenom", + request: &types.QueryTotalSwappableToCoinAmountRequest{ + FromDenom: "", + ToDenom: s.toDenom, + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, + { + name: "invalid: empty toDenom", + request: &types.QueryTotalSwappableToCoinAmountRequest{ + FromDenom: s.fromDenom, + ToDenom: "", + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, + { + name: "invalid: unregistered swap", + request: &types.QueryTotalSwappableToCoinAmountRequest{ + FromDenom: s.toDenom, + ToDenom: s.fromDenom, + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, + } + for _, tc := range tests { + s.Run(tc.name, func() { + response, err := s.queryClient.TotalSwappableToCoinAmount(s.ctx.Context(), tc.request) + s.Require().Equal(tc.expectedResponse, response) + actualGrpcCode := status.Code(err) + s.Require().Equal(tc.expectedGrpcCode, actualGrpcCode, actualGrpcCode.String()) + }) + } +} + +func (s *FSwapQueryTestSuite) TestQuerySwapsRequest() { + tests := []struct { + name string + request *types.QuerySwapsRequest + expectedResponse *types.QuerySwapsResponse + expectedGrpcCode codes.Code + }{ + { + name: "valid", + request: &types.QuerySwapsRequest{ + Pagination: nil, + }, + expectedResponse: &types.QuerySwapsResponse{ + Swaps: []types.Swap{ + { + FromDenom: s.swap.FromDenom, + ToDenom: s.swap.ToDenom, + AmountCapForToDenom: s.swap.AmountCapForToDenom, + SwapRate: s.swap.SwapRate, + }, + }, + Pagination: &query.PageResponse{ + NextKey: nil, + Total: 1, + }, + }, + expectedGrpcCode: codes.OK, + }, + { + name: "invalid request", + request: &types.QuerySwapsRequest{ + Pagination: &query.PageRequest{ + Key: []byte("invalid-key"), + Offset: 1, + Limit: 0, + }, + }, + expectedResponse: nil, + expectedGrpcCode: codes.Unknown, + }, + } + for _, tc := range tests { + s.Run(tc.name, func() { + response, err := s.queryClient.Swaps(s.ctx.Context(), tc.request) + s.Require().Equal(tc.expectedResponse, response) actualGrpcCode := status.Code(err) s.Require().Equal(tc.expectedGrpcCode, actualGrpcCode, actualGrpcCode.String()) }) diff --git a/x/fswap/keeper/keeper_test.go b/x/fswap/keeper/keeper_test.go index 1ebffa116a..f5f45c3c9f 100644 --- a/x/fswap/keeper/keeper_test.go +++ b/x/fswap/keeper/keeper_test.go @@ -242,6 +242,22 @@ func (s *KeeperTestSuite) TestSwap() { true, sdkerrors.ErrInsufficientFunds, }, + "invalid: unregistered swap": { + s.accWithToCoin, + sdk.NewCoin(s.swap.GetFromDenom(), sdk.NewInt(100)), + "nono", + sdk.ZeroInt(), + true, + sdkerrors.ErrNotFound, + }, + "invalid: amount exceed": { + s.accWithToCoin, + sdk.NewCoin(s.swap.GetFromDenom(), s.swap.AmountCapForToDenom.Add(sdk.OneInt())), + s.swap.GetToDenom(), + sdk.ZeroInt(), + true, + types.ErrExceedSwappableToCoinAmount, + }, } for name, tc := range testCases { s.Run(name, func() { diff --git a/x/fswap/keeper/msg_server_test.go b/x/fswap/keeper/msg_server_test.go index ab8be87e04..81ce7529ac 100644 --- a/x/fswap/keeper/msg_server_test.go +++ b/x/fswap/keeper/msg_server_test.go @@ -1,8 +1,19 @@ package keeper_test import ( + "testing" + + "github.com/stretchr/testify/require" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/Finschia/finschia-sdk/simapp" + "github.com/Finschia/finschia-sdk/testutil/testdata" sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" + authtypes "github.com/Finschia/finschia-sdk/x/auth/types" + bank "github.com/Finschia/finschia-sdk/x/bank/types" + "github.com/Finschia/finschia-sdk/x/foundation" + fkeeper "github.com/Finschia/finschia-sdk/x/fswap/keeper" "github.com/Finschia/finschia-sdk/x/fswap/types" ) @@ -133,3 +144,117 @@ func (s *KeeperTestSuite) TestMsgSwapAll() { }) } } + +func TestMsgSetSwap(t *testing.T) { + authority := authtypes.NewModuleAddress(foundation.ModuleName) + checkTx := false + app := simapp.Setup(checkTx) + testdata.RegisterInterfaces(app.InterfaceRegistry()) + testdata.RegisterMsgServer(app.MsgServiceRouter(), testdata.MsgServerImpl{}) + ctx := app.BaseApp.NewContext(checkTx, tmproto.Header{}) + keeper := app.FswapKeeper + msgServer := fkeeper.NewMsgServer(keeper) + fromDenomStr := "cony" + fromDenom := bank.Metadata{ + Description: "This is metadata for from-coin", + DenomUnits: []*bank.DenomUnit{ + {Denom: fromDenomStr, Exponent: 0}, + }, + Base: fromDenomStr, + Display: fromDenomStr, + Name: "FROM", + Symbol: "FROM", + } + app.BankKeeper.SetDenomMetaData(ctx, fromDenom) + + testCases := map[string]struct { + request *types.MsgSetSwap + expectedError error + }{ + "valid": { + request: &types.MsgSetSwap{ + Authority: authority.String(), + Swap: types.Swap{ + FromDenom: fromDenomStr, + ToDenom: "kei", + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(1), + }, + ToDenomMetadata: bank.Metadata{ + Description: "desc", + DenomUnits: []*bank.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "kei", + Display: "kei", + Name: "kei", + Symbol: "KAIA", + }, + }, + expectedError: nil, + }, + "invalid: authority": { + request: &types.MsgSetSwap{ + Authority: "invalid-authority", + Swap: types.Swap{ + FromDenom: fromDenomStr, + ToDenom: "kei", + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(1), + }, + ToDenomMetadata: bank.Metadata{ + Description: "desc", + DenomUnits: []*bank.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "kei", + Display: "kei", + Name: "kei", + Symbol: "KAIA", + }, + }, + expectedError: sdkerrors.ErrUnauthorized, + }, + "invalid: Swap.ToDenom": { + request: &types.MsgSetSwap{ + Authority: authority.String(), + Swap: types.Swap{ + FromDenom: fromDenomStr, + ToDenom: fromDenomStr, + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(1), + }, + ToDenomMetadata: bank.Metadata{ + Description: "desc", + DenomUnits: []*bank.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "kei", + Display: "kei", + Name: "kei", + Symbol: "KAIA", + }, + }, + expectedError: sdkerrors.ErrInvalidRequest, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + context, _ := ctx.CacheContext() + _, err := msgServer.SetSwap(sdk.WrapSDKContext(context), tc.request) + require.ErrorIs(t, err, tc.expectedError) + }) + } +} diff --git a/x/fswap/types/config_test.go b/x/fswap/types/config_test.go new file mode 100644 index 0000000000..90a078a4d7 --- /dev/null +++ b/x/fswap/types/config_test.go @@ -0,0 +1,14 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDefaultConfig(t *testing.T) { + config := DefaultConfig() + + require.Equal(t, false, config.UpdateAllowed) + require.Equal(t, 1, config.MaxSwaps) +} diff --git a/x/fswap/types/genesis_test.go b/x/fswap/types/genesis_test.go index fc2ed9a781..289e1626af 100644 --- a/x/fswap/types/genesis_test.go +++ b/x/fswap/types/genesis_test.go @@ -6,7 +6,10 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/Finschia/finschia-sdk/types" + authtypes "github.com/Finschia/finschia-sdk/x/auth/types" + "github.com/Finschia/finschia-sdk/x/foundation" "github.com/Finschia/finschia-sdk/x/fswap/types" + govtypes "github.com/Finschia/finschia-sdk/x/gov/types" ) func TestGenesisStateValidate(t *testing.T) { @@ -174,3 +177,22 @@ func TestGenesisStateValidate(t *testing.T) { }) } } + +func TestDefaultAuthority(t *testing.T) { + expectedDefaultAuthority := authtypes.NewModuleAddress(foundation.ModuleName) + + defaultAuthority := types.DefaultAuthority() + + require.Equal(t, expectedDefaultAuthority, defaultAuthority) +} + +func TestAuthorityCandidates(t *testing.T) { + defaultAuthorityCandidates := []sdk.AccAddress{ + authtypes.NewModuleAddress(govtypes.ModuleName), + authtypes.NewModuleAddress(foundation.ModuleName), + } + + authorityCandidates := types.AuthorityCandidates() + + require.Equal(t, defaultAuthorityCandidates, authorityCandidates) +} diff --git a/x/fswap/types/msgs_test.go b/x/fswap/types/msgs_test.go index e3dd86b7dd..d6091af476 100644 --- a/x/fswap/types/msgs_test.go +++ b/x/fswap/types/msgs_test.go @@ -1,13 +1,14 @@ package types_test import ( + "errors" "testing" "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "github.com/Finschia/finschia-sdk/crypto/keys/secp256k1" sdk "github.com/Finschia/finschia-sdk/types" + sdkerrors "github.com/Finschia/finschia-sdk/types/errors" "github.com/Finschia/finschia-sdk/x/auth/legacy/legacytx" banktypes "github.com/Finschia/finschia-sdk/x/bank/types" fswaptypes "github.com/Finschia/finschia-sdk/x/fswap/types" @@ -86,52 +87,278 @@ func TestAminoJSON(t *testing.T) { } } -func TestQuerySwapRequestValidate(t *testing.T) { +func TestMsgSwapValidate(t *testing.T) { + pk := secp256k1.GenPrivKey().PubKey() + address, err := sdk.Bech32ifyAddressBytes("link", pk.Address()) + if err != nil { + return + } + tests := []struct { + name string + msg *fswaptypes.MsgSwap + expectedError error + }{ + { + name: "valid", + msg: &fswaptypes.MsgSwap{ + FromAddress: address, + FromCoinAmount: sdk.NewCoin("fromDenom", sdk.OneInt()), + ToDenom: "kei", + }, + expectedError: nil, + }, + { + name: "invalid: address", + msg: &fswaptypes.MsgSwap{ + FromAddress: "invalid-address", + FromCoinAmount: sdk.NewCoin("fromDenom", sdk.OneInt()), + ToDenom: "kei", + }, + expectedError: sdkerrors.ErrInvalidAddress, + }, + { + name: "invalid: FromCoinAmount empty denom", + msg: &fswaptypes.MsgSwap{ + FromAddress: address, + FromCoinAmount: sdk.Coin{ + Denom: "", + Amount: sdk.OneInt(), + }, + ToDenom: "kei", + }, + expectedError: sdkerrors.ErrInvalidCoins, + }, + { + name: "invalid: FromCoinAmount zero amount", + msg: &fswaptypes.MsgSwap{ + FromAddress: address, + FromCoinAmount: sdk.Coin{ + Denom: "cony", + Amount: sdk.ZeroInt(), + }, + ToDenom: "kei", + }, + expectedError: sdkerrors.ErrInvalidCoins, + }, + { + name: "invalid: ToDenom", + msg: &fswaptypes.MsgSwap{ + FromAddress: address, + FromCoinAmount: sdk.NewCoin("fromDenom", sdk.OneInt()), + ToDenom: "", + }, + expectedError: sdkerrors.ErrInvalidRequest, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + require.ErrorIs(t, err, tc.expectedError) + }) + } +} + +func TestMsgSwapAllValidate(t *testing.T) { + pk := secp256k1.GenPrivKey().PubKey() + address, err := sdk.Bech32ifyAddressBytes("link", pk.Address()) + if err != nil { + return + } + tests := []struct { + name string + msg *fswaptypes.MsgSwapAll + expectedError error + }{ + { + name: "valid", + msg: &fswaptypes.MsgSwapAll{ + FromAddress: address, + FromDenom: "cony", + ToDenom: "kei", + }, + expectedError: nil, + }, + { + name: "invalid: address", + msg: &fswaptypes.MsgSwapAll{ + FromAddress: "invalid-address", + FromDenom: "cony", + ToDenom: "kei", + }, + expectedError: sdkerrors.ErrInvalidAddress, + }, + { + name: "invalid: FromDenom", + msg: &fswaptypes.MsgSwapAll{ + FromAddress: address, + FromDenom: "", + ToDenom: "kei", + }, + expectedError: sdkerrors.ErrInvalidRequest, + }, + { + name: "invalid: ToDenom", + msg: &fswaptypes.MsgSwapAll{ + FromAddress: address, + FromDenom: "cony", + ToDenom: "", + }, + expectedError: sdkerrors.ErrInvalidRequest, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + require.ErrorIs(t, err, tc.expectedError) + }) + } +} + +func TestMsgSetSwapValidate(t *testing.T) { + pk := secp256k1.GenPrivKey().PubKey() + address, err := sdk.Bech32ifyAddressBytes("link", pk.Address()) + if err != nil { + return + } tests := []struct { - name string - FromDenom string - ToDenom string - wantErr bool - expectedGrpcCode codes.Code + name string + msg *fswaptypes.MsgSetSwap + expectedError error }{ { - name: "valid", - FromDenom: "cony", - ToDenom: "peb", - wantErr: false, - expectedGrpcCode: codes.OK, + name: "valid", + msg: &fswaptypes.MsgSetSwap{ + Authority: address, + Swap: fswaptypes.Swap{ + FromDenom: "cony", + ToDenom: "kei", + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(123), + }, + ToDenomMetadata: banktypes.Metadata{ + Description: "desc", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "kei", + Display: "kei", + Name: "kei", + Symbol: "KAIA", + }, + }, + expectedError: nil, + }, + { + name: "invalid: address", + msg: &fswaptypes.MsgSetSwap{ + Authority: "invalid-address", + Swap: fswaptypes.Swap{ + FromDenom: "cony", + ToDenom: "kei", + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(123), + }, + ToDenomMetadata: banktypes.Metadata{ + Description: "desc", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "kei", + Display: "kei", + Name: "kei", + Symbol: "KAIA", + }, + }, + expectedError: sdkerrors.ErrInvalidAddress, }, { - name: "invalid: empty fromDenom", - FromDenom: "", - ToDenom: "peb", - wantErr: true, - expectedGrpcCode: codes.InvalidArgument, + name: "invalid: Swap", + msg: &fswaptypes.MsgSetSwap{ + Authority: address, + Swap: fswaptypes.Swap{}, + ToDenomMetadata: banktypes.Metadata{ + Description: "desc", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "kei", + Display: "kei", + Name: "kei", + Symbol: "KAIA", + }, + }, + expectedError: sdkerrors.ErrInvalidRequest, }, { - name: "invalid: empty toDenom", - FromDenom: "cony", - ToDenom: "", - wantErr: true, - expectedGrpcCode: codes.InvalidArgument, + name: "invalid: ToDenomMetadata", + msg: &fswaptypes.MsgSetSwap{ + Authority: address, + Swap: fswaptypes.Swap{ + FromDenom: "cony", + ToDenom: "kei", + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(123), + }, + ToDenomMetadata: banktypes.Metadata{ + Description: "", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "kei", + Exponent: 0, + Aliases: nil, + }, + }, + }, + }, + expectedError: errors.New("name field cannot be blank"), }, + { - name: "invalid: the same fromDenom and toDenom", - FromDenom: "cony", - ToDenom: "cony", - wantErr: true, - expectedGrpcCode: codes.InvalidArgument, + name: "invalid: mismatched toDenom", + msg: &fswaptypes.MsgSetSwap{ + Authority: address, + Swap: fswaptypes.Swap{ + FromDenom: "cony", + ToDenom: "kei", + AmountCapForToDenom: sdk.OneInt(), + SwapRate: sdk.NewDec(123), + }, + ToDenomMetadata: banktypes.Metadata{ + Description: "desc", + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "fkei", + Exponent: 0, + Aliases: nil, + }, + }, + Base: "fkei", + Display: "fkei", + Name: "fkei", + Symbol: "KAIA", + }, + }, + expectedError: sdkerrors.ErrInvalidRequest, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - m := &fswaptypes.QuerySwapRequest{ - FromDenom: tc.FromDenom, - ToDenom: tc.ToDenom, + err := tc.msg.ValidateBasic() + if tc.expectedError != nil { + require.Contains(t, err.Error(), tc.expectedError.Error()) } - err := m.Validate() - actualGrpcCode := status.Code(err) - require.Equal(t, tc.expectedGrpcCode, actualGrpcCode) }) } }