Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/service"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParsePreviewInputsIgnoresNullUserOverride(t *testing.T) {
|
||||
raw := []byte(`{
|
||||
"groups": [{
|
||||
"group": {
|
||||
"id": 50,
|
||||
"name": "preview",
|
||||
"platform": "openai",
|
||||
"rate_multiplier": 0.5,
|
||||
"subscription_type": "standard",
|
||||
"profit_control_enabled": false,
|
||||
"profit_min_margin": 0.1,
|
||||
"profit_safety_buffer": 0
|
||||
},
|
||||
"accounts": [{
|
||||
"id": 1,
|
||||
"name": "cheap",
|
||||
"platform": "openai",
|
||||
"type": "apikey",
|
||||
"rate_multiplier": 0.2
|
||||
}],
|
||||
"user_overrides": {"40": null, "41": 0.4},
|
||||
"models": ["gpt-test"]
|
||||
}]
|
||||
}`)
|
||||
|
||||
inputs, err := parsePreviewInputs(raw, true)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, inputs, 1)
|
||||
require.Equal(t, map[int64]float64{41: 0.4}, inputs[0].UserOverrides)
|
||||
require.True(t, inputs[0].AssumeEnabled)
|
||||
|
||||
report := service.PreviewProfitAdmission(inputs, time.Date(2026, 1, 15, 8, 30, 0, 0, time.UTC))[0]
|
||||
require.InDelta(t, 0.4, report.MinEffectiveD, 1e-12, "null 覆盖不能被解码成 0 倍率")
|
||||
require.InDelta(t, 0.36, report.ThresholdMinD, 1e-12)
|
||||
}
|
||||
|
||||
func TestParsePreviewInputsRejectsEmptyGroups(t *testing.T) {
|
||||
for _, raw := range [][]byte{
|
||||
[]byte(`{"groups":null}`),
|
||||
[]byte(`{"groups":[]}`),
|
||||
} {
|
||||
inputs, err := parsePreviewInputs(raw, false)
|
||||
require.ErrorContains(t, err, "input contains no groups")
|
||||
require.Nil(t, inputs)
|
||||
}
|
||||
}
|
||||
|
||||
// TestModelsWithZeroRemainingWarnings 钉死两档 D 的归零告警分工:
|
||||
// 默认 D 归零由 modelsWithZeroRemaining 报告;默认 D 仍有账号但最低有效 D
|
||||
// (分组内存在更低的用户级倍率覆盖)归零的模型必须单独告警——那些用户的该
|
||||
// 模型会全黑,只看默认 D 完全看不出来。两档都为 0 时不重复告警。
|
||||
func TestModelsWithZeroRemainingWarnings(t *testing.T) {
|
||||
report := service.ProfitPreviewGroupReport{
|
||||
RemainingByModel: map[string]int{
|
||||
"both-zero": 0,
|
||||
"min-d-zero": 2,
|
||||
"healthy": 3,
|
||||
"min-d-zero-alt": 1,
|
||||
},
|
||||
RemainingByModelMinD: map[string]int{
|
||||
"both-zero": 0,
|
||||
"min-d-zero": 0,
|
||||
"healthy": 3,
|
||||
"min-d-zero-alt": 0,
|
||||
},
|
||||
}
|
||||
|
||||
if got := modelsWithZeroRemaining(report); len(got) != 1 || got[0] != "both-zero" {
|
||||
t.Fatalf("默认D归零告警应只覆盖 both-zero,got %v", got)
|
||||
}
|
||||
|
||||
got := modelsWithZeroRemainingUnderMinD(report)
|
||||
want := []string{"min-d-zero", "min-d-zero-alt"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("最低有效D归零告警不符: got %v want %v", got, want)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("最低有效D归零告警不符(应按模型名排序): got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user