github.com/koko1123/flow-go-1@v0.29.6/ledger/complete/mtrie/trieCache_test.go (about) 1 package mtrie 2 3 // test addition 4 // test under capacity 5 // test on capacity 6 // test across boundry 7 8 import ( 9 "math/rand" 10 "testing" 11 12 "github.com/stretchr/testify/require" 13 14 "github.com/koko1123/flow-go-1/ledger" 15 "github.com/koko1123/flow-go-1/ledger/common/hash" 16 "github.com/koko1123/flow-go-1/ledger/complete/mtrie/node" 17 "github.com/koko1123/flow-go-1/ledger/complete/mtrie/trie" 18 "github.com/koko1123/flow-go-1/utils/unittest" 19 ) 20 21 func TestTrieCache(t *testing.T) { 22 const capacity = 10 23 24 tc := NewTrieCache(capacity, nil) 25 require.Equal(t, 0, tc.Count()) 26 27 tries := tc.Tries() 28 require.Equal(t, 0, len(tries)) 29 require.Equal(t, 0, tc.Count()) 30 require.Equal(t, 0, len(tc.lookup)) 31 32 // savedTries contains all tries that are pushed to queue 33 var savedTries []*trie.MTrie 34 35 // Push tries to queue to fill out capacity 36 for i := 0; i < capacity; i++ { 37 trie, err := randomMTrie() 38 require.NoError(t, err) 39 40 tc.Push(trie) 41 42 savedTries = append(savedTries, trie) 43 44 tr := tc.Tries() 45 require.Equal(t, savedTries, tr) 46 require.Equal(t, len(savedTries), tc.Count()) 47 require.Equal(t, len(savedTries), len(tc.lookup)) 48 49 retTrie, found := tc.Get(trie.RootHash()) 50 require.Equal(t, retTrie, trie) 51 require.True(t, found) 52 53 // check last added trie functionality 54 retTrie = tc.LastAddedTrie() 55 require.Equal(t, retTrie, trie) 56 } 57 58 // Push more tries to queue to overwrite older elements 59 for i := 0; i < capacity; i++ { 60 trie, err := randomMTrie() 61 require.NoError(t, err) 62 63 tc.Push(trie) 64 65 savedTries = append(savedTries, trie) 66 67 tr := tc.Tries() 68 require.Equal(t, capacity, len(tr)) 69 70 // After queue reaches capacity in previous loop, 71 // queue overwrites older elements with new insertions, 72 // and element count is its capacity value. 73 // savedTries contains all elements inserted from previous loop and current loop, so 74 // tr (queue snapshot) matches the last C elements in savedTries (where C is capacity). 75 require.Equal(t, savedTries[len(savedTries)-capacity:], tr) 76 require.Equal(t, capacity, tc.Count()) 77 require.Equal(t, capacity, len(tc.lookup)) 78 79 // check the trie is lookable 80 retTrie, found := tc.Get(trie.RootHash()) 81 require.Equal(t, retTrie, trie) 82 require.True(t, found) 83 84 // check the last evicted value is not kept 85 retTrie, found = tc.Get(savedTries[len(savedTries)-capacity-1].RootHash()) 86 require.Nil(t, retTrie) 87 require.False(t, found) 88 89 // check last added trie functionality 90 retTrie = tc.LastAddedTrie() 91 require.Equal(t, retTrie, trie) 92 } 93 94 } 95 96 func TestPurge(t *testing.T) { 97 const capacity = 5 98 99 trie1, err := randomMTrie() 100 require.NoError(t, err) 101 trie2, err := randomMTrie() 102 require.NoError(t, err) 103 trie3, err := randomMTrie() 104 require.NoError(t, err) 105 106 called := 0 107 tc := NewTrieCache(capacity, func(tree *trie.MTrie) { 108 switch called { 109 case 0: 110 require.Equal(t, trie1, tree) 111 case 1: 112 require.Equal(t, trie2, tree) 113 case 2: 114 require.Equal(t, trie3, tree) 115 } 116 called++ 117 118 }) 119 tc.Push(trie1) 120 tc.Push(trie2) 121 tc.Push(trie3) 122 123 tc.Purge() 124 require.Equal(t, 0, tc.Count()) 125 require.Equal(t, 0, tc.tail) 126 require.Equal(t, 0, len(tc.lookup)) 127 128 require.Equal(t, 3, called) 129 } 130 131 func TestEvictCallBack(t *testing.T) { 132 const capacity = 2 133 134 trie1, err := randomMTrie() 135 require.NoError(t, err) 136 137 called := false 138 tc := NewTrieCache(capacity, func(tree *trie.MTrie) { 139 called = true 140 require.Equal(t, trie1, tree) 141 }) 142 tc.Push(trie1) 143 144 trie2, err := randomMTrie() 145 require.NoError(t, err) 146 tc.Push(trie2) 147 148 trie3, err := randomMTrie() 149 require.NoError(t, err) 150 tc.Push(trie3) 151 152 require.True(t, called) 153 } 154 155 func TestConcurrentAccess(t *testing.T) { 156 157 const worker = 50 158 const capacity = 100 // large enough to not worry evicts 159 160 tc := NewTrieCache(capacity, nil) 161 162 unittest.Concurrently(worker, func(i int) { 163 trie, err := randomMTrie() 164 require.NoError(t, err) 165 tc.Push(trie) 166 167 ret, found := tc.Get(trie.RootHash()) 168 require.True(t, found) 169 require.Equal(t, trie, ret) 170 }) 171 172 require.Equal(t, worker, tc.Count()) 173 } 174 175 func randomMTrie() (*trie.MTrie, error) { 176 var randomPath ledger.Path 177 rand.Read(randomPath[:]) 178 179 var randomHashValue hash.Hash 180 rand.Read(randomHashValue[:]) 181 182 root := node.NewNode(256, nil, nil, randomPath, nil, randomHashValue) 183 184 return trie.NewMTrie(root, 1, 1) 185 }