Files
dsfree2api/internal/api/responses_format_test.go
nyoung ed51efd8bc fix: 网关与控制台代码审查修复批次(含回归测试)
- Chat 接口拒绝 n>1(此前静默丢弃多余 choice),返回 400 结构化错误
- Responses 接口透传 text.format(json_schema / json_object),三种接口协议对齐
- TLS 指纹统一升级到 Chrome_150(internal/httpx.DefaultProfile),与 UA 匹配
- metrics 落盘失败不再静默:Save() 返回错误并打日志,临时文件失败会清理
- GET /api/config 脱敏 admin.password 与 turnstile.api_key(控制台从不展示,
  不应随 5s 轮询下发);PUT 改走 ReplaceJSON,先校验后替换、失败回滚
- set_limits / set_turnstile 改指针部分更新:缺字段保持现状,不会把并发、
  限流或求解开关按零值清掉
- 读请求体统一 64MB 上限;配置写盘原子替换 + 0600 权限
- main.go 改为 run() 返回退出码:日志落盘、指标落盘、xray 子进程回收全部
  挂 defer,任何退出路径(含启动失败)都会执行,杜绝孤儿 xray
- proxypool / turnstile / upstream / openai / config / httpx / logbuf 等
  逐项补红绿回归测试,新增 14 个测试文件,race 下全绿
2026-10-08 15:13:23 +08:00

56 lines
1.9 KiB
Go

package api
import (
"encoding/json"
"strings"
"testing"
"github.com/nyoungo/dsfree2api/internal/openai"
)
// 回归:Responses API 的 text.format 必须转成提示词里的输出格式约束。
// 之前 ResponsesRequest 根本不解析 text 字段,客户端指定的 json_schema
// 被静默丢弃 —— 模型可以随便输出非 JSON,客户端的 schema 校验必炸。
func TestResponsesTextFormatBecomesPromptConstraint(t *testing.T) {
body := `{"model":"m","input":"hi",` +
`"text":{"format":{"type":"json_schema",` +
`"json_schema":{"name":"addr","schema":{"type":"object",` +
`"properties":{"city":{"type":"string"}},"required":["city"]}}}}}`
var req openai.ResponsesRequest
if err := json.Unmarshal([]byte(body), &req); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if req.Text == nil || req.Text.Format == nil {
t.Fatalf("text.format 没解析出来: %+v", req.Text)
}
messages, err := openai.ResponsesToMessages(&req)
if err != nil {
t.Fatalf("responses to messages: %v", err)
}
prompt := openai.BuildPrompt(messages, responsesPromptOptions(&req, nil))
if !strings.Contains(prompt, "JSON Schema") {
t.Fatalf("提示词里没有 schema 约束: %q", prompt)
}
if !strings.Contains(prompt, "city") {
t.Fatalf("提示词里没有 schema 内容: %q", prompt)
}
}
// 回归:没有 text.format 的请求照常工作,不能凭空多出约束。
func TestResponsesWithoutTextFormatHasNoConstraint(t *testing.T) {
var req openai.ResponsesRequest
if err := json.Unmarshal([]byte(`{"model":"m","input":"hi"}`), &req); err != nil {
t.Fatalf("unmarshal: %v", err)
}
messages, err := openai.ResponsesToMessages(&req)
if err != nil {
t.Fatalf("responses to messages: %v", err)
}
prompt := openai.BuildPrompt(messages, responsesPromptOptions(&req, nil))
if strings.Contains(prompt, "JSON Schema") {
t.Fatalf("没有 text.format 却出现了 schema 约束: %q", prompt)
}
}