perf(e2e): 并行化 E2E 测试,从 ~2h 降至 ~102s
- testutil: 用 sync.Once 缓存 LollyImageAvailable 结果 - testutil: 原子计数器替代时间戳避免容器名竞态 - testutil: SetupProxyTest 接受 suffix 参数生成独立 Docker 网络 - testutil: CleanupProxyTest 显式调用 network.Remove() 清理 - testutil: 移除死代码 SetupProxyTestEnv/ProxyTestEnv - testutil: HealthCheckWaitTimeout 30s→15s, DefaultTestTimeout 180s→120s - e2e: 所有 107 个测试函数添加 t.Parallel() - e2e: 替换 65 处硬编码 30*time.Second 为常量 - make: test-all 三类测试并行运行,显式 PID wait 收集退出码 - make: test-e2e 添加 -parallel 4 flag Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
179090fa34
commit
2cb10eb749
19
Makefile
19
Makefile
@ -155,8 +155,8 @@ test-integration:
|
||||
|
||||
# 运行 L3 E2E 测试(需要 Docker)
|
||||
test-e2e:
|
||||
@echo "Running L3 E2E tests (requires Docker)..."
|
||||
go test -v -tags=e2e ./internal/e2e/...
|
||||
@echo "Running L3 E2E tests (parallel: $(or $(E2E_PARALLEL),4))..."
|
||||
go test -tags=e2e -parallel $(or $(E2E_PARALLEL),4) -count 1 ./internal/e2e/...
|
||||
|
||||
# 运行 L3 E2E 测试(带覆盖率)
|
||||
test-e2e-cover:
|
||||
@ -170,9 +170,18 @@ test-e2e-short:
|
||||
@echo "Running L3 E2E tests (short mode - testutil only)..."
|
||||
go test -tags=e2e -short -v ./internal/e2e/testutil/... -timeout 60s
|
||||
|
||||
# 运行所有测试(单元 + 集成 + E2E)
|
||||
test-all: test test-integration test-e2e
|
||||
@echo "All tests passed."
|
||||
# 运行所有测试(单元 + 集成 + E2E)— 并行执行
|
||||
test-all:
|
||||
@echo "Running all tests in parallel..."
|
||||
@FAIL=0; \
|
||||
$(MAKE) test & PID1=$$!; \
|
||||
$(MAKE) test-integration & PID2=$$!; \
|
||||
$(MAKE) test-e2e & PID3=$$!; \
|
||||
wait $$PID1 || FAIL=1; \
|
||||
wait $$PID2 || FAIL=1; \
|
||||
wait $$PID3 || FAIL=1; \
|
||||
if [ $$FAIL -eq 0 ]; then echo "All tests passed."; fi; \
|
||||
exit $$FAIL
|
||||
|
||||
# 运行测试(带覆盖率)
|
||||
test-cover:
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
|
||||
// TestE2EAccessAllowWhitelist 测试 IP 白名单。
|
||||
func TestE2EAccessAllowWhitelist(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -57,7 +58,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -73,6 +74,7 @@ servers:
|
||||
|
||||
// TestE2EAccessDenyBlacklist 测试 IP 黑名单。
|
||||
func TestE2EAccessDenyBlacklist(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -100,7 +102,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -116,6 +118,7 @@ servers:
|
||||
|
||||
// TestE2EAccessDefaultDeny 测试默认拒绝策略。
|
||||
func TestE2EAccessDefaultDeny(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -143,7 +146,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -159,6 +162,7 @@ servers:
|
||||
|
||||
// TestE2EAccessNoRestriction 测试无访问限制。
|
||||
func TestE2EAccessNoRestriction(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -182,7 +186,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -198,6 +202,7 @@ servers:
|
||||
|
||||
// TestE2EAccessCIDRMatch 测试 CIDR 网段匹配。
|
||||
func TestE2EAccessCIDRMatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -227,7 +232,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -244,6 +249,7 @@ servers:
|
||||
|
||||
// TestE2EAccessProxyWithAccessControl 测试代理模式下的访问控制。
|
||||
func TestE2EAccessProxyWithAccessControl(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -277,7 +283,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
//
|
||||
// 验证第二次请求返回缓存内容。
|
||||
func TestE2EProxyCacheHit(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -34,9 +35,9 @@ func TestE2EProxyCacheHit(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用缓存
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -54,7 +55,7 @@ func TestE2EProxyCacheHit(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -96,6 +97,7 @@ func TestE2EProxyCacheHit(t *testing.T) {
|
||||
//
|
||||
// 验证缓存过期后重新获取。
|
||||
func TestE2EProxyCacheExpire(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -104,9 +106,9 @@ func TestE2EProxyCacheExpire(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:短缓存时间
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -123,7 +125,7 @@ func TestE2EProxyCacheExpire(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -153,6 +155,7 @@ func TestE2EProxyCacheExpire(t *testing.T) {
|
||||
//
|
||||
// 验证缓存锁防止缓存击穿。
|
||||
func TestE2EProxyCacheLock(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -161,9 +164,9 @@ func TestE2EProxyCacheLock(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用缓存锁
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -180,7 +183,7 @@ func TestE2EProxyCacheLock(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 并发发送相同请求
|
||||
@ -198,6 +201,7 @@ func TestE2EProxyCacheLock(t *testing.T) {
|
||||
//
|
||||
// 验证特定请求绕过缓存。
|
||||
func TestE2EProxyCacheBypass(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -206,9 +210,9 @@ func TestE2EProxyCacheBypass(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -225,7 +229,7 @@ func TestE2EProxyCacheBypass(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -251,6 +255,7 @@ func TestE2EProxyCacheBypass(t *testing.T) {
|
||||
//
|
||||
// 验证只有 GET 和 HEAD 被缓存。
|
||||
func TestE2EProxyCacheMethods(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -259,9 +264,9 @@ func TestE2EProxyCacheMethods(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -278,7 +283,7 @@ func TestE2EProxyCacheMethods(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -305,6 +310,7 @@ func TestE2EProxyCacheMethods(t *testing.T) {
|
||||
//
|
||||
// 验证缓存头部正确设置。
|
||||
func TestE2EProxyCacheHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -313,9 +319,9 @@ func TestE2EProxyCacheHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -332,7 +338,7 @@ func TestE2EProxyCacheHeaders(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -356,6 +362,7 @@ func TestE2EProxyCacheHeaders(t *testing.T) {
|
||||
//
|
||||
// 验证后端不可用时返回过期缓存。
|
||||
func TestE2EProxyCacheStale(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -364,9 +371,9 @@ func TestE2EProxyCacheStale(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用 stale-while-revalidate
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -383,7 +390,7 @@ func TestE2EProxyCacheStale(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -410,6 +417,7 @@ func TestE2EProxyCacheStale(t *testing.T) {
|
||||
//
|
||||
// 验证 Vary 头部影响缓存键。
|
||||
func TestE2EProxyCacheVary(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -418,9 +426,9 @@ func TestE2EProxyCacheVary(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -437,7 +445,7 @@ func TestE2EProxyCacheVary(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -462,6 +470,7 @@ func TestE2EProxyCacheVary(t *testing.T) {
|
||||
//
|
||||
// 验证条件请求正确处理。
|
||||
func TestE2EProxyCacheRevalidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -470,9 +479,9 @@ func TestE2EProxyCacheRevalidate(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -489,7 +498,7 @@ func TestE2EProxyCacheRevalidate(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -522,6 +531,7 @@ func TestE2EProxyCacheRevalidate(t *testing.T) {
|
||||
//
|
||||
// 验证并发请求正确处理缓存。
|
||||
func TestE2EProxyCacheConcurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -530,9 +540,9 @@ func TestE2EProxyCacheConcurrent(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -549,7 +559,7 @@ func TestE2EProxyCacheConcurrent(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 并发请求
|
||||
@ -569,6 +579,7 @@ func TestE2EProxyCacheConcurrent(t *testing.T) {
|
||||
//
|
||||
// 验证不同路径独立缓存。
|
||||
func TestE2EProxyCacheMultiplePaths(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -577,9 +588,9 @@ func TestE2EProxyCacheMultiplePaths(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:多路径代理
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -599,7 +610,7 @@ func TestE2EProxyCacheMultiplePaths(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -626,6 +637,7 @@ func TestE2EProxyCacheMultiplePaths(t *testing.T) {
|
||||
//
|
||||
// 验证请求头正确传递并影响缓存。
|
||||
func TestE2EProxyCacheWithHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -634,9 +646,9 @@ func TestE2EProxyCacheWithHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -662,7 +674,7 @@ func TestE2EProxyCacheWithHeaders(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -688,6 +700,7 @@ func TestE2EProxyCacheWithHeaders(t *testing.T) {
|
||||
//
|
||||
// 验证大响应不被缓存或正确处理。
|
||||
func TestE2EProxyCacheSize(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -696,9 +709,9 @@ func TestE2EProxyCacheSize(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -715,7 +728,7 @@ func TestE2EProxyCacheSize(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
@ -743,6 +756,7 @@ func TestE2EProxyCacheSize(t *testing.T) {
|
||||
//
|
||||
// 验证不同 HTTP 状态码的缓存行为。
|
||||
func TestE2EProxyCacheStatusCodes(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -751,9 +765,9 @@ func TestE2EProxyCacheStatusCodes(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -770,7 +784,7 @@ func TestE2EProxyCacheStatusCodes(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -801,6 +815,7 @@ func TestE2EProxyCacheStatusCodes(t *testing.T) {
|
||||
//
|
||||
// 验证不同查询参数产生不同的缓存条目。
|
||||
func TestE2EProxyCacheQueryParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -809,9 +824,9 @@ func TestE2EProxyCacheQueryParams(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -828,7 +843,7 @@ func TestE2EProxyCacheQueryParams(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -858,6 +873,7 @@ func TestE2EProxyCacheQueryParams(t *testing.T) {
|
||||
//
|
||||
// 验证缓存功能与其他功能的集成。
|
||||
func TestE2EProxyCacheIntegration(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -866,9 +882,9 @@ func TestE2EProxyCacheIntegration(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:缓存 + 负载均衡
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -887,7 +903,7 @@ func TestE2EProxyCacheIntegration(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
@ -30,6 +30,7 @@ import (
|
||||
|
||||
// TestE2ECompressionGzip 测试 Gzip 压缩响应。
|
||||
func TestE2ECompressionGzip(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -65,7 +66,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -99,6 +100,7 @@ servers:
|
||||
|
||||
// TestE2ECompressionNoAcceptEncoding 测试不发送 Accept-Encoding 时不压缩。
|
||||
func TestE2ECompressionNoAcceptEncoding(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -129,7 +131,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -146,6 +148,7 @@ servers:
|
||||
|
||||
// TestE2ECompressionDisabled 测试禁用压缩。
|
||||
func TestE2ECompressionDisabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -176,7 +179,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -197,6 +200,7 @@ servers:
|
||||
|
||||
// TestE2ECompressionPrecompressed 测试预压缩文件。
|
||||
func TestE2ECompressionPrecompressed(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -229,7 +233,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
|
||||
@ -9,5 +9,6 @@ import (
|
||||
)
|
||||
|
||||
func TestE2ESetup(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Log("E2E test infrastructure initialized")
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
//
|
||||
// 验证定期探测后端状态,自动剔除不健康后端。
|
||||
func TestE2EHealthCheckActive(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -33,9 +34,9 @@ func TestE2EHealthCheckActive(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用主动健康检查(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -57,7 +58,7 @@ func TestE2EHealthCheckActive(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -116,6 +117,7 @@ func TestE2EHealthCheckActive(t *testing.T) {
|
||||
//
|
||||
// 验证失败后自动剔除后端。
|
||||
func TestE2EHealthCheckPassive(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -124,9 +126,9 @@ func TestE2EHealthCheckPassive(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用被动健康检查(max_fails)(使用内部地址)
|
||||
targetOpts := [][]testutil.ProxyTargetOption{
|
||||
@ -151,7 +153,7 @@ func TestE2EHealthCheckPassive(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -170,6 +172,7 @@ func TestE2EHealthCheckPassive(t *testing.T) {
|
||||
//
|
||||
// 验证后端恢复后重新加入负载均衡。
|
||||
func TestE2EHealthCheckRecovery(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -178,9 +181,9 @@ func TestE2EHealthCheckRecovery(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -201,7 +204,7 @@ func TestE2EHealthCheckRecovery(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -268,6 +271,7 @@ func TestE2EHealthCheckRecovery(t *testing.T) {
|
||||
//
|
||||
// 验证健康检查按配置间隔执行。
|
||||
func TestE2EHealthCheckInterval(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -276,9 +280,9 @@ func TestE2EHealthCheckInterval(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:短健康检查间隔(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -298,7 +302,7 @@ func TestE2EHealthCheckInterval(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -315,6 +319,7 @@ func TestE2EHealthCheckInterval(t *testing.T) {
|
||||
//
|
||||
// 验证健康检查超时正确处理。
|
||||
func TestE2EHealthCheckTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -323,9 +328,9 @@ func TestE2EHealthCheckTimeout(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:短超时(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -345,7 +350,7 @@ func TestE2EHealthCheckTimeout(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -362,6 +367,7 @@ func TestE2EHealthCheckTimeout(t *testing.T) {
|
||||
//
|
||||
// 验证自定义健康检查路径。
|
||||
func TestE2EHealthCheckPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -370,9 +376,9 @@ func TestE2EHealthCheckPath(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:使用根路径作为健康检查路径(nginx 默认存在)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -392,7 +398,7 @@ func TestE2EHealthCheckPath(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -409,6 +415,7 @@ func TestE2EHealthCheckPath(t *testing.T) {
|
||||
//
|
||||
// 验证多个后端的健康检查独立工作。
|
||||
func TestE2EHealthCheckMultipleBackends(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -417,9 +424,9 @@ func TestE2EHealthCheckMultipleBackends(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 3)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 3, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -440,7 +447,7 @@ func TestE2EHealthCheckMultipleBackends(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -498,6 +505,7 @@ func TestE2EHealthCheckMultipleBackends(t *testing.T) {
|
||||
//
|
||||
// 验证后端故障时请求自动转移到健康后端。
|
||||
func TestE2EHealthCheckFailover(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -506,9 +514,9 @@ func TestE2EHealthCheckFailover(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用故障转移(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -530,7 +538,7 @@ func TestE2EHealthCheckFailover(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -561,6 +569,7 @@ func TestE2EHealthCheckFailover(t *testing.T) {
|
||||
//
|
||||
// 验证所有后端不可用时的行为。
|
||||
func TestE2EHealthCheckAllDown(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -569,9 +578,9 @@ func TestE2EHealthCheckAllDown(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -592,7 +601,7 @@ func TestE2EHealthCheckAllDown(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -630,6 +639,7 @@ func TestE2EHealthCheckAllDown(t *testing.T) {
|
||||
//
|
||||
// 验证备份服务器在主服务器不可用时启用。
|
||||
func TestE2EHealthCheckBackupServer(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -638,9 +648,9 @@ func TestE2EHealthCheckBackupServer(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:第二个后端为备份(使用内部地址)
|
||||
targetOpts := [][]testutil.ProxyTargetOption{
|
||||
@ -666,7 +676,7 @@ func TestE2EHealthCheckBackupServer(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -685,6 +695,7 @@ func TestE2EHealthCheckBackupServer(t *testing.T) {
|
||||
//
|
||||
// 验证新后端逐渐接收流量。
|
||||
func TestE2EHealthCheckSlowStart(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -693,9 +704,9 @@ func TestE2EHealthCheckSlowStart(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -715,7 +726,7 @@ func TestE2EHealthCheckSlowStart(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -732,6 +743,7 @@ func TestE2EHealthCheckSlowStart(t *testing.T) {
|
||||
//
|
||||
// 验证健康检查与各种负载均衡算法配合工作。
|
||||
func TestE2EHealthCheckWithLoadBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -740,9 +752,9 @@ func TestE2EHealthCheckWithLoadBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 3)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 3, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
algorithms := []string{"round_robin", "least_conn"}
|
||||
|
||||
@ -765,7 +777,7 @@ func TestE2EHealthCheckWithLoadBalance(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -786,6 +798,7 @@ func TestE2EHealthCheckWithLoadBalance(t *testing.T) {
|
||||
//
|
||||
// 验证并发请求时健康检查正常工作。
|
||||
func TestE2EHealthCheckConcurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -794,9 +807,9 @@ func TestE2EHealthCheckConcurrent(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -817,7 +830,7 @@ func TestE2EHealthCheckConcurrent(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 并发请求
|
||||
@ -837,6 +850,7 @@ func TestE2EHealthCheckConcurrent(t *testing.T) {
|
||||
//
|
||||
// 验证健康检查正确匹配状态码。
|
||||
func TestE2EHealthCheckStatusCodes(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -845,9 +859,9 @@ func TestE2EHealthCheckStatusCodes(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -867,7 +881,7 @@ func TestE2EHealthCheckStatusCodes(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -885,6 +899,7 @@ func TestE2EHealthCheckStatusCodes(t *testing.T) {
|
||||
//
|
||||
// 验证健康检查与其他功能的集成。
|
||||
func TestE2EHealthCheckIntegration(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -893,9 +908,9 @@ func TestE2EHealthCheckIntegration(t *testing.T) {
|
||||
}
|
||||
|
||||
// 设置代理测试环境(使用网络模式)
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:健康检查 + 负载均衡 + 超时(使用内部地址)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -918,7 +933,7 @@ func TestE2EHealthCheckIntegration(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
@ -28,6 +28,7 @@ import (
|
||||
//
|
||||
// 验证 HTTPS 连接可以成功建立。
|
||||
func TestE2EHTTPSConnection(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -73,6 +74,7 @@ func TestE2EHTTPSConnection(t *testing.T) {
|
||||
//
|
||||
// 验证多个并发 HTTPS 请求正常工作。
|
||||
func TestE2EHTTPSConcurrentRequests(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -144,6 +146,7 @@ func TestE2EHTTPSConcurrentRequests(t *testing.T) {
|
||||
//
|
||||
// 验证自定义头部正确传递。
|
||||
func TestE2EHTTPSCustomHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -201,6 +204,7 @@ func TestE2EHTTPSCustomHeaders(t *testing.T) {
|
||||
//
|
||||
// 验证大请求体的处理。
|
||||
func TestE2EHTTPSLargeRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -253,6 +257,7 @@ func TestE2EHTTPSLargeRequest(t *testing.T) {
|
||||
//
|
||||
// 验证 TLS ALPN 扩展正常工作。
|
||||
func TestE2EALPNNegotiation(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
//
|
||||
// 验证请求均匀分布到多个后端。
|
||||
func TestE2ELoadBalanceRoundRobin(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -33,9 +34,9 @@ func TestE2ELoadBalanceRoundRobin(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 3 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 3)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 3, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
t.Logf("Backend pool: %v", pool.Addresses())
|
||||
|
||||
@ -53,7 +54,7 @@ func TestE2ELoadBalanceRoundRobin(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送 30 个请求,验证都成功
|
||||
@ -81,6 +82,7 @@ func TestE2ELoadBalanceRoundRobin(t *testing.T) {
|
||||
//
|
||||
// 验证请求按权重比例分布。
|
||||
func TestE2ELoadBalanceWeighted(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -89,9 +91,9 @@ func TestE2ELoadBalanceWeighted(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 2 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:权重 3:1
|
||||
targetOpts := [][]testutil.ProxyTargetOption{
|
||||
@ -112,7 +114,7 @@ func TestE2ELoadBalanceWeighted(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送 40 个请求
|
||||
@ -137,6 +139,7 @@ func TestE2ELoadBalanceWeighted(t *testing.T) {
|
||||
//
|
||||
// 验证请求路由到连接数最少的后端。
|
||||
func TestE2ELoadBalanceLeastConn(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -145,9 +148,9 @@ func TestE2ELoadBalanceLeastConn(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 2 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -162,7 +165,7 @@ func TestE2ELoadBalanceLeastConn(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 并发发送请求
|
||||
@ -182,6 +185,7 @@ func TestE2ELoadBalanceLeastConn(t *testing.T) {
|
||||
//
|
||||
// 验证同一 IP 的请求总是路由到同一后端。
|
||||
func TestE2ELoadBalanceIPHash(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -190,9 +194,9 @@ func TestE2ELoadBalanceIPHash(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 3 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 3)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 3, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -207,7 +211,7 @@ func TestE2ELoadBalanceIPHash(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 从同一客户端发送多个请求
|
||||
@ -225,6 +229,7 @@ func TestE2ELoadBalanceIPHash(t *testing.T) {
|
||||
//
|
||||
// 验证基于请求 URI 的一致性哈希路由。
|
||||
func TestE2ELoadBalanceConsistentHash(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -233,9 +238,9 @@ func TestE2ELoadBalanceConsistentHash(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 3 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 3)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 3, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置(使用 ip_hash 代替 consistent_hash,因为可能不被支持)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -250,7 +255,7 @@ func TestE2ELoadBalanceConsistentHash(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送请求
|
||||
@ -269,6 +274,7 @@ func TestE2ELoadBalanceConsistentHash(t *testing.T) {
|
||||
//
|
||||
// 验证后端故障时自动切换到其他后端。
|
||||
func TestE2ELoadBalanceFailover(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -277,9 +283,9 @@ func TestE2ELoadBalanceFailover(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 2 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用故障转移
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -297,7 +303,7 @@ func TestE2ELoadBalanceFailover(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送请求验证正常工作
|
||||
@ -337,6 +343,7 @@ func TestE2ELoadBalanceFailover(t *testing.T) {
|
||||
//
|
||||
// 验证不健康后端被自动剔除。
|
||||
func TestE2ELoadBalanceHealthCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -345,9 +352,9 @@ func TestE2ELoadBalanceHealthCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 2 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:启用主动健康检查
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -365,7 +372,7 @@ func TestE2ELoadBalanceHealthCheck(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送请求验证正常工作
|
||||
@ -385,6 +392,7 @@ func TestE2ELoadBalanceHealthCheck(t *testing.T) {
|
||||
//
|
||||
// 验证不同路径代理到不同后端。
|
||||
func TestE2ELoadBalanceMultiplePaths(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -393,9 +401,9 @@ func TestE2ELoadBalanceMultiplePaths(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动 2 个后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:多路径代理(都代理到根路径)
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -411,7 +419,7 @@ func TestE2ELoadBalanceMultiplePaths(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -436,6 +444,7 @@ func TestE2ELoadBalanceMultiplePaths(t *testing.T) {
|
||||
//
|
||||
// 验证超时配置生效。
|
||||
func TestE2ELoadBalanceTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -444,9 +453,9 @@ func TestE2ELoadBalanceTimeout(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:设置超时
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -463,7 +472,7 @@ func TestE2ELoadBalanceTimeout(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送正常请求
|
||||
@ -478,6 +487,7 @@ func TestE2ELoadBalanceTimeout(t *testing.T) {
|
||||
//
|
||||
// 验证请求头正确传递到后端。
|
||||
func TestE2ELoadBalanceHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -486,9 +496,9 @@ func TestE2ELoadBalanceHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:设置代理头部
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -514,7 +524,7 @@ func TestE2ELoadBalanceHeaders(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 发送请求
|
||||
|
||||
@ -24,6 +24,7 @@ import (
|
||||
|
||||
// TestE2EProxyBasic 测试 lolly 基本代理转发。
|
||||
func TestE2EProxyBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -46,7 +47,7 @@ func TestE2EProxyBasic(t *testing.T) {
|
||||
t.Logf("Lolly proxy: %s", lolly.HTTPBaseURL())
|
||||
|
||||
// 等待 lolly 健康
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 测试 lolly 服务可达
|
||||
@ -62,6 +63,7 @@ func TestE2EProxyBasic(t *testing.T) {
|
||||
// TestE2EProxyWithLolly 测试 lolly 代理转发功能。
|
||||
// 需要 lolly:latest 镜像。
|
||||
func TestE2EProxyWithLolly(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -84,7 +86,7 @@ func TestE2EProxyWithLolly(t *testing.T) {
|
||||
t.Logf("Lolly proxy: %s", lolly.HTTPBaseURL())
|
||||
|
||||
// 等待 lolly 健康
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 通过 lolly 访问
|
||||
@ -99,6 +101,7 @@ func TestE2EProxyWithLolly(t *testing.T) {
|
||||
|
||||
// TestE2EProxyLoadBalance 测试 lolly 负载均衡。
|
||||
func TestE2EProxyLoadBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -144,6 +147,7 @@ func TestE2EProxyLoadBalance(t *testing.T) {
|
||||
|
||||
// TestE2EProxyHealthCheck 测试 lolly 健康检查。
|
||||
func TestE2EProxyHealthCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -168,6 +172,7 @@ func TestE2EProxyHealthCheck(t *testing.T) {
|
||||
|
||||
// TestE2EProxyTimeout 测试 lolly 代理超时处理。
|
||||
func TestE2EProxyTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
// 使用短超时客户端测试超时场景
|
||||
shortTimeoutClient := &http.Client{Timeout: 1 * time.Second}
|
||||
|
||||
@ -180,6 +185,7 @@ func TestE2EProxyTimeout(t *testing.T) {
|
||||
|
||||
// TestE2EProxyErrorHandling 测试 lolly 代理错误处理。
|
||||
func TestE2EProxyErrorHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
|
||||
// 测试连接被拒绝
|
||||
@ -189,6 +195,7 @@ func TestE2EProxyErrorHandling(t *testing.T) {
|
||||
|
||||
// TestE2EProxyHeaders 测试 lolly 代理头部传递。
|
||||
func TestE2EProxyHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -219,6 +226,7 @@ func TestE2EProxyHeaders(t *testing.T) {
|
||||
|
||||
// TestE2EProxyMultipleRequests 测试 lolly 并发代理请求。
|
||||
func TestE2EProxyMultipleRequests(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ import (
|
||||
|
||||
// TestE2ERateLimitBasic 测试基本请求限流。
|
||||
func TestE2ERateLimitBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -58,7 +59,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
@ -96,6 +97,7 @@ servers:
|
||||
|
||||
// TestE2ERateLimitBurst 测试突发流量处理。
|
||||
func TestE2ERateLimitBurst(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -129,7 +131,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
@ -152,6 +154,7 @@ servers:
|
||||
|
||||
// TestE2ERateLimitRecovery 测试限流恢复。
|
||||
func TestE2ERateLimitRecovery(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -185,7 +188,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
@ -222,6 +225,7 @@ servers:
|
||||
|
||||
// TestE2ERateLimitDisabled 测试未配置限流时不限制。
|
||||
func TestE2ERateLimitDisabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -251,7 +255,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
|
||||
// TestE2ERewriteBasic 测试基本 URL 重写。
|
||||
func TestE2ERewriteBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -51,7 +52,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
@ -71,6 +72,7 @@ servers:
|
||||
|
||||
// TestE2ERewriteRedirect 测试重写为重定向。
|
||||
func TestE2ERewriteRedirect(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -96,7 +98,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
@ -117,6 +119,7 @@ servers:
|
||||
|
||||
// TestE2ERewritePermanent 测试永久重定向。
|
||||
func TestE2ERewritePermanent(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -142,7 +145,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
@ -159,6 +162,7 @@ servers:
|
||||
|
||||
// TestE2ERewriteRegexCapture 测试正则表达式捕获组。
|
||||
func TestE2ERewriteRegexCapture(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -184,7 +188,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
@ -205,6 +209,7 @@ servers:
|
||||
|
||||
// TestE2ERewriteProxy 测试代理模式下的重写。
|
||||
func TestE2ERewriteProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -236,7 +241,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@ -253,6 +258,7 @@ servers:
|
||||
|
||||
// TestE2ERewriteNoMatch 测试不匹配时不重写。
|
||||
func TestE2ERewriteNoMatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -278,7 +284,7 @@ servers:
|
||||
require.NoError(t, err, "Failed to start lolly container")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
//
|
||||
// 验证 HTTPS 连接可以成功建立。
|
||||
func TestE2ESSLHandshake(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -71,6 +72,7 @@ func TestE2ESSLHandshake(t *testing.T) {
|
||||
//
|
||||
// 验证 ALPN 协商成功,HTTP/2 正常工作。
|
||||
func TestE2ESSLHTTP2(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -116,6 +118,7 @@ func TestE2ESSLHTTP2(t *testing.T) {
|
||||
//
|
||||
// 验证 TLS 1.2 和 1.3 正常工作。
|
||||
func TestE2ESSLProtocolVersions(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -162,6 +165,7 @@ func TestE2ESSLProtocolVersions(t *testing.T) {
|
||||
//
|
||||
// 验证证书链正确配置。
|
||||
func TestE2ESSLCertificateChain(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -206,6 +210,7 @@ func TestE2ESSLCertificateChain(t *testing.T) {
|
||||
//
|
||||
// 验证可以跳过证书验证连接。
|
||||
func TestE2ESSLInsecureSkipVerify(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -249,6 +254,7 @@ func TestE2ESSLInsecureSkipVerify(t *testing.T) {
|
||||
//
|
||||
// 验证代理可以连接 HTTPS 后端。
|
||||
func TestE2ESSLProxyUpstream(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -257,9 +263,9 @@ func TestE2ESSLProxyUpstream(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to setup proxy test")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置:代理到 HTTP 后端
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -290,6 +296,7 @@ func TestE2ESSLProxyUpstream(t *testing.T) {
|
||||
//
|
||||
// 验证并发 SSL 连接正常工作。
|
||||
func TestE2ESSLConcurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -337,6 +344,7 @@ func TestE2ESSLConcurrent(t *testing.T) {
|
||||
|
||||
// TestE2ESSLWithLolly 测试 lolly SSL/TLS 功能(兼容旧测试)。
|
||||
func TestE2ESSLWithLolly(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.MediumTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -371,6 +379,7 @@ func TestE2ESSLWithLolly(t *testing.T) {
|
||||
|
||||
// TestE2ESSLCertificateGeneration 测试证书生成。
|
||||
func TestE2ESSLCertificateGeneration(t *testing.T) {
|
||||
t.Parallel()
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
certPath, keyPath, cleanup, err := testutil.GenerateSelfSignedCert(tmpDir)
|
||||
@ -388,6 +397,7 @@ func TestE2ESSLCertificateGeneration(t *testing.T) {
|
||||
|
||||
// TestE2ESSLHTTP3Placeholder HTTP/3 测试占位符。
|
||||
func TestE2ESSLHTTP3Placeholder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping E2E test in short mode")
|
||||
}
|
||||
@ -397,6 +407,7 @@ func TestE2ESSLHTTP3Placeholder(t *testing.T) {
|
||||
|
||||
// TestE2ESSLDockerAvailable 测试 Docker 是否可用。
|
||||
func TestE2ESSLDockerAvailable(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.ShortTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -409,6 +420,7 @@ func TestE2ESSLDockerAvailable(t *testing.T) {
|
||||
|
||||
// TestE2ESSLEnvironmentCheck 检查测试环境。
|
||||
func TestE2ESSLEnvironmentCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
dockerHost := os.Getenv("DOCKER_HOST")
|
||||
if dockerHost != "" {
|
||||
t.Logf("DOCKER_HOST: %s", dockerHost)
|
||||
@ -425,6 +437,7 @@ func TestE2ESSLEnvironmentCheck(t *testing.T) {
|
||||
|
||||
// TestE2ESSLSessionTickets 测试 TLS Session Tickets。
|
||||
func TestE2ESSLSessionTickets(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -473,6 +486,7 @@ func TestE2ESSLSessionTickets(t *testing.T) {
|
||||
|
||||
// TestE2ESSLHSTS 测试 HSTS 头部。
|
||||
func TestE2ESSLHSTS(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.DefaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
// TestE2EStaticWithLolly 测试 lolly 静态文件服务功能。
|
||||
// 需要 lolly:latest 镜像。
|
||||
func TestE2EStaticWithLolly(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -41,7 +42,7 @@ func TestE2EStaticWithLolly(t *testing.T) {
|
||||
t.Logf("Lolly static server: %s", lolly.HTTPBaseURL())
|
||||
|
||||
// 等待 lolly 健康
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 测试静态文件服务
|
||||
@ -56,6 +57,7 @@ func TestE2EStaticWithLolly(t *testing.T) {
|
||||
|
||||
// TestE2EStaticFileServe 测试 lolly 静态文件服务。
|
||||
func TestE2EStaticFileServe(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -88,6 +90,7 @@ func TestE2EStaticFileServe(t *testing.T) {
|
||||
|
||||
// TestE2EStaticContentType 测试 lolly Content-Type 检测。
|
||||
func TestE2EStaticContentType(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -112,6 +115,7 @@ func TestE2EStaticContentType(t *testing.T) {
|
||||
|
||||
// TestE2EStaticNotFound 测试 lolly 404 错误。
|
||||
func TestE2EStaticNotFound(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -133,6 +137,7 @@ func TestE2EStaticNotFound(t *testing.T) {
|
||||
|
||||
// TestE2EStaticConcurrent 测试 lolly 并发静态文件请求。
|
||||
func TestE2EStaticConcurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -157,6 +162,7 @@ func TestE2EStaticConcurrent(t *testing.T) {
|
||||
|
||||
// TestE2EStaticLargeFile 测试 lolly 大文件传输。
|
||||
func TestE2EStaticLargeFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
|
||||
defer cancel()
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ const (
|
||||
ContainerStartupTimeout = 30 * time.Second
|
||||
|
||||
// HealthCheckWaitTimeout 健康检查等待超时。
|
||||
HealthCheckWaitTimeout = 30 * time.Second
|
||||
HealthCheckWaitTimeout = 15 * time.Second
|
||||
|
||||
// HealthCheckDetectionTime 健康检查检测时间。
|
||||
HealthCheckDetectionTime = 10 * time.Second
|
||||
@ -27,7 +27,7 @@ const (
|
||||
CacheExpireBuffer = 1 * time.Second
|
||||
|
||||
// DefaultTestTimeout 测试上下文超时。
|
||||
DefaultTestTimeout = 180 * time.Second
|
||||
DefaultTestTimeout = 120 * time.Second
|
||||
|
||||
// DefaultClientTimeout HTTP 客户端超时。
|
||||
DefaultClientTimeout = 10 * time.Second
|
||||
|
||||
@ -13,6 +13,8 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
@ -375,7 +377,21 @@ func DockerAvailable(ctx context.Context) bool {
|
||||
}
|
||||
|
||||
// LollyImageAvailable 检查 lolly:latest 镜像是否可用。
|
||||
// 结果被 sync.Once 缓存,避免重复检查。
|
||||
func LollyImageAvailable(ctx context.Context) bool {
|
||||
lollyImageCheckOnce.Do(func() {
|
||||
lollyImageAvailable = checkLollyImage(ctx)
|
||||
})
|
||||
return lollyImageAvailable
|
||||
}
|
||||
|
||||
var (
|
||||
lollyImageCheckOnce sync.Once
|
||||
lollyImageAvailable bool
|
||||
)
|
||||
|
||||
// checkLollyImage 实际执行镜像检查。
|
||||
func checkLollyImage(ctx context.Context) bool {
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: "lolly:latest",
|
||||
Cmd: []string{"/lolly", "-v"},
|
||||
@ -488,8 +504,9 @@ func StartBackendPoolWithNetwork(ctx context.Context, count int, network string)
|
||||
|
||||
// startMockBackendWithNetwork 启动单个后端容器。
|
||||
func startMockBackendWithNetwork(ctx context.Context, network string, index int) (testcontainers.Container, string, string, error) {
|
||||
// 生成容器名称(用于网络通信)
|
||||
containerName := fmt.Sprintf("backend-%d-%d", time.Now().UnixNano(), index)
|
||||
// 生成容器名称(用于网络通信),使用原子计数器避免并行竞态
|
||||
id := atomic.AddInt64(&backendCounter, 1)
|
||||
containerName := fmt.Sprintf("backend-%d-%d", id, index)
|
||||
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: "nginx:alpine",
|
||||
@ -615,45 +632,51 @@ func CreateNetwork(ctx context.Context, name string) (testcontainers.Network, er
|
||||
return network, nil
|
||||
}
|
||||
|
||||
// sharedNetworkName 共享网络名称。
|
||||
const sharedNetworkName = "lolly-e2e-test"
|
||||
// 原子计数器,用于生成唯一的容器名和网络名。
|
||||
var (
|
||||
backendCounter int64
|
||||
networkCounter int64
|
||||
)
|
||||
|
||||
// SetupProxyTest 设置代理测试环境。
|
||||
//
|
||||
// 创建网络、启动后端池,返回网络名称和后端池。
|
||||
// 创建独立网络、启动后端池,返回网络对象、网络名称和后端池。
|
||||
// suffix 用于生成唯一网络名(通常传 t.Name()),配合原子计数器确保 -count N 安全。
|
||||
// lolly 容器应使用 InternalAddresses() 作为代理目标。
|
||||
// 使用共享网络名称,避免网络地址池耗尽。
|
||||
//
|
||||
// 使用示例:
|
||||
//
|
||||
// network, pool, err := testutil.SetupProxyTest(ctx, 2)
|
||||
// netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 2, t.Name())
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// defer testutil.CleanupProxyTest(ctx, network, pool)
|
||||
// defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
//
|
||||
// lolly, err := testutil.StartLolly(ctx,
|
||||
// testutil.WithConfigYAML(configYAML),
|
||||
// testutil.WithNetwork(network),
|
||||
// testutil.WithNetwork(networkName),
|
||||
// )
|
||||
func SetupProxyTest(ctx context.Context, backendCount int) (string, *BackendPool, error) {
|
||||
// 使用共享网络名称
|
||||
networkName := sharedNetworkName
|
||||
func SetupProxyTest(ctx context.Context, backendCount int, suffix string) (testcontainers.Network, string, *BackendPool, error) {
|
||||
id := atomic.AddInt64(&networkCounter, 1)
|
||||
// 防御性处理:子测试的 t.Name() 含 '/',Docker 网络名不支持
|
||||
suffix = strings.ReplaceAll(suffix, "/", "-")
|
||||
networkName := fmt.Sprintf("lolly-e2e-%s-%d", suffix, id)
|
||||
|
||||
// 尝试创建网络(如果不存在)
|
||||
// 忽略"已存在"错误
|
||||
_, err := CreateNetwork(ctx, networkName)
|
||||
network, err := CreateNetwork(ctx, networkName)
|
||||
if err != nil && !isNetworkExistsError(err) {
|
||||
return "", nil, fmt.Errorf("failed to create network: %w", err)
|
||||
return nil, "", nil, fmt.Errorf("failed to create network: %w", err)
|
||||
}
|
||||
|
||||
// 启动后端池并加入网络
|
||||
pool, err := StartBackendPoolWithNetwork(ctx, backendCount, networkName)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to start backend pool: %w", err)
|
||||
if network != nil {
|
||||
network.Remove(ctx)
|
||||
}
|
||||
return nil, "", nil, fmt.Errorf("failed to start backend pool: %w", err)
|
||||
}
|
||||
|
||||
return networkName, pool, nil
|
||||
return network, networkName, pool, nil
|
||||
}
|
||||
|
||||
// isNetworkExistsError 检查是否是网络已存在错误。
|
||||
@ -678,75 +701,11 @@ func containsSubstring(s, substr string) bool {
|
||||
}
|
||||
|
||||
// CleanupProxyTest 清理代理测试环境。
|
||||
func CleanupProxyTest(ctx context.Context, networkName string, pool *BackendPool) {
|
||||
func CleanupProxyTest(ctx context.Context, network testcontainers.Network, networkName string, pool *BackendPool) {
|
||||
if pool != nil {
|
||||
pool.Terminate(ctx)
|
||||
}
|
||||
// 网络会随容器终止自动清理
|
||||
}
|
||||
|
||||
// ProxyTestEnv 代理测试环境。
|
||||
//
|
||||
// 封装代理测试所需的资源。
|
||||
type ProxyTestEnv struct {
|
||||
Network string
|
||||
Pool *BackendPool
|
||||
Lolly *LollyContainer
|
||||
Cleanup func()
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// SetupProxyTestEnv 设置完整的代理测试环境。
|
||||
//
|
||||
// 创建网络、启动后端池、启动 lolly,返回封装的环境。
|
||||
// 这是一个便捷函数,简化测试设置。
|
||||
//
|
||||
// 使用示例:
|
||||
//
|
||||
// env, err := testutil.SetupProxyTestEnv(ctx, t, 2, func(pool *testutil.BackendPool) string {
|
||||
// cfg := testutil.NewConfigBuilder().
|
||||
// WithServer(":8080").
|
||||
// WithProxy("/", pool.InternalAddresses())
|
||||
// yaml, _ := cfg.Build()
|
||||
// return yaml
|
||||
// })
|
||||
func SetupProxyTestEnv(ctx context.Context, backendCount int, configBuilder func(*BackendPool) string) (*ProxyTestEnv, error) {
|
||||
// 设置代理测试环境
|
||||
networkName, pool, err := SetupProxyTest(ctx, backendCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 构建配置
|
||||
configYAML := configBuilder(pool)
|
||||
|
||||
// 启动 lolly
|
||||
lolly, err := StartLolly(ctx,
|
||||
WithConfigYAML(configYAML),
|
||||
WithNetwork(networkName),
|
||||
)
|
||||
if err != nil {
|
||||
CleanupProxyTest(ctx, networkName, pool)
|
||||
return nil, fmt.Errorf("failed to start lolly: %w", err)
|
||||
}
|
||||
|
||||
// 等待健康
|
||||
if err := lolly.WaitForHealthy(ctx, 30*time.Second); err != nil {
|
||||
CleanupProxyTest(ctx, networkName, pool)
|
||||
lolly.Terminate(ctx)
|
||||
return nil, fmt.Errorf("lolly not healthy: %w", err)
|
||||
}
|
||||
|
||||
cleanup := func() {
|
||||
lolly.Terminate(ctx)
|
||||
CleanupProxyTest(ctx, networkName, pool)
|
||||
}
|
||||
|
||||
return &ProxyTestEnv{
|
||||
Network: networkName,
|
||||
Pool: pool,
|
||||
Lolly: lolly,
|
||||
Cleanup: cleanup,
|
||||
HTTPClient: &http.Client{Timeout: 10 * time.Second},
|
||||
}, nil
|
||||
if network != nil {
|
||||
network.Remove(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,18 +12,21 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
)
|
||||
|
||||
// E2ETestEnv E2E 测试环境。
|
||||
//
|
||||
// 封装测试所需的资源和清理函数。
|
||||
type E2ETestEnv struct {
|
||||
Ctx context.Context
|
||||
Network string
|
||||
Pool *BackendPool
|
||||
Lolly *LollyContainer
|
||||
Client *http.Client
|
||||
cleanup func()
|
||||
Ctx context.Context
|
||||
Network testcontainers.Network
|
||||
NetworkName string
|
||||
Pool *BackendPool
|
||||
Lolly *LollyContainer
|
||||
Client *http.Client
|
||||
cleanup func()
|
||||
}
|
||||
|
||||
// SetupE2ETest 设置 E2E 测试环境。
|
||||
@ -55,7 +58,7 @@ func SetupE2ETest(t *testing.T, backendCount int, cfgBuilder func(*BackendPool)
|
||||
t.Skip("lolly:latest image not available, run 'make docker-build' first")
|
||||
}
|
||||
|
||||
network, pool, err := SetupProxyTest(ctx, backendCount)
|
||||
netObj, networkName, pool, err := SetupProxyTest(ctx, backendCount, t.Name())
|
||||
if err != nil {
|
||||
cancel()
|
||||
t.Fatalf("Failed to setup proxy test: %v", err)
|
||||
@ -65,32 +68,33 @@ func SetupE2ETest(t *testing.T, backendCount int, cfgBuilder func(*BackendPool)
|
||||
|
||||
lolly, err := StartLolly(ctx,
|
||||
WithConfigYAML(cfgYAML),
|
||||
WithNetwork(network),
|
||||
WithNetwork(networkName),
|
||||
)
|
||||
if err != nil {
|
||||
CleanupProxyTest(ctx, network, pool)
|
||||
CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
cancel()
|
||||
t.Fatalf("Failed to start lolly: %v", err)
|
||||
}
|
||||
|
||||
if err := lolly.WaitForHealthy(ctx, HealthCheckWaitTimeout); err != nil {
|
||||
lolly.Terminate(ctx)
|
||||
CleanupProxyTest(ctx, network, pool)
|
||||
CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
cancel()
|
||||
t.Fatalf("Lolly not healthy: %v", err)
|
||||
}
|
||||
|
||||
env := &E2ETestEnv{
|
||||
Ctx: ctx,
|
||||
Network: network,
|
||||
Pool: pool,
|
||||
Lolly: lolly,
|
||||
Client: CreateDefaultHTTPClient(),
|
||||
Ctx: ctx,
|
||||
Network: netObj,
|
||||
NetworkName: networkName,
|
||||
Pool: pool,
|
||||
Lolly: lolly,
|
||||
Client: CreateDefaultHTTPClient(),
|
||||
}
|
||||
|
||||
env.cleanup = func() {
|
||||
lolly.Terminate(ctx)
|
||||
CleanupProxyTest(ctx, network, pool)
|
||||
CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
cancel()
|
||||
}
|
||||
|
||||
@ -109,7 +113,7 @@ func SetupE2ETestWithTimeout(t *testing.T, backendCount int, timeout time.Durati
|
||||
t.Skip("lolly:latest image not available, run 'make docker-build' first")
|
||||
}
|
||||
|
||||
network, pool, err := SetupProxyTest(ctx, backendCount)
|
||||
netObj, networkName, pool, err := SetupProxyTest(ctx, backendCount, t.Name())
|
||||
if err != nil {
|
||||
cancel()
|
||||
t.Fatalf("Failed to setup proxy test: %v", err)
|
||||
@ -119,32 +123,33 @@ func SetupE2ETestWithTimeout(t *testing.T, backendCount int, timeout time.Durati
|
||||
|
||||
lolly, err := StartLolly(ctx,
|
||||
WithConfigYAML(cfgYAML),
|
||||
WithNetwork(network),
|
||||
WithNetwork(networkName),
|
||||
)
|
||||
if err != nil {
|
||||
CleanupProxyTest(ctx, network, pool)
|
||||
CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
cancel()
|
||||
t.Fatalf("Failed to start lolly: %v", err)
|
||||
}
|
||||
|
||||
if err := lolly.WaitForHealthy(ctx, HealthCheckWaitTimeout); err != nil {
|
||||
lolly.Terminate(ctx)
|
||||
CleanupProxyTest(ctx, network, pool)
|
||||
CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
cancel()
|
||||
t.Fatalf("Lolly not healthy: %v", err)
|
||||
}
|
||||
|
||||
env := &E2ETestEnv{
|
||||
Ctx: ctx,
|
||||
Network: network,
|
||||
Pool: pool,
|
||||
Lolly: lolly,
|
||||
Client: CreateDefaultHTTPClient(),
|
||||
Ctx: ctx,
|
||||
Network: netObj,
|
||||
NetworkName: networkName,
|
||||
Pool: pool,
|
||||
Lolly: lolly,
|
||||
Client: CreateDefaultHTTPClient(),
|
||||
}
|
||||
|
||||
env.cleanup = func() {
|
||||
lolly.Terminate(ctx)
|
||||
CleanupProxyTest(ctx, network, pool)
|
||||
CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
cancel()
|
||||
}
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ func wsEchoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
//
|
||||
// 验证 WebSocket 连接可以成功建立和消息传递。
|
||||
func TestE2EWebSocketBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
// 创建本地 WebSocket Echo 服务器
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
@ -80,6 +81,7 @@ func TestE2EWebSocketBasic(t *testing.T) {
|
||||
//
|
||||
// 验证二进制消息正确传递。
|
||||
func TestE2EWebSocketBinary(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -105,6 +107,7 @@ func TestE2EWebSocketBinary(t *testing.T) {
|
||||
//
|
||||
// 验证 JSON 消息正确传递。
|
||||
func TestE2EWebSocketJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -131,6 +134,7 @@ func TestE2EWebSocketJSON(t *testing.T) {
|
||||
//
|
||||
// 验证多个并发连接正常工作。
|
||||
func TestE2EWebSocketConcurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -166,6 +170,7 @@ func TestE2EWebSocketConcurrent(t *testing.T) {
|
||||
//
|
||||
// 验证连续发送多条消息正常工作。
|
||||
func TestE2EWebSocketMultipleMessages(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -194,6 +199,7 @@ func TestE2EWebSocketMultipleMessages(t *testing.T) {
|
||||
//
|
||||
// 验证连接正确关闭。
|
||||
func TestE2EWebSocketClose(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -226,6 +232,7 @@ func TestE2EWebSocketClose(t *testing.T) {
|
||||
//
|
||||
// 验证超时配置生效。
|
||||
func TestE2EWebSocketTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -249,6 +256,7 @@ func TestE2EWebSocketTimeout(t *testing.T) {
|
||||
//
|
||||
// 验证自定义请求头正确传递。
|
||||
func TestE2EWebSocketHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -278,6 +286,7 @@ func TestE2EWebSocketHeaders(t *testing.T) {
|
||||
//
|
||||
// 验证连接池的各种操作。
|
||||
func TestE2EWebSocketPoolOperations(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -303,6 +312,7 @@ func TestE2EWebSocketPoolOperations(t *testing.T) {
|
||||
//
|
||||
// 验证客户端可以重新建立连接。
|
||||
func TestE2EWebSocketReconnect(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -341,6 +351,7 @@ func TestE2EWebSocketReconnect(t *testing.T) {
|
||||
//
|
||||
// 验证大消息正确传递。
|
||||
func TestE2EWebSocketLargeMessage(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(wsEchoHandler))
|
||||
defer server.Close()
|
||||
|
||||
@ -370,6 +381,7 @@ func TestE2EWebSocketLargeMessage(t *testing.T) {
|
||||
//
|
||||
// 注意:此测试需要 Docker 环境,验证 lolly WebSocket 代理功能。
|
||||
func TestE2EWebSocketProxyIntegration(t *testing.T) {
|
||||
t.Parallel()
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping E2E WebSocket proxy test in short mode")
|
||||
}
|
||||
@ -382,9 +394,9 @@ func TestE2EWebSocketProxyIntegration(t *testing.T) {
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
networkName, pool, err := testutil.SetupProxyTest(ctx, 1)
|
||||
netObj, networkName, pool, err := testutil.SetupProxyTest(ctx, 1, t.Name())
|
||||
require.NoError(t, err, "Failed to start backend pool")
|
||||
defer testutil.CleanupProxyTest(ctx, networkName, pool)
|
||||
defer testutil.CleanupProxyTest(ctx, netObj, networkName, pool)
|
||||
|
||||
// 构建配置
|
||||
cfg := testutil.NewConfigBuilder().
|
||||
@ -399,7 +411,7 @@ func TestE2EWebSocketProxyIntegration(t *testing.T) {
|
||||
require.NoError(t, err, "Failed to start lolly")
|
||||
defer lolly.Terminate(ctx)
|
||||
|
||||
err = lolly.WaitForHealthy(ctx, 30*time.Second)
|
||||
err = lolly.WaitForHealthy(ctx, testutil.HealthCheckWaitTimeout)
|
||||
require.NoError(t, err, "Lolly not healthy")
|
||||
|
||||
// 测试 HTTP 代理(WebSocket 需要 WebSocket 后端)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user