github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/mempool/stdmap/eject_test.go (about) 1 package stdmap 2 3 import ( 4 crand "crypto/rand" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 10 "github.com/onflow/flow-go/model/flow" 11 "github.com/onflow/flow-go/utils/unittest" 12 ) 13 14 // TestLRUEjector_Track evaluates that tracking a new item adds the item to the ejector table. 15 func TestLRUEjector_Track(t *testing.T) { 16 ejector := NewLRUEjector() 17 // ejector's table should be empty 18 assert.Len(t, ejector.table, 0) 19 20 // sequence number of ejector should initially be zero 21 assert.Equal(t, ejector.seqNum, uint64(0)) 22 23 // creates adds an item to the ejector 24 item := flow.Identifier{0x00} 25 ejector.Track(item) 26 27 // size of ejector's table should be one 28 // which indicates that ejector is tracking the item 29 assert.Len(t, ejector.table, 1) 30 31 // item should reside in the ejector's table 32 _, ok := ejector.table[item] 33 assert.True(t, ok) 34 35 // sequence number of ejector should be increased by one 36 assert.Equal(t, ejector.seqNum, uint64(1)) 37 } 38 39 // TestLRUEjector_Track_Duplicate evaluates that tracking a duplicate item 40 // does not change the internal state of the ejector. 41 func TestLRUEjector_Track_Duplicate(t *testing.T) { 42 ejector := NewLRUEjector() 43 44 // creates adds an item to the ejector 45 item := flow.Identifier{0x00} 46 ejector.Track(item) 47 48 // size of ejector's table should be one 49 // which indicates that ejector is tracking the item 50 assert.Len(t, ejector.table, 1) 51 52 // item should reside in the ejector's table 53 _, ok := ejector.table[item] 54 assert.True(t, ok) 55 56 // sequence number of ejector should be increased by one 57 assert.Equal(t, ejector.seqNum, uint64(1)) 58 59 // adds the duplicate item 60 ejector.Track(item) 61 62 // internal state of the ejector should be unchaged 63 assert.Len(t, ejector.table, 1) 64 assert.Equal(t, ejector.seqNum, uint64(1)) 65 _, ok = ejector.table[item] 66 assert.True(t, ok) 67 } 68 69 // TestLRUEjector_Track_Many evaluates that tracking many items 70 // changes the state of ejector properly, i.e., items reside on the 71 // memory, and sequence number changed accordingly. 72 func TestLRUEjector_Track_Many(t *testing.T) { 73 ejector := NewLRUEjector() 74 75 // creates and tracks 100 items 76 size := 100 77 items := flow.IdentifierList{} 78 for i := 0; i < size; i++ { 79 var id flow.Identifier 80 _, _ = crand.Read(id[:]) 81 ejector.Track(id) 82 items = append(items, id) 83 } 84 85 // size of ejector's table should be 100 86 assert.Len(t, ejector.table, size) 87 88 // all items should reside in the ejector's table 89 for _, id := range items { 90 _, ok := ejector.table[id] 91 require.True(t, ok) 92 } 93 94 // sequence number of ejector should be increased by size 95 assert.Equal(t, ejector.seqNum, uint64(size)) 96 } 97 98 // TestLRUEjector_Untrack_One evaluates that untracking an existing item 99 // removes it from the ejector state and changes the state accordingly. 100 func TestLRUEjector_Untrack_One(t *testing.T) { 101 ejector := NewLRUEjector() 102 103 // creates adds an item to the ejector 104 item := flow.Identifier{0x00} 105 ejector.Track(item) 106 107 // size of ejector's table should be one 108 // which indicates that ejector is tracking the item 109 assert.Len(t, ejector.table, 1) 110 111 // item should reside in the ejector's table 112 _, ok := ejector.table[item] 113 assert.True(t, ok) 114 115 // sequence number of ejector should be increased by one 116 assert.Equal(t, ejector.seqNum, uint64(1)) 117 118 // untracks the item 119 ejector.Untrack(item) 120 121 // internal state of the ejector should be changed 122 assert.Len(t, ejector.table, 0) 123 124 // sequence number should not be changed 125 assert.Equal(t, ejector.seqNum, uint64(1)) 126 127 // item should no longer reside on internal state of ejector 128 _, ok = ejector.table[item] 129 assert.False(t, ok) 130 } 131 132 // TestLRUEjector_Untrack_Duplicate evaluates that untracking an item twice 133 // removes it from the ejector state only once and changes the state safely. 134 func TestLRUEjector_Untrack_Duplicate(t *testing.T) { 135 ejector := NewLRUEjector() 136 137 // creates and adds two items to the ejector 138 item1 := flow.Identifier{0x00} 139 item2 := flow.Identifier{0x01} 140 ejector.Track(item1) 141 ejector.Track(item2) 142 143 // size of ejector's table should be two 144 // which indicates that ejector is tracking the items 145 assert.Len(t, ejector.table, 2) 146 147 // items should reside in the ejector's table 148 _, ok := ejector.table[item1] 149 assert.True(t, ok) 150 _, ok = ejector.table[item2] 151 assert.True(t, ok) 152 153 // sequence number of ejector should be increased by two 154 assert.Equal(t, ejector.seqNum, uint64(2)) 155 156 // untracks the item twice 157 ejector.Untrack(item1) 158 ejector.Untrack(item1) 159 160 // internal state of the ejector should be changed 161 assert.Len(t, ejector.table, 1) 162 163 // sequence number should not be changed 164 assert.Equal(t, ejector.seqNum, uint64(2)) 165 166 // double untracking should only affect the untracked item1 167 _, ok = ejector.table[item1] 168 assert.False(t, ok) 169 170 // item 2 should still reside in the memory 171 _, ok = ejector.table[item2] 172 assert.True(t, ok) 173 } 174 175 // TestLRUEjector_UntrackEject evaluates that untracking the next ejectable item 176 // properly changes the next ejectable item in the ejector. 177 func TestLRUEjector_UntrackEject(t *testing.T) { 178 ejector := NewLRUEjector() 179 180 // creates and tracks 100 items 181 size := 100 182 backEnd := NewBackend() 183 184 items := make([]flow.Identifier, size) 185 186 for i := 0; i < size; i++ { 187 mockEntity := unittest.MockEntityFixture() 188 require.True(t, backEnd.Add(mockEntity)) 189 190 id := mockEntity.ID() 191 ejector.Track(id) 192 items[i] = id 193 } 194 195 // untracks the oldest item 196 ejector.Untrack(items[0]) 197 198 // next ejectable item should be the second oldest item 199 id := ejector.Eject(backEnd) 200 assert.Equal(t, id, items[1]) 201 } 202 203 // TestLRUEjector_EjectAll adds many item to the ejector and then ejects them 204 // all one by one and evaluates an LRU ejection behavior. 205 func TestLRUEjector_EjectAll(t *testing.T) { 206 ejector := NewLRUEjector() 207 208 // creates and tracks 100 items 209 size := 100 210 backEnd := NewBackend() 211 212 items := make([]flow.Identifier, size) 213 214 for i := 0; i < size; i++ { 215 mockEntity := unittest.MockEntityFixture() 216 require.True(t, backEnd.Add(mockEntity)) 217 218 id := mockEntity.ID() 219 ejector.Track(id) 220 items[i] = id 221 } 222 223 require.Equal(t, uint(size), backEnd.Size()) 224 225 // ejects one by one 226 for i := 0; i < size; i++ { 227 id := ejector.Eject(backEnd) 228 require.Equal(t, id, items[i]) 229 } 230 }