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  }