github.com/Finschia/finschia-sdk@v0.48.1/types/dec_coin_test.go (about)

     1  package types_test
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/suite"
     8  
     9  	sdk "github.com/Finschia/finschia-sdk/types"
    10  )
    11  
    12  type decCoinTestSuite struct {
    13  	suite.Suite
    14  }
    15  
    16  func TestDecCoinTestSuite(t *testing.T) {
    17  	suite.Run(t, new(decCoinTestSuite))
    18  }
    19  
    20  func (s *decCoinTestSuite) TestNewDecCoin() {
    21  	s.Require().NotPanics(func() {
    22  		sdk.NewInt64DecCoin(testDenom1, 5)
    23  	})
    24  	s.Require().NotPanics(func() {
    25  		sdk.NewInt64DecCoin(testDenom1, 0)
    26  	})
    27  	s.Require().NotPanics(func() {
    28  		sdk.NewInt64DecCoin(strings.ToUpper(testDenom1), 5)
    29  	})
    30  	s.Require().Panics(func() {
    31  		sdk.NewInt64DecCoin(testDenom1, -5)
    32  	})
    33  }
    34  
    35  func (s *decCoinTestSuite) TestNewDecCoinFromDec() {
    36  	s.Require().NotPanics(func() {
    37  		sdk.NewDecCoinFromDec(testDenom1, sdk.NewDec(5))
    38  	})
    39  	s.Require().NotPanics(func() {
    40  		sdk.NewDecCoinFromDec(testDenom1, sdk.ZeroDec())
    41  	})
    42  	s.Require().NotPanics(func() {
    43  		sdk.NewDecCoinFromDec(strings.ToUpper(testDenom1), sdk.NewDec(5))
    44  	})
    45  	s.Require().Panics(func() {
    46  		sdk.NewDecCoinFromDec(testDenom1, sdk.NewDec(-5))
    47  	})
    48  }
    49  
    50  func (s *decCoinTestSuite) TestNewDecCoinFromCoin() {
    51  	s.Require().NotPanics(func() {
    52  		sdk.NewDecCoinFromCoin(sdk.Coin{testDenom1, sdk.NewInt(5)})
    53  	})
    54  	s.Require().NotPanics(func() {
    55  		sdk.NewDecCoinFromCoin(sdk.Coin{testDenom1, sdk.NewInt(0)})
    56  	})
    57  	s.Require().NotPanics(func() {
    58  		sdk.NewDecCoinFromCoin(sdk.Coin{strings.ToUpper(testDenom1), sdk.NewInt(5)})
    59  	})
    60  	s.Require().Panics(func() {
    61  		sdk.NewDecCoinFromCoin(sdk.Coin{testDenom1, sdk.NewInt(-5)})
    62  	})
    63  }
    64  
    65  func (s *decCoinTestSuite) TestDecCoinIsPositive() {
    66  	dc := sdk.NewInt64DecCoin(testDenom1, 5)
    67  	s.Require().True(dc.IsPositive())
    68  
    69  	dc = sdk.NewInt64DecCoin(testDenom1, 0)
    70  	s.Require().False(dc.IsPositive())
    71  }
    72  
    73  func (s *decCoinTestSuite) TestAddDecCoin() {
    74  	decCoinA1 := sdk.NewDecCoinFromDec(testDenom1, sdk.NewDecWithPrec(11, 1))
    75  	decCoinA2 := sdk.NewDecCoinFromDec(testDenom1, sdk.NewDecWithPrec(22, 1))
    76  	decCoinB1 := sdk.NewDecCoinFromDec(testDenom2, sdk.NewDecWithPrec(11, 1))
    77  
    78  	// regular add
    79  	res := decCoinA1.Add(decCoinA1)
    80  	s.Require().Equal(decCoinA2, res, "sum of coins is incorrect")
    81  
    82  	// bad denom add
    83  	s.Require().Panics(func() {
    84  		decCoinA1.Add(decCoinB1)
    85  	}, "expected panic on sum of different denoms")
    86  }
    87  
    88  func (s *decCoinTestSuite) TestAddDecCoins() {
    89  	one := sdk.NewDec(1)
    90  	zero := sdk.NewDec(0)
    91  	two := sdk.NewDec(2)
    92  
    93  	cases := []struct {
    94  		inputOne sdk.DecCoins
    95  		inputTwo sdk.DecCoins
    96  		expected sdk.DecCoins
    97  	}{
    98  		{sdk.DecCoins{{testDenom1, one}, {testDenom2, one}}, sdk.DecCoins{{testDenom1, one}, {testDenom2, one}}, sdk.DecCoins{{testDenom1, two}, {testDenom2, two}}},
    99  		{sdk.DecCoins{{testDenom1, zero}, {testDenom2, one}}, sdk.DecCoins{{testDenom1, zero}, {testDenom2, zero}}, sdk.DecCoins{{testDenom2, one}}},
   100  		{sdk.DecCoins{{testDenom1, zero}, {testDenom2, zero}}, sdk.DecCoins{{testDenom1, zero}, {testDenom2, zero}}, sdk.DecCoins(nil)},
   101  	}
   102  
   103  	for tcIndex, tc := range cases {
   104  		res := tc.inputOne.Add(tc.inputTwo...)
   105  		s.Require().Equal(tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
   106  	}
   107  }
   108  
   109  func (s *decCoinTestSuite) TestFilteredZeroDecCoins() {
   110  	cases := []struct {
   111  		name     string
   112  		input    sdk.DecCoins
   113  		original string
   114  		expected string
   115  	}{
   116  		{
   117  			name: "all greater than zero",
   118  			input: sdk.DecCoins{
   119  				{"testa", sdk.NewDec(1)},
   120  				{"testb", sdk.NewDec(2)},
   121  				{"testc", sdk.NewDec(3)},
   122  				{"testd", sdk.NewDec(4)},
   123  				{"teste", sdk.NewDec(5)},
   124  			},
   125  			original: "1.000000000000000000testa,2.000000000000000000testb,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   126  			expected: "1.000000000000000000testa,2.000000000000000000testb,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   127  		},
   128  		{
   129  			name: "zero coin in middle",
   130  			input: sdk.DecCoins{
   131  				{"testa", sdk.NewDec(1)},
   132  				{"testb", sdk.NewDec(2)},
   133  				{"testc", sdk.NewDec(0)},
   134  				{"testd", sdk.NewDec(4)},
   135  				{"teste", sdk.NewDec(5)},
   136  			},
   137  			original: "1.000000000000000000testa,2.000000000000000000testb,0.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   138  			expected: "1.000000000000000000testa,2.000000000000000000testb,4.000000000000000000testd,5.000000000000000000teste",
   139  		},
   140  		{
   141  			name: "zero coin end (unordered)",
   142  			input: sdk.DecCoins{
   143  				{"teste", sdk.NewDec(5)},
   144  				{"testc", sdk.NewDec(3)},
   145  				{"testa", sdk.NewDec(1)},
   146  				{"testd", sdk.NewDec(4)},
   147  				{"testb", sdk.NewDec(0)},
   148  			},
   149  			original: "5.000000000000000000teste,3.000000000000000000testc,1.000000000000000000testa,4.000000000000000000testd,0.000000000000000000testb",
   150  			expected: "1.000000000000000000testa,3.000000000000000000testc,4.000000000000000000testd,5.000000000000000000teste",
   151  		},
   152  	}
   153  
   154  	for _, tt := range cases {
   155  		undertest := sdk.NewDecCoins(tt.input...)
   156  		s.Require().Equal(tt.expected, undertest.String(), "NewDecCoins must return expected results")
   157  		s.Require().Equal(tt.original, tt.input.String(), "input must be unmodified and match original")
   158  	}
   159  }
   160  
   161  func (s *decCoinTestSuite) TestIsValid() {
   162  	tests := []struct {
   163  		coin       sdk.DecCoin
   164  		expectPass bool
   165  		msg        string
   166  	}{
   167  		{
   168  			sdk.NewDecCoin("mytoken", sdk.NewInt(10)),
   169  			true,
   170  			"valid coins should have passed",
   171  		},
   172  		{
   173  			sdk.DecCoin{Denom: "BTC", Amount: sdk.NewDec(10)},
   174  			true,
   175  			"valid uppercase denom",
   176  		},
   177  		{
   178  			sdk.DecCoin{Denom: "Bitcoin", Amount: sdk.NewDec(10)},
   179  			true,
   180  			"valid mixed case denom",
   181  		},
   182  		{
   183  			sdk.DecCoin{Denom: "btc", Amount: sdk.NewDec(-10)},
   184  			false,
   185  			"negative amount",
   186  		},
   187  	}
   188  
   189  	for _, tc := range tests {
   190  		tc := tc
   191  		if tc.expectPass {
   192  			s.Require().True(tc.coin.IsValid(), tc.msg)
   193  		} else {
   194  			s.Require().False(tc.coin.IsValid(), tc.msg)
   195  		}
   196  	}
   197  }
   198  
   199  func (s *decCoinTestSuite) TestSubDecCoin() {
   200  	tests := []struct {
   201  		coin       sdk.DecCoin
   202  		expectPass bool
   203  		msg        string
   204  	}{
   205  		{
   206  			sdk.NewDecCoin("mytoken", sdk.NewInt(20)),
   207  			true,
   208  			"valid coins should have passed",
   209  		},
   210  		{
   211  			sdk.NewDecCoin("othertoken", sdk.NewInt(20)),
   212  			false,
   213  			"denom mismatch",
   214  		},
   215  		{
   216  			sdk.NewDecCoin("mytoken", sdk.NewInt(9)),
   217  			false,
   218  			"negative amount",
   219  		},
   220  	}
   221  
   222  	decCoin := sdk.NewDecCoin("mytoken", sdk.NewInt(10))
   223  
   224  	for _, tc := range tests {
   225  		tc := tc
   226  		if tc.expectPass {
   227  			equal := tc.coin.Sub(decCoin)
   228  			s.Require().Equal(equal, decCoin, tc.msg)
   229  		} else {
   230  			s.Require().Panics(func() { tc.coin.Sub(decCoin) }, tc.msg)
   231  		}
   232  	}
   233  }
   234  
   235  func (s *decCoinTestSuite) TestSubDecCoins() {
   236  	tests := []struct {
   237  		coins      sdk.DecCoins
   238  		expectPass bool
   239  		msg        string
   240  	}{
   241  		{
   242  			sdk.NewDecCoinsFromCoins(sdk.NewCoin("mytoken", sdk.NewInt(10)), sdk.NewCoin("btc", sdk.NewInt(20)), sdk.NewCoin("eth", sdk.NewInt(30))),
   243  			true,
   244  			"sorted coins should have passed",
   245  		},
   246  		{
   247  			sdk.DecCoins{sdk.NewDecCoin("mytoken", sdk.NewInt(10)), sdk.NewDecCoin("btc", sdk.NewInt(20)), sdk.NewDecCoin("eth", sdk.NewInt(30))},
   248  			false,
   249  			"unorted coins should panic",
   250  		},
   251  		{
   252  			sdk.DecCoins{sdk.DecCoin{Denom: "BTC", Amount: sdk.NewDec(10)}, sdk.NewDecCoin("eth", sdk.NewInt(15)), sdk.NewDecCoin("mytoken", sdk.NewInt(5))},
   253  			false,
   254  			"invalid denoms",
   255  		},
   256  	}
   257  
   258  	decCoins := sdk.NewDecCoinsFromCoins(sdk.NewCoin("btc", sdk.NewInt(10)), sdk.NewCoin("eth", sdk.NewInt(15)), sdk.NewCoin("mytoken", sdk.NewInt(5)))
   259  
   260  	for _, tc := range tests {
   261  		tc := tc
   262  		if tc.expectPass {
   263  			equal := tc.coins.Sub(decCoins)
   264  			s.Require().Equal(equal, decCoins, tc.msg)
   265  		} else {
   266  			s.Require().Panics(func() { tc.coins.Sub(decCoins) }, tc.msg)
   267  		}
   268  	}
   269  }
   270  
   271  func (s *decCoinTestSuite) TestSortDecCoins() {
   272  	good := sdk.DecCoins{
   273  		sdk.NewInt64DecCoin("gas", 1),
   274  		sdk.NewInt64DecCoin("mineral", 1),
   275  		sdk.NewInt64DecCoin("tree", 1),
   276  	}
   277  	empty := sdk.DecCoins{
   278  		sdk.NewInt64DecCoin("gold", 0),
   279  	}
   280  	badSort1 := sdk.DecCoins{
   281  		sdk.NewInt64DecCoin("tree", 1),
   282  		sdk.NewInt64DecCoin("gas", 1),
   283  		sdk.NewInt64DecCoin("mineral", 1),
   284  	}
   285  	badSort2 := sdk.DecCoins{ // both are after the first one, but the second and third are in the wrong order
   286  		sdk.NewInt64DecCoin("gas", 1),
   287  		sdk.NewInt64DecCoin("tree", 1),
   288  		sdk.NewInt64DecCoin("mineral", 1),
   289  	}
   290  	badAmt := sdk.DecCoins{
   291  		sdk.NewInt64DecCoin("gas", 1),
   292  		sdk.NewInt64DecCoin("tree", 0),
   293  		sdk.NewInt64DecCoin("mineral", 1),
   294  	}
   295  	dup := sdk.DecCoins{
   296  		sdk.NewInt64DecCoin("gas", 1),
   297  		sdk.NewInt64DecCoin("gas", 1),
   298  		sdk.NewInt64DecCoin("mineral", 1),
   299  	}
   300  	cases := []struct {
   301  		name          string
   302  		coins         sdk.DecCoins
   303  		before, after bool // valid before/after sort
   304  	}{
   305  		{"valid coins", good, true, true},
   306  		{"empty coins", empty, false, false},
   307  		{"unsorted coins (1)", badSort1, false, true},
   308  		{"unsorted coins (2)", badSort2, false, true},
   309  		{"zero amount coins", badAmt, false, false},
   310  		{"duplicate coins", dup, false, false},
   311  	}
   312  
   313  	for _, tc := range cases {
   314  		s.Require().Equal(tc.before, tc.coins.IsValid(), "coin validity is incorrect before sorting; %s", tc.name)
   315  		tc.coins.Sort()
   316  		s.Require().Equal(tc.after, tc.coins.IsValid(), "coin validity is incorrect after sorting;  %s", tc.name)
   317  	}
   318  }
   319  
   320  func (s *decCoinTestSuite) TestDecCoinsValidate() {
   321  	testCases := []struct {
   322  		input        sdk.DecCoins
   323  		expectedPass bool
   324  	}{
   325  		{sdk.DecCoins{}, true},
   326  		{sdk.DecCoins{sdk.DecCoin{testDenom1, sdk.NewDec(5)}}, true},
   327  		{sdk.DecCoins{sdk.DecCoin{testDenom1, sdk.NewDec(5)}, sdk.DecCoin{testDenom2, sdk.NewDec(100000)}}, true},
   328  		{sdk.DecCoins{sdk.DecCoin{testDenom1, sdk.NewDec(-5)}}, false},
   329  		{sdk.DecCoins{sdk.DecCoin{"BTC", sdk.NewDec(5)}}, true},
   330  		{sdk.DecCoins{sdk.DecCoin{"0BTC", sdk.NewDec(5)}}, false},
   331  		{sdk.DecCoins{sdk.DecCoin{testDenom1, sdk.NewDec(5)}, sdk.DecCoin{"B", sdk.NewDec(100000)}}, false},
   332  		{sdk.DecCoins{sdk.DecCoin{testDenom1, sdk.NewDec(5)}, sdk.DecCoin{testDenom2, sdk.NewDec(-100000)}}, false},
   333  		{sdk.DecCoins{sdk.DecCoin{testDenom1, sdk.NewDec(-5)}, sdk.DecCoin{testDenom2, sdk.NewDec(100000)}}, false},
   334  		{sdk.DecCoins{sdk.DecCoin{"BTC", sdk.NewDec(5)}, sdk.DecCoin{testDenom2, sdk.NewDec(100000)}}, true},
   335  		{sdk.DecCoins{sdk.DecCoin{"0BTC", sdk.NewDec(5)}, sdk.DecCoin{testDenom2, sdk.NewDec(100000)}}, false},
   336  	}
   337  
   338  	for i, tc := range testCases {
   339  		err := tc.input.Validate()
   340  		if tc.expectedPass {
   341  			s.Require().NoError(err, "unexpected result for test case #%d, input: %v", i, tc.input)
   342  		} else {
   343  			s.Require().Error(err, "unexpected result for test case #%d, input: %v", i, tc.input)
   344  		}
   345  	}
   346  }
   347  
   348  func (s *decCoinTestSuite) TestParseDecCoins() {
   349  	testCases := []struct {
   350  		input          string
   351  		expectedResult sdk.DecCoins
   352  		expectedErr    bool
   353  	}{
   354  		{"", nil, false},
   355  		{"4stake", sdk.DecCoins{sdk.NewDecCoinFromDec("stake", sdk.NewDecFromInt(sdk.NewInt(4)))}, false},
   356  		{"5.5atom,4stake", sdk.DecCoins{
   357  			sdk.NewDecCoinFromDec("atom", sdk.NewDecWithPrec(5500000000000000000, sdk.Precision)),
   358  			sdk.NewDecCoinFromDec("stake", sdk.NewDec(4)),
   359  		}, false},
   360  		{"0.0stake", sdk.DecCoins{}, false}, // remove zero coins
   361  		{"10.0btc,1.0atom,20.0btc", nil, true},
   362  		{
   363  			"0.004STAKE",
   364  			sdk.DecCoins{sdk.NewDecCoinFromDec("STAKE", sdk.NewDecWithPrec(4000000000000000, sdk.Precision))},
   365  			false,
   366  		},
   367  		{
   368  			"0.004stake",
   369  			sdk.DecCoins{sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(4000000000000000, sdk.Precision))},
   370  			false,
   371  		},
   372  		{
   373  			"5.04atom,0.004stake",
   374  			sdk.DecCoins{
   375  				sdk.NewDecCoinFromDec("atom", sdk.NewDecWithPrec(5040000000000000000, sdk.Precision)),
   376  				sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(4000000000000000, sdk.Precision)),
   377  			},
   378  			false,
   379  		},
   380  		{
   381  			"0.0stake,0.004stake,5.04atom", // remove zero coins
   382  			sdk.DecCoins{
   383  				sdk.NewDecCoinFromDec("atom", sdk.NewDecWithPrec(5040000000000000000, sdk.Precision)),
   384  				sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(4000000000000000, sdk.Precision)),
   385  			},
   386  			false,
   387  		},
   388  	}
   389  
   390  	for i, tc := range testCases {
   391  		res, err := sdk.ParseDecCoins(tc.input)
   392  		if tc.expectedErr {
   393  			s.Require().Error(err, "expected error for test case #%d, input: %v", i, tc.input)
   394  		} else {
   395  			s.Require().NoError(err, "unexpected error for test case #%d, input: %v", i, tc.input)
   396  			s.Require().Equal(tc.expectedResult, res, "unexpected result for test case #%d, input: %v", i, tc.input)
   397  		}
   398  	}
   399  }
   400  
   401  func (s *decCoinTestSuite) TestDecCoinsString() {
   402  	testCases := []struct {
   403  		input    sdk.DecCoins
   404  		expected string
   405  	}{
   406  		{sdk.DecCoins{}, ""},
   407  		{
   408  			sdk.DecCoins{
   409  				sdk.NewDecCoinFromDec("atom", sdk.NewDecWithPrec(5040000000000000000, sdk.Precision)),
   410  				sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(4000000000000000, sdk.Precision)),
   411  			},
   412  			"5.040000000000000000atom,0.004000000000000000stake",
   413  		},
   414  	}
   415  
   416  	for i, tc := range testCases {
   417  		out := tc.input.String()
   418  		s.Require().Equal(tc.expected, out, "unexpected result for test case #%d, input: %v", i, tc.input)
   419  	}
   420  }
   421  
   422  func (s *decCoinTestSuite) TestDecCoinsIntersect() {
   423  	testCases := []struct {
   424  		input1         string
   425  		input2         string
   426  		expectedResult string
   427  	}{
   428  		{"", "", ""},
   429  		{"1.0stake", "", ""},
   430  		{"1.0stake", "1.0stake", "1.0stake"},
   431  		{"", "1.0stake", ""},
   432  		{"1.0stake", "", ""},
   433  		{"2.0stake,1.0trope", "1.9stake", "1.9stake"},
   434  		{"2.0stake,1.0trope", "2.1stake", "2.0stake"},
   435  		{"2.0stake,1.0trope", "0.9trope", "0.9trope"},
   436  		{"2.0stake,1.0trope", "1.9stake,0.9trope", "1.9stake,0.9trope"},
   437  		{"2.0stake,1.0trope", "1.9stake,0.9trope,20.0other", "1.9stake,0.9trope"},
   438  		{"2.0stake,1.0trope", "1.0other", ""},
   439  	}
   440  
   441  	for i, tc := range testCases {
   442  		in1, err := sdk.ParseDecCoins(tc.input1)
   443  		s.Require().NoError(err, "unexpected parse error in %v", i)
   444  		in2, err := sdk.ParseDecCoins(tc.input2)
   445  		s.Require().NoError(err, "unexpected parse error in %v", i)
   446  		exr, err := sdk.ParseDecCoins(tc.expectedResult)
   447  		s.Require().NoError(err, "unexpected parse error in %v", i)
   448  		s.Require().True(in1.Intersect(in2).IsEqual(exr), "in1.cap(in2) != exr in %v", i)
   449  	}
   450  }
   451  
   452  func (s *decCoinTestSuite) TestDecCoinsTruncateDecimal() {
   453  	decCoinA := sdk.NewDecCoinFromDec("bar", sdk.MustNewDecFromStr("5.41"))
   454  	decCoinB := sdk.NewDecCoinFromDec("foo", sdk.MustNewDecFromStr("6.00"))
   455  
   456  	testCases := []struct {
   457  		input          sdk.DecCoins
   458  		truncatedCoins sdk.Coins
   459  		changeCoins    sdk.DecCoins
   460  	}{
   461  		{sdk.DecCoins{}, sdk.Coins(nil), sdk.DecCoins(nil)},
   462  		{
   463  			sdk.DecCoins{decCoinA, decCoinB},
   464  			sdk.Coins{sdk.NewInt64Coin(decCoinA.Denom, 5), sdk.NewInt64Coin(decCoinB.Denom, 6)},
   465  			sdk.DecCoins{sdk.NewDecCoinFromDec(decCoinA.Denom, sdk.MustNewDecFromStr("0.41"))},
   466  		},
   467  		{
   468  			sdk.DecCoins{decCoinB},
   469  			sdk.Coins{sdk.NewInt64Coin(decCoinB.Denom, 6)},
   470  			sdk.DecCoins(nil),
   471  		},
   472  	}
   473  
   474  	for i, tc := range testCases {
   475  		truncatedCoins, changeCoins := tc.input.TruncateDecimal()
   476  		s.Require().Equal(
   477  			tc.truncatedCoins, truncatedCoins,
   478  			"unexpected truncated coins; tc #%d, input: %s", i, tc.input,
   479  		)
   480  		s.Require().Equal(
   481  			tc.changeCoins, changeCoins,
   482  			"unexpected change coins; tc #%d, input: %s", i, tc.input,
   483  		)
   484  	}
   485  }
   486  
   487  func (s *decCoinTestSuite) TestDecCoinsQuoDecTruncate() {
   488  	x := sdk.MustNewDecFromStr("1.00")
   489  	y := sdk.MustNewDecFromStr("10000000000000000000.00")
   490  
   491  	testCases := []struct {
   492  		coins  sdk.DecCoins
   493  		input  sdk.Dec
   494  		result sdk.DecCoins
   495  		panics bool
   496  	}{
   497  		{sdk.DecCoins{}, sdk.ZeroDec(), sdk.DecCoins(nil), true},
   498  		{sdk.DecCoins{sdk.NewDecCoinFromDec("foo", x)}, y, sdk.DecCoins(nil), false},
   499  		{sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}, sdk.NewDec(2), sdk.DecCoins{sdk.NewDecCoinFromDec("foo", sdk.MustNewDecFromStr("2.5"))}, false},
   500  	}
   501  
   502  	for i, tc := range testCases {
   503  		tc := tc
   504  		if tc.panics {
   505  			s.Require().Panics(func() { tc.coins.QuoDecTruncate(tc.input) })
   506  		} else {
   507  			res := tc.coins.QuoDecTruncate(tc.input)
   508  			s.Require().Equal(tc.result, res, "unexpected result; tc #%d, coins: %s, input: %s", i, tc.coins, tc.input)
   509  		}
   510  	}
   511  }
   512  
   513  func (s *decCoinTestSuite) TestNewDecCoinsWithIsValid() {
   514  	fake1 := append(sdk.NewDecCoins(sdk.NewDecCoin("mytoken", sdk.NewInt(10))), sdk.DecCoin{Denom: "10BTC", Amount: sdk.NewDec(10)})
   515  	fake2 := append(sdk.NewDecCoins(sdk.NewDecCoin("mytoken", sdk.NewInt(10))), sdk.DecCoin{Denom: "BTC", Amount: sdk.NewDec(-10)})
   516  
   517  	tests := []struct {
   518  		coin       sdk.DecCoins
   519  		expectPass bool
   520  		msg        string
   521  	}{
   522  		{
   523  			sdk.NewDecCoins(sdk.NewDecCoin("mytoken", sdk.NewInt(10))),
   524  			true,
   525  			"valid coins should have passed",
   526  		},
   527  		{
   528  			fake1,
   529  			false,
   530  			"invalid denoms",
   531  		},
   532  		{
   533  			fake2,
   534  			false,
   535  			"negative amount",
   536  		},
   537  	}
   538  
   539  	for _, tc := range tests {
   540  		tc := tc
   541  		if tc.expectPass {
   542  			s.Require().True(tc.coin.IsValid(), tc.msg)
   543  		} else {
   544  			s.Require().False(tc.coin.IsValid(), tc.msg)
   545  		}
   546  	}
   547  }
   548  
   549  func (s *decCoinTestSuite) TestDecCoins_AddDecCoinWithIsValid() {
   550  	lengthTestDecCoins := sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", sdk.NewInt(10))).Add(sdk.DecCoin{Denom: "BTC", Amount: sdk.NewDec(10)})
   551  	s.Require().Equal(2, len(lengthTestDecCoins), "should be 2")
   552  
   553  	tests := []struct {
   554  		coin       sdk.DecCoins
   555  		expectPass bool
   556  		msg        string
   557  	}{
   558  		{
   559  			sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", sdk.NewInt(10))),
   560  			true,
   561  			"valid coins should have passed",
   562  		},
   563  		{
   564  			sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", sdk.NewInt(10))).Add(sdk.DecCoin{Denom: "0BTC", Amount: sdk.NewDec(10)}),
   565  			false,
   566  			"invalid denoms",
   567  		},
   568  		{
   569  			sdk.NewDecCoins().Add(sdk.NewDecCoin("mytoken", sdk.NewInt(10))).Add(sdk.DecCoin{Denom: "BTC", Amount: sdk.NewDec(-10)}),
   570  			false,
   571  			"negative amount",
   572  		},
   573  	}
   574  
   575  	for _, tc := range tests {
   576  		tc := tc
   577  		if tc.expectPass {
   578  			s.Require().True(tc.coin.IsValid(), tc.msg)
   579  		} else {
   580  			s.Require().False(tc.coin.IsValid(), tc.msg)
   581  		}
   582  	}
   583  }