github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/util/evicting_queue_test.go (about) 1 package util 2 3 import ( 4 "math" 5 "math/rand" 6 "sync" 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func noopOnEvict() {} 13 14 func TestQueueAppend(t *testing.T) { 15 q, err := NewEvictingQueue(10, noopOnEvict) 16 require.Nil(t, err) 17 18 q.Append(1) 19 q.Append(2) 20 q.Append(3) 21 q.Append(4) 22 q.Append(5) 23 24 require.Equal(t, 5, q.Length()) 25 } 26 27 func TestQueueCapacity(t *testing.T) { 28 q, err := NewEvictingQueue(9, noopOnEvict) 29 require.Nil(t, err) 30 require.Equal(t, 9, q.Capacity()) 31 32 q.capacity = 11 33 require.Equal(t, 11, q.Capacity()) 34 } 35 36 func TestZeroCapacityQueue(t *testing.T) { 37 q, err := NewEvictingQueue(0, noopOnEvict) 38 require.Error(t, err) 39 require.Nil(t, q) 40 } 41 42 func TestNegativeCapacityQueue(t *testing.T) { 43 q, err := NewEvictingQueue(-1, noopOnEvict) 44 require.Error(t, err) 45 require.Nil(t, q) 46 } 47 48 func TestQueueEvict(t *testing.T) { 49 q, err := NewEvictingQueue(3, noopOnEvict) 50 require.Nil(t, err) 51 52 // appending 5 entries will cause the first (oldest) 2 entries to be evicted 53 entries := []interface{}{1, 2, 3, 4, 5} 54 for _, entry := range entries { 55 q.Append(entry) 56 } 57 58 require.Equal(t, 3, q.Length()) 59 require.Equal(t, entries[2:], q.Entries()) 60 } 61 62 func TestQueueClear(t *testing.T) { 63 q, err := NewEvictingQueue(3, noopOnEvict) 64 require.Nil(t, err) 65 66 q.Append(1) 67 q.Clear() 68 69 require.Equal(t, 0, q.Length()) 70 } 71 72 func TestQueueEvictionCallback(t *testing.T) { 73 var evictionCallbackCalls int 74 75 q, err := NewEvictingQueue(3, func() { 76 evictionCallbackCalls++ 77 }) 78 require.Nil(t, err) 79 80 for i := 0; i < 5; i++ { 81 q.Append(i) 82 } 83 84 require.Equal(t, 2, evictionCallbackCalls) 85 } 86 87 func TestSafeConcurrentAccess(t *testing.T) { 88 q, err := NewEvictingQueue(3, noopOnEvict) 89 require.Nil(t, err) 90 91 var wg sync.WaitGroup 92 93 for w := 0; w < 30; w++ { 94 wg.Add(1) 95 go func() { 96 defer wg.Done() 97 98 for i := 0; i < 500; i++ { 99 q.Append(rand.Int()) 100 } 101 }() 102 } 103 104 wg.Wait() 105 106 require.Equal(t, 3, q.Length()) 107 } 108 109 type queueEntry struct { 110 key string 111 value interface{} 112 } 113 114 func BenchmarkAppendAndEvict(b *testing.B) { 115 capacity := 5000 116 q, err := NewEvictingQueue(capacity, noopOnEvict) 117 require.Nil(b, err) 118 119 b.ResetTimer() 120 b.ReportAllocs() 121 122 for n := 0; n < b.N; n++ { 123 q.Append(&queueEntry{ 124 key: "hello", 125 value: "world", 126 }) 127 } 128 129 require.EqualValues(b, math.Min(float64(b.N), float64(capacity)), q.Length()) 130 }