Files
JuYou/API/internal/worker/drama_parse_test.go
T
2026-08-25 17:59:42 +08:00

96 lines
3.5 KiB
Go

package worker
import (
"context"
"net/http"
"strings"
"testing"
"time"
)
// TestClassifyDramaErrorTreatsTimeoutAsUpstreamFailure 验证超时不会再进入提交未知状态。
func TestClassifyDramaErrorTreatsTimeoutAsUpstreamFailure(t *testing.T) {
if code := classifyDramaError(context.DeadlineExceeded); code != "upstream_timeout" {
t.Fatalf("timeout code = %q, want upstream_timeout", code)
}
}
// TestDramaModelRetryLimit 验证剧本解析调用的自动重试次数。
func TestDramaModelRetryLimit(t *testing.T) {
if maxDramaModelAttempts != 5 {
t.Fatalf("retry attempts = %d, want 5", maxDramaModelAttempts)
}
}
func TestDramaHTTPClientAllowsLongTextResponses(t *testing.T) {
sharedTransport := &http.Transport{TLSHandshakeTimeout: 10 * time.Second, ResponseHeaderTimeout: time.Minute}
shared := &http.Client{Transport: sharedTransport}
client := dramaHTTPClient(shared)
transport, ok := client.Transport.(*http.Transport)
if !ok {
t.Fatal("drama client transport was not preserved")
}
if transport.TLSHandshakeTimeout != 30*time.Second || transport.ResponseHeaderTimeout != 10*time.Minute {
t.Fatalf("unexpected drama timeouts: TLS=%s response=%s", transport.TLSHandshakeTimeout, transport.ResponseHeaderTimeout)
}
if sharedTransport.TLSHandshakeTimeout != 10*time.Second || sharedTransport.ResponseHeaderTimeout != time.Minute {
t.Fatal("shared AI transport was modified")
}
}
func TestParseDramaJSONNormalizesStoryboard(t *testing.T) {
result, err := parseDramaJSON("<think>hidden</think>```json\n{\"entities\":{\"roles\":[{\"name\":\"林夏\",\"image_prompt\":\"二十五岁女性,黑色长发\"}]},\"storyboards\":[{\"content\":\"走进房间\",\"duration_seconds\":99}]}\n```")
if err != nil {
t.Fatalf("parseDramaJSON returned error: %v", err)
}
if len(result.Entities.Characters) != 1 || len(result.Storyboards) != 1 {
t.Fatalf("unexpected normalized result: %#v", result)
}
if result.Storyboards[0].ScriptContent != "走进房间" || result.Storyboards[0].DurationSeconds != 5 {
t.Fatalf("storyboard was not normalized: %#v", result.Storyboards[0])
}
if result.Entities.Characters[0].ImagePrompt != "二十五岁女性,黑色长发" {
t.Fatalf("asset image prompt was not preserved: %#v", result.Entities.Characters[0])
}
}
func TestEstimateTextTokens(t *testing.T) {
if estimateTextTokens("中文ABCD") != 3 {
t.Fatalf("unexpected token estimate")
}
}
func TestBuildDramaUserPromptUsesOnlyCurrentContext(t *testing.T) {
snapshot := dramaParseSnapshot{
ProjectName: "测试项目",
StyleName: "国风水墨",
EraType: "ancient_xianxia",
EpisodeNo: 4,
EpisodeName: "再入山门",
}
prompt := buildDramaUserPrompt(snapshot, "当前集正文", []map[string]any{{"name": "林夏"}})
for _, expected := range []string{
"视觉风格:国风水墨",
"故事时代:古代仙侠",
"项目资产:",
"林夏",
"当前原文:\n当前集正文",
"按上述视觉风格和故事时代解析角色、场景、道具及分镜",
} {
if !strings.Contains(prompt, expected) {
t.Fatalf("prompt does not contain %q: %s", expected, prompt)
}
}
for _, forbidden := range []string{"continuity", "解析分段", "前序"} {
if strings.Contains(prompt, forbidden) {
t.Fatalf("prompt contains forbidden content %q: %s", forbidden, prompt)
}
}
}
func TestDramaEraNameUsesCustomEra(t *testing.T) {
if got := dramaEraName("other", " 民国时期 "); got != "民国时期" {
t.Fatalf("unexpected custom era: %q", got)
}
}