Files
Pulse/internal/buffer/buffer_test.go
rcourtman b4a33c4f2d Fix offline buffering: add tests, remove unused config, fix flaky test
- Add unit tests for internal/buffer package
- Fix misleading "ring buffer" comment (it's a bounded FIFO queue)
- Remove unused BufferCapacity config field from both agents
- Rewrite flaky integration test to use polling instead of fixed sleeps
2025-12-02 22:31:44 +00:00

166 lines
2.7 KiB
Go

package buffer
import (
"sync"
"testing"
)
func TestNew(t *testing.T) {
q := New[int](5)
if q.capacity != 5 {
t.Errorf("expected capacity 5, got %d", q.capacity)
}
if q.Len() != 0 {
t.Errorf("expected empty queue, got len %d", q.Len())
}
}
func TestPushPop(t *testing.T) {
q := New[int](3)
q.Push(1)
q.Push(2)
q.Push(3)
if q.Len() != 3 {
t.Errorf("expected len 3, got %d", q.Len())
}
val, ok := q.Pop()
if !ok || val != 1 {
t.Errorf("expected (1, true), got (%d, %v)", val, ok)
}
val, ok = q.Pop()
if !ok || val != 2 {
t.Errorf("expected (2, true), got (%d, %v)", val, ok)
}
val, ok = q.Pop()
if !ok || val != 3 {
t.Errorf("expected (3, true), got (%d, %v)", val, ok)
}
val, ok = q.Pop()
if ok {
t.Errorf("expected (_, false), got (%d, %v)", val, ok)
}
}
func TestPushDropsOldest(t *testing.T) {
q := New[int](3)
q.Push(1)
q.Push(2)
q.Push(3)
q.Push(4) // should drop 1
if q.Len() != 3 {
t.Errorf("expected len 3, got %d", q.Len())
}
val, ok := q.Pop()
if !ok || val != 2 {
t.Errorf("expected (2, true), got (%d, %v)", val, ok)
}
val, ok = q.Pop()
if !ok || val != 3 {
t.Errorf("expected (3, true), got (%d, %v)", val, ok)
}
val, ok = q.Pop()
if !ok || val != 4 {
t.Errorf("expected (4, true), got (%d, %v)", val, ok)
}
}
func TestPeek(t *testing.T) {
q := New[string](2)
_, ok := q.Peek()
if ok {
t.Error("expected Peek on empty queue to return false")
}
q.Push("a")
q.Push("b")
val, ok := q.Peek()
if !ok || val != "a" {
t.Errorf("expected (a, true), got (%s, %v)", val, ok)
}
// Peek should not remove
if q.Len() != 2 {
t.Errorf("Peek should not modify queue, len is %d", q.Len())
}
}
func TestIsEmpty(t *testing.T) {
q := New[int](2)
if !q.IsEmpty() {
t.Error("new queue should be empty")
}
q.Push(1)
if q.IsEmpty() {
t.Error("queue with item should not be empty")
}
q.Pop()
if !q.IsEmpty() {
t.Error("queue after pop should be empty")
}
}
func TestConcurrentAccess(t *testing.T) {
q := New[int](100)
var wg sync.WaitGroup
// Concurrent pushes
for i := 0; i < 10; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
for j := 0; j < 20; j++ {
q.Push(n*20 + j)
}
}(i)
}
// Concurrent pops
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10; j++ {
q.Pop()
}
}()
}
wg.Wait()
// Should not panic and queue should be in valid state
_ = q.Len()
_ = q.IsEmpty()
}
func TestCapacityOne(t *testing.T) {
q := New[int](1)
q.Push(1)
q.Push(2) // drops 1
if q.Len() != 1 {
t.Errorf("expected len 1, got %d", q.Len())
}
val, ok := q.Pop()
if !ok || val != 2 {
t.Errorf("expected (2, true), got (%d, %v)", val, ok)
}
}