github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/network/bqueue/queue_test.go (about) 1 package bqueue 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/nspcc-dev/neo-go/internal/fakechain" 8 "github.com/nspcc-dev/neo-go/pkg/core/block" 9 "github.com/stretchr/testify/assert" 10 "go.uber.org/zap/zaptest" 11 ) 12 13 func TestBlockQueue(t *testing.T) { 14 chain := fakechain.NewFakeChain() 15 // notice, it's not yet running 16 bq := New(chain, zaptest.NewLogger(t), nil, nil) 17 blocks := make([]*block.Block, 11) 18 for i := 1; i < 11; i++ { 19 blocks[i] = &block.Block{Header: block.Header{Index: uint32(i)}} 20 } 21 // not the ones expected currently 22 for i := 3; i < 5; i++ { 23 assert.NoError(t, bq.PutBlock(blocks[i])) 24 } 25 last, capLeft := bq.LastQueued() 26 assert.Equal(t, uint32(0), last) 27 assert.Equal(t, CacheSize-2, capLeft) 28 // nothing should be put into the blockchain 29 assert.Equal(t, uint32(0), chain.BlockHeight()) 30 assert.Equal(t, 2, bq.length()) 31 // now added the expected ones (with duplicates) 32 for i := 1; i < 5; i++ { 33 assert.NoError(t, bq.PutBlock(blocks[i])) 34 } 35 // but they're still not put into the blockchain, because bq isn't running 36 last, capLeft = bq.LastQueued() 37 assert.Equal(t, uint32(4), last) 38 assert.Equal(t, CacheSize-4, capLeft) 39 assert.Equal(t, uint32(0), chain.BlockHeight()) 40 assert.Equal(t, 4, bq.length()) 41 // block with too big index is dropped 42 assert.NoError(t, bq.PutBlock(&block.Block{Header: block.Header{Index: bq.chain.BlockHeight() + CacheSize + 1}})) 43 assert.Equal(t, 4, bq.length()) 44 go bq.Run() 45 // run() is asynchronous, so we need some kind of timeout anyway and this is the simplest one 46 assert.Eventually(t, func() bool { return chain.BlockHeight() == 4 }, 4*time.Second, 100*time.Millisecond) 47 last, capLeft = bq.LastQueued() 48 assert.Equal(t, uint32(4), last) 49 assert.Equal(t, CacheSize, capLeft) 50 assert.Equal(t, 0, bq.length()) 51 assert.Equal(t, uint32(4), chain.BlockHeight()) 52 // put some old blocks 53 for i := 1; i < 5; i++ { 54 assert.NoError(t, bq.PutBlock(blocks[i])) 55 } 56 last, capLeft = bq.LastQueued() 57 assert.Equal(t, uint32(4), last) 58 assert.Equal(t, CacheSize, capLeft) 59 assert.Equal(t, 0, bq.length()) 60 assert.Equal(t, uint32(4), chain.BlockHeight()) 61 // unexpected blocks with run() active 62 assert.NoError(t, bq.PutBlock(blocks[8])) 63 assert.Equal(t, 1, bq.length()) 64 assert.Equal(t, uint32(4), chain.BlockHeight()) 65 assert.NoError(t, bq.PutBlock(blocks[7])) 66 assert.Equal(t, 2, bq.length()) 67 assert.Equal(t, uint32(4), chain.BlockHeight()) 68 // sparse put 69 assert.NoError(t, bq.PutBlock(blocks[10])) 70 assert.Equal(t, 3, bq.length()) 71 assert.Equal(t, uint32(4), chain.BlockHeight()) 72 assert.NoError(t, bq.PutBlock(blocks[6])) 73 assert.NoError(t, bq.PutBlock(blocks[5])) 74 // run() is asynchronous, so we need some kind of timeout anyway and this is the simplest one 75 assert.Eventually(t, func() bool { return chain.BlockHeight() == 8 }, 4*time.Second, 100*time.Millisecond) 76 last, capLeft = bq.LastQueued() 77 assert.Equal(t, uint32(8), last) 78 assert.Equal(t, CacheSize-1, capLeft) 79 assert.Equal(t, 1, bq.length()) 80 assert.Equal(t, uint32(8), chain.BlockHeight()) 81 bq.Discard() 82 assert.Equal(t, 0, bq.length()) 83 } 84 85 // length wraps len access for tests to make them thread-safe. 86 func (bq *Queue) length() int { 87 bq.queueLock.Lock() 88 defer bq.queueLock.Unlock() 89 return bq.len 90 }