Download internal/server/handler_credit_floor_test.go from a3216/gcli2api: direct link, hf CLI and curl.
- Browser
- Download file 5.62 kB
-
https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/server/handler_credit_floor_test.go
- Command line
-
hf download hf://spaces/a3216/gcli2api/internal/server/handler_credit_floor_test.go
-
curl -L -o handler_credit_floor_test.go https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/server/handler_credit_floor_test.go
5.62 kB
| // handler_credit_floor_test.go 积分保底的可观测性与端到端拦截: | |
| // /status 透出 credit_floor;触底账号打收费模型时网关无号可选(503)。 | |
| package server | |
| import ( | |
| "encoding/json" | |
| "net/http/httptest" | |
| "strings" | |
| "testing" | |
| "github.com/linguo2625469/workbuddy2api-panel/internal/auth" | |
| "github.com/linguo2625469/workbuddy2api-panel/internal/upstream" | |
| ) | |
| // TestStatusCreditFloor /status 透出 pool 层的 credit_floor 生效值: | |
| // 运维查账时一并看到保底线(结合 accounts[].credits 与 model_costs 即可判定 | |
| // 某号为何对某模型不出票)。关闭(0)时也显式透出——缺失会让人误以为没记录。 | |
| func TestStatusCreditFloor(t *testing.T) { | |
| p := testPoolWith(&auth.Auth{UID: "u1", AccessToken: "at", ExpiresAt: 9999999999}) | |
| p.SetCreditFloor(100) | |
| h := NewHandler(Config{Pool: p, Upstream: upstream.New()}) | |
| rec := httptest.NewRecorder() | |
| h.ServeHTTP(rec, httptest.NewRequest("GET", "/status", nil)) | |
| if rec.Code != 200 { | |
| t.Fatalf("code=%d body=%s", rec.Code, rec.Body) | |
| } | |
| var body map[string]any | |
| if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { | |
| t.Fatalf("status not json: %v", err) | |
| } | |
| if body["credit_floor"] != float64(100) { | |
| t.Errorf("credit_floor=%v want 100", body["credit_floor"]) | |
| } | |
| } | |
| // TestStatusCreditFloorZeroOff 未配置(默认 0)同样透出 0(显式写出,零值不省略)。 | |
| func TestStatusCreditFloorZeroOff(t *testing.T) { | |
| p := testPoolWith(&auth.Auth{UID: "u1", AccessToken: "at", ExpiresAt: 9999999999}) | |
| h := NewHandler(Config{Pool: p, Upstream: upstream.New()}) | |
| rec := httptest.NewRecorder() | |
| h.ServeHTTP(rec, httptest.NewRequest("GET", "/status", nil)) | |
| var body map[string]any | |
| if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { | |
| t.Fatalf("status not json: %v", err) | |
| } | |
| if body["credit_floor"] != float64(0) { | |
| t.Errorf("credit_floor=%v want 0 (off)", body["credit_floor"]) | |
| } | |
| } | |
| // TestCreditFloorBlocksPaidRequest 端到端:触底 + 实测收费模型 → 选号无候选, | |
| // 网关回 503(硬语义:宁 503 不打穿;免费模型照常可用)。 | |
| // | |
| // 诚实性约束:本用例的 upstream 是打不通的假上游,floor 开与关最终都回 503—— | |
| // 若只断言 503,就无法区分「floor 拦的」与「上游不可达」,断言会被虚假原因满足。 | |
| // 真正证明拦截落在选号层的是**对照断言**:对照组(不开 floor)必须能选到 poor, | |
| // 实验组(开 floor)必须在同一条件下选不到号。 | |
| func TestCreditFloorBlocksPaidRequest(t *testing.T) { | |
| const body = `{"model":"paid-model","messages":[{"role":"user","content":"hi"}]}` | |
| // 对照组:不设 floor,其余逐字相同(同一触底号、同一 tier 2 观测)。 | |
| ctlPool := testPoolWith(&auth.Auth{UID: "poor", AccessToken: "at", ExpiresAt: 9999999999}) | |
| ctlPool.SetCredits("poor", 30, 0) | |
| ctlPool.NoteModelCost("poor", "paid-model", 2.9, 1000) | |
| if a := ctlPool.PickExcludingForRealm(nil, "paid-model", ""); a == nil { | |
| t.Fatal("对照组前置失效:未设 floor 时应选到 poor(否则本用例不构成对照)") | |
| } | |
| // 实验组:开 floor 100。 | |
| p := testPoolWith(&auth.Auth{UID: "poor", AccessToken: "at", ExpiresAt: 9999999999}) | |
| p.SetCreditFloor(100) | |
| p.SetCredits("poor", 30, 0) | |
| p.NoteModelCost("poor", "paid-model", 2.9, 1000) | |
| if a := p.PickExcludingForRealm(nil, "paid-model", ""); a != nil { | |
| t.Fatalf("floor 应在 pool 层拦住触底号,got %v(拦截必须发生在选号层,而非靠上游报错)", a.UID) | |
| } | |
| h := NewHandler(Config{Pool: p, Upstream: upstream.New()}) | |
| rec := httptest.NewRecorder() | |
| h.ServeHTTP(rec, httptest.NewRequest("POST", "/v1/chat/completions", strings.NewReader(body))) | |
| if rec.Code != 503 { | |
| t.Fatalf("code=%d want 503(全池触底 + 收费模型 → 不放行), body=%s", rec.Code, rec.Body) | |
| } | |
| if !strings.Contains(rec.Body.String(), "no_healthy_account") { | |
| t.Errorf("body=%s want no_healthy_account", rec.Body) | |
| } | |
| } | |
| // TestCreditFloorAllowsFreeRequest 端到端:同一触底号打免费模型照常透出(非 503)。 | |
| // 这是保底的立身之本——保完了就得还能用。 | |
| func TestCreditFloorAllowsFreeRequest(t *testing.T) { | |
| p := testPoolWith(&auth.Auth{UID: "poor", AccessToken: "at", ExpiresAt: 9999999999}) | |
| p.SetCreditFloor(100) | |
| p.SetCredits("poor", 30, 0) | |
| p.NoteModelCost("poor", "free-model", 0, 1000) | |
| // 选号层面必须出票(上游转发失败与否不在本用例关心范围,见 TestCreditFloor* 单测)。 | |
| if a := p.PickExcludingForRealm(nil, "free-model", ""); a == nil || a.UID != "poor" { | |
| t.Fatalf("触底号打免费模型应选到号,got %v", a) | |
| } | |
| // pool 层与 handler 层口径一致(避免 handler 绕过 pool 的 floor 判定)。 | |
| if p.PickByUIDForModel("poor", "free-model") == nil { | |
| t.Error("粘性路径对免费模型不应被 floor 拦") | |
| } | |
| } | |
| // TestCreditFloorPersistsAcquireRelease 保底拦截不影响在途租约语义: | |
| // 触底 + 收费 → Acquire 仍可占名额(floor 只在选号层拦),释放幂等。 | |
| func TestCreditFloorPersistsAcquireRelease(t *testing.T) { | |
| p := testPoolWith(&auth.Auth{UID: "poor", AccessToken: "at", ExpiresAt: 9999999999}) | |
| p.SetCreditFloor(100) | |
| p.SetCredits("poor", 30, 0) | |
| p.NoteModelCost("poor", "paid-model", 2.9, 1000) | |
| p.SetMaxInFlight(2) | |
| if !p.Acquire("poor") { | |
| t.Fatal("Acquire 应成功(floor 不介入租约语义)") | |
| } | |
| p.Release("poor") | |
| p.Release("poor") // 幂等释放不扣成负数 | |
| } | |