Includes solved 02-worker-pool and 09-safe-counter (mutex, atomic, sharded). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GbnJj9ZqEx9nUvzkjdwfMq
66 lines
1.6 KiB
Go
66 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestTopNBasic(t *testing.T) {
|
|
logs := strings.Join([]string{
|
|
"t GET /a 200 1ms",
|
|
"t GET /b 200 1ms",
|
|
"t GET /a 200 1ms",
|
|
"t GET /c 200 1ms",
|
|
"t GET /a 200 1ms",
|
|
"t GET /b 200 1ms",
|
|
}, "\n")
|
|
|
|
got, err := TopN(strings.NewReader(logs), 2)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(got) != 2 {
|
|
t.Fatalf("want 2 results, got %d: %v", len(got), got)
|
|
}
|
|
if got[0].Endpoint != "/a" || got[0].Count != 3 {
|
|
t.Errorf("want /a x3 first, got %+v", got[0])
|
|
}
|
|
if got[1].Endpoint != "/b" || got[1].Count != 2 {
|
|
t.Errorf("want /b x2 second, got %+v", got[1])
|
|
}
|
|
}
|
|
|
|
func TestMalformedLinesSkipped(t *testing.T) {
|
|
logs := "t GET /a 200 1ms\n\ngarbage\nonly two\nt GET /a 200 1ms\n"
|
|
got, err := TopN(strings.NewReader(logs), 5)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(got) != 1 || got[0].Count != 2 {
|
|
t.Fatalf("malformed lines mishandled: %v", got)
|
|
}
|
|
}
|
|
|
|
func TestNLargerThanDistinct(t *testing.T) {
|
|
got, err := TopN(strings.NewReader("t GET /a 200 1ms"), 10)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(got) != 1 {
|
|
t.Fatalf("want 1 result, got %d", len(got))
|
|
}
|
|
}
|
|
|
|
func TestLongLines(t *testing.T) {
|
|
// A single line > 64KB (bufio.Scanner default max token size).
|
|
long := "t GET /huge?q=" + strings.Repeat("x", 80*1024) + " 200 1ms"
|
|
logs := long + "\nt GET /small 200 1ms\nt GET /small 200 1ms\n"
|
|
got, err := TopN(strings.NewReader(logs), 1)
|
|
if err != nil {
|
|
t.Fatalf("long line broke the scanner: %v (raise Scanner.Buffer)", err)
|
|
}
|
|
if len(got) == 0 || got[0].Endpoint != "/small" {
|
|
t.Fatalf("want /small on top, got %v", got)
|
|
}
|
|
}
|