github.com/Finschia/finschia-sdk@v0.49.1/x/bank/types/balance_test.go (about) 1 package types_test 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 9 "github.com/Finschia/finschia-sdk/crypto/keys/ed25519" 10 sdk "github.com/Finschia/finschia-sdk/types" 11 bank "github.com/Finschia/finschia-sdk/x/bank/types" 12 ) 13 14 func TestBalanceValidate(t *testing.T) { 15 testCases := []struct { 16 name string 17 balance bank.Balance 18 expErr bool 19 }{ 20 { 21 "valid balance", 22 bank.Balance{ 23 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 24 Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, 25 }, 26 false, 27 }, 28 {"empty balance", bank.Balance{}, true}, 29 { 30 "nil balance coins", 31 bank.Balance{ 32 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 33 }, 34 false, 35 }, 36 { 37 "dup coins", 38 bank.Balance{ 39 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 40 Coins: sdk.Coins{ 41 sdk.NewInt64Coin("uatom", 1), 42 sdk.NewInt64Coin("uatom", 1), 43 }, 44 }, 45 true, 46 }, 47 { 48 "invalid coin denom", 49 bank.Balance{ 50 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 51 Coins: sdk.Coins{ 52 sdk.Coin{Denom: "", Amount: sdk.OneInt()}, 53 }, 54 }, 55 true, 56 }, 57 { 58 "negative coin", 59 bank.Balance{ 60 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 61 Coins: sdk.Coins{ 62 sdk.Coin{Denom: "uatom", Amount: sdk.NewInt(-1)}, 63 }, 64 }, 65 true, 66 }, 67 { 68 "0 value coin", 69 bank.Balance{ 70 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 71 Coins: sdk.Coins{ 72 sdk.NewInt64Coin("atom", 0), 73 sdk.NewInt64Coin("zatom", 2), 74 }, 75 }, 76 true, 77 }, 78 { 79 "unsorted coins", 80 bank.Balance{ 81 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 82 Coins: sdk.Coins{ 83 sdk.NewInt64Coin("atom", 2), 84 sdk.NewInt64Coin("zatom", 2), 85 sdk.NewInt64Coin("batom", 12), 86 }, 87 }, 88 true, 89 }, 90 { 91 "valid sorted coins", 92 bank.Balance{ 93 Address: "link1yq8lgssgxlx9smjhes6ryjasmqmd3ts2p6925r", 94 Coins: sdk.Coins{ 95 sdk.NewInt64Coin("atom", 2), 96 sdk.NewInt64Coin("batom", 12), 97 sdk.NewInt64Coin("zatom", 2), 98 }, 99 }, 100 false, 101 }, 102 } 103 104 for _, tc := range testCases { 105 t.Run(tc.name, func(t *testing.T) { 106 err := tc.balance.Validate() 107 108 if tc.expErr { 109 require.Error(t, err) 110 } else { 111 require.NoError(t, err) 112 } 113 }) 114 } 115 } 116 117 func TestBalance_GetAddress(t *testing.T) { 118 tests := []struct { 119 name string 120 Address string 121 wantPanic bool 122 }{ 123 {"empty address", "", true}, 124 {"malformed address", "invalid", true}, 125 {"valid address", "link1vy0ga0klndqy92ceqehfkvgmn4t94ete4mhemy", false}, 126 } 127 for _, tt := range tests { 128 t.Run(tt.name, func(t *testing.T) { 129 b := bank.Balance{Address: tt.Address} 130 if tt.wantPanic { 131 require.Panics(t, func() { b.GetAddress() }) 132 } else { 133 require.False(t, b.GetAddress().Empty()) 134 } 135 }) 136 } 137 } 138 139 func TestSanitizeBalances(t *testing.T) { 140 // 1. Generate balances 141 tokens := sdk.TokensFromConsensusPower(81, sdk.DefaultPowerReduction) 142 coin := sdk.NewCoin("benchcoin", tokens) 143 coins := sdk.Coins{coin} 144 addrs, _ := makeRandomAddressesAndPublicKeys(20) 145 146 var balances []bank.Balance 147 for _, addr := range addrs { 148 balances = append(balances, bank.Balance{ 149 Address: addr.String(), 150 Coins: coins, 151 }) 152 } 153 // 2. Sort the values. 154 sorted := bank.SanitizeGenesisBalances(balances) 155 156 // 3. Compare and ensure that all the values are sorted in ascending order. 157 // Invariant after sorting: 158 // a[i] <= a[i+1...n] 159 for i := 0; i < len(sorted); i++ { 160 ai := sorted[i] 161 // Ensure that every single value that comes after i is less than it. 162 for j := i + 1; j < len(sorted); j++ { 163 aj := sorted[j] 164 165 if got := bytes.Compare(ai.GetAddress(), aj.GetAddress()); got > 0 { 166 t.Errorf("Balance(%d) > Balance(%d)", i, j) 167 } 168 } 169 } 170 } 171 172 func makeRandomAddressesAndPublicKeys(n int) (accL []sdk.AccAddress, pkL []*ed25519.PubKey) { 173 for i := 0; i < n; i++ { 174 pk := ed25519.GenPrivKey().PubKey().(*ed25519.PubKey) 175 pkL = append(pkL, pk) 176 accL = append(accL, sdk.AccAddress(pk.Address())) 177 } 178 return accL, pkL 179 } 180 181 var sink, revert interface{} 182 183 func BenchmarkSanitizeBalances500(b *testing.B) { 184 benchmarkSanitizeBalances(b, 500) 185 } 186 187 func BenchmarkSanitizeBalances1000(b *testing.B) { 188 benchmarkSanitizeBalances(b, 1000) 189 } 190 191 func benchmarkSanitizeBalances(b *testing.B, nAddresses int) { 192 b.Helper() 193 b.ReportAllocs() 194 tokens := sdk.TokensFromConsensusPower(81, sdk.DefaultPowerReduction) 195 coin := sdk.NewCoin("benchcoin", tokens) 196 coins := sdk.Coins{coin} 197 addrs, _ := makeRandomAddressesAndPublicKeys(nAddresses) 198 199 b.ResetTimer() 200 for i := 0; i < b.N; i++ { 201 var balances []bank.Balance 202 for _, addr := range addrs { 203 balances = append(balances, bank.Balance{ 204 Address: addr.String(), 205 Coins: coins, 206 }) 207 } 208 sink = bank.SanitizeGenesisBalances(balances) 209 } 210 if sink == nil { 211 b.Fatal("Benchmark did not run") 212 } 213 sink = revert 214 }