github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/common/syscoins_test.go (about)

     1  package common
     2  
     3  import (
     4  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
     5  	"github.com/stretchr/testify/assert"
     6  	"testing"
     7  
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  // ----------------------------------------------------------------------------
    13  // Coins tests
    14  
    15  var (
    16  	syscoinsTestDenom1 = "eos"
    17  	syscoinsTestDenom2 = "fibo"
    18  )
    19  
    20  func TestIsZeroCoins(t *testing.T) {
    21  	cases := []struct {
    22  		inputOne sdk.SysCoins
    23  		expected bool
    24  	}{
    25  		{sdk.SysCoins{}, true},
    26  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0)}, true},
    27  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 0)}, true},
    28  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 1)}, false},
    29  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 1)}, false},
    30  	}
    31  
    32  	for _, tc := range cases {
    33  		res := tc.inputOne.IsZero()
    34  		require.Equal(t, tc.expected, res)
    35  	}
    36  }
    37  
    38  func TestEqualCoins(t *testing.T) {
    39  	cases := []struct {
    40  		inputOne sdk.SysCoins
    41  		inputTwo sdk.SysCoins
    42  		expected bool
    43  		panics   bool
    44  	}{
    45  		{sdk.SysCoins{}, sdk.SysCoins{}, true, false},
    46  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0)}, sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0)}, true, false},
    47  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 1)}, sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 1)}, true, false},
    48  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0)}, sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom2, 0)}, false, true},
    49  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0)}, sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 1)}, false, false},
    50  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0)}, sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 1)}, false, false},
    51  		{sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 1)}, sdk.SysCoins{sdk.NewInt64Coin(syscoinsTestDenom1, 0), sdk.NewInt64Coin(syscoinsTestDenom2, 1)}, true, false},
    52  	}
    53  
    54  	for tcIndex, tc := range cases {
    55  		tc := tc
    56  		if tc.panics {
    57  			require.Panics(t, func() { tc.inputOne.IsEqual(tc.inputTwo) })
    58  		} else {
    59  			res := tc.inputOne.IsEqual(tc.inputTwo)
    60  			require.Equal(t, tc.expected, res, "Equality is differed from exported. tc #%d, expected %b, actual %b.", tcIndex, tc.expected, res)
    61  		}
    62  	}
    63  }
    64  
    65  func TestAddCoins(t *testing.T) {
    66  	cases := []struct {
    67  		inputOne    sdk.SysCoins
    68  		inputTwo    sdk.SysCoins
    69  		expected    sdk.SysCoins
    70  		shouldPanic bool
    71  	}{
    72  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}, {syscoinsTestDenom2, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}, {syscoinsTestDenom2, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}, {syscoinsTestDenom2, sdk.NewDec(2)}}, false},
    73  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(0)}, {syscoinsTestDenom2, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(0)}, {syscoinsTestDenom2, sdk.NewDec(0)}}, sdk.SysCoins{{syscoinsTestDenom2, sdk.NewDec(1)}}, false},
    74  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}}, sdk.SysCoins{{syscoinsTestDenom2, sdk.NewDec(0)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}}, false},
    75  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}, {syscoinsTestDenom2, sdk.NewDec(2)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}, {syscoinsTestDenom2, sdk.NewDec(2)}}, false},
    76  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(0)}, {syscoinsTestDenom2, sdk.NewDec(0)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(0)}, {syscoinsTestDenom2, sdk.NewDec(0)}}, sdk.SysCoins(nil), false},
    77  	}
    78  
    79  	for tcIndex, tc := range cases {
    80  		tc := tc
    81  		if tc.shouldPanic {
    82  			require.Panics(t, func() { tc.inputOne.Add2(tc.inputTwo) })
    83  		} else {
    84  			res := tc.inputOne.Add2(tc.inputTwo)
    85  			assert.True(t, res.IsValid())
    86  			require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
    87  		}
    88  	}
    89  }
    90  
    91  func TestSubCoins(t *testing.T) {
    92  	testCases := []struct {
    93  		inputOne    sdk.SysCoins
    94  		inputTwo    sdk.SysCoins
    95  		expected    sdk.SysCoins
    96  		shouldPanic bool
    97  	}{
    98  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}}, sdk.SysCoins{{syscoinsTestDenom2, sdk.NewDec(0)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}}, false},
    99  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom2, sdk.NewDec(0)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}}, false},
   100  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}, {syscoinsTestDenom2, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom2, sdk.NewDec(1)}}, false},
   101  		{sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(1)}, {syscoinsTestDenom2, sdk.NewDec(1)}}, sdk.SysCoins{{syscoinsTestDenom1, sdk.NewDec(2)}}, sdk.SysCoins{}, true},
   102  	}
   103  
   104  	for tcIndex, tc := range testCases {
   105  		tc := tc
   106  		if tc.shouldPanic {
   107  			require.Panics(t, func() { tc.inputOne.Sub(tc.inputTwo) })
   108  		} else {
   109  			res := tc.inputOne.Sub(tc.inputTwo)
   110  			assert.True(t, res.IsValid())
   111  			require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
   112  		}
   113  	}
   114  }
   115  
   116  func TestSortDecCoins(t *testing.T) {
   117  	good := sdk.SysCoins{
   118  		{"gas", sdk.NewDec(1)},
   119  		{"mineral", sdk.NewDec(1)},
   120  		{"tree", sdk.NewDec(1)},
   121  	}
   122  	mixedCase1 := sdk.SysCoins{
   123  		{"gAs", sdk.NewDec(1)},
   124  		{"MineraL", sdk.NewDec(1)},
   125  		{"TREE", sdk.NewDec(1)},
   126  	}
   127  	mixedCase2 := sdk.SysCoins{
   128  		{"gAs", sdk.NewDec(1)},
   129  		{"mineral", sdk.NewDec(1)},
   130  	}
   131  	mixedCase3 := sdk.SysCoins{
   132  		{"gAs", sdk.NewDec(1)},
   133  	}
   134  	empty := sdk.NewCoins()
   135  	badSort1 := sdk.SysCoins{
   136  		{"tree", sdk.NewDec(1)},
   137  		{"gas", sdk.NewDec(1)},
   138  		{"mineral", sdk.NewDec(1)},
   139  	}
   140  
   141  	// both are after the first one, but the second and third are in the wrong order
   142  	badSort2 := sdk.SysCoins{
   143  		{"gas", sdk.NewDec(1)},
   144  		{"tree", sdk.NewDec(1)},
   145  		{"mineral", sdk.NewDec(1)},
   146  	}
   147  	badAmt := sdk.SysCoins{
   148  		{"gas", sdk.NewDec(1)},
   149  		{"tree", sdk.NewDec(0)},
   150  		{"mineral", sdk.NewDec(1)},
   151  	}
   152  	dup := sdk.SysCoins{
   153  		{"gas", sdk.NewDec(1)},
   154  		{"gas", sdk.NewDec(1)},
   155  		{"mineral", sdk.NewDec(1)},
   156  	}
   157  	neg := sdk.SysCoins{
   158  		{"gas", sdk.NewDec(-1)},
   159  		{"mineral", sdk.NewDec(1)},
   160  	}
   161  
   162  	assert.True(t, good.IsValid(), "Coins are valid")
   163  	assert.False(t, mixedCase1.IsValid(), "Coins denoms contain upper case characters")
   164  	assert.False(t, mixedCase2.IsValid(), "First Coins denoms contain upper case characters")
   165  	assert.False(t, mixedCase3.IsValid(), "Single denom in Coins contains upper case characters")
   166  	assert.True(t, good.IsAllPositive(), "Expected coins to be positive: %v", good)
   167  	assert.False(t, empty.IsAllPositive(), "Expected coins to not be positive: %v", empty)
   168  	assert.True(t, good.IsAllGTE(empty), "Expected %v to be >= %v", good, empty)
   169  	assert.False(t, good.IsAllLT(empty), "Expected %v to be < %v", good, empty)
   170  	assert.True(t, empty.IsAllLT(good), "Expected %v to be < %v", empty, good)
   171  	assert.False(t, badSort1.IsValid(), "Coins are not sorted")
   172  	assert.False(t, badSort2.IsValid(), "Coins are not sorted")
   173  	assert.False(t, badAmt.IsValid(), "Coins cannot include 0 amounts")
   174  	assert.False(t, dup.IsValid(), "Duplicate coin")
   175  	assert.False(t, neg.IsValid(), "Negative first-denom coin")
   176  }
   177  
   178  func TestCoinsGT(t *testing.T) {
   179  	one := sdk.NewDec(1)
   180  	two := sdk.NewDec(2)
   181  
   182  	assert.False(t, sdk.SysCoins{}.IsAllGT(sdk.SysCoins{}))
   183  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{}))
   184  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   185  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   186  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   187  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom2, two}}))
   188  }
   189  
   190  func TestCoinsLT(t *testing.T) {
   191  	one := sdk.NewDec(1)
   192  	two := sdk.NewDec(2)
   193  
   194  	assert.False(t, sdk.SysCoins{}.IsAllLT(sdk.SysCoins{}))
   195  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllLT(sdk.SysCoins{}))
   196  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   197  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   198  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   199  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom2, two}}))
   200  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}))
   201  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom1, two}, {syscoinsTestDenom2, two}}))
   202  	assert.True(t, sdk.SysCoins{}.IsAllLT(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   203  }
   204  
   205  func TestCoinsLTE(t *testing.T) {
   206  	one := sdk.NewDec(1)
   207  	two := sdk.NewDec(2)
   208  
   209  	assert.True(t, sdk.SysCoins{}.IsAllLTE(sdk.SysCoins{}))
   210  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllLTE(sdk.SysCoins{}))
   211  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   212  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   213  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   214  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom2, two}}))
   215  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}))
   216  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   217  	assert.True(t, sdk.SysCoins{}.IsAllLTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   218  }
   219  
   220  func TestParse(t *testing.T) {
   221  	cases := []struct {
   222  		input    string
   223  		valid    bool         // if false, we expect an error on parse
   224  		expected sdk.SysCoins // if valid is true, make sure this is returned
   225  	}{
   226  		{"", true, nil},
   227  		{"1foo", true, sdk.SysCoins{{"foo", sdk.NewDec(1)}}},
   228  		{"10bar", true, sdk.SysCoins{{"bar", sdk.NewDec(10)}}},
   229  		{"99bar,1foo", true, sdk.SysCoins{{"bar", sdk.NewDec(99)}, {"foo", sdk.NewDec(1)}}},
   230  		{"98 bar , 1 foo  ", true, sdk.SysCoins{{"bar", sdk.NewDec(98)}, {"foo", sdk.NewDec(1)}}},
   231  		{"  55\t \t bling\n", true, sdk.SysCoins{{"bling", sdk.NewDec(55)}}},
   232  		{"2foo, 97 bar", true, sdk.SysCoins{{"bar", sdk.NewDec(97)}, {"foo", sdk.NewDec(2)}}},
   233  		{"5 mycoin,", false, nil},             // no empty coins in a list
   234  		{"2 3foo, 97 bar", false, nil},        // 3foo is invalid coin name
   235  		{"11me coin, 12you coin", false, nil}, // no spaces in coin names
   236  		//{"1.2btc", true, sdk.Coins{{"btc", sdk.NewDec(1.2)}}},                // amount must be integer
   237  		{"5foo-bar", false, nil}, // once more, only letters in coin name
   238  	}
   239  
   240  	for tcIndex, tc := range cases {
   241  		res, err := sdk.ParseCoins(tc.input)
   242  		if !tc.valid {
   243  			require.NotNil(t, err, "%s: %#v. tc #%d", tc.input, res, tcIndex)
   244  		} else if assert.Nil(t, err, "%s: %+v", tc.input, err) {
   245  			require.Equal(t, tc.expected, res, "coin parsing was incorrect, tc #%d", tcIndex)
   246  		}
   247  	}
   248  }
   249  
   250  func TestSortCoins(t *testing.T) {
   251  	good := sdk.SysCoins{
   252  		sdk.NewInt64Coin("gas", 1),
   253  		sdk.NewInt64Coin("mineral", 1),
   254  		sdk.NewInt64Coin("tree", 1),
   255  	}
   256  	empty := sdk.SysCoins{
   257  		sdk.NewInt64Coin("gold", 0),
   258  	}
   259  	badSort1 := sdk.SysCoins{
   260  		sdk.NewInt64Coin("tree", 1),
   261  		sdk.NewInt64Coin("gas", 1),
   262  		sdk.NewInt64Coin("mineral", 1),
   263  	}
   264  	badSort2 := sdk.SysCoins{ // both are after the first one, but the second and third are in the wrong order
   265  		sdk.NewInt64Coin("gas", 1),
   266  		sdk.NewInt64Coin("tree", 1),
   267  		sdk.NewInt64Coin("mineral", 1),
   268  	}
   269  	badAmt := sdk.SysCoins{
   270  		sdk.NewInt64Coin("gas", 1),
   271  		sdk.NewInt64Coin("tree", 0),
   272  		sdk.NewInt64Coin("mineral", 1),
   273  	}
   274  	dup := sdk.SysCoins{
   275  		sdk.NewInt64Coin("gas", 1),
   276  		sdk.NewInt64Coin("gas", 1),
   277  		sdk.NewInt64Coin("mineral", 1),
   278  	}
   279  
   280  	cases := []struct {
   281  		coins         sdk.SysCoins
   282  		before, after bool // valid before/after sort
   283  	}{
   284  		{good, true, true},
   285  		{empty, false, false},
   286  		{badSort1, false, true},
   287  		{badSort2, false, true},
   288  		{badAmt, false, false},
   289  		{dup, false, false},
   290  	}
   291  
   292  	for tcIndex, tc := range cases {
   293  		require.Equal(t, tc.before, tc.coins.IsValid(), "coin validity is incorrect before sorting, tc #%d", tcIndex)
   294  		tc.coins.Sort()
   295  		require.Equal(t, tc.after, tc.coins.IsValid(), "coin validity is incorrect after sorting, tc #%d", tcIndex)
   296  	}
   297  }
   298  
   299  func TestAmountOf(t *testing.T) {
   300  	case0 := sdk.SysCoins{}
   301  	case1 := sdk.SysCoins{
   302  		sdk.NewInt64Coin("gold", 0),
   303  	}
   304  	case2 := sdk.SysCoins{
   305  		sdk.NewInt64Coin("gas", 1),
   306  		sdk.NewInt64Coin("mineral", 1),
   307  		sdk.NewInt64Coin("tree", 1),
   308  	}
   309  	case3 := sdk.SysCoins{
   310  		sdk.NewInt64Coin("mineral", 1),
   311  		sdk.NewInt64Coin("tree", 1),
   312  	}
   313  	case4 := sdk.SysCoins{
   314  		sdk.NewInt64Coin("gas", 8),
   315  	}
   316  
   317  	cases := []struct {
   318  		coins           sdk.SysCoins
   319  		amountOf        int64
   320  		amountOfSpace   int64
   321  		amountOfGAS     int64
   322  		amountOfMINERAL int64
   323  		amountOfTREE    int64
   324  	}{
   325  		{case0, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000},
   326  		{case1, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000},
   327  		{case2, 0.0000000000000000000, 0.000000000000000000, 1.000000000000000000, 1.000000000000000000, 1.000000000000000000},
   328  		{case3, 0.000000000000000000, 0.000000000000000000, 0.000000000000000000, 1.000000000000000000, 1.000000000000000000},
   329  		{case4, 0.000000000000000000, 0.000000000000000000, 8.000000000000000000, 0.000000000000000000, 0.000000000000000000},
   330  	}
   331  
   332  	for _, tc := range cases {
   333  		assert.Equal(t, sdk.NewDec(tc.amountOfGAS), tc.coins.AmountOf("gas"))
   334  		assert.Equal(t, sdk.NewDec(tc.amountOfMINERAL), tc.coins.AmountOf("mineral"))
   335  		assert.Equal(t, sdk.NewDec(tc.amountOfTREE), tc.coins.AmountOf("tree"))
   336  	}
   337  
   338  	assert.Panics(t, func() { cases[0].coins.AmountOf("Invalid") })
   339  }
   340  
   341  func TestCoinsIsAnyGTE(t *testing.T) {
   342  	one := sdk.NewDec(1)
   343  	two := sdk.NewDec(2)
   344  
   345  	assert.False(t, sdk.SysCoins{}.IsAnyGTE(sdk.SysCoins{}))
   346  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAnyGTE(sdk.SysCoins{}))
   347  	assert.False(t, sdk.SysCoins{}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   348  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, two}}))
   349  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   350  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, two}, {syscoinsTestDenom2, one}}))
   351  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   352  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, two}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   353  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   354  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom2, two}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   355  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom2, one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   356  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}))
   357  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   358  	assert.True(t, sdk.SysCoins{{"xxx", one}, {"yyy", one}}.IsAnyGTE(sdk.SysCoins{{syscoinsTestDenom2, one}, {"ccc", one}, {"yyy", one}, {"zzz", one}}))
   359  }
   360  
   361  func TestCoinsIsAllGT(t *testing.T) {
   362  	one := sdk.NewDec(1)
   363  	two := sdk.NewDec(2)
   364  
   365  	assert.False(t, sdk.SysCoins{}.IsAllGT(sdk.SysCoins{}))
   366  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{}))
   367  	assert.False(t, sdk.SysCoins{}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   368  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, two}}))
   369  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   370  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, two}, {syscoinsTestDenom2, one}}))
   371  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   372  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, two}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   373  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   374  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom2, two}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   375  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom2, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   376  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}))
   377  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   378  	assert.False(t, sdk.SysCoins{{"xxx", one}, {"yyy", one}}.IsAllGT(sdk.SysCoins{{syscoinsTestDenom2, one}, {"ccc", one}, {"yyy", one}, {"zzz", one}}))
   379  }
   380  
   381  func TestCoinsIsAllGTE(t *testing.T) {
   382  	one := sdk.NewDec(1)
   383  	two := sdk.NewDec(2)
   384  
   385  	assert.True(t, sdk.SysCoins{}.IsAllGTE(sdk.SysCoins{}))
   386  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGTE(sdk.SysCoins{}))
   387  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   388  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom2, two}}))
   389  	assert.False(t, sdk.SysCoins{}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   390  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, two}}))
   391  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom2, one}}))
   392  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, two}, {syscoinsTestDenom2, one}}))
   393  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   394  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, two}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}}))
   395  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   396  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom2, two}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   397  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom2, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   398  	assert.True(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}))
   399  	assert.False(t, sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom1, one}, {syscoinsTestDenom2, two}}))
   400  	assert.False(t, sdk.SysCoins{{"xxx", one}, {"yyy", one}}.IsAllGTE(sdk.SysCoins{{syscoinsTestDenom2, one}, {"ccc", one}, {"yyy", one}, {"zzz", one}}))
   401  }
   402  
   403  func TestNewCoins(t *testing.T) {
   404  	tenatom := sdk.NewInt64Coin("atom", 10)
   405  	tenbtc := sdk.NewInt64Coin("btc", 10)
   406  	zeroeth := sdk.NewInt64Coin("eth", 0)
   407  	tests := []struct {
   408  		name      string
   409  		coins     sdk.SysCoins
   410  		want      sdk.SysCoins
   411  		wantPanic bool
   412  	}{
   413  		{"empty args", []sdk.SysCoin{}, sdk.SysCoins{}, false},
   414  		{"one coin", []sdk.SysCoin{tenatom}, sdk.SysCoins{tenatom}, false},
   415  		{"sort after create", []sdk.SysCoin{tenbtc, tenatom}, sdk.SysCoins{tenatom, tenbtc}, false},
   416  		{"sort and remove zeroes", []sdk.SysCoin{zeroeth, tenbtc, tenatom}, sdk.SysCoins{tenatom, tenbtc}, false},
   417  		{"panic on dups", []sdk.SysCoin{tenatom, tenatom}, sdk.SysCoins{}, true},
   418  	}
   419  	for _, tt := range tests {
   420  		tt := tt
   421  		t.Run(tt.name, func(t *testing.T) {
   422  			if tt.wantPanic {
   423  				require.Panics(t, func() { sdk.NewCoins(tt.coins...) })
   424  				return
   425  			}
   426  			got := sdk.NewCoins(tt.coins...)
   427  			require.True(t, got.IsEqual(tt.want))
   428  		})
   429  	}
   430  }
   431  
   432  func TestCoinsIsAnyGT(t *testing.T) {
   433  	twoAtom := sdk.NewInt64Coin("atom", 2)
   434  	fiveAtom := sdk.NewInt64Coin("atom", 5)
   435  	threeEth := sdk.NewInt64Coin("eth", 3)
   436  	sixEth := sdk.NewInt64Coin("eth", 6)
   437  	twoBtc := sdk.NewInt64Coin("btc", 2)
   438  
   439  	require.False(t, sdk.SysCoins{}.IsAnyGT(sdk.SysCoins{}))
   440  
   441  	require.False(t, sdk.SysCoins{fiveAtom}.IsAnyGT(sdk.SysCoins{}))
   442  	require.False(t, sdk.SysCoins{}.IsAnyGT(sdk.SysCoins{fiveAtom}))
   443  	require.True(t, sdk.SysCoins{fiveAtom}.IsAnyGT(sdk.SysCoins{twoAtom}))
   444  	require.False(t, sdk.SysCoins{twoAtom}.IsAnyGT(sdk.SysCoins{fiveAtom}))
   445  
   446  	require.True(t, sdk.SysCoins{twoAtom, sixEth}.IsAnyGT(sdk.SysCoins{twoBtc, fiveAtom, threeEth}))
   447  	require.False(t, sdk.SysCoins{twoBtc, twoAtom, threeEth}.IsAnyGT(sdk.SysCoins{fiveAtom, sixEth}))
   448  	require.False(t, sdk.SysCoins{twoAtom, sixEth}.IsAnyGT(sdk.SysCoins{twoBtc, fiveAtom}))
   449  }
   450  
   451  func TestMarshalJSONCoins(t *testing.T) {
   452  	cdc := codec.New()
   453  	sdk.RegisterCodec(cdc)
   454  
   455  	testCases := []struct {
   456  		name      string
   457  		input     sdk.SysCoins
   458  		strOutput string
   459  	}{
   460  		{"nil coins", nil, `[]`},
   461  		{"empty coins", sdk.SysCoins{}, `[]`},
   462  		{"non-empty coins", sdk.NewCoins(sdk.NewInt64Coin("foo", 50)), `[{"denom":"foo","amount":"50.000000000000000000"}]`},
   463  	}
   464  
   465  	for _, tc := range testCases {
   466  		tc := tc
   467  		t.Run(tc.name, func(t *testing.T) {
   468  			bz, err := cdc.MarshalJSON(tc.input)
   469  			require.NoError(t, err)
   470  			require.Equal(t, tc.strOutput, string(bz))
   471  
   472  			var newCoins sdk.SysCoins
   473  			require.NoError(t, cdc.UnmarshalJSON(bz, &newCoins))
   474  
   475  			if tc.input.Empty() {
   476  				require.Nil(t, newCoins)
   477  			} else {
   478  				require.Equal(t, tc.input, newCoins)
   479  			}
   480  		})
   481  	}
   482  }
   483  
   484  func TestCoinsIsValid(t *testing.T) {
   485  	testCases := []struct {
   486  		input    sdk.Coins
   487  		expected bool
   488  	}{
   489  		{sdk.SysCoins{}, true},
   490  		{sdk.SysCoins{sdk.DecCoin{Denom: syscoinsTestDenom1, Amount: sdk.NewDec(5)}}, true},
   491  		{sdk.SysCoins{sdk.DecCoin{Denom: syscoinsTestDenom1, Amount: sdk.NewDec(5)}, sdk.DecCoin{Denom: syscoinsTestDenom2, Amount: sdk.NewDec(100000)}}, true},
   492  		{sdk.SysCoins{sdk.DecCoin{Denom: syscoinsTestDenom1, Amount: sdk.NewDec(-5)}}, false},
   493  		{sdk.SysCoins{sdk.DecCoin{Denom: "AAA", Amount: sdk.NewDec(5)}}, false},
   494  		{sdk.SysCoins{sdk.DecCoin{Denom: syscoinsTestDenom1, Amount: sdk.NewDec(5)}, sdk.DecCoin{Denom: "B", Amount: sdk.NewDec(100000)}}, false},
   495  		{sdk.SysCoins{sdk.DecCoin{Denom: syscoinsTestDenom1, Amount: sdk.NewDec(5)}, sdk.DecCoin{Denom: syscoinsTestDenom2, Amount: sdk.NewDec(-100000)}}, false},
   496  		{sdk.SysCoins{sdk.DecCoin{Denom: syscoinsTestDenom1, Amount: sdk.NewDec(-5)}, sdk.DecCoin{Denom: syscoinsTestDenom2, Amount: sdk.NewDec(100000)}}, false},
   497  		{sdk.SysCoins{sdk.DecCoin{Denom: "AAA", Amount: sdk.NewDec(5)}, sdk.DecCoin{Denom: syscoinsTestDenom2, Amount: sdk.NewDec(100000)}}, false},
   498  	}
   499  
   500  	for i, tc := range testCases {
   501  		res := tc.input.IsValid()
   502  		require.Equal(t, tc.expected, res, "unexpected result for test case #%d, input: %v", i, tc.input)
   503  	}
   504  }
   505  
   506  func TestDecCoinsString(t *testing.T) {
   507  	testCases := []struct {
   508  		input    sdk.SysCoins
   509  		expected string
   510  	}{
   511  		{sdk.SysCoins{}, ""},
   512  		{
   513  			sdk.SysCoins{
   514  				sdk.NewDecCoinFromDec("atom", sdk.NewDecWithPrec(5040000000000000000, sdk.Precision)),
   515  				sdk.NewDecCoinFromDec("stake", sdk.NewDecWithPrec(4000000000000000, sdk.Precision)),
   516  			},
   517  			"5.040000000000000000atom,0.004000000000000000stake",
   518  		},
   519  	}
   520  
   521  	for i, tc := range testCases {
   522  		out := tc.input.String()
   523  		require.Equal(t, tc.expected, out, "unexpected result for test case #%d, input: %v", i, tc.input)
   524  	}
   525  }
   526  
   527  func TestDecCoinsIntersect(t *testing.T) {
   528  	testCases := []struct {
   529  		input1         string
   530  		input2         string
   531  		expectedResult string
   532  	}{
   533  		{"", "", ""},
   534  		{"1.0stake", "", ""},
   535  		{"1.0stake", "1.0stake", "1.0stake"},
   536  		{"", "1.0stake", ""},
   537  		{"1.0stake", "", ""},
   538  		{"2.0stake,1.0trope", "1.9stake", "1.9stake"},
   539  		{"2.0stake,1.0trope", "2.1stake", "2.0stake"},
   540  		{"2.0stake,1.0trope", "0.9trope", "0.9trope"},
   541  		{"2.0stake,1.0trope", "1.9stake,0.9trope", "1.9stake,0.9trope"},
   542  		{"2.0stake,1.0trope", "1.9stake,0.9trope,20.0other", "1.9stake,0.9trope"},
   543  		{"2.0stake,1.0trope", "1.0other", ""},
   544  	}
   545  
   546  	for i, tc := range testCases {
   547  		in1, err := sdk.ParseDecCoins(tc.input1)
   548  		require.NoError(t, err, "unexpected parse error in %v", i)
   549  		in2, err := sdk.ParseDecCoins(tc.input2)
   550  		require.NoError(t, err, "unexpected parse error in %v", i)
   551  		exr, err := sdk.ParseDecCoins(tc.expectedResult)
   552  		require.NoError(t, err, "unexpected parse error in %v", i)
   553  
   554  		require.True(t, in1.Intersect(in2).IsEqual(exr), "in1.cap(in2) != exr in %v", i)
   555  	}
   556  }
   557  
   558  func TestDecCoinsTruncateDecimal(t *testing.T) {
   559  	decCoinA := sdk.NewDecCoinFromDec("bar", sdk.MustNewDecFromStr("5.41"))
   560  	decCoinB := sdk.NewDecCoinFromDec("foo", sdk.MustNewDecFromStr("6.00"))
   561  
   562  	testCases := []struct {
   563  		input          sdk.DecCoins
   564  		truncatedCoins sdk.SysCoins
   565  		changeCoins    sdk.DecCoins
   566  	}{
   567  		{sdk.DecCoins{}, sdk.SysCoins(nil), sdk.DecCoins(nil)},
   568  		{
   569  			sdk.DecCoins{decCoinA, decCoinB},
   570  			sdk.SysCoins{sdk.NewInt64Coin(decCoinA.Denom, 5), sdk.NewInt64Coin(decCoinB.Denom, 6)},
   571  			sdk.DecCoins{sdk.NewDecCoinFromDec(decCoinA.Denom, sdk.MustNewDecFromStr("0.41"))},
   572  		},
   573  		{
   574  			sdk.DecCoins{decCoinB},
   575  			sdk.SysCoins{sdk.NewInt64Coin(decCoinB.Denom, 6)},
   576  			sdk.DecCoins(nil),
   577  		},
   578  	}
   579  
   580  	for i, tc := range testCases {
   581  		truncatedCoins, changeCoins := tc.input.TruncateDecimal()
   582  		require.Equal(
   583  			t, tc.truncatedCoins, truncatedCoins,
   584  			"unexpected truncated coins; tc #%d, input: %s", i, tc.input,
   585  		)
   586  		require.Equal(
   587  			t, tc.changeCoins, changeCoins,
   588  			"unexpected change coins; tc #%d, input: %s", i, tc.input,
   589  		)
   590  	}
   591  }
   592  
   593  func TestDecCoinsQuoDecTruncate(t *testing.T) {
   594  	x := sdk.MustNewDecFromStr("1.00")
   595  	y := sdk.MustNewDecFromStr("10000000000000000000.00")
   596  
   597  	testCases := []struct {
   598  		coins  sdk.DecCoins
   599  		input  sdk.Dec
   600  		result sdk.DecCoins
   601  		panics bool
   602  	}{
   603  		{sdk.DecCoins{}, sdk.ZeroDec(), sdk.DecCoins(nil), true},
   604  		{sdk.DecCoins{sdk.NewDecCoinFromDec("foo", x)}, y, sdk.DecCoins(nil), false},
   605  		{sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}, sdk.NewDec(2), sdk.DecCoins{sdk.NewDecCoinFromDec("foo", sdk.MustNewDecFromStr("2.5"))}, false},
   606  	}
   607  
   608  	for i, tc := range testCases {
   609  		tc := tc
   610  		if tc.panics {
   611  			require.Panics(t, func() { tc.coins.QuoDecTruncate(tc.input) })
   612  		} else {
   613  			res := tc.coins.QuoDecTruncate(tc.input)
   614  			require.Equal(t, tc.result, res, "unexpected result; tc #%d, coins: %s, input: %s", i, tc.coins, tc.input)
   615  		}
   616  	}
   617  }