github.com/koko1123/flow-go-1@v0.29.6/module/mempool/queue/queue_test.go (about) 1 package queue 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 "github.com/stretchr/testify/require" 8 9 "github.com/koko1123/flow-go-1/module/mempool/entity" 10 "github.com/koko1123/flow-go-1/utils/unittest" 11 ) 12 13 func TestQueue(t *testing.T) { 14 15 /* Input queue: 16 g-b 17 \ 18 f--d--c-a 19 / 20 e 21 22 */ 23 24 a := unittest.ExecutableBlockFixture(nil) 25 c := unittest.ExecutableBlockFixtureWithParent(nil, a.Block.Header) 26 b := unittest.ExecutableBlockFixtureWithParent(nil, c.Block.Header) 27 d := unittest.ExecutableBlockFixtureWithParent(nil, c.Block.Header) 28 e := unittest.ExecutableBlockFixtureWithParent(nil, d.Block.Header) 29 f := unittest.ExecutableBlockFixtureWithParent(nil, d.Block.Header) 30 g := unittest.ExecutableBlockFixtureWithParent(nil, b.Block.Header) 31 32 dBroken := unittest.ExecutableBlockFixtureWithParent(nil, c.Block.Header) 33 dBroken.Block.Header.Height += 2 //change height 34 35 queue := NewQueue(a) 36 37 t.Run("Adding", func(t *testing.T) { 38 stored, _ := queue.TryAdd(b) //parent not stored yet 39 size := queue.Size() 40 height := queue.Height() 41 assert.False(t, stored) 42 assert.Equal(t, 1, size) 43 assert.Equal(t, uint64(0), height) 44 45 stored, new := queue.TryAdd(c) 46 size = queue.Size() 47 height = queue.Height() 48 assert.True(t, stored) 49 assert.True(t, new) 50 assert.Equal(t, 2, size) 51 assert.Equal(t, uint64(1), height) 52 53 stored, new = queue.TryAdd(b) 54 size = queue.Size() 55 height = queue.Height() 56 assert.True(t, stored) 57 assert.True(t, new) 58 assert.Equal(t, 3, size) 59 assert.Equal(t, uint64(2), height) 60 61 stored, new = queue.TryAdd(b) //repeat 62 size = queue.Size() 63 height = queue.Height() 64 assert.True(t, stored) 65 assert.False(t, new) 66 assert.Equal(t, 3, size) 67 assert.Equal(t, uint64(2), height) 68 69 stored, _ = queue.TryAdd(f) //parent not stored yet 70 assert.False(t, stored) 71 72 stored, new = queue.TryAdd(d) 73 size = queue.Size() 74 height = queue.Height() 75 assert.True(t, stored) 76 assert.True(t, new) 77 assert.Equal(t, 4, size) 78 assert.Equal(t, uint64(2), height) 79 80 stored, _ = queue.TryAdd(dBroken) // wrong height 81 assert.False(t, stored) 82 83 stored, new = queue.TryAdd(e) 84 size = queue.Size() 85 height = queue.Height() 86 assert.True(t, stored) 87 assert.True(t, new) 88 assert.Equal(t, 5, size) 89 assert.Equal(t, uint64(3), height) 90 91 stored, new = queue.TryAdd(f) 92 size = queue.Size() 93 height = queue.Height() 94 assert.True(t, stored) 95 assert.True(t, new) 96 assert.Equal(t, 6, size) 97 assert.Equal(t, uint64(3), height) 98 99 stored, new = queue.TryAdd(g) 100 size = queue.Size() 101 height = queue.Height() 102 assert.True(t, stored) 103 assert.True(t, new) 104 assert.Equal(t, 7, size) 105 assert.Equal(t, uint64(3), height) 106 }) 107 108 t.Run("Dismounting", func(t *testing.T) { 109 // dismount queue 110 blockA, queuesA := queue.Dismount() 111 assert.Equal(t, a, blockA) 112 require.Len(t, queuesA, 1) 113 assert.Equal(t, 6, queuesA[0].Size()) 114 assert.Equal(t, uint64(2), queuesA[0].Height()) 115 116 blockC, queuesC := queuesA[0].Dismount() 117 assert.Equal(t, c, blockC) 118 require.Len(t, queuesC, 2) 119 120 // order of children is not guaranteed 121 var queueD *Queue 122 var queueB *Queue 123 if queuesC[0].Head.Item == d { 124 queueD = queuesC[0] 125 queueB = queuesC[1] 126 } else { 127 queueD = queuesC[1] 128 queueB = queuesC[0] 129 } 130 assert.Equal(t, d, queueD.Head.Item) 131 sizeD := queueD.Size() 132 heightD := queueD.Height() 133 sizeB := queueB.Size() 134 heightB := queueB.Height() 135 136 assert.Equal(t, 3, sizeD) 137 assert.Equal(t, uint64(1), heightD) 138 assert.Equal(t, 2, sizeB) 139 assert.Equal(t, uint64(1), heightB) 140 141 blockD, queuesD := queueD.Dismount() 142 assert.Equal(t, d, blockD) 143 assert.Len(t, queuesD, 2) 144 }) 145 146 t.Run("Process all", func(t *testing.T) { 147 // Dismounting iteratively all queues should yield all nodes/blocks only once 148 // and in the proper order (parents are always evaluated first) 149 blocksInOrder := make([]*entity.ExecutableBlock, 0) 150 151 executionHeads := make(chan *Queue, 10) 152 executionHeads <- queue 153 154 for len(executionHeads) > 0 { 155 currentHead := <-executionHeads 156 block, newQueues := currentHead.Dismount() 157 blocksInOrder = append(blocksInOrder, block.(*entity.ExecutableBlock)) 158 for _, newQueue := range newQueues { 159 executionHeads <- newQueue 160 } 161 } 162 163 // Couldn't find ready assertion for subset in order, so lets 164 // map nodes by their index and check if order is as expected 165 indices := make(map[*entity.ExecutableBlock]int) 166 167 for i, block := range blocksInOrder { 168 indices[block] = i 169 } 170 171 // a -> c -> b -> g 172 assert.Less(t, indices[a], indices[c]) 173 assert.Less(t, indices[c], indices[b]) 174 assert.Less(t, indices[b], indices[g]) 175 176 // a -> c -> d -> f 177 assert.Less(t, indices[a], indices[c]) 178 assert.Less(t, indices[c], indices[d]) 179 assert.Less(t, indices[d], indices[f]) 180 181 // a -> c -> d -> e 182 assert.Less(t, indices[a], indices[c]) 183 assert.Less(t, indices[c], indices[d]) 184 assert.Less(t, indices[d], indices[e]) 185 }) 186 187 //t.Run("Attaching", func(t *testing.T) { 188 // queue := NewQueue(a) 189 // 190 // added, new := queue.TryAdd(c) 191 // assert.True(t, added) 192 // assert.True(t, new) 193 // assert.Equal(t, 2, queue.Size()) 194 // assert.Equal(t, uint64(1), queue.Height()) 195 // 196 // queueB := NewQueue(b) 197 // added, new = queueB.TryAdd(g) 198 // assert.True(t, added) 199 // assert.True(t, new) 200 // 201 // assert.Equal(t, 2, queueB.Size()) 202 // assert.Equal(t, uint64(1), queueB.Height()) 203 // 204 // queueF := NewQueue(f) 205 // 206 // err := queue.Attach(queueF) // node D is missing 207 // assert.Error(t, err) 208 // 209 // err = queue.Attach(queueB) 210 // assert.NoError(t, err) 211 // assert.Equal(t, 4, queue.Size()) 212 // assert.Equal(t, uint64(3), queue.Height()) 213 // 214 // added, new = queue.TryAdd(d) 215 // assert.True(t, added) 216 // assert.True(t, new) 217 // assert.Equal(t, 5, queue.Size()) 218 // assert.Equal(t, uint64(3), queue.Height()) 219 // 220 // err = queue.Attach(queueF) // node D is now in the queue 221 // assert.NoError(t, err) 222 // assert.Equal(t, 6, queue.Size()) 223 // assert.Equal(t, uint64(3), queue.Height()) 224 //}) 225 226 // Creating queue: 227 // f--d--c-a 228 // Addingan element should be an idempotent operation: 229 // * adding c a second time 230 // * Dequeueing single head: 231 // we should only get one child queue f--d--c 232 t.Run("Adding_Idempotent", func(t *testing.T) { 233 queue := NewQueue(a) 234 add, new := queue.TryAdd(c) 235 assert.True(t, add) 236 assert.True(t, new) 237 238 add, new = queue.TryAdd(d) 239 assert.True(t, add) 240 assert.True(t, new) 241 242 add, new = queue.TryAdd(f) 243 assert.True(t, add) 244 assert.True(t, new) 245 246 assert.Equal(t, 4, queue.Size()) 247 assert.Equal(t, uint64(3), queue.Height()) 248 249 // adding c a second time 250 add, new = queue.TryAdd(c) 251 assert.True(t, add) 252 assert.False(t, new) 253 254 // Dequeueing a 255 head, childQueues := queue.Dismount() 256 assert.Equal(t, a, head) 257 assert.Equal(t, 1, len(childQueues), "There should only be a single child queue") 258 assert.Equal(t, c.ID(), childQueues[0].Head.Item.ID()) 259 }) 260 261 // Testing attaching overlapping queues: 262 // queue A: 263 // g-b 264 // \ 265 // c 266 // queue B: 267 // d--c-a 268 // attach queueA to queueB: we expect an error as the queues have nodes in common 269 //t.Run("Attaching_partially_overlapped_queue", func(t *testing.T) { 270 // queueA := NewQueue(c) 271 // add, new := queueA.TryAdd(b) 272 // assert.True(t, add) 273 // assert.True(t, new) 274 // 275 // add, new = queueA.TryAdd(g) 276 // assert.True(t, add) 277 // assert.True(t, new) 278 // 279 // queueB := NewQueue(a) 280 // add, new = queueB.TryAdd(c) 281 // assert.True(t, add) 282 // assert.True(t, new) 283 // 284 // add, new = queueB.TryAdd(d) 285 // assert.True(t, add) 286 // assert.True(t, new) 287 // 288 // err := queueB.Attach(queueA) 289 // assert.Error(t, err) 290 //}) 291 292 }