From 0d33400e0987a0424866d67958c659ca9229d6f6 Mon Sep 17 00:00:00 2001 From: wangbo Date: Mon, 3 Aug 2026 10:45:09 +0800 Subject: [PATCH] =?UTF-8?q?test(acceptance):=20=E5=A2=9E=E5=8A=A0=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E5=AE=B9=E9=87=8F=E9=98=B6=E6=A2=AF=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 30 至 45 秒模拟上游等待的视频容量场景,使单 Worker 自适应控制在每级突发负载中获得连续占满窗口,同时保持提交、轮询、结果处理和回调全链路。\n\n未修改生产 Worker 和厂商限流逻辑。已执行完整 Go 测试、go vet、gofmt、bash -n、ShellCheck 和生产验收脚本测试。 --- apps/api/cmd/acceptance-load/main.go | 11 ++++++++++- apps/api/internal/acceptanceemulator/server.go | 15 +++++++++++++++ .../internal/acceptanceemulator/server_test.go | 14 ++++++++++++++ scripts/cluster/run-production-acceptance.sh | 2 +- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/apps/api/cmd/acceptance-load/main.go b/apps/api/cmd/acceptance-load/main.go index bb85519..b4b3335 100644 --- a/apps/api/cmd/acceptance-load/main.go +++ b/apps/api/cmd/acceptance-load/main.go @@ -279,7 +279,7 @@ func parseOptions() (options, error) { return options{}, errors.New("requests must be between 0 and 10000") } switch opts.profile { - case "simulated-smoke", "simulated-all", "gemini-baseline", "gemini-multi-image", "gemini-large", "gemini-peak", "video-throughput", "video-recovery", + case "simulated-smoke", "simulated-all", "gemini-baseline", "gemini-multi-image", "gemini-large", "gemini-peak", "video-throughput", "video-capacity", "video-recovery", "mixed-soak", "mixed-overload": if opts.emulatorURL == "" { return options{}, errors.New("AI_GATEWAY_ACCEPTANCE_EMULATOR_URL is required for simulated profiles") @@ -365,6 +365,12 @@ func run(ctx context.Context, opts options) ([]phaseResult, error) { requests = opts.requestCount } result = runVideo(ctx, client, opts, name, opts.shardRequestCount(requests), false, opts.emulatorFixtureURLs(), false, opts.shardIndex, opts.shardCount) + case "video-capacity": + requests := 1200 + if opts.requestCount > 0 { + requests = opts.requestCount + } + result = runVideo(ctx, client, opts, name, opts.shardRequestCount(requests), false, opts.emulatorFixtureURLs(), false, opts.shardIndex, opts.shardCount) case "video-recovery": result = runVideo(ctx, client, opts, name, opts.shardRequestCount(96), true, opts.emulatorFixtureURLs(), false, opts.shardIndex, opts.shardCount) case "mixed-soak", "mixed-overload": @@ -659,6 +665,9 @@ func runVideo( if longRun { prompt += " acceptance-long-recovery" } + if name == "video-capacity" { + prompt += " acceptance-capacity-ladder" + } if !realUpstream && logicalIndex%4 == 0 { prompt += " acceptance-force-conversion" } diff --git a/apps/api/internal/acceptanceemulator/server.go b/apps/api/internal/acceptanceemulator/server.go index 1f2e89a..d7aa913 100644 --- a/apps/api/internal/acceptanceemulator/server.go +++ b/apps/api/internal/acceptanceemulator/server.go @@ -674,9 +674,24 @@ func videoDelay(body map[string]any, longRun bool) time.Duration { if longRun { return 2*time.Minute + time.Duration(seed%61)*time.Second } + if videoPromptContains(body, "acceptance-capacity-ladder") { + return 30*time.Second + time.Duration(seed%16)*time.Second + } return 5*time.Second + time.Duration(seed%11)*time.Second } +func videoPromptContains(body map[string]any, marker string) bool { + content, _ := body["content"].([]any) + for _, raw := range content { + item, _ := raw.(map[string]any) + if strings.TrimSpace(stringValue(item["type"])) == "text" && + strings.Contains(strings.ToLower(stringValue(item["text"])), marker) { + return true + } + } + return false +} + func requestOrigin(r *http.Request) string { scheme := strings.TrimSpace(r.Header.Get("X-Forwarded-Proto")) if scheme == "" { diff --git a/apps/api/internal/acceptanceemulator/server_test.go b/apps/api/internal/acceptanceemulator/server_test.go index 6477365..48a3d54 100644 --- a/apps/api/internal/acceptanceemulator/server_test.go +++ b/apps/api/internal/acceptanceemulator/server_test.go @@ -228,6 +228,20 @@ func TestScaledDelayStaysOnWholeSecondsWithinProfile(t *testing.T) { } } +func TestVideoCapacityDelay(t *testing.T) { + body := map[string]any{ + "seed": json.Number("7"), + "content": []any{map[string]any{ + "type": "text", + "text": "capacity acceptance-capacity-ladder", + }}, + } + delay := videoDelay(body, false) + if delay < 30*time.Second || delay > 45*time.Second { + t.Fatalf("video capacity delay=%s, want 30s..45s", delay) + } +} + func TestVolcesProtocolAcceptsThreeSixAndNineReferenceImages(t *testing.T) { server := New(Config{Wait: func(context.Context, time.Duration) error { return nil }}) httpServer := httptest.NewServer(server.Handler()) diff --git a/scripts/cluster/run-production-acceptance.sh b/scripts/cluster/run-production-acceptance.sh index 21b86b8..c037bd6 100755 --- a/scripts/cluster/run-production-acceptance.sh +++ b/scripts/cluster/run-production-acceptance.sh @@ -3819,7 +3819,7 @@ run_single_node_acceptance() { apply_single_node_capacity "$slots" || break requests=$((slots * 3)) (( requests < 32 )) && requests=32 - if ! run_single_node_profile image-video video-throughput "$slots" "$requests"; then + if ! run_single_node_profile image-video video-capacity "$slots" "$requests"; then break fi single_node_stable_slots=$slots