github.com/cilium/cilium@v1.16.2/pkg/container/ring_buffer_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package container 5 6 import ( 7 "math/rand/v2" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 ) 12 13 func dumpBuffer(b *RingBuffer) []int { 14 acc := []int{} 15 b.dumpWithCallback(func(n interface{}) { 16 acc = append(acc, n.(int)) 17 }) 18 return acc 19 } 20 21 func dumpFunc(b *RingBuffer) func() []int { 22 return func() []int { 23 acc := []int{} 24 b.Iterate(func(i interface{}) { 25 acc = append(acc, i.(int)) 26 }) 27 return acc 28 } 29 } 30 31 func TestRingBuffer_AddingAndIterating(t *testing.T) { 32 assert := assert.New(t) 33 bufferSize := 5 34 buffer := NewRingBuffer(bufferSize) 35 dumpAll := dumpFunc(buffer) 36 for i := 1; i <= 10; i++ { 37 buffer.Add(i) 38 } 39 assert.Len(buffer.buffer, bufferSize) 40 acc := dumpAll() 41 assert.IsIncreasing(acc) 42 assert.Equal([]int{6, 7, 8, 9, 10}, acc) 43 44 buffer.Add(11) 45 acc = dumpAll() 46 assert.Equal([]int{7, 8, 9, 10, 11}, acc) 47 48 d := []int{} 49 buffer.Iterate(func(i interface{}) { 50 d = append(d, i.(int)) 51 }) 52 assert.IsNonDecreasing(d) 53 assert.Equal([]int{7, 8, 9, 10, 11}, d) 54 acc = []int{} 55 buffer.IterateValid(func(n interface{}) bool { 56 return n.(int) >= 9 57 }, func(n interface{}) { 58 acc = append(acc, n.(int)) 59 }) 60 assert.Equal([]int{9, 10, 11}, acc) 61 62 acc = []int{} 63 buffer.IterateValid(func(n interface{}) bool { 64 return n.(int) >= 0 65 }, func(n interface{}) { 66 acc = append(acc, n.(int)) 67 }) 68 assert.Equal([]int{7, 8, 9, 10, 11}, acc) 69 70 acc = []int{} 71 buffer.IterateValid(func(n interface{}) bool { 72 return n.(int) >= 11 73 }, func(n interface{}) { 74 acc = append(acc, n.(int)) 75 }) 76 assert.Equal([]int{11}, acc) 77 78 acc = []int{} 79 buffer.IterateValid(func(n interface{}) bool { 80 return n.(int) > 11 81 }, func(n interface{}) { 82 acc = append(acc, n.(int)) 83 }) 84 assert.Empty(acc) 85 86 // Test empty buffer. 87 buffer = NewRingBuffer(0) 88 acc = dumpBuffer(buffer) 89 assert.Empty(acc) 90 assert.Empty(buffer.buffer) 91 buffer.Add(123) 92 assert.Empty(buffer.buffer) 93 94 } 95 96 func TestEventBuffer_GC(t *testing.T) { 97 assert := assert.New(t) 98 for i := 0; i < 3; i++ { 99 buffer := NewRingBuffer(100) 100 for i := 1; i <= 102; i++ { 101 buffer.Add(i) 102 } 103 buffer.Compact(func(n interface{}) bool { 104 return n.(int) > 95 105 }) 106 df := dumpFunc(buffer) 107 assert.Equal([]int{96, 97, 98, 99, 100, 101, 102}, df()) 108 109 buffer.Compact(func(n interface{}) bool { return true }) 110 assert.Equal(7, buffer.Size(), "always valid shouldn't clear anything") 111 buffer.Compact(func(n interface{}) bool { return false }) 112 assert.Equal(0, buffer.Size(), "nothing valid should empty buffer") 113 buffer.Compact(func(n interface{}) bool { return true }) 114 assert.Equal(0, buffer.Size(), "test gc empty buffer") 115 } 116 } 117 118 func TestEventBuffer_GC2(t *testing.T) { 119 assert := assert.New(t) 120 buffer := NewRingBuffer(3) 121 df := dumpFunc(buffer) 122 buffer.buffer = []interface{}{3, 1, 2} 123 buffer.next = 1 124 buffer.Compact(func(n interface{}) bool { 125 return n.(int) >= 2 126 }) 127 assert.Equal([]int{2, 3}, df()) 128 buffer.Compact(func(n interface{}) bool { 129 return n.(int) >= 2 // noop 130 }) 131 assert.Equal([]int{2, 3}, df()) 132 buffer.Compact(func(n interface{}) bool { 133 return n.(int) >= 3 134 }) 135 assert.Equal([]int{3}, df()) 136 } 137 138 func TestEventBuffer_GCFullBufferWithOverlap(t *testing.T) { 139 assert := assert.New(t) 140 buffer := NewRingBuffer(5) 141 buffer.Add(1) 142 buffer.Add(2) 143 buffer.Add(3) 144 buffer.Add(4) 145 buffer.Add(5) 146 buffer.Add(6) 147 buffer.Add(7) 148 df := dumpFunc(buffer) 149 assert.Equal([]int{3, 4, 5, 6, 7}, df()) 150 assert.True(buffer.isFull(), "this is a full buffer, which has gone around past its tail") 151 assert.Equal([]interface{}{6, 7, 3, 4, 5}, buffer.buffer) 152 assert.Equal(2, buffer.next) 153 buffer.Compact(func(n interface{}) bool { 154 return n.(int) >= 5 // -> 5, 6, 7 155 }) 156 acc := dumpBuffer(buffer) 157 assert.Equal([]int{5, 6, 7}, acc) 158 } 159 160 func TestEventBuffer_GCFullBuffer(t *testing.T) { 161 assert := assert.New(t) 162 buffer := NewRingBuffer(5) 163 buffer.Add(1) 164 buffer.Add(2) 165 buffer.Add(3) 166 buffer.Add(4) 167 buffer.Add(5) 168 assert.Equal([]interface{}{1, 2, 3, 4, 5}, buffer.buffer) 169 assert.True(buffer.isFull()) 170 buffer.Compact(func(n interface{}) bool { 171 return n.(int) >= 2 172 }) 173 assert.Equal([]interface{}{2, 3, 4, 5}, buffer.buffer) 174 } 175 176 func TestEventBuffer_GCNotFullBuffer(t *testing.T) { 177 assert := assert.New(t) 178 buffer := NewRingBuffer(5) 179 buffer.Add(1) 180 buffer.Add(2) 181 buffer.Add(3) 182 buffer.Add(4) 183 assert.Equal([]interface{}{1, 2, 3, 4}, buffer.buffer) 184 assert.False(buffer.isFull()) 185 i := buffer.firstValidIndex(func(n interface{}) bool { 186 return n.(int) > 3 187 }) 188 assert.Equal(3, i) 189 i = buffer.firstValidIndex(func(n interface{}) bool { 190 return n.(int) > 4 191 }) 192 assert.Equal(4, i, "should be out of bounds") 193 buffer.Compact(func(n interface{}) bool { 194 return n.(int) > 4 195 }) 196 assert.Equal([]interface{}{}, buffer.buffer) 197 buffer.Add(1) 198 buffer.Add(1) 199 buffer.Add(1) 200 buffer.Add(1) 201 buffer.Add(1) 202 i = buffer.firstValidIndex(func(n interface{}) bool { 203 return n.(int) >= 1 204 }) 205 assert.Equal(0, i) 206 buffer.Compact(func(n interface{}) bool { 207 return n.(int) > 0 208 }) 209 assert.Equal([]interface{}{1, 1, 1, 1, 1}, buffer.buffer) 210 buffer.Compact(func(n interface{}) bool { 211 return false 212 }) 213 assert.Empty(buffer.buffer) 214 } 215 216 func Test_firstValidIndex(t *testing.T) { 217 assert := assert.New(t) 218 buffer := NewRingBuffer(4) 219 df := dumpFunc(buffer) 220 for i := 0; i < 5; i++ { 221 buffer.Add(i) 222 } 223 assert.IsNonDecreasing(df()) 224 for i := 1; i <= 4; i++ { 225 assert.Equal(i, buffer.firstValidIndex(func(ii interface{}) bool { 226 return ii.(int) > i 227 })) 228 } 229 assert.Equal(4, buffer.firstValidIndex(func(ii interface{}) bool { return ii.(int) > 4 })) 230 assert.Equal(4, buffer.firstValidIndex(func(ii interface{}) bool { return false })) 231 assert.Equal(0, buffer.firstValidIndex(func(ii interface{}) bool { return true })) 232 } 233 234 func Test_firstValidIndex2(t *testing.T) { 235 assert := assert.New(t) 236 for i := 0; i <= 1000; i++ { 237 s := rand.IntN(1000) 238 buffer := NewRingBuffer(s) 239 df := dumpFunc(buffer) 240 for i := 0; i < s+1; i++ { 241 buffer.Add(i) 242 } 243 assert.IsNonDecreasing(df()) 244 for i := 1; i <= s; i++ { 245 assert.Equal(i, buffer.firstValidIndex(func(ii interface{}) bool { 246 return ii.(int) > i 247 })) 248 } 249 assert.Equal(s, buffer.firstValidIndex(func(ii interface{}) bool { return ii.(int) > s })) 250 assert.Equal(s, buffer.firstValidIndex(func(ii interface{}) bool { return false })) 251 assert.Equal(0, buffer.firstValidIndex(func(ii interface{}) bool { return true })) 252 } 253 }