Files
Cyrene_v2/internal/runtime/multimodal/voice/upstream_token_test.go
T
AskaEth fe3872ee28 fix(trace): 令牌守卫上移进 trace.UpstreamError,构造即安全
M48 复审的中危 finding:error.type 里的散文经 trace.UpstreamError 原样出镜,
因为守卫加在调用方(M46 的 model/voice 两处),构造函数自己不套守卫 ——
任何新调用点默认不安全,httpclient / vision / embedding / weixin 四条出口一直漏。

- trace.UpstreamError 构造时对 error.code / error.type 各走一次 ErrorToken
  ([A-Za-z0-9_.-]{<=64},不合规即空串):默认安全,不是可选加固。
- 构造后注入这条窄路收进 UpstreamErrorInfo.SetCode / SetType(同一道守卫),
  供 DashScope 顶层 code 与 Anthropic 流内 error.type 两处使用 —— 调用方不再
  各抄一份 ErrorToken。
- 删除因此冗余的调用方守卫:model.providerUpstreamError 与
  voice.dashscopeOKBodyError。保留 voice 的 request_id 守卫(它不是 code/type,
  构造函数看不见)。
- 四条漏的出口一行没改,只加用例证明守卫上移后自动安全;摘掉构造函数守卫时
  四条用例 + model/voice 旧用例同时变红。
2026-10-26 19:13:38 +08:00

42 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package voice
// 本文件是 M49 的**出口回归探针**:DashScope 的「HTTP 200 但业务失败」收口里,
// error.code / error.type 的守卫已经上移进 trace.UpstreamError —— 本包那处调用点的
// 重复守卫已删除,因此这里的断言直接钉在**构造函数**上(摘掉构造函数的守卫就变红)。
//
// 与它相邻的一条(TestDashscopeTTS_Non200DropsFreeTextCode)钉的是另一件事:
// DashScope 的 4xx 把错误码放在**顶层** code(构造函数看不见),那一处靠
// UpstreamErrorInfo.SetCode 注入,守卫仍在。两条合起来覆盖这一族的两个面。
import (
"errors"
"strings"
"testing"
)
// TestDashscopeOKBodyError_DropsFreeTextErrorCode 200 报文的 error.code / error.type
// 里带散文(TTS 场景下可能是她要念的台词被回显)⇒ 两个字段整体消失,而 status=200
// 与 body_bytes(体积摘要)仍在。
func TestDashscopeOKBodyError_DropsFreeTextErrorCode(t *testing.T) {
t.Parallel()
const prose = "Invalid value: '她刚才说的那句话'"
body := []byte(`{"error":{"code":"` + prose + `","type":"` + prose + `"}}`)
err := dashscopeOKBodyError("https://dashscope.example.com/api/v1/services/audio/tts", body)
if !errors.Is(err, ErrProviderFailed) {
t.Fatalf("err = %v, want ErrProviderFailed(熔断口径不变)", err)
}
msg := err.Error()
if strings.Contains(msg, "她刚才说的那句话") {
t.Fatalf("上游 error.code/type 里的散文进了错误:%v", msg)
}
if strings.Contains(msg, " code=") || strings.Contains(msg, " type=") {
t.Fatalf("非令牌形状的 code/type 没有被丢弃:%v", msg)
}
for _, want := range []string{"status=200", "body_bytes="} {
if !strings.Contains(msg, want) {
t.Fatalf("错误里缺少 %q(诊断面不能一起丢):%v", want, msg)
}
}
}