156 lines
3.8 KiB
Go
156 lines
3.8 KiB
Go
package buffer
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
func TestRingBuffer_PushAndSnapshot(t *testing.T) {
|
|
b := New(3)
|
|
for i := 0; i < 3; i++ {
|
|
b.Push(Entry{Message: string(rune('a' + i))})
|
|
}
|
|
snap := b.Snapshot()
|
|
if len(snap) != 3 {
|
|
t.Fatalf("expected 3 entries, got %d", len(snap))
|
|
}
|
|
for i, want := range []string{"a", "b", "c"} {
|
|
if snap[i].Message != want {
|
|
t.Errorf("entry %d: got %q, want %q", i, snap[i].Message, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRingBuffer_FIFOEvictionAtCapacity(t *testing.T) {
|
|
b := New(3)
|
|
for i := 0; i < 5; i++ {
|
|
b.Push(Entry{Message: string(rune('a' + i))})
|
|
}
|
|
snap := b.Snapshot()
|
|
if len(snap) != 3 {
|
|
t.Fatalf("expected 3 entries after eviction, got %d", len(snap))
|
|
}
|
|
for i, want := range []string{"c", "d", "e"} {
|
|
if snap[i].Message != want {
|
|
t.Errorf("entry %d: got %q, want %q", i, snap[i].Message, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRingBuffer_DefaultCapacity(t *testing.T) {
|
|
b := New(0)
|
|
if b.capacity != DefaultCapacity {
|
|
t.Fatalf("non-positive capacity should default to %d, got %d", DefaultCapacity, b.capacity)
|
|
}
|
|
}
|
|
|
|
func TestRingBuffer_SnapshotIsolation(t *testing.T) {
|
|
b := New(5)
|
|
b.Push(Entry{Message: "first"})
|
|
snap := b.Snapshot()
|
|
snap[0].Message = "mutated"
|
|
if got := b.Snapshot()[0].Message; got != "first" {
|
|
t.Fatalf("snapshot mutation leaked: got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestRingBuffer_ConcurrentWrites(t *testing.T) {
|
|
const writers = 8
|
|
const perWriter = 200
|
|
b := New(writers * perWriter)
|
|
var wg sync.WaitGroup
|
|
wg.Add(writers)
|
|
for w := 0; w < writers; w++ {
|
|
go func() {
|
|
defer wg.Done()
|
|
for i := 0; i < perWriter; i++ {
|
|
b.Push(Entry{Timestamp: time.Now(), Message: "x"})
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
if got := b.Len(); got != writers*perWriter {
|
|
t.Fatalf("expected %d entries, got %d", writers*perWriter, got)
|
|
}
|
|
}
|
|
|
|
func TestRingBuffer_Clear(t *testing.T) {
|
|
b := New(3)
|
|
b.Push(Entry{Message: "a"})
|
|
b.Push(Entry{Message: "b"})
|
|
b.Clear()
|
|
if got := b.Len(); got != 0 {
|
|
t.Fatalf("expected 0 entries after clear, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestDefault_ReturnsSameInstance(t *testing.T) {
|
|
first := Default()
|
|
second := Default()
|
|
if first != second {
|
|
t.Fatal("Default() should return the same singleton")
|
|
}
|
|
}
|
|
|
|
func TestCore_CapturesEntriesWithFields(t *testing.T) {
|
|
buf := New(10)
|
|
core := NewCore(buf, zapcore.DebugLevel)
|
|
logger := zap.New(core).With(zap.String("service", "test"))
|
|
|
|
logger.Info("hello", zap.Int("count", 42))
|
|
logger.Warn("careful")
|
|
|
|
snap := buf.Snapshot()
|
|
if len(snap) != 2 {
|
|
t.Fatalf("expected 2 entries, got %d", len(snap))
|
|
}
|
|
if snap[0].Message != "hello" || snap[0].Level != "info" {
|
|
t.Errorf("entry 0: got message=%q level=%q", snap[0].Message, snap[0].Level)
|
|
}
|
|
if got, _ := snap[0].Fields["service"].(string); got != "test" {
|
|
t.Errorf("entry 0 service field: got %v", snap[0].Fields["service"])
|
|
}
|
|
if got, _ := snap[0].Fields["count"].(int64); got != 42 {
|
|
t.Errorf("entry 0 count field: got %v", snap[0].Fields["count"])
|
|
}
|
|
if snap[1].Level != "warn" {
|
|
t.Errorf("entry 1 level: got %q", snap[1].Level)
|
|
}
|
|
}
|
|
|
|
func TestRingBuffer_SnapshotDeepCopiesFields(t *testing.T) {
|
|
b := New(3)
|
|
b.Push(Entry{Message: "m", Fields: map[string]any{"k": "v1"}})
|
|
|
|
snap1 := b.Snapshot()
|
|
snap1[0].Fields["k"] = "mutated"
|
|
snap1[0].Fields["new"] = "added"
|
|
|
|
snap2 := b.Snapshot()
|
|
if got := snap2[0].Fields["k"]; got != "v1" {
|
|
t.Errorf("buffered field mutated: got %v", got)
|
|
}
|
|
if _, ok := snap2[0].Fields["new"]; ok {
|
|
t.Errorf("buffered field map had extra key added")
|
|
}
|
|
}
|
|
|
|
func TestCore_RespectsLevelEnabler(t *testing.T) {
|
|
buf := New(10)
|
|
core := NewCore(buf, zapcore.WarnLevel)
|
|
logger := zap.New(core)
|
|
|
|
logger.Debug("nope")
|
|
logger.Info("nope")
|
|
logger.Warn("yes")
|
|
logger.Error("yes")
|
|
|
|
if got := buf.Len(); got != 2 {
|
|
t.Fatalf("expected only warn+error to be captured, got %d entries", got)
|
|
}
|
|
}
|