86 lines
3.1 KiB
Go
86 lines
3.1 KiB
Go
package main
|
|
|
|
// store_stats_test.go — SessionStats/StatsTotals aggregation over agent_end.
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func appendAgentEnd(t *testing.T, s *Store, sessionID string, seq int64, payload string) {
|
|
t.Helper()
|
|
if err := s.AppendEvent(Event{
|
|
SessionID: sessionID, Seq: seq, TS: 1, Type: evAgentEnd, Payload: []byte(payload),
|
|
}); err != nil {
|
|
t.Fatalf("append agent_end %s/%d: %v", sessionID, seq, err)
|
|
}
|
|
}
|
|
|
|
func TestStoreSessionStats(t *testing.T) {
|
|
store := openTestStore(t)
|
|
appendAgentEnd(t, store, "s1", 1, `{"usage":{"inputTokens":100,"outputTokens":50,"totalCost":0.25}}`)
|
|
appendAgentEnd(t, store, "s1", 2, `{"usage":{"inputTokens":30,"outputTokens":20,"totalCost":0.5}}`)
|
|
appendAgentEnd(t, store, "s1", 3, `{}`) // no usage → zeros
|
|
appendAgentEnd(t, store, "s1", 4, `{"usage":{"inputTokens":7}}`) // partial usage
|
|
if err := store.AppendEvent(Event{SessionID: "s1", Seq: 5, TS: 1, Type: evMessageEnd, Payload: []byte(`{}`)}); err != nil {
|
|
t.Fatalf("append message_end: %v", err)
|
|
}
|
|
|
|
stats, err := store.SessionStats("s1")
|
|
if err != nil {
|
|
t.Fatalf("session stats: %v", err)
|
|
}
|
|
if stats.Turns != 4 || stats.InputTokens != 137 || stats.OutputTokens != 70 || stats.TotalCost != 0.75 {
|
|
t.Fatalf("stats = %+v, want turns 4, input 137, output 70, cost 0.75", stats)
|
|
}
|
|
|
|
unknown, err := store.SessionStats("nope")
|
|
if err != nil {
|
|
t.Fatalf("unknown session stats: %v", err)
|
|
}
|
|
if unknown != (UsageStats{}) {
|
|
t.Fatalf("unknown session stats = %+v, want zeros", unknown)
|
|
}
|
|
}
|
|
|
|
func TestStoreSessionStatsCorruptPayloadCountsTurn(t *testing.T) {
|
|
store := openTestStore(t)
|
|
appendAgentEnd(t, store, "s1", 1, `{"usage":{"inputTokens":5,"outputTokens":5,"totalCost":0.1}}`)
|
|
if err := store.AppendEvent(Event{SessionID: "s1", Seq: 2, TS: 1, Type: evAgentEnd, Payload: []byte(`not-json`)}); err != nil {
|
|
t.Fatalf("append corrupt: %v", err)
|
|
}
|
|
stats, err := store.SessionStats("s1")
|
|
if err != nil {
|
|
t.Fatalf("stats: %v", err)
|
|
}
|
|
if stats.Turns != 2 || stats.InputTokens != 5 || stats.OutputTokens != 5 || stats.TotalCost != 0.1 {
|
|
t.Fatalf("stats = %+v, want turns 2 with usage only from row 1", stats)
|
|
}
|
|
}
|
|
|
|
func TestStoreStatsTotals(t *testing.T) {
|
|
store := openTestStore(t)
|
|
empty, err := store.StatsTotals()
|
|
if err != nil {
|
|
t.Fatalf("empty totals: %v", err)
|
|
}
|
|
if empty != (StatsTotals{}) {
|
|
t.Fatalf("empty totals = %+v, want zeros", empty)
|
|
}
|
|
|
|
appendAgentEnd(t, store, "s1", 1, `{"usage":{"inputTokens":1000,"outputTokens":200,"totalCost":1.5}}`)
|
|
appendAgentEnd(t, store, "s1", 2, `{}`)
|
|
appendAgentEnd(t, store, "s2", 1, `{"usage":{"inputTokens":40,"outputTokens":60,"totalCost":0.25}}`)
|
|
if err := store.AppendEvent(Event{SessionID: "s2", Seq: 2, TS: 1, Type: evAgentSettled, Payload: []byte(`{}`)}); err != nil {
|
|
t.Fatalf("append settled: %v", err)
|
|
}
|
|
|
|
totals, err := store.StatsTotals()
|
|
if err != nil {
|
|
t.Fatalf("totals: %v", err)
|
|
}
|
|
want := StatsTotals{UsageStats: UsageStats{Turns: 3, InputTokens: 1040, OutputTokens: 260, TotalCost: 1.75}, SessionsCount: 2}
|
|
if totals != want {
|
|
t.Fatalf("totals = %+v, want %+v", totals, want)
|
|
}
|
|
}
|