From 5a5c63890e5d8b0d7b547697dfa2a0d630a502cc Mon Sep 17 00:00:00 2001 From: Emil Georgiev Date: Wed, 8 May 2024 09:15:18 +0300 Subject: [PATCH] test(types/coin): add unit tests for the coins (#20253) --- types/coin_test.go | 103 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/types/coin_test.go b/types/coin_test.go index 42fd51768e0a..5e7389e994ed 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -641,6 +641,21 @@ func TestCoinsAddCoalescesDuplicateDenominations(t *testing.T) { } } +func TestCoinsAddUnorderedDenominations(t *testing.T) { + A := sdk.Coins{ + {"aaa", math.NewInt(2)}, + {"bbb", math.NewInt(3)}, + } + B := sdk.Coins{ + {"bbb", math.NewInt(3)}, + {"aaa", math.NewInt(2)}, + } + + require.Panics(t, func() { + A.Add(B...) + }) +} + func (s *coinTestSuite) TestSubCoins() { cA0M0 := sdk.Coins{s.ca0, s.cm0} cA0M1 := sdk.Coins{s.ca0, s.cm1} @@ -930,6 +945,13 @@ func (s *coinTestSuite) TestMinMax() { sdk.Coins{{testDenom1, one}, {testDenom2, one}}, sdk.Coins{{testDenom1, two}, {testDenom2, two}}, }, + { + "one-one", + sdk.Coins{{testDenom2, one}}, + sdk.Coins{{testDenom1, one}}, + sdk.Coins{}, + sdk.Coins{{testDenom1, one}, {testDenom2, one}}, + }, } for _, tc := range cases { @@ -1385,3 +1407,84 @@ func (s *coinTestSuite) TestCoinAminoEncoding() { s.Require().Equal(bz1, bz3) s.Require().Equal(bz2[1:], bz3) } + +func (s *coinTestSuite) TestGetDenomByIndex() { + twoAtom := sdk.NewInt64Coin("atom", 2) + threeEth := sdk.NewInt64Coin("eth", 3) + + coins := sdk.Coins{twoAtom, threeEth} + + actual := coins.GetDenomByIndex(0) + s.Require().Equal("atom", actual) + actual = coins.GetDenomByIndex(1) + s.Require().Equal("eth", actual) +} + +func (s *coinTestSuite) TestIsAllPositive() { + negative := sdk.Coin{ + Denom: "atom", + Amount: math.NewInt(-2), + } + + cases := map[string]struct { + coins sdk.Coins + expected bool + }{ + "Coins with zero length": { + coins: sdk.Coins{}, + expected: false, + }, + "Coins with negative value": { + coins: sdk.Coins{negative, sdk.NewInt64Coin("atom", 2)}, + expected: false, + }, + "Coins only with positive values": { + coins: sdk.Coins{sdk.NewInt64Coin("atom", 2), sdk.NewInt64Coin("eth", 10)}, + expected: true, + }, + } + + for name, tc := range cases { + c := tc + s.T().Run(name, func(t *testing.T) { + s.Require().Equal(c.expected, c.coins.IsAllPositive()) + }) + } +} + +func (s *coinTestSuite) TestParseCoin() { + one := math.OneInt() + + cases := []struct { + input string + valid bool // if false, we expect an error on parse + expected sdk.Coin // if valid is true, make sure this is returned + }{ + {"", false, sdk.Coin{}}, + {"0stake", true, sdk.Coin{Denom: "stake", Amount: math.NewInt(0)}}, // remove zero coins + {"1foo", true, sdk.Coin{Denom: "foo", Amount: one}}, + {"10btc", true, sdk.Coin{Denom: "btc", Amount: math.NewInt(10)}}, + {"10bar", true, sdk.Coin{Denom: "bar", Amount: math.NewInt(10)}}, + {"98 bar", true, sdk.Coin{Denom: "bar", Amount: math.NewInt(98)}}, + {" 55\t \t bling\n", true, sdk.Coin{Denom: "bling", Amount: math.NewInt(55)}}, + {"2foo", true, sdk.Coin{Denom: "foo", Amount: math.NewInt(2)}}, + {"5 mycoin,", false, sdk.Coin{}}, // no empty coins in a list + {"2 3foo", false, sdk.Coin{}}, // 3foo is invalid coin name + {"11me coin", false, sdk.Coin{}}, // no spaces in coin names + {"1.2btc", true, sdk.Coin{Denom: "btc", Amount: math.NewInt(1)}}, // amount can be decimal, will get truncated + {"5foo:bar", true, sdk.Coin{Denom: "foo:bar", Amount: math.NewInt(5)}}, + {"10atom10", true, sdk.Coin{Denom: "atom10", Amount: math.NewInt(10)}}, + {"200transfer/channelToA/uatom", true, sdk.Coin{Denom: "transfer/channelToA/uatom", Amount: math.NewInt(200)}}, + {"50ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", true, sdk.Coin{Denom: "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", Amount: math.NewInt(50)}}, + {"120000000000000000000000000000000000000000000000000000000000000000000000000000btc", false, sdk.Coin{}}, + } + + for tcIndex, tc := range cases { + res, err := sdk.ParseCoinNormalized(tc.input) + if !tc.valid { + s.Require().Error(err, "%s: %#v. tc #%d", tc.input, res, tcIndex) + } else if s.Assert().Nil(err) { + s.Require().Equal(tc.expected, res, "coin parsing was incorrect, tc #%d", tcIndex) + } + } +}