package services import ( "strings" "testing" ) // 脱敏的两条底线: // 1. 凭据必须挡住(否则把 key 发给外部模型); // 2. 排查必需的信息必须留着(IP/端口/命名空间/错误码), // 否则模型给不出有用结论 —— 这比"脱得太干净"更常见。 func TestRedactText(t *testing.T) { in := `2026-10-30 12:00:01 ERROR redis client: dial tcp 172.19.16.17:6379: connect: connection refused password=Sup3rS3cret! user-admin Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.abcdefghijklmn url: mysql://appuser:P@ssw0rd@10.2.3.4:3306/cex contact: ops@example.com phone: 13800138000 accessKey=AKIAIOSFODNN7EXAMPLE` out, invalid := RedactText(in, nil) if len(invalid) != 0 { t.Fatalf("内置规则不应产生无效正则: %v", invalid) } mustRedact := []string{"Sup3rS3cret", "eyJhbGciOiJIUzI1NiJ9", "P@ssw0rd", "ops@example.com", "13800138000", "AKIAIOSFODNN7EXAMPLE"} for _, secret := range mustRedact { if strings.Contains(out, secret) { t.Errorf("敏感内容未脱敏: %q\n%s", secret, out) } } mustKeep := []string{"172.19.16.17:6379", "connection refused", "10.2.3.4:3306", "redis"} for _, keep := range mustKeep { if !strings.Contains(out, keep) { t.Errorf("排查必需的信息被误删: %q\n%s", keep, out) } } } // 用户自定义正则写错不能拖垮整次分析:跳过并在返回值里报告。 func TestRedactTextInvalidExtraRule(t *testing.T) { out, invalid := RedactText("hello internal-id-12345", []string{`(unclosed`, `internal-id-\d+`}) if len(invalid) != 1 || invalid[0] != `(unclosed` { t.Errorf("应报告 1 条无效规则,实际 %v", invalid) } if strings.Contains(out, "internal-id-12345") { t.Errorf("有效自定义规则应生效: %s", out) } } // 模型经常不按 JSON 返回,解析必须宽容,不能只报"解析失败"。 func TestParseAIResultTolerance(t *testing.T) { cases := []struct { name string in string want string // 期望的 summary 片段 }{ { name: "标准 JSON", in: `{"summary":"日志量正常","findings":[],"actions":[],"unknowns":[]}`, want: "日志量正常", }, { name: "包了 ```json 代码块", in: "```json\n{\"summary\":\"体积上涨 2 倍\",\"findings\":[{\"title\":\"t\",\"evidence\":\"e\",\"severity\":\"high\"}],\"actions\":[],\"unknowns\":[]}\n```", want: "体积上涨 2 倍", }, { name: "前后加了解释", in: `分析如下:{"summary":"存在告警","findings":[],"actions":[],"unknowns":[]} 希望有帮助`, want: "存在告警", }, { name: "纯文本(降级)", in: "看起来一切正常,没有异常日志。", want: "看起来一切正常", }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { got := parseAIResult(c.in) if !strings.Contains(got.Summary, c.want) { t.Errorf("summary 不符: got %q want contains %q", got.Summary, c.want) } }) } }