The cluster page's usage table showed session:usr-... and proj-... ids; it now shows the person's email, whether it came through a key or the chat page, and the project's path or "personal". Times read "3 hours ago" rather than "3h7m25s ago", everywhere. The usage page's legend gave each line's latest slice, which was 0 beside a table of hundreds; it gives the window's total, and the table's numbers are right-aligned like everywhere else. The PostgreSQL placeholder rewriting skips line comments. An apostrophe in one opened a string that swallowed every placeholder after it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// checkUsageNamesWhoAndWhere is run against both dialects: a report that
|
|
// named people by id and projects by id was a table nobody could read.
|
|
func checkUsageNamesWhoAndWhere(t *testing.T, s *DB) {
|
|
t.Helper()
|
|
ctx := context.Background()
|
|
must := func(err error) {
|
|
t.Helper()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
must(s.PutOrg(ctx, Org{ID: "o", Name: "Acme"}))
|
|
must(s.PutTeam(ctx, Team{ID: "t", OrgID: "o", Name: "ml"}))
|
|
must(s.PutProject(ctx, Project{ID: "p", TeamID: "t", Name: "training"}))
|
|
must(s.CreateUser(ctx, User{ID: "usr-1", Email: "ada@example.com", CreatedAt: time.Now()}))
|
|
now := time.Now()
|
|
must(s.WriteUsage(ctx, []Usage{
|
|
{At: now, KeyID: "session:usr-1", UserID: "usr-1", ProjectID: "p", Model: "m", ServedModel: "m", Status: 200},
|
|
{At: now, KeyID: "session:usr-1", UserID: "usr-1", Model: "m", ServedModel: "m", Status: 200},
|
|
}))
|
|
|
|
rows, err := s.UsageSince(ctx, now.Add(-time.Hour))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(rows) != 2 {
|
|
t.Fatalf("expected two rows, got %+v", rows)
|
|
}
|
|
places := map[string]bool{}
|
|
for _, r := range rows {
|
|
if r.Email != "ada@example.com" || !r.Chat() {
|
|
t.Errorf("row %+v should name ada and read as the chat page", r)
|
|
}
|
|
places[r.ProjectPath] = true
|
|
}
|
|
if !places["Acme / ml / training"] || !places[""] {
|
|
t.Errorf("places = %v, expected the project's path and personal", places)
|
|
}
|
|
}
|
|
|
|
func TestUsageNamesWhoAndWhere(t *testing.T) {
|
|
s, err := OpenSQLite(context.Background(), filepath.Join(t.TempDir(), "u.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { _ = s.Close() })
|
|
checkUsageNamesWhoAndWhere(t, s)
|
|
}
|
|
|
|
func TestPostgresUsageNamesWhoAndWhere(t *testing.T) {
|
|
checkUsageNamesWhoAndWhere(t, openPG(t))
|
|
}
|