github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/cache_test.go (about) 1 package types 2 3 import ( 4 "fmt" 5 ethcmn "github.com/ethereum/go-ethereum/common" 6 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 7 "github.com/stretchr/testify/require" 8 "testing" 9 "time" 10 ) 11 12 type mockAccount struct { 13 data int 14 } 15 16 func newMockAccount(data int) *mockAccount { 17 return &mockAccount{ 18 data: data, 19 } 20 } 21 22 func (m *mockAccount) Copy() Account { 23 return m 24 } 25 26 func (m *mockAccount) GetAddress() AccAddress { 27 return nil 28 } 29 30 func (m *mockAccount) SetAddress(AccAddress) error { 31 return nil 32 } 33 34 func (m *mockAccount) GetPubKey() crypto.PubKey { 35 return nil 36 } 37 38 func (m *mockAccount) SetPubKey(crypto.PubKey) error { 39 return nil 40 } 41 42 func (m *mockAccount) GetAccountNumber() uint64 { 43 return uint64(m.data) 44 } 45 46 func (m *mockAccount) SetAccountNumber(uint64) error { 47 return nil 48 } 49 func (m *mockAccount) GetSequence() uint64 { 50 return 0 51 } 52 func (m *mockAccount) SetSequence(uint64) error { 53 return nil 54 } 55 func (m *mockAccount) GetCoins() Coins { 56 return nil 57 } 58 func (m *mockAccount) SetCoins(Coins) error { 59 return nil 60 } 61 func (m *mockAccount) SpendableCoins(blockTime time.Time) Coins { 62 return nil 63 } 64 func (m *mockAccount) String() string { 65 return "" 66 } 67 68 func newCache(parent *Cache) *Cache { 69 return NewCache(parent, true) 70 } 71 func bz(s string) ethcmn.Address { return ethcmn.BytesToAddress([]byte(s)) } 72 73 func keyFmt(i int) ethcmn.Address { return bz(fmt.Sprintf("key%0.8d", i)) } 74 func accountValueFmt(i int) Account { return newMockAccount(i) } 75 76 func TestCache(t *testing.T) { 77 parent := newCache(nil) 78 st := newCache(parent) 79 80 key1Value, _, _ := st.GetAccount(keyFmt(1)) 81 require.Empty(t, key1Value, "should 'key1' to be empty") 82 83 // put something in mem and in cache 84 parent.UpdateAccount(keyFmt(1).Bytes(), accountValueFmt(1), 0, true) 85 st.UpdateAccount(keyFmt(1).Bytes(), accountValueFmt(1), 0, true) 86 key1Value, _, _ = st.GetAccount(keyFmt(1)) 87 require.Equal(t, key1Value.GetAccountNumber(), uint64(1)) 88 89 // update it in cache, shoudn't change mem 90 st.UpdateAccount(keyFmt(1).Bytes(), accountValueFmt(2), 0, true) 91 key1ValueInParent, _, _ := parent.GetAccount(keyFmt(1)) 92 key1ValueInSt, _, _ := st.GetAccount(keyFmt(1)) 93 require.Equal(t, key1ValueInParent.GetAccountNumber(), uint64(1)) 94 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(2)) 95 96 // write it . should change mem 97 st.Write(true) 98 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 99 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 100 require.Equal(t, key1ValueInParent.GetAccountNumber(), uint64(2)) 101 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(2)) 102 103 // more writes and checks 104 st.Write(true) 105 st.Write(true) 106 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 107 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 108 require.Equal(t, key1ValueInParent.GetAccountNumber(), uint64(2)) 109 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(2)) 110 111 // make a new one, check it 112 st = newCache(parent) 113 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 114 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(2)) 115 116 // make a new one and delete - should not be removed from mem 117 st = newCache(parent) 118 st.UpdateAccount(keyFmt(1).Bytes(), nil, 0, true) 119 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 120 require.Empty(t, key1ValueInSt) 121 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 122 require.Equal(t, key1ValueInParent.GetAccountNumber(), uint64(2)) 123 124 // Write. should now be removed from both 125 st.Write(true) 126 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 127 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 128 require.Empty(t, key1ValueInParent) 129 require.Empty(t, key1ValueInSt) 130 } 131 132 func TestCacheNested(t *testing.T) { 133 parent := newCache(nil) 134 st := newCache(parent) 135 136 // set. check its there on st and not on mem. 137 st.UpdateAccount(keyFmt(1).Bytes(), accountValueFmt(1), 0, true) 138 key1ValueInParent, _, _ := parent.GetAccount(keyFmt(1)) 139 key1ValueInSt, _, _ := st.GetAccount(keyFmt(1)) 140 require.Empty(t, key1ValueInParent) 141 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(1)) 142 143 // make a new from st and check 144 st2 := newCache(st) 145 key1ValueInSt, _, _ = st2.GetAccount(keyFmt(1)) 146 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(1)) 147 148 // update the value on st2, check it only effects st2 149 st2.UpdateAccount(keyFmt(1).Bytes(), accountValueFmt(3), 0, true) 150 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 151 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 152 key1ValueInSt2, _, _ := st2.GetAccount(keyFmt(1)) 153 require.Empty(t, key1ValueInParent) 154 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(1)) 155 require.Equal(t, key1ValueInSt2.GetAccountNumber(), uint64(3)) 156 157 // st2 write to its parent, st. doesnt effect parent 158 st2.Write(true) 159 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 160 key1ValueInSt, _, _ = st.GetAccount(keyFmt(1)) 161 require.Empty(t, key1ValueInParent) 162 require.Equal(t, key1ValueInSt.GetAccountNumber(), uint64(3)) 163 164 // updates parent 165 st.Write(true) 166 key1ValueInParent, _, _ = parent.GetAccount(keyFmt(1)) 167 require.Equal(t, key1ValueInParent.GetAccountNumber(), uint64(3)) 168 } 169 170 func BenchmarkCacheKVStoreGetNoKeyFound(b *testing.B) { 171 st := newCache(nil) 172 b.ResetTimer() 173 // assumes b.N < 2**24 174 for i := 0; i < b.N; i++ { 175 st.GetAccount(ethcmn.BytesToAddress([]byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)})) 176 } 177 } 178 179 func BenchmarkCacheKVStoreGetKeyFound(b *testing.B) { 180 st := newCache(nil) 181 for i := 0; i < b.N; i++ { 182 arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)} 183 st.UpdateAccount(arr, nil, 0, true) 184 } 185 b.ResetTimer() 186 // assumes b.N < 2**24 187 for i := 0; i < b.N; i++ { 188 st.GetAccount(ethcmn.BytesToAddress([]byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)})) 189 } 190 }