package core import ( "strings" "testing" "llmsproxy/internal/config" ) // ★ P2(内核改动):新增/修改源时,源名含 `:` 或 `/` 必须**硬拒**(API 400)。 // // 这里验的是**真实写入入口** Core.AddSource(WebUI / 插件的 add_source 都走它), // 不是 config 层那个校验器 —— 校验器写对了但没接到入口上,问题依旧存在。 // // 根因见 internal/config/config.go 的 ValidateSourceName 注释:`:` 与 `/` 是 // `源名:模型名` 的**分隔符**,出现在源名里会让限定名产生两种都自圆其说的切法, // 同一请求串在不同部署下可能路由到不同源,且**不报错**。 func TestAddSourceRejectsPinnedSeparatorInName(t *testing.T) { for _, name := range []string{ "a:b", "channels-trae-abc:glm-5.2", // 把"限定名"当源名写进来 "a/b", "openai/gpt", } { t.Run(name, func(t *testing.T) { c := kernelTestCore(t) err := c.AddSource(config.Source{ Name: name, BaseURL: "http://127.0.0.1:1/v1", Adapter: "openai", Models: []config.Model{{ID: "m1", Kind: "chat"}}, }) if err == nil { t.Fatalf("★ 源名 %q 含限定名分隔符,AddSource 必须拒绝\n"+ " 否则 `%s:m1` 既可能解析成源 %q,也可能解析成别的源 —— 且不报错", name, name, name) } msg := err.Error() if !strings.Contains(msg, "pinning separator") { t.Fatalf("错误信息应点名「pinning separator」(运维才知道是限定名冲突),实得: %v", err) } // 源不得被写进配置(拒绝必须是**彻底的**,不能先写后报错) for _, s := range c.Sources() { if s.Name == name { t.Fatalf("★ 被拒绝的源 %q 竟然写进了配置 —— 拒绝必须发生在写盘之前", name) } } }) } } // 配对判据:合法的渠道源名(含 `-`)必须照常接受。 // 这条防"校验器写太严把真实渠道源全拒了"——那会让整个渠道功能失效。 func TestAddSourceAcceptsChannelStyleNames(t *testing.T) { for _, name := range []string{ "channels-trae-b8dd6b3df30e", "channels-buddy-buddy-main", "my_source_1", } { t.Run(name, func(t *testing.T) { c := kernelTestCore(t) if err := c.AddSource(config.Source{ Name: name, BaseURL: "http://127.0.0.1:1/v1", Adapter: "openai", Models: []config.Model{{ID: "m1", Kind: "chat"}}, }); err != nil { t.Fatalf("★ 合法渠道源名 %q 被拒(会把真实渠道全废掉): %v", name, err) } }) } }