Files
ai-router/internal/server/stats_timezone_test.go
2026-10-23 18:35:44 +08:00

75 lines
2.7 KiB
Go

package server
import (
"ai-router/internal/protocol"
"encoding/json"
"net/url"
"reflect"
"testing"
)
func TestStatsBrowserTimezone(t *testing.T) {
for _, tc := range []struct {
name, zone string
stamps []string
want map[string]int
}{
{"Shanghai midnight", "Asia/Shanghai", []string{"2026-10-20T15:59:59Z", "2026-10-20T16:00:00Z"}, map[string]int{"2026-10-20": 1, "2026-10-21": 1}},
{"UTC default", "", []string{"2026-10-20T15:59:59Z", "2026-10-20T16:00:00Z"}, map[string]int{"2026-10-20": 2}},
{"New York DST spring", "America/New_York", []string{"2025-03-09T04:59:59Z", "2025-03-09T05:00:00Z", "2025-03-10T03:59:59Z", "2025-03-10T04:00:00Z"}, map[string]int{"2025-03-08": 1, "2025-03-09": 2, "2025-03-10": 1}},
{"New York DST fall", "America/New_York", []string{"2025-11-02T03:59:59Z", "2025-11-02T04:00:00Z", "2025-11-03T04:59:59Z", "2025-11-03T05:00:00Z"}, map[string]int{"2025-11-01": 1, "2025-11-02": 2, "2025-11-03": 1}},
} {
t.Run(tc.name, func(t *testing.T) {
s := testServer(t)
cookie := loginCookie(t, s)
for _, stamp := range tc.stamps {
s.record(requestLog{CreatedAt: stamp, KeyID: "one", Status: 200, Usage: protocol.Usage{Known: true, Input: 10}})
}
s.record(requestLog{CreatedAt: tc.stamps[0], KeyID: "other", Status: 200})
if err := s.flushLogs(); err != nil {
t.Fatal(err)
}
w := call(s, "GET", "/admin/api/stats?key_id=one&timezone="+url.QueryEscape(tc.zone), "", cookie)
if w.Code != 200 {
t.Fatal(w.Code, w.Body.String())
}
var result struct {
Timezone string `json:"timezone"`
Summary summary `json:"summary"`
Daily []struct {
Day string `json:"day"`
Requests int `json:"requests"`
} `json:"daily"`
}
if err := json.Unmarshal(w.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
got := map[string]int{}
for _, d := range result.Daily {
got[d.Day] = d.Requests
}
if !reflect.DeepEqual(got, tc.want) {
t.Fatalf("got %v want %v", got, tc.want)
}
if result.Summary.Requests != int64(len(tc.stamps)) || result.Summary.Input == nil || *result.Summary.Input != int64(10*len(tc.stamps)) {
t.Fatal(result.Summary)
}
var stored string
if err := s.db.QueryRow("SELECT created_at FROM logs ORDER BY id LIMIT 1").Scan(&stored); err != nil || stored != tc.stamps[0] {
t.Fatal("UTC storage changed", stored, err)
}
})
}
}
func TestStatsRejectsInvalidTimezone(t *testing.T) {
s := testServer(t)
c := loginCookie(t, s)
for _, zone := range []string{"Local", "not/a-zone", "../../etc/passwd"} {
w := call(s, "GET", "/admin/api/stats?timezone="+url.QueryEscape(zone), "", c)
if w.Code != 400 {
t.Fatal(zone, w.Code)
}
}
}