// store 语义契约测试(内存实现;PG 实现同接口同语义)。 package store import ( "testing" "time" ) func newUsage(id, user, model, endpoint, status string, p, c int) UsageLog { return UsageLog{ID: id, RunID: "run_t", UserID: user, Model: model, Slot: "chat", Endpoint: endpoint, Status: status, PromptTokens: p, CompletionTokens: c, At: time.Now().UTC()} } func TestUsageAggregateFiltersByUserAndCountsOK(t *testing.T) { st := NewMem() _ = st.InsertUsage(newUsage("1", "u1", "m", "e1", "ok", 10, 20)) _ = st.InsertUsage(newUsage("2", "u1", "m", "e1", "error", 0, 0)) _ = st.InsertUsage(newUsage("3", "u2", "m", "e2", "ok", 1, 2)) rows, err := st.AggregateUsage("u1") if err != nil { t.Fatal(err) } if len(rows) != 1 { t.Fatalf("u1 聚合行数 = %d, 期望 1", len(rows)) } r := rows[0] if r.Requests != 2 || r.OK != 1 || r.PromptTokens != 10 || r.CompletionTokens != 20 { t.Fatalf("聚合字段错误: %+v", r) } all, _ := st.AggregateUsage("") if len(all) != 2 { t.Fatalf("全体聚合行数 = %d, 期望 2", len(all)) } } func TestUsageSampleReturnsLatest(t *testing.T) { st := NewMem() for i := 0; i < 5; i++ { _ = st.InsertUsage(newUsage(string(rune('a'+i)), "u1", "m", "e", "ok", i, 0)) } rows, _ := st.SampleUsage(2) if len(rows) != 2 || rows[1].ID != "e" { t.Fatalf("抽样应返回最新 2 条(d,e),实际 %+v", rows) } } func TestByokLifecycle(t *testing.T) { st := NewMem() key := ByokKey{ID: "byok_x", UserID: "u1", Name: "主力", Type: "openai_compatible", BaseURL: "https://api.example.com", APIKey: "enc", Model: "m1", CreatedAt: time.Now().UTC()} if err := st.UpsertByok(key); err != nil { t.Fatal(err) } got, err := st.GetByok("u1", "byok_x") if err != nil || got == nil || got.Model != "m1" { t.Fatalf("GetByok 失败: %v %+v", err, got) } // 跨用户隔离 if other, _ := st.GetByok("u2", "byok_x"); other != nil { t.Fatal("u2 不应读到 u1 的密钥") } if err := st.RevokeByok("u1", "byok_x"); err != nil { t.Fatal(err) } got2, _ := st.GetByok("u1", "byok_x") if got2 != nil { t.Fatal("撤回后不应可读") } if err := st.RevokeByok("u1", "byok_x"); err != ErrByokNotFound { t.Fatalf("重复撤回应返回 ErrByokNotFound,实际 %v", err) } } func TestQuotaSaturatingRefund(t *testing.T) { st := NewMem() if err := st.Reserve("u1", 100); err != nil { t.Fatal(err) } // 幂等退款:重复退款不产生负余额 if err := st.Refund("u1", 100); err != nil { t.Fatal(err) } if err := st.Refund("u1", 100); err != nil { t.Fatal(err) } b, _ := st.Balance("u1") if b.Reserved < 0 || b.Used != 0 { t.Fatalf("重复退款后余额为负: %+v", b) } } func TestQuotaSettleReleasesDifference(t *testing.T) { st := NewMem() _ = st.Reserve("u1", 100) if err := st.Settle("u1", 100, 37); err != nil { t.Fatal(err) } b, _ := st.Balance("u1") if b.Reserved != 0 || b.Used != 37 { t.Fatalf("结算后应释放全部预扣并记实际用量: %+v", b) } }