107 lines
3.4 KiB
Go
107 lines
3.4 KiB
Go
package agents
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"g.fc.run/misc/byre/internal/api"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestAssessStuck(t *testing.T) {
|
||
|
|
now := time.Now()
|
||
|
|
procs := []procInfo{
|
||
|
|
{sessionID: "a", pid: 10, state: api.AgentSessionStateRunning, lastLine: now.Add(-StuckAfter - time.Second)},
|
||
|
|
{sessionID: "b", pid: 11, state: api.AgentSessionStateRunning, lastLine: now.Add(-StuckAfter + time.Second)},
|
||
|
|
{sessionID: "c", pid: 12, state: api.AgentSessionStateIdle, lastLine: now.Add(-time.Hour)},
|
||
|
|
}
|
||
|
|
running := []api.AgentSession{{Id: "a"}, {Id: "b"}}
|
||
|
|
|
||
|
|
h := assess(now, procs, running, []int{10, 11, 12})
|
||
|
|
|
||
|
|
want := map[string]api.AgentProcessHealth{"a": api.HealthStuck, "b": api.HealthOk, "c": api.HealthOk}
|
||
|
|
for _, p := range h.Processes {
|
||
|
|
if p.Health != want[p.SessionId] {
|
||
|
|
t.Errorf("session %s health = %s, want %s", p.SessionId, p.Health, want[p.SessionId])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if len(h.Zombies) != 0 {
|
||
|
|
t.Errorf("zombies = %+v, want none", h.Zombies)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAssessZombies(t *testing.T) {
|
||
|
|
now := time.Now()
|
||
|
|
procs := []procInfo{
|
||
|
|
{sessionID: "exited", pid: 20, state: api.AgentSessionStateRunning, lastLine: now, exited: true},
|
||
|
|
{sessionID: "done", pid: 21, state: api.AgentSessionStateCompleted, lastLine: now},
|
||
|
|
{sessionID: "idle", pid: 22, state: api.AgentSessionStateIdle, lastLine: now},
|
||
|
|
}
|
||
|
|
running := []api.AgentSession{{Id: "exited", TaskId: "t1"}, {Id: "gone", TaskId: "t2"}}
|
||
|
|
|
||
|
|
h := assess(now, procs, running, []int{21, 22, 99})
|
||
|
|
|
||
|
|
got := []string{}
|
||
|
|
for _, z := range h.Zombies {
|
||
|
|
key := string(z.Kind)
|
||
|
|
if z.SessionId != nil {
|
||
|
|
key += " " + *z.SessionId
|
||
|
|
}
|
||
|
|
if z.Pid != nil {
|
||
|
|
key += fmt.Sprintf(" %d", *z.Pid)
|
||
|
|
}
|
||
|
|
got = append(got, key)
|
||
|
|
}
|
||
|
|
want := []string{
|
||
|
|
"process_without_session done 21",
|
||
|
|
"running_without_process exited",
|
||
|
|
"running_without_process gone",
|
||
|
|
"process_without_session 99",
|
||
|
|
}
|
||
|
|
if strings.Join(got, "\n") != strings.Join(want, "\n") {
|
||
|
|
t.Errorf("zombies:\n%s\nwant:\n%s", strings.Join(got, "\n"), strings.Join(want, "\n"))
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, p := range h.Processes {
|
||
|
|
if p.SessionId == "exited" && p.Health != api.HealthExited {
|
||
|
|
t.Errorf("exited process health = %s", p.Health)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBadLinesRing(t *testing.T) {
|
||
|
|
b := newBadLines()
|
||
|
|
at := time.Now()
|
||
|
|
for i := range keptBadLines + 5 {
|
||
|
|
b.add("claude", "s", fmt.Sprintf("reason %d", i), []byte(fmt.Sprintf("line %d", i)), at)
|
||
|
|
}
|
||
|
|
b.add("other", "s", "big", []byte(strings.Repeat("x", badLineBytes*2)), at)
|
||
|
|
|
||
|
|
snap := b.snapshot()
|
||
|
|
if snap.Counts["claude"] != keptBadLines+5 || snap.Counts["other"] != 1 {
|
||
|
|
t.Errorf("counts = %v", snap.Counts)
|
||
|
|
}
|
||
|
|
if len(snap.Recent) != keptBadLines {
|
||
|
|
t.Fatalf("kept %d, want %d", len(snap.Recent), keptBadLines)
|
||
|
|
}
|
||
|
|
if snap.Recent[0].Reason != "big" || len(snap.Recent[0].Raw) != badLineBytes || snap.Recent[0].Size != badLineBytes*2 {
|
||
|
|
t.Errorf("newest = %q, %d raw bytes, size %d", snap.Recent[0].Reason, len(snap.Recent[0].Raw), snap.Recent[0].Size)
|
||
|
|
}
|
||
|
|
if snap.Recent[1].Raw != fmt.Sprintf("line %d", keptBadLines+4) {
|
||
|
|
t.Errorf("second newest = %q", snap.Recent[1].Raw)
|
||
|
|
}
|
||
|
|
oldest := snap.Recent[len(snap.Recent)-1].Raw
|
||
|
|
if oldest != "line 6" {
|
||
|
|
t.Errorf("oldest = %q, want line 6", oldest)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseChildren(t *testing.T) {
|
||
|
|
out := []byte(" 100 1 launchd\n 200 100 claude\n 201 100 /Users/x/.local/bin/claude\n 202 100 git\n 203 999 claude\n")
|
||
|
|
got := parseChildren(out, 100)
|
||
|
|
if fmt.Sprint(got) != "[200 201]" {
|
||
|
|
t.Errorf("children = %v", got)
|
||
|
|
}
|
||
|
|
}
|