You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

108 lines
4.0 KiB

package echomeet
import (
"testing"
"yunyan/comm"
)
// 编排选路的语言过滤(svcSupportsLanguage)回归:
// 铁律沿袭「未知语言绝不 fallback」——languages 配置了就必须命中(精确或主语言段),
// 防止重蹈「西语送进 paraformer-v2 静默返回空转写」的线上事故(该白名单现由后台
// 服务池 languages 字段承担,本测试钉住过滤语义)。
func TestSvcSupportsLanguage(t *testing.T) {
// 老白名单:没配 workspace_id 的阿里服务仍跑 paraformer-v2,只有这 8 种
legacyLangs := []string{"zh-CN", "yue-CN", "en-US", "ja-JP", "ko-KR", "de-DE", "fr-FR", "ru-RU"}
// 新白名单:配了 workspace_id 走 qwen-audio-3.0-asr-flash-filetrans,扩到 24 个码(节选)
qwenLangs := []string{"zh-CN", "en-US", "ja-JP", "es-ES", "vi-VN", "pt-BR", "th-TH"}
cases := []struct {
langs []string
want string
ok bool
}{
{legacyLangs, "es-ES", false}, // 西语:paraformer-v2 不支持,必须被过滤
{legacyLangs, "vi-VN", false}, // 越南语同理
{legacyLangs, "zh-CN", true},
{legacyLangs, "zh", true}, // 主语言段命中
{legacyLangs, "en-GB", true}, // en 主段命中
{legacyLangs, "pt-BR", false},
{qwenLangs, "vi-VN", true}, // 新模型下越南语放行
{qwenLangs, "es-ES", true},
{qwenLangs, "uk-UA", false}, // 乌克兰语未确认,白名单里不放,仍须被过滤
{nil, "es-ES", true}, // 未配置 languages = 不限
{legacyLangs, "", true}, // 空语言 = 不过滤(交给引擎自动检测)
}
for _, c := range cases {
if got := svcSupportsLanguage(c.langs, c.want); got != c.ok {
t.Errorf("svcSupportsLanguage(%v, %q) = %v, want %v", c.langs, c.want, got, c.ok)
}
}
}
// 作用域具体度(scopeRank)回归:(app,region) > (app,0) > ('',region) > ('',0),
// 非本部署作用域链上的行必须是 0。
func TestScopeRank(t *testing.T) {
const app, reg = "voitrans", int32(1)
cases := []struct {
appName string
region int32
want int
}{
{"voitrans", 1, 4},
{"voitrans", 0, 3},
{"", 1, 2},
{"", 0, 1},
{"otherapp", 1, 0}, // 别的应用
{"voitrans", 2, 0}, // 别的区域
}
for _, c := range cases {
if got := scopeRank(c.appName, c.region, app, reg); got != c.want {
t.Errorf("scopeRank(%q,%d) = %d, want %d", c.appName, c.region, got, c.want)
}
}
}
// 区域覆盖合并 + 解密(resolveSvcFields)回归:
// Overrides 覆盖默认值、ExtraFields 追加、DisabledKeys 剔除;加密字段解不开必须整体报错(fail-closed)。
func TestResolveSvcFields(t *testing.T) {
const key = "test-field-encrypt-key"
enc, err := comm.Encrypt(key, "sk-plain")
if err != nil {
t.Fatalf("encrypt: %v", err)
}
svc := &comm.ThirdSvcConfig{
Id: "asr1", Name: "阿里识别", Provider: "alibaba",
Fields: []comm.SvcField{
{Key: "api_key", Encrypted: true, DefValue: enc},
{Key: "languages", DefValue: "zh-CN,en-US"},
{Key: "callback_path", DefValue: "/api/home/echomeet_alibackcall"},
{Key: "obsolete", DefValue: "x"},
},
}
ovr := &comm.SvcRegionOverride{
SvcId: "asr1",
Overrides: map[string]string{"languages": "ja-JP"},
ExtraFields: []comm.SvcField{{Key: "extra", DefValue: "y"}},
DisabledKeys: []string{"obsolete"},
}
rs, err := resolveSvcFields(svc, ovr, key)
if err != nil {
t.Fatalf("resolve: %v", err)
}
if rs.Fields["api_key"] != "sk-plain" {
t.Errorf("加密字段应解出明文, got %q", rs.Fields["api_key"])
}
if len(rs.Languages) != 1 || rs.Languages[0] != "ja-JP" {
t.Errorf("languages 应被区域覆盖为 ja-JP, got %v", rs.Languages)
}
if rs.Fields["extra"] != "y" {
t.Errorf("ExtraFields 应追加")
}
if _, ok := rs.Fields["obsolete"]; ok {
t.Errorf("DisabledKeys 应剔除 obsolete")
}
// fail-closed:错的 key 解不开必须报错,绝不把密文当明文用
if _, err := resolveSvcFields(svc, nil, "wrong-key"); err == nil {
t.Errorf("错误密钥应整体报错(fail-closed),不能静默把密文当明文")
}
}