Files
superwork/tui/internal/logging/logger_test.go
T
2026-06-23 05:02:15 +08:00

143 lines
3.2 KiB
Go

package logging
import (
"fmt"
"sync"
"testing"
)
func newTestLogger() *Logger {
l := NewLogger()
var ts int64
l.now = func() int64 {
ts++
return ts
}
return l
}
func TestLogger_ringBuffer_evictsOldest(t *testing.T) {
l := newTestLogger()
for i := 1; i <= 600; i++ {
l.Info("src", fmt.Sprintf("msg%d", i))
}
snap := l.Snapshot()
if len(snap) != 500 {
t.Fatalf("want 500 entries, got %d", len(snap))
}
if snap[0].Message != "msg101" {
t.Errorf("oldest entry: want msg101, got %q", snap[0].Message)
}
if snap[499].Message != "msg600" {
t.Errorf("newest entry: want msg600, got %q", snap[499].Message)
}
}
func TestLogger_levels(t *testing.T) {
l := newTestLogger()
l.Info("s", "info-msg")
l.Warn("s", "warn-msg")
l.Error("s", "error-msg")
snap := l.Snapshot()
if len(snap) != 3 {
t.Fatalf("want 3 entries, got %d", len(snap))
}
if snap[0].Level != LevelInfo {
t.Errorf("entry 0: want LevelInfo, got %v", snap[0].Level)
}
if snap[1].Level != LevelWarn {
t.Errorf("entry 1: want LevelWarn, got %v", snap[1].Level)
}
if snap[2].Level != LevelError {
t.Errorf("entry 2: want LevelError, got %v", snap[2].Level)
}
}
func TestLogger_snapshotOrder(t *testing.T) {
l := newTestLogger()
for i := 1; i <= 10; i++ {
l.Info("s", fmt.Sprintf("msg%d", i))
}
snap := l.Snapshot()
for i, e := range snap {
want := fmt.Sprintf("msg%d", i+1)
if e.Message != want {
t.Errorf("snap[%d].Message = %q, want %q", i, e.Message, want)
}
}
}
func TestLogger_detailsOptional(t *testing.T) {
l := newTestLogger()
l.Info("s", "no-details")
l.Warn("s", "with-details", "extra info")
snap := l.Snapshot()
if snap[0].Details != "" {
t.Errorf("Details without arg should be empty, got %q", snap[0].Details)
}
if snap[1].Details != "extra info" {
t.Errorf("Details = %q, want %q", snap[1].Details, "extra info")
}
}
func TestLogger_subscribe(t *testing.T) {
l := newTestLogger()
var received []Entry
l.Subscribe(func(e Entry) {
received = append(received, e)
})
l.Info("s", "one")
l.Error("s", "two")
if len(received) != 2 {
t.Fatalf("want 2 callbacks, got %d", len(received))
}
if received[0].Message != "one" {
t.Errorf("first callback message = %q, want 'one'", received[0].Message)
}
if received[1].Level != LevelError {
t.Error("second callback should have LevelError")
}
}
func TestLogger_concurrencySafe(t *testing.T) {
l := NewLogger()
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
l.Info("src", fmt.Sprintf("msg%d", n))
_ = l.Snapshot()
}(i)
}
wg.Wait()
}
func TestLogger_sourceAndMessage(t *testing.T) {
l := newTestLogger()
l.Info("webhook", "connected")
snap := l.Snapshot()
if snap[0].Source != "webhook" {
t.Errorf("Source = %q, want 'webhook'", snap[0].Source)
}
if snap[0].Message != "connected" {
t.Errorf("Message = %q, want 'connected'", snap[0].Message)
}
}
func TestLogger_snapshotIsACopy(t *testing.T) {
l := newTestLogger()
l.Info("s", "first")
snap := l.Snapshot()
l.Info("s", "second")
if len(snap) != 1 {
t.Errorf("snapshot should be a copy; len = %d, want 1", len(snap))
}
}
func TestDefault_exists(t *testing.T) {
if Default == nil {
t.Error("Default logger should not be nil")
}
}