test(acceptance): 在单窗口验证厂商额度峰值

厂商额度验收此前复用了多图与超大图容量素材,3 Worker 的下载和预处理使 24 个任务跨越多个固定分钟窗口,无法精确证明 RPM 与 TPM 上限。\n\n额度场景固定使用三张正常尺寸引用图并为每个任务增加唯一 URL 变体,使请求满足视频协议且能在单窗口完成;6、9 图和超大图转换继续由独立视频容量 profile 覆盖。\n\n验证:\n- go test ./cmd/acceptance-load ./internal/acceptanceworkload -count=1\n- go vet ./cmd/acceptance-load ./internal/acceptanceworkload\n- gofmt -l cmd/acceptance-load/main.go cmd/acceptance-load/main_test.go
This commit is contained in:
2026-08-03 13:04:03 +08:00
parent 76bb730b13
commit c9393af43a
2 changed files with 73 additions and 3 deletions
+48 -2
View File
@@ -640,6 +640,13 @@ func runVideo(
combinationCount = 1 combinationCount = 1
} }
combinations := videoCombinations(imageURLs, combinationCount) combinations := videoCombinations(imageURLs, combinationCount)
if name == "video-provider-quota" {
// The quota profile must complete in one fixed rate-limit window so
// RPM and TPM can be proven at their exact configured ceilings. Use
// three distinct normal-sized references per task; larger multi-image
// and oversized conversion remain covered by video capacity profiles.
combinations = videoProviderQuotaCombinations(imageURLs, combinationCount)
}
var taskIDs = make([]string, requestCount) var taskIDs = make([]string, requestCount)
latencies := make([]time.Duration, requestCount) latencies := make([]time.Duration, requestCount)
startedTasks := make([]time.Time, requestCount) startedTasks := make([]time.Time, requestCount)
@@ -658,7 +665,7 @@ func runVideo(
logicalIndex := requestOffset + index*requestStride logicalIndex := requestOffset + index*requestStride
requestStarted := time.Now() requestStarted := time.Now()
startedTasks[index] = requestStarted startedTasks[index] = requestStarted
imageCount := acceptanceworkload.VideoImageCount(logicalIndex) imageCount := videoImageCountForProfile(name, logicalIndex)
combo := append([]string(nil), combinations[logicalIndex%len(combinations)]...) combo := append([]string(nil), combinations[logicalIndex%len(combinations)]...)
if len(combo) > imageCount { if len(combo) > imageCount {
combo = combo[:imageCount] combo = combo[:imageCount]
@@ -784,6 +791,7 @@ func runVideo(
wg.Wait() wg.Wait()
uniqueImageCombinations := requestedVideoCombinationCount( uniqueImageCombinations := requestedVideoCombinationCount(
combinations, combinations,
name,
requestCount, requestCount,
requestOffset, requestOffset,
requestStride, requestStride,
@@ -1180,8 +1188,46 @@ func videoCombinations(images []string, count int) [][]string {
return out return out
} }
func videoProviderQuotaCombinations(images []string, count int) [][]string {
if len(images) == 0 || count <= 0 {
return nil
}
fixtureCount := min(len(images), 4)
if fixtureCount < 3 {
return nil
}
out := make([][]string, 0, count)
for index := 0; index < count; index++ {
combination := make([]string, 0, 3)
for imageIndex := 0; imageIndex < 3; imageIndex++ {
imageURL := images[(index+imageIndex)%fixtureCount]
separator := "?"
if strings.Contains(imageURL, "?") {
separator = "&"
}
combination = append(combination, fmt.Sprintf(
"%s%sacceptance_quota_variant=%d-%d",
imageURL,
separator,
index,
imageIndex,
))
}
out = append(out, combination)
}
return out
}
func videoImageCountForProfile(profile string, index int) int {
if profile == "video-provider-quota" {
return 3
}
return acceptanceworkload.VideoImageCount(index)
}
func requestedVideoCombinationCount( func requestedVideoCombinationCount(
combinations [][]string, combinations [][]string,
profile string,
requestCount int, requestCount int,
requestOffset int, requestOffset int,
requestStride int, requestStride int,
@@ -1195,7 +1241,7 @@ func requestedVideoCombinationCount(
seen := map[string]struct{}{} seen := map[string]struct{}{}
for index := 0; index < requestCount; index++ { for index := 0; index < requestCount; index++ {
logicalIndex := requestOffset + index*requestStride logicalIndex := requestOffset + index*requestStride
imageCount := acceptanceworkload.VideoImageCount(logicalIndex) imageCount := videoImageCountForProfile(profile, logicalIndex)
combo := combinations[logicalIndex%len(combinations)] combo := combinations[logicalIndex%len(combinations)]
if len(combo) > imageCount { if len(combo) > imageCount {
combo = combo[:imageCount] combo = combo[:imageCount]
+25 -1
View File
@@ -13,6 +13,7 @@ import (
"net/http/httptest" "net/http/httptest"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"sync/atomic" "sync/atomic"
"testing" "testing"
) )
@@ -172,11 +173,34 @@ func TestVideoCombinationsProvide128UniqueInputs(t *testing.T) {
if len(seen) != 128 { if len(seen) != 128 {
t.Fatalf("unique combinations=%d", len(seen)) t.Fatalf("unique combinations=%d", len(seen))
} }
if got := requestedVideoCombinationCount(combinations, 144, 0, 1); got != 131 { if got := requestedVideoCombinationCount(combinations, "video-capacity", 144, 0, 1); got != 131 {
t.Fatalf("requested combinations=%d, want 131", got) t.Fatalf("requested combinations=%d, want 131", got)
} }
} }
func TestVideoProviderQuotaCombinationsUseDistinctNormalSizedImages(t *testing.T) {
images := []string{
"https://fixtures.example/image-00.png",
"https://fixtures.example/image-01.png",
"https://fixtures.example/image-02.png",
"https://fixtures.example/image-03.png",
}
combinations := videoProviderQuotaCombinations(images, 24)
if got := requestedVideoCombinationCount(combinations, "video-provider-quota", 24, 0, 1); got != 24 {
t.Fatalf("quota combinations=%d, want 24", got)
}
for _, combination := range combinations {
if len(combination) != 3 {
t.Fatalf("invalid quota combination: %v", combination)
}
for _, imageURL := range combination {
if !strings.Contains(imageURL, "acceptance_quota_variant=") {
t.Fatalf("quota image lacks unique variant: %s", imageURL)
}
}
}
}
func TestGeminiLoadIsSplitAcrossTwoGatewayAPIs(t *testing.T) { func TestGeminiLoadIsSplitAcrossTwoGatewayAPIs(t *testing.T) {
output := paddedPNG(256 << 10) output := paddedPNG(256 << 10)
encoded := base64.StdEncoding.EncodeToString(output) encoded := base64.StdEncoding.EncodeToString(output)