//go:build e2e // Package testutil 提供 E2E 测试的工具函数。 package testutil import ( "fmt" "io" "net/http" "sync" "testing" "time" ) // ConcurrentRequestConfig 并发请求配置。 type ConcurrentRequestConfig struct { URL string Count int Timeout time.Duration ExpectCode int Client *http.Client // 可选的自定义客户端 } // ConcurrentRequestResult 并发请求结果。 type ConcurrentRequestResult struct { Index int StatusCode int Error error } // RunConcurrentRequests 运行并发请求并返回结果。 // // 使用 sync.WaitGroup 实现真正的并发。 // 返回所有请求的结果,包括状态码和错误。 func RunConcurrentRequests(cfg ConcurrentRequestConfig) []ConcurrentRequestResult { results := make([]ConcurrentRequestResult, cfg.Count) var wg sync.WaitGroup client := cfg.Client if client == nil { client = &http.Client{ Timeout: cfg.Timeout, } } for i := 0; i < cfg.Count; i++ { wg.Add(1) go func(index int) { defer wg.Done() result := ConcurrentRequestResult{Index: index} resp, err := client.Get(cfg.URL) if err != nil { result.Error = fmt.Errorf("request %d failed: %w", index, err) results[index] = result return } // 读取并丢弃响应体,确保连接可复用 io.Copy(io.Discard, resp.Body) resp.Body.Close() result.StatusCode = resp.StatusCode results[index] = result }(i) } wg.Wait() return results } // VerifyConcurrentResults 验证并发请求结果。 // // 检查所有请求是否返回预期状态码。 // 返回失败的请求列表。 func VerifyConcurrentResults(t *testing.T, results []ConcurrentRequestResult, expectCode int) []ConcurrentRequestResult { var failures []ConcurrentRequestResult for _, r := range results { if r.Error != nil { t.Logf("Request %d error: %v", r.Index, r.Error) failures = append(failures, r) continue } if r.StatusCode != expectCode { t.Logf("Request %d: expected %d, got %d", r.Index, expectCode, r.StatusCode) failures = append(failures, r) } } return failures } // RunAndVerifyConcurrentRequests 运行并发请求并验证结果。 // // 组合 RunConcurrentRequests 和 VerifyConcurrentResults。 // 如果有任何失败,返回错误列表。 func RunAndVerifyConcurrentRequests(t *testing.T, cfg ConcurrentRequestConfig) []ConcurrentRequestResult { results := RunConcurrentRequests(cfg) failures := VerifyConcurrentResults(t, results, cfg.ExpectCode) return failures }