mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-31 08:25:35 +00:00
- custom-voices endpoint 改由匹配到的路由模板推导(c.FullPath())。 原实现按请求 URL 字面后缀判 /audio,voice_id 恰为 "audio" 时 GET /custom-voices/audio 会被改写成 custom-voices/audio/audio, 把档案查询变成音频下载。补 voice_id="audio" 的路由推导测试。 - NormalizeVideoModelPrices 不再把无法识别的分辨率静默折算成 480p: 新增 LookupVideoBillingResolution 报告未知档位,配置解析路径丢弃并告警, 运行时计费仍走 OrDefault 兜底。model/tier 两层遍历改为排序遍历, 多个别名收敛到同一 family 时结果不再随 Go map 顺序漂移,冲突单价告警。 - grok free quota 软门禁缓存新增过期淘汰。条目按 account_id 键控且只写不删, 账号下线后会驻留至进程结束;淘汰只挂在已受 TTL 约束的查询路径上, 不影响缓存命中热路径。 - 迁移 220 清空非 Grok 分组视频价前先落快照表 groups_video_price_backup_220, 原 UPDATE 不可回滚。 - 简化 grok_search_count 两处等价冗余的事件类型分支。
125 lines
5.0 KiB
Go
125 lines
5.0 KiB
Go
package service
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCanonicalGrokImagineVideoPriceFamily(t *testing.T) {
|
|
t.Parallel()
|
|
require.Equal(t, VideoPriceFamilyGrokImagineVideo, CanonicalGrokImagineVideoPriceFamily("grok-imagine-video"))
|
|
require.Equal(t, VideoPriceFamilyGrokImagineVideo15, CanonicalGrokImagineVideoPriceFamily("grok-imagine-video-1.5"))
|
|
require.Equal(t, VideoPriceFamilyGrokImagineVideo15, CanonicalGrokImagineVideoPriceFamily("grok-imagine-video-1.5-preview"))
|
|
require.Equal(t, VideoPriceFamilyGrokImagineVideo15, CanonicalGrokImagineVideoPriceFamily("xai/grok-video-1.5"))
|
|
require.Equal(t, "grok-imagine-video-2", CanonicalGrokImagineVideoPriceFamily("grok-imagine-video-2"))
|
|
require.Equal(t, "grok-imagine-video-2", CanonicalGrokImagineVideoPriceFamily("xai/grok-imagine-video-2"))
|
|
}
|
|
|
|
func TestNormalizeAndLookupVideoModelPrices(t *testing.T) {
|
|
t.Parallel()
|
|
raw := map[string]map[string]float64{
|
|
"grok-imagine-video-1.5-preview": {"480p": 0.08, "720p": 0.14},
|
|
"grok-imagine-video": {"480p": 0.05},
|
|
"grok-imagine-video-2": {"1080p": 0.4},
|
|
}
|
|
norm := NormalizeVideoModelPrices(raw)
|
|
require.NotNil(t, norm)
|
|
require.Contains(t, norm, VideoPriceFamilyGrokImagineVideo15)
|
|
require.Contains(t, norm, VideoPriceFamilyGrokImagineVideo)
|
|
require.Contains(t, norm, "grok-imagine-video-2")
|
|
|
|
p15 := LookupVideoModelPrice(norm, "grok-imagine-video-1.5", "480p")
|
|
require.NotNil(t, p15)
|
|
require.InDelta(t, 0.08, *p15, 1e-9)
|
|
|
|
pBase := LookupVideoModelPrice(norm, "grok-imagine-video", "480p")
|
|
require.NotNil(t, pBase)
|
|
require.InDelta(t, 0.05, *pBase, 1e-9)
|
|
// A missing model-specific tier must fall back to the flat tier price,
|
|
// rather than borrowing another model-specific resolution.
|
|
require.Nil(t, LookupVideoModelPrice(norm, "grok-imagine-video", "720p"))
|
|
|
|
p2 := LookupVideoModelPrice(norm, "grok-imagine-video-2", "1080p")
|
|
require.NotNil(t, p2)
|
|
require.InDelta(t, 0.4, *p2, 1e-9)
|
|
|
|
// Unmatched model → nil (caller falls back to flat columns / defaults).
|
|
require.Nil(t, LookupVideoModelPrice(norm, "unknown-model", "480p"))
|
|
}
|
|
|
|
func TestNormalizeVideoModelPricesDropsUnknownResolutions(t *testing.T) {
|
|
t.Parallel()
|
|
// "4k" and "1080i" are not billable tiers. Collapsing them into 480p would
|
|
// charge a 480p request at the operator's high-resolution price.
|
|
norm := NormalizeVideoModelPrices(map[string]map[string]float64{
|
|
"grok-imagine-video": {"480p": 0.05, "4k": 0.50, "1080i": 0.30},
|
|
})
|
|
require.NotNil(t, norm)
|
|
require.Equal(t, map[string]float64{VideoBillingResolution480P: 0.05}, norm[VideoPriceFamilyGrokImagineVideo])
|
|
|
|
// A model whose tiers are all unrecognized contributes no family at all.
|
|
require.Nil(t, NormalizeVideoModelPrices(map[string]map[string]float64{
|
|
"grok-imagine-video": {"4k": 0.50},
|
|
}))
|
|
}
|
|
|
|
func TestNormalizeVideoModelPricesIsDeterministicAcrossAliasConflicts(t *testing.T) {
|
|
t.Parallel()
|
|
// Both keys canonicalize onto grok-imagine-video-1.5 and disagree on 480p.
|
|
// Whichever price wins, it must be the same one on every run — a Go map walk
|
|
// would let two processes bill the same request differently.
|
|
raw := map[string]map[string]float64{
|
|
"grok-imagine-video-1.5": {"480p": 0.08},
|
|
"grok-imagine-video-1.5-preview": {"480p": 0.11},
|
|
"grok-video-1.5": {"480p": 0.09},
|
|
}
|
|
first := NormalizeVideoModelPrices(raw)
|
|
require.NotNil(t, first)
|
|
for i := 0; i < 50; i++ {
|
|
require.Equal(t, first, NormalizeVideoModelPrices(raw), "run %d diverged", i)
|
|
}
|
|
|
|
// Aliases within one model key normalize to the same tier deterministically too.
|
|
aliased := map[string]map[string]float64{
|
|
"grok-imagine-video": {"720": 0.12, "720p": 0.13, "hd": 0.14},
|
|
}
|
|
firstAliased := NormalizeVideoModelPrices(aliased)
|
|
require.NotNil(t, firstAliased)
|
|
for i := 0; i < 50; i++ {
|
|
require.Equal(t, firstAliased, NormalizeVideoModelPrices(aliased), "run %d diverged", i)
|
|
}
|
|
}
|
|
|
|
func TestLookupVideoBillingResolutionReportsUnknownTiers(t *testing.T) {
|
|
t.Parallel()
|
|
for _, in := range []string{"480", "480p", "SD", "720", "hd", "1080", "full-hd", " fhd "} {
|
|
normalized, ok := LookupVideoBillingResolution(in)
|
|
require.True(t, ok, "input=%q", in)
|
|
require.NotEmpty(t, normalized)
|
|
}
|
|
for _, in := range []string{"", "4k", "1080i", "2160p", "potato"} {
|
|
normalized, ok := LookupVideoBillingResolution(in)
|
|
require.False(t, ok, "input=%q", in)
|
|
require.Empty(t, normalized)
|
|
}
|
|
// Runtime billing still needs a tier for unrecognized upstream values.
|
|
require.Equal(t, VideoBillingResolution480P, NormalizeVideoBillingResolutionOrDefault("4k"))
|
|
require.Equal(t, VideoBillingResolution1080P, NormalizeVideoBillingResolutionOrDefault("full_hd"))
|
|
}
|
|
|
|
func TestVideoModelPriceMissingTierFallsBackToFlatTierPrice(t *testing.T) {
|
|
t.Parallel()
|
|
flat720P := 0.7
|
|
service := &BillingService{}
|
|
|
|
result := service.CalculateVideoCost("grok-imagine-video", "720p", 1, 1, &VideoPriceConfig{
|
|
Price720P: &flat720P,
|
|
ModelPrices: map[string]map[string]float64{
|
|
VideoPriceFamilyGrokImagineVideo: {VideoBillingResolution480P: 0.05},
|
|
},
|
|
}, 1)
|
|
|
|
require.InDelta(t, flat720P, result.TotalCost, 1e-9)
|
|
}
|