添加配置生成、常量定义、测试设置、SSL 和 WebSocket 工具函数。 重构 container.go 支持函数式选项模式配置容器。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
105 lines
2.5 KiB
Go
105 lines
2.5 KiB
Go
//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
|
|
}
|