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  }