github.com/Finschia/finschia-sdk@v0.48.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 tc := tc 106 t.Run(tc.name, func(t *testing.T) { 107 err := tc.balance.Validate() 108 109 if tc.expErr { 110 require.Error(t, err) 111 } else { 112 require.NoError(t, err) 113 } 114 }) 115 } 116 } 117 118 func TestBalance_GetAddress(t *testing.T) { 119 tests := []struct { 120 name string 121 Address string 122 wantPanic bool 123 }{ 124 {"empty address", "", true}, 125 {"malformed address", "invalid", true}, 126 {"valid address", "link1vy0ga0klndqy92ceqehfkvgmn4t94ete4mhemy", false}, 127 } 128 for _, tt := range tests { 129 tt := tt 130 t.Run(tt.name, func(t *testing.T) { 131 b := bank.Balance{Address: tt.Address} 132 if tt.wantPanic { 133 require.Panics(t, func() { b.GetAddress() }) 134 } else { 135 require.False(t, b.GetAddress().Empty()) 136 } 137 }) 138 } 139 } 140 141 func TestSanitizeBalances(t *testing.T) { 142 // 1. Generate balances 143 tokens := sdk.TokensFromConsensusPower(81, sdk.DefaultPowerReduction) 144 coin := sdk.NewCoin("benchcoin", tokens) 145 coins := sdk.Coins{coin} 146 addrs, _ := makeRandomAddressesAndPublicKeys(20) 147 148 var balances []bank.Balance 149 for _, addr := range addrs { 150 balances = append(balances, bank.Balance{ 151 Address: addr.String(), 152 Coins: coins, 153 }) 154 } 155 // 2. Sort the values. 156 sorted := bank.SanitizeGenesisBalances(balances) 157 158 // 3. Compare and ensure that all the values are sorted in ascending order. 159 // Invariant after sorting: 160 // a[i] <= a[i+1...n] 161 for i := 0; i < len(sorted); i++ { 162 ai := sorted[i] 163 // Ensure that every single value that comes after i is less than it. 164 for j := i + 1; j < len(sorted); j++ { 165 aj := sorted[j] 166 167 if got := bytes.Compare(ai.GetAddress(), aj.GetAddress()); got > 0 { 168 t.Errorf("Balance(%d) > Balance(%d)", i, j) 169 } 170 } 171 } 172 } 173 174 func makeRandomAddressesAndPublicKeys(n int) (accL []sdk.AccAddress, pkL []*ed25519.PubKey) { 175 for i := 0; i < n; i++ { 176 pk := ed25519.GenPrivKey().PubKey().(*ed25519.PubKey) 177 pkL = append(pkL, pk) 178 accL = append(accL, sdk.AccAddress(pk.Address())) 179 } 180 return accL, pkL 181 } 182 183 var sink, revert interface{} 184 185 func BenchmarkSanitizeBalances500(b *testing.B) { 186 benchmarkSanitizeBalances(b, 500) 187 } 188 189 func BenchmarkSanitizeBalances1000(b *testing.B) { 190 benchmarkSanitizeBalances(b, 1000) 191 } 192 193 func benchmarkSanitizeBalances(b *testing.B, nAddresses int) { 194 b.ReportAllocs() 195 tokens := sdk.TokensFromConsensusPower(81, sdk.DefaultPowerReduction) 196 coin := sdk.NewCoin("benchcoin", tokens) 197 coins := sdk.Coins{coin} 198 addrs, _ := makeRandomAddressesAndPublicKeys(nAddresses) 199 200 b.ResetTimer() 201 for i := 0; i < b.N; i++ { 202 var balances []bank.Balance 203 for _, addr := range addrs { 204 balances = append(balances, bank.Balance{ 205 Address: addr.String(), 206 Coins: coins, 207 }) 208 } 209 sink = bank.SanitizeGenesisBalances(balances) 210 } 211 if sink == nil { 212 b.Fatal("Benchmark did not run") 213 } 214 sink = revert 215 }