- Update CHANGELOG.md for v0.4.0 - Update Makefile FALLBACK_VERSION to 0.4.0 - Fix lint warnings (godoc comments, goconst) - Clean up code formatting
357 lines
8.9 KiB
Go
357 lines
8.9 KiB
Go
//go:build integration
|
||
|
||
// proxy_integration_test.go - 代理集成测试(L2 层,进程内)
|
||
//
|
||
// 测试反向代理的配置和创建逻辑。
|
||
// 实际的网络转发测试在 L3 E2E 测试中进行。
|
||
//
|
||
// 作者:xfy
|
||
package integration
|
||
|
||
import (
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/stretchr/testify/assert"
|
||
"github.com/stretchr/testify/require"
|
||
"rua.plus/lolly/internal/config"
|
||
"rua.plus/lolly/internal/loadbalance"
|
||
"rua.plus/lolly/internal/proxy"
|
||
)
|
||
|
||
// TestProxyCreation 测试代理创建
|
||
func TestProxyCreation(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
Write: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{
|
||
URL: "http://127.0.0.1:8081",
|
||
Weight: 1,
|
||
MaxFails: 3,
|
||
},
|
||
}
|
||
|
||
p, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err, "failed to create proxy")
|
||
require.NotNil(t, p)
|
||
|
||
// 验证配置
|
||
assert.Equal(t, "round_robin", cfg.LoadBalance)
|
||
assert.Equal(t, 5*time.Second, cfg.Timeout.Connect)
|
||
assert.Equal(t, 10*time.Second, cfg.Timeout.Read)
|
||
}
|
||
|
||
// TestProxyRequestHeaders 测试请求头修改配置
|
||
func TestProxyRequestHeaders(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Headers: config.ProxyHeaders{
|
||
SetRequest: map[string]string{
|
||
"X-Custom-Header": "custom-value",
|
||
"X-Forwarded-Proto": "https",
|
||
},
|
||
},
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证代理配置已设置
|
||
assert.NotNil(t, cfg.Headers.SetRequest)
|
||
assert.Equal(t, "custom-value", cfg.Headers.SetRequest["X-Custom-Header"])
|
||
assert.Equal(t, "https", cfg.Headers.SetRequest["X-Forwarded-Proto"])
|
||
}
|
||
|
||
// TestProxyResponseHeaders 测试响应头修改配置
|
||
func TestProxyResponseHeaders(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Headers: config.ProxyHeaders{
|
||
SetResponse: map[string]string{
|
||
"X-Server": "lolly",
|
||
},
|
||
Remove: []string{"X-Powered-By"},
|
||
},
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证响应头配置
|
||
assert.Equal(t, "lolly", cfg.Headers.SetResponse["X-Server"])
|
||
assert.Contains(t, cfg.Headers.Remove, "X-Powered-By")
|
||
}
|
||
|
||
// TestProxyTimeout 测试代理超时配置
|
||
func TestProxyTimeout(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 1 * time.Second,
|
||
Read: 50 * time.Millisecond,
|
||
Write: 1 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证超时配置
|
||
assert.Equal(t, 1*time.Second, cfg.Timeout.Connect)
|
||
assert.Equal(t, 50*time.Millisecond, cfg.Timeout.Read)
|
||
assert.Equal(t, 1*time.Second, cfg.Timeout.Write)
|
||
}
|
||
|
||
// TestProxyLoadBalanceRoundRobin 测试轮询负载均衡配置
|
||
func TestProxyLoadBalanceRoundRobin(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
{URL: "http://127.0.0.1:8082", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证负载均衡器类型
|
||
assert.Equal(t, "round_robin", cfg.LoadBalance)
|
||
assert.Len(t, targets, 2)
|
||
}
|
||
|
||
// TestProxyWeightedRoundRobin 测试加权轮询配置
|
||
func TestProxyWeightedRoundRobin(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "weighted_round_robin",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 3},
|
||
{URL: "http://127.0.0.1:8082", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证权重配置
|
||
assert.Equal(t, 3, targets[0].Weight)
|
||
assert.Equal(t, 1, targets[1].Weight)
|
||
}
|
||
|
||
// TestProxyLeastConn 测试最少连接负载均衡配置
|
||
func TestProxyLeastConn(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "least_conn",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
{URL: "http://127.0.0.1:8082", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
assert.Equal(t, "least_conn", cfg.LoadBalance)
|
||
}
|
||
|
||
// TestProxyIPHash 测试 IP 哈希负载均衡配置
|
||
func TestProxyIPHash(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "ip_hash",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
{URL: "http://127.0.0.1:8082", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
assert.Equal(t, "ip_hash", cfg.LoadBalance)
|
||
}
|
||
|
||
// TestProxyConsistentHash 测试一致性哈希负载均衡配置
|
||
func TestProxyConsistentHash(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "consistent_hash",
|
||
HashKey: "uri",
|
||
VirtualNodes: 150,
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
{URL: "http://127.0.0.1:8082", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
assert.Equal(t, "consistent_hash", cfg.LoadBalance)
|
||
assert.Equal(t, "uri", cfg.HashKey)
|
||
assert.Equal(t, 150, cfg.VirtualNodes)
|
||
}
|
||
|
||
// TestProxyErrorHandling 测试错误处理配置
|
||
func TestProxyErrorHandling(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{
|
||
URL: "http://127.0.0.1:8081",
|
||
Weight: 1,
|
||
MaxFails: 3,
|
||
FailTimeout: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证 MaxFails 配置 (int64 类型)
|
||
assert.Equal(t, int64(3), targets[0].MaxFails)
|
||
assert.Equal(t, 10*time.Second, targets[0].FailTimeout)
|
||
}
|
||
|
||
// TestProxyCacheConfig 测试缓存配置
|
||
func TestProxyCacheConfig(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
Cache: config.ProxyCacheConfig{
|
||
Enabled: true,
|
||
MaxAge: 60 * time.Second,
|
||
Methods: []string{"GET", "HEAD"},
|
||
MinUses: 1,
|
||
CacheLock: true,
|
||
CacheLockTimeout: 5 * time.Second,
|
||
StaleWhileRevalidate: 30 * time.Second,
|
||
},
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证缓存配置
|
||
assert.True(t, cfg.Cache.Enabled)
|
||
assert.Equal(t, 60*time.Second, cfg.Cache.MaxAge)
|
||
assert.Contains(t, cfg.Cache.Methods, "GET")
|
||
assert.True(t, cfg.Cache.CacheLock)
|
||
}
|
||
|
||
// TestProxyNextUpstream 测试故障转移配置
|
||
func TestProxyNextUpstream(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
NextUpstream: config.NextUpstreamConfig{
|
||
Tries: 3,
|
||
HTTPCodes: []int{502, 503, 504},
|
||
},
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
{URL: "http://127.0.0.1:8082", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证故障转移配置
|
||
assert.Equal(t, 3, cfg.NextUpstream.Tries)
|
||
assert.Contains(t, cfg.NextUpstream.HTTPCodes, 502)
|
||
assert.Contains(t, cfg.NextUpstream.HTTPCodes, 503)
|
||
assert.Contains(t, cfg.NextUpstream.HTTPCodes, 504)
|
||
}
|
||
|
||
// TestProxyHealthCheck 测试健康检查配置
|
||
func TestProxyHealthCheck(t *testing.T) {
|
||
cfg := &config.ProxyConfig{
|
||
LoadBalance: "round_robin",
|
||
HealthCheck: config.HealthCheckConfig{
|
||
Interval: 10 * time.Second,
|
||
Path: "/health",
|
||
Timeout: 5 * time.Second,
|
||
},
|
||
Timeout: config.ProxyTimeout{
|
||
Connect: 5 * time.Second,
|
||
Read: 10 * time.Second,
|
||
},
|
||
}
|
||
|
||
targets := []*loadbalance.Target{
|
||
{URL: "http://127.0.0.1:8081", Weight: 1},
|
||
}
|
||
|
||
_, err := proxy.NewProxy(cfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
// 验证健康检查配置
|
||
assert.Equal(t, 10*time.Second, cfg.HealthCheck.Interval)
|
||
assert.Equal(t, "/health", cfg.HealthCheck.Path)
|
||
assert.Equal(t, 5*time.Second, cfg.HealthCheck.Timeout)
|
||
}
|