Go 77 lines
package ai
import (
"os"
"path/filepath"
"testing"
)
// writeLedger drops a crafted ai-calls.json into stateDir. The body is the
// frozen on-disk shape, so hand-authoring it is safe.
func writeLedger(t *testing.T, stateDir, body string) {
t.Helper()
if err := os.MkdirAll(stateDir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(stateDir, AICallsFilename), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
}
func TestSummarize_Aggregates(t *testing.T) {
dir := t.TempDir()
writeLedger(t, dir, `{"records":[
{"label":"a","provider":"anthropic","ran":true,"parked":false,
"tokens":{"input":1000,"cached_input":200,"output":500},"ts":"2026-05-21T10:00:00Z"},
{"label":"b","provider":"cli","ran":true,"parked":false,
"tokens":{"input":2000,"cached_input":0,"output":800},"ts":"2026-05-30T12:00:00Z"},
{"label":"c","provider":"anthropic","ran":false,"parked":true,
"tokens":{"input":0,"cached_input":0,"output":0},"ts":"2026-05-25T09:00:00Z"}
]}`)
s := Summarize(dir)
if s.TotalCalls != 3 {
t.Errorf("TotalCalls = %d, want 3", s.TotalCalls)
}
if s.Ran != 2 {
t.Errorf("Ran = %d, want 2", s.Ran)
}
if s.Parked != 1 {
t.Errorf("Parked = %d, want 1", s.Parked)
}
if s.Tokens.Input != 3000 || s.Tokens.CachedInput != 200 || s.Tokens.Output != 1300 {
t.Errorf("Tokens = %+v, want {3000 200 1300}", s.Tokens)
}
if got := s.Tokens.Total(); got != 4500 {
t.Errorf("Tokens.Total() = %d, want 4500", got)
}
if s.ByProvider["anthropic"] != 2 || s.ByProvider["cli"] != 1 {
t.Errorf("ByProvider = %v, want anthropic:2 cli:1", s.ByProvider)
}
if s.FirstTS != "2026-05-21T10:00:00Z" {
t.Errorf("FirstTS = %q, want 2026-05-21T10:00:00Z", s.FirstTS)
}
if s.LastTS != "2026-05-30T12:00:00Z" {
t.Errorf("LastTS = %q, want 2026-05-30T12:00:00Z", s.LastTS)
}
}
func TestSummarize_MissingFile(t *testing.T) {
s := Summarize(t.TempDir())
if s.TotalCalls != 0 || s.Tokens.Total() != 0 || len(s.ByProvider) != 0 {
t.Errorf("missing ledger should be the zero summary, got %+v", s)
}
if s.FirstTS != "" || s.LastTS != "" {
t.Errorf("missing ledger should have empty range, got first=%q last=%q", s.FirstTS, s.LastTS)
}
}
func TestSummarize_EmptyRecords(t *testing.T) {
dir := t.TempDir()
writeLedger(t, dir, `{"records":[]}`)
s := Summarize(dir)
if s.TotalCalls != 0 || s.Tokens.Total() != 0 {
t.Errorf("empty ledger should be the zero summary, got %+v", s)
}
}