github.com/MetalBlockchain/metalgo@v1.11.9/utils/buffer/bounded_nonblocking_queue_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package buffer 5 6 import ( 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestNewBoundedQueue(t *testing.T) { 13 require := require.New(t) 14 15 // Case: maxSize < 1 16 _, err := NewBoundedQueue[bool](0, nil) 17 require.ErrorIs(err, errInvalidMaxSize) 18 19 // Case: maxSize == 1 and nil onEvict 20 b, err := NewBoundedQueue[bool](1, nil) 21 require.NoError(err) 22 23 // Put 2 elements to make sure we don't panic on evict 24 b.Push(true) 25 b.Push(true) 26 } 27 28 func TestBoundedQueue(t *testing.T) { 29 require := require.New(t) 30 31 maxSize := 3 32 evicted := []int{} 33 onEvict := func(elt int) { 34 evicted = append(evicted, elt) 35 } 36 b, err := NewBoundedQueue(maxSize, onEvict) 37 require.NoError(err) 38 39 require.Zero(b.Len()) 40 41 // Fill the queue 42 for i := 0; i < maxSize; i++ { 43 b.Push(i) 44 require.Equal(i+1, b.Len()) 45 got, ok := b.Peek() 46 require.True(ok) 47 require.Zero(got) 48 got, ok = b.Index(i) 49 require.True(ok) 50 require.Equal(i, got) 51 require.Len(b.List(), i+1) 52 } 53 require.Equal([]int{}, evicted) 54 require.Len(b.List(), maxSize) 55 // Queue is [0, 1, 2] 56 57 // Empty the queue 58 for i := 0; i < maxSize; i++ { 59 got, ok := b.Pop() 60 require.True(ok) 61 require.Equal(i, got) 62 require.Equal(maxSize-i-1, b.Len()) 63 require.Len(b.List(), maxSize-i-1) 64 } 65 66 // Queue is empty 67 68 _, ok := b.Pop() 69 require.False(ok) 70 _, ok = b.Peek() 71 require.False(ok) 72 _, ok = b.Index(0) 73 require.False(ok) 74 require.Zero(b.Len()) 75 require.Empty(b.List()) 76 77 // Fill the queue again 78 for i := 0; i < maxSize; i++ { 79 b.Push(i) 80 require.Equal(i+1, b.Len()) 81 } 82 83 // Queue is [0, 1, 2] 84 85 // Putting another element should evict the oldest. 86 b.Push(maxSize) 87 88 // Queue is [1, 2, 3] 89 90 require.Equal(maxSize, b.Len()) 91 require.Len(b.List(), maxSize) 92 got, ok := b.Peek() 93 require.True(ok) 94 require.Equal(1, got) 95 got, ok = b.Index(0) 96 require.True(ok) 97 require.Equal(1, got) 98 got, ok = b.Index(maxSize - 1) 99 require.True(ok) 100 require.Equal(maxSize, got) 101 require.Equal([]int{0}, evicted) 102 103 // Put 2 more elements 104 b.Push(maxSize + 1) 105 b.Push(maxSize + 2) 106 107 // Queue is [3, 4, 5] 108 109 require.Equal(maxSize, b.Len()) 110 require.Equal([]int{0, 1, 2}, evicted) 111 got, ok = b.Peek() 112 require.True(ok) 113 require.Equal(3, got) 114 require.Equal([]int{3, 4, 5}, b.List()) 115 116 for i := maxSize; i < 2*maxSize; i++ { 117 got, ok := b.Index(i - maxSize) 118 require.True(ok) 119 require.Equal(i, got) 120 } 121 122 // Empty the queue 123 for i := 0; i < maxSize; i++ { 124 got, ok := b.Pop() 125 require.True(ok) 126 require.Equal(i+3, got) 127 require.Equal(maxSize-i-1, b.Len()) 128 require.Len(b.List(), maxSize-i-1) 129 } 130 131 // Queue is empty 132 133 require.Empty(b.List()) 134 require.Zero(b.Len()) 135 require.Equal([]int{0, 1, 2}, evicted) 136 _, ok = b.Pop() 137 require.False(ok) 138 _, ok = b.Peek() 139 require.False(ok) 140 _, ok = b.Index(0) 141 require.False(ok) 142 }