lolly/internal/server/server_test.go
xfy 7a96db9f05 test(server): 重构并扩展服务器测试
- 拆分 server_extended_test.go 到独立测试文件
- 添加 pprof、purge、vhost、internal 测试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 08:12:33 +08:00

1378 lines
30 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package server 提供 HTTP 服务器功能的测试。
//
// 该文件测试服务器模块的各项功能,包括:
// - 服务器创建和初始化
// - 启动和停止控制
// - 优雅关闭
// - 中间件链构建
// - 请求统计追踪
// - 监听器管理
// - TLS 配置
// - 代理缓存统计
//
// 作者xfy
package server
import (
"net"
"os"
"testing"
"time"
"github.com/valyala/fasthttp"
"rua.plus/lolly/internal/config"
"rua.plus/lolly/internal/version"
)
// TestNew 测试服务器创建
func TestNew(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
Static: []config.StaticConfig{{
Path: "/",
Root: "./static",
Index: []string{"index.html"},
}},
}},
}
s := New(cfg)
if s == nil {
t.Fatal("New() returned nil, expected non-nil Server")
}
if s.config != cfg {
t.Error("Server.config not set correctly")
}
if s.running {
t.Error("Server.running should be false initially")
}
if s.fastServer != nil {
t.Error("Server.fastServer should be nil before Start()")
}
}
// TestStopWithoutServer 测试无服务器时调用 Stop
func TestStopWithoutServer(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 在未启动时调用 Stop应返回 nil
err := s.StopWithTimeout(5 * time.Second)
if err != nil {
t.Errorf("StopWithTimeout() on non-started server returned error: %v", err)
}
}
// TestGracefulStop 测试 GracefulStop 调用
func TestGracefulStop(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 在未启动时调用 GracefulStop应返回 nil
err := s.GracefulStop(5 * time.Second)
if err != nil {
t.Errorf("GracefulStop() on non-started server returned error: %v", err)
}
}
// TestStopAfterStop 测试多次调用 Stop
func TestStopAfterStop(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 多次调用 StopWithTimeout 应该都是安全的
for i := 0; i < 3; i++ {
err := s.StopWithTimeout(5 * time.Second)
if err != nil {
t.Errorf("StopWithTimeout() call %d returned error: %v", i+1, err)
}
}
}
// TestGracefulStopWithZeroTimeout 测试零超时的 GracefulStop
func TestGracefulStopWithZeroTimeout(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
err := s.GracefulStop(0)
if err != nil {
t.Errorf("GracefulStop(0) returned error: %v", err)
}
}
// TestBuildMiddlewareChain_AccessLog 测试访问日志中间件
func TestBuildMiddlewareChain_AccessLog(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_AccessControl 测试访问控制中间件
func TestBuildMiddlewareChain_AccessControl(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Security: config.SecurityConfig{
Access: config.AccessConfig{
Allow: []string{"127.0.0.1"},
},
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_RateLimiter 测试限流中间件
func TestBuildMiddlewareChain_RateLimiter(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Security: config.SecurityConfig{
RateLimit: config.RateLimitConfig{
RequestRate: 100,
Burst: 200,
},
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_Rewrite 测试重写中间件
func TestBuildMiddlewareChain_Rewrite(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Rewrite: []config.RewriteRule{
{Pattern: "/old/(.*)", Replacement: "/new/$1"},
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_Compression 测试压缩中间件
func TestBuildMiddlewareChain_Compression(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Compression: config.CompressionConfig{
Level: 6,
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_SecurityHeaders 测试安全头中间件
func TestBuildMiddlewareChain_SecurityHeaders(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Security: config.SecurityConfig{
Headers: config.SecurityHeaders{
XFrameOptions: "DENY",
XContentTypeOptions: "nosniff",
},
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_AllMiddlewares 测试所有中间件组合
func TestBuildMiddlewareChain_AllMiddlewares(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Security: config.SecurityConfig{
Access: config.AccessConfig{
Allow: []string{"127.0.0.1"},
},
RateLimit: config.RateLimitConfig{
RequestRate: 100,
Burst: 200,
},
Headers: config.SecurityHeaders{
XFrameOptions: "DENY",
},
},
Rewrite: []config.RewriteRule{
{Pattern: "/old/(.*)", Replacement: "/new/$1"},
},
Compression: config.CompressionConfig{
Level: 6,
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestTrackStats 测试请求统计追踪
func TestTrackStats(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 初始统计应该为 0
if s.requests.Load() != 0 {
t.Error("Initial requests should be 0")
}
if s.bytesSent.Load() != 0 {
t.Error("Initial bytesSent should be 0")
}
if s.bytesReceived.Load() != 0 {
t.Error("Initial bytesReceived should be 0")
}
// 创建测试 handler
handler := func(ctx *fasthttp.RequestCtx) {
ctx.SetBodyString("response body")
}
// 包装 handler
wrappedHandler := s.trackStats(handler)
// 创建测试请求上下文
ctx := &fasthttp.RequestCtx{}
ctx.Init(&fasthttp.Request{}, nil, nil)
ctx.Request.SetBody([]byte("request body"))
// 执行
wrappedHandler(ctx)
// 验证统计
if s.requests.Load() != 1 {
t.Errorf("Expected 1 request, got %d", s.requests.Load())
}
if s.bytesReceived.Load() != int64(len("request body")) {
t.Errorf("Expected bytesReceived %d, got %d", len("request body"), s.bytesReceived.Load())
}
if s.bytesSent.Load() != int64(len("response body")) {
t.Errorf("Expected bytesSent %d, got %d", len("response body"), s.bytesSent.Load())
}
}
// TestTrackStats_MultipleRequests 测试多次请求统计
func TestTrackStats_MultipleRequests(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
handler := func(ctx *fasthttp.RequestCtx) {
ctx.SetBodyString("ok")
}
wrappedHandler := s.trackStats(handler)
// 执行多次请求
for i := 0; i < 10; i++ {
ctx := &fasthttp.RequestCtx{}
ctx.Init(&fasthttp.Request{}, nil, nil)
wrappedHandler(ctx)
}
if s.requests.Load() != 10 {
t.Errorf("Expected 10 requests, got %d", s.requests.Load())
}
}
// TestGetListeners_Empty 测试空监听器列表
func TestGetListeners_Empty(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
listeners := s.GetListeners()
if listeners != nil {
t.Errorf("Expected nil listeners, got %v", listeners)
}
}
// TestSetListeners 测试设置监听器
func TestSetListeners(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 创建模拟监听器
listener1, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
defer func() {
_ = listener1.Close()
}()
listener2, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
defer func() {
_ = listener2.Close()
}()
listeners := []net.Listener{listener1, listener2}
s.SetListeners(listeners)
// 验证设置成功
got := s.GetListeners()
if len(got) != 2 {
t.Errorf("Expected 2 listeners, got %d", len(got))
}
}
// TestGetTLSConfig_NotConfigured 测试未配置 TLS
func TestGetTLSConfig_NotConfigured(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
tlsConfig, err := s.GetTLSConfig()
if err == nil {
t.Error("Expected error for unconfigured TLS")
}
if tlsConfig != nil {
t.Error("Expected nil TLS config")
}
if err.Error() != "TLS not configured" {
t.Errorf("Expected error 'TLS not configured', got: %v", err)
}
}
// TestGetHandler 测试获取 handler
func TestGetHandler(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 初始 handler 应该为 nil
handler := s.GetHandler()
if handler != nil {
t.Error("Expected nil handler initially")
}
// 设置一个 handler
testHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetBodyString("test")
}
s.handler = testHandler
// 验证获取成功
got := s.GetHandler()
if got == nil {
t.Error("Expected non-nil handler after setting")
}
}
// TestServer_Connections 测试连接统计
func TestServer_Connections(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 初始连接数应该为 0
if s.connections.Load() != 0 {
t.Error("Initial connections should be 0")
}
// 增加
s.connections.Add(1)
if s.connections.Load() != 1 {
t.Errorf("Expected 1 connection, got %d", s.connections.Load())
}
// 减少
s.connections.Add(-1)
if s.connections.Load() != 0 {
t.Errorf("Expected 0 connections, got %d", s.connections.Load())
}
}
// TestServer_Proxies 测试代理管理
func TestServer_Proxies(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 初始代理列表应为空
if len(s.proxies) != 0 {
t.Error("Initial proxies should be empty")
}
}
// TestServer_Running 测试运行状态
func TestServer_Running(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 初始状态应为未运行
if s.running {
t.Error("Initial running state should be false")
}
}
// TestServer_StopWithNilFastServer 测试无 fastServer 时停止
func TestServer_StopWithNilFastServer(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
s.fastServer = nil
err := s.StopWithTimeout(5 * time.Second)
if err != nil {
t.Errorf("StopWithTimeout with nil fastServer should succeed: %v", err)
}
}
// TestServer_GracefulStopWithNilFastServer 测试无 fastServer 时优雅停止
func TestServer_GracefulStopWithNilFastServer(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
s.fastServer = nil
err := s.GracefulStop(5 * time.Second)
if err != nil {
t.Errorf("GracefulStop with nil fastServer should succeed: %v", err)
}
}
// TestServer_GetProxyCacheStats 测试代理缓存统计
func TestServer_GetProxyCacheStats(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 无代理时应返回空统计
stats := s.getProxyCacheStats()
if stats.Entries != 0 {
t.Errorf("Expected 0 entries, got %d", stats.Entries)
}
if stats.Pending != 0 {
t.Errorf("Expected 0 pending, got %d", stats.Pending)
}
}
// TestServer_BuildMiddlewareChain_EmptyConfig 测试空配置的中间件链
func TestServer_BuildMiddlewareChain_EmptyConfig(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestServer_TrackStats_EmptyBody 测试空响应体的统计
func TestServer_TrackStats_EmptyBody(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
handler := func(_ *fasthttp.RequestCtx) {
// 空响应
}
wrappedHandler := s.trackStats(handler)
ctx := &fasthttp.RequestCtx{}
ctx.Init(&fasthttp.Request{}, nil, nil)
ctx.Request.SetBody(nil)
wrappedHandler(ctx)
if s.requests.Load() != 1 {
t.Errorf("Expected 1 request, got %d", s.requests.Load())
}
if s.bytesSent.Load() != 0 {
t.Errorf("Expected 0 bytes sent, got %d", s.bytesSent.Load())
}
}
// TestStart_Success 测试服务器配置初始化
func TestStart_Success(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 验证服务器正确初始化
if s == nil {
t.Fatal("New() returned nil, expected non-nil Server")
}
if s.config != cfg {
t.Error("Server.config not set correctly")
}
}
// TestStart_WithStaticFiles 测试静态文件配置
func TestStart_WithStaticFiles(t *testing.T) {
// 创建临时目录
tempDir := t.TempDir()
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
Static: []config.StaticConfig{{
Path: "/static",
Root: tempDir,
Index: []string{"index.html"},
}},
}},
}
s := New(cfg)
if s == nil {
t.Fatal("New() returned nil")
}
}
// TestStart_WithGoroutinePool 测试 GoroutinePool 配置
func TestStart_WithGoroutinePool(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
Performance: config.PerformanceConfig{
GoroutinePool: config.GoroutinePoolConfig{
Enabled: true,
MaxWorkers: 100,
MinWorkers: 10,
IdleTimeout: 30 * time.Second,
},
},
}
s := New(cfg)
if s == nil {
t.Fatal("New() returned nil")
}
}
// TestStart_WithFileCache 测试文件缓存配置
func TestStart_WithFileCache(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
Performance: config.PerformanceConfig{
FileCache: config.FileCacheConfig{
MaxEntries: 1000,
MaxSize: 100 * 1024 * 1024,
},
},
}
s := New(cfg)
if s == nil {
t.Fatal("New() returned nil")
}
}
// TestStop_Graceful 测试优雅停止(无 race 模式)
func TestStop_Graceful(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
// 在未启动时调用 GracefulStop应返回 nil
err := s.GracefulStop(1 * time.Second)
if err != nil {
t.Errorf("GracefulStop() on non-started server returned error: %v", err)
}
}
// TestGetTLSConfig_Nil 测试无 TLS 配置
func TestGetTLSConfig_Nil(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
tlsCfg, err := s.GetTLSConfig()
if err == nil {
t.Error("GetTLSConfig() should return error when TLS not configured")
}
if tlsCfg != nil {
t.Error("GetTLSConfig() should return nil when TLS not configured")
}
}
// TestGetTLSConfig_NilServer 测试 nil 服务器调用 GetTLSConfig
func TestGetTLSConfig_NilServer(t *testing.T) {
var s *Server
// 防御性:如果 s 为 nil调用方法会 panic这是预期的行为
// 这里我们只测试非 nil 但 tlsManager 为 nil 的情况
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s = New(cfg)
// 确保 tlsManager 为 nil
if s.tlsManager != nil {
t.Skip("tlsManager should be nil initially")
}
tlsCfg, err := s.GetTLSConfig()
if err == nil {
t.Error("Expected error when tlsManager is nil")
}
if tlsCfg != nil {
t.Error("Expected nil TLS config when tlsManager is nil")
}
if err.Error() != "TLS not configured" {
t.Errorf("Expected error 'TLS not configured', got: %v", err)
}
}
// TestGetServerName 测试服务器名称返回。
func TestGetServerName(t *testing.T) {
tests := []struct {
name string
cfg *config.ServerConfig
wantName string
}{
{
name: "nil config",
cfg: nil,
wantName: "lolly/" + version.Version,
},
{
name: "ServerTokens true (default)",
cfg: &config.ServerConfig{
ServerTokens: true,
},
wantName: "lolly/" + version.Version,
},
{
name: "ServerTokens false",
cfg: &config.ServerConfig{
ServerTokens: false,
},
wantName: "lolly",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Server{}
got := s.getServerName(tt.cfg)
if got != tt.wantName {
t.Errorf("getServerName() = %q, want %q", got, tt.wantName)
}
})
}
}
// TestApplyTypesConfig 测试 MIME 类型配置应用。
func TestApplyTypesConfig(t *testing.T) {
t.Run("nil config", func(t *testing.T) {
s := &Server{}
// 不应该 panic
s.applyTypesConfig(nil)
})
t.Run("empty config", func(t *testing.T) {
s := &Server{}
cfg := &config.ServerConfig{}
// 不应该 panic
s.applyTypesConfig(cfg)
})
t.Run("with types map", func(t *testing.T) {
s := &Server{}
cfg := &config.ServerConfig{
Types: config.TypesConfig{
Map: map[string]string{
".custom": "application/x-custom",
},
},
}
// 不应该 panic
s.applyTypesConfig(cfg)
})
t.Run("with default type", func(t *testing.T) {
s := &Server{}
cfg := &config.ServerConfig{
Types: config.TypesConfig{
DefaultType: "application/octet-stream",
},
}
// 不应该 panic
s.applyTypesConfig(cfg)
})
}
// TestCreateListener_TCP 测试 TCP 监听器创建。
func TestCreateListener_TCP(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: "127.0.0.1:0", // 随机端口
}},
}
s := New(cfg)
ln, err := s.createListener(&cfg.Servers[0])
if err != nil {
t.Fatalf("createListener() error: %v", err)
}
if ln == nil {
t.Fatal("createListener() returned nil listener")
}
defer ln.Close()
if ln.Addr().Network() != "tcp" {
t.Errorf("expected tcp network, got %s", ln.Addr().Network())
}
}
// TestCreateListener_UnixSocket 测试 Unix Socket 监听器创建。
func TestCreateListener_UnixSocket(t *testing.T) {
tempDir := t.TempDir()
socketPath := tempDir + "/test.sock"
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: "unix:" + socketPath,
}},
}
s := New(cfg)
ln, err := s.createListener(&cfg.Servers[0])
if err != nil {
t.Fatalf("createListener() error: %v", err)
}
if ln == nil {
t.Fatal("createListener() returned nil listener")
}
defer ln.Close()
if ln.Addr().Network() != "unix" {
t.Errorf("expected unix network, got %s", ln.Addr().Network())
}
}
// TestCreateListener_UnixSocketWithPermissions 测试带权限的 Unix Socket 创建。
func TestCreateListener_UnixSocketWithPermissions(t *testing.T) {
tempDir := t.TempDir()
socketPath := tempDir + "/test_perm.sock"
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: "unix:" + socketPath,
UnixSocket: config.UnixSocketConfig{
Mode: 0o600,
User: "nobody",
Group: "nobody",
},
}},
}
s := New(cfg)
ln, err := s.createListener(&cfg.Servers[0])
if err != nil {
t.Fatalf("createListener() error: %v", err)
}
if ln == nil {
t.Fatal("createListener() returned nil listener")
}
defer ln.Close()
}
// TestCreateListener_UnixSocketCleanup 测试 Unix Socket 文件清理。
func TestCreateListener_UnixSocketCleanup(t *testing.T) {
tempDir := t.TempDir()
socketPath := tempDir + "/cleanup.sock"
// 先创建一个已存在的 socket 文件
if err := os.WriteFile(socketPath, []byte{}, 0o666); err != nil {
t.Fatalf("failed to create existing socket file: %v", err)
}
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: "unix:" + socketPath,
}},
}
s := New(cfg)
ln, err := s.createListener(&cfg.Servers[0])
if err != nil {
t.Fatalf("createListener() error: %v", err)
}
defer ln.Close()
}
// TestServer_StatsMethods 测试服务器统计方法。
func TestServer_StatsMethods(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 测试 startTime 初始值
if !s.startTime.IsZero() {
t.Error("startTime should be zero initially")
}
// 设置 startTime
s.startTime = time.Now()
if s.startTime.IsZero() {
t.Error("startTime should not be zero after setting")
}
// 测试统计值
if s.connections.Load() != 0 {
t.Error("initial connections should be 0")
}
if s.requests.Load() != 0 {
t.Error("initial requests should be 0")
}
if s.bytesSent.Load() != 0 {
t.Error("initial bytesSent should be 0")
}
if s.bytesReceived.Load() != 0 {
t.Error("initial bytesReceived should be 0")
}
}
// TestServer_SetResolver 测试设置解析器。
func TestServer_SetResolver(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 设置 nil resolver
s.SetResolver(nil)
if s.resolver != nil {
t.Error("resolver should be nil")
}
}
// TestServer_SetUpgradeManager 测试设置升级管理器。
func TestServer_SetUpgradeManager(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 设置 nil upgrade manager
s.SetUpgradeManager(nil)
if s.upgradeManager != nil {
t.Error("upgradeManager should be nil")
}
// 设置实际的 upgrade manager
um := NewUpgradeManager(s)
s.SetUpgradeManager(um)
if s.upgradeManager == nil {
t.Error("upgradeManager should not be nil after setting")
}
}
// TestServer_GetResolver 测试获取解析器。
func TestServer_GetResolver(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 初始 resolver 应为 nil
resolver := s.GetResolver()
if resolver != nil {
t.Error("expected nil resolver initially")
}
}
// TestServer_StopWithTimeout_WithListeners 测试带监听器的停止。
func TestServer_StopWithTimeout_WithListeners(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
// 创建监听器
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("failed to create listener: %v", err)
}
s.listeners = []net.Listener{ln}
// 调用停止
err = s.StopWithTimeout(1 * time.Second)
if err != nil {
t.Errorf("StopWithTimeout failed: %v", err)
}
}
// TestServer_GracefulStop_WithListeners 测试带监听器的优雅停止。
func TestServer_GracefulStop_WithListeners(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
// 创建监听器
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("failed to create listener: %v", err)
}
s.listeners = []net.Listener{ln}
// 调用优雅停止
err = s.GracefulStop(1 * time.Second)
if err != nil {
t.Errorf("GracefulStop failed: %v", err)
}
}
// TestServer_StopWithTimeout_WithFastServer 测试带 fastServer 的停止。
func TestServer_StopWithTimeout_WithFastServer(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
s.running = true
// 创建 mock fastServer
s.fastServer = &fasthttp.Server{}
// 调用停止
err := s.StopWithTimeout(1 * time.Second)
if err != nil {
t.Errorf("StopWithTimeout failed: %v", err)
}
}
// TestBuildMiddlewareChain_BodyLimit 测试请求体限制中间件。
func TestBuildMiddlewareChain_BodyLimit(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
ClientMaxBodySize: "1MB",
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_ErrorIntercept 测试错误拦截中间件。
func TestBuildMiddlewareChain_ErrorIntercept(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":8080",
Security: config.SecurityConfig{
ErrorPage: config.ErrorPageConfig{
Pages: map[int]string{
404: "/404.html",
},
},
},
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestBuildMiddlewareChain_NilServerConfig 测试 nil 服务器配置。
// 注意buildMiddlewareChain 不接受 nil所以这个测试验证空配置。
func TestBuildMiddlewareChain_NilServerConfig(t *testing.T) {
cfg := &config.Config{
Logging: config.LoggingConfig{},
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
chain, err := s.buildMiddlewareChain(&cfg.Servers[0])
if err != nil {
t.Errorf("buildMiddlewareChain failed: %v", err)
}
if chain == nil {
t.Error("Expected non-nil chain")
}
}
// TestServer_StatusCode_MethodNotAllowed 测试不支持的 HTTP 方法。
func TestServer_StatusCode_MethodNotAllowed(t *testing.T) {
// 简单验证
if fasthttp.StatusMethodNotAllowed != 405 {
t.Errorf("StatusMethodNotAllowed should be 405")
}
}
// TestServer_ConnectionTracking 测试连接追踪。
func TestServer_ConnectionTracking(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 测试原子操作
initial := s.connections.Load()
s.connections.Add(1)
if s.connections.Load() != initial+1 {
t.Error("connections should have incremented")
}
s.connections.Add(-1)
if s.connections.Load() != initial {
t.Error("connections should be back to initial")
}
}
// TestServer_RequestTracking 测试请求追踪。
func TestServer_RequestTracking(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 测试原子操作
s.requests.Add(5)
if s.requests.Load() != 5 {
t.Errorf("expected 5 requests, got %d", s.requests.Load())
}
}
// TestServer_BytesTracking 测试字节追踪。
func TestServer_BytesTracking(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
// 测试原子操作
s.bytesSent.Add(1024)
s.bytesReceived.Add(512)
if s.bytesSent.Load() != 1024 {
t.Errorf("expected 1024 bytes sent, got %d", s.bytesSent.Load())
}
if s.bytesReceived.Load() != 512 {
t.Errorf("expected 512 bytes received, got %d", s.bytesReceived.Load())
}
}
// TestServer_GracefulStop_WithFastServers 测试带多个 fastServer 的优雅停止。
func TestServer_GracefulStop_WithFastServers(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
s.running = true
// 创建多个 fastServer
s.fastServers = []*fasthttp.Server{
{},
{},
}
// 调用优雅停止
err := s.GracefulStop(1 * time.Second)
if err != nil {
t.Errorf("GracefulStop failed: %v", err)
}
}
// TestServer_StopWithTimeout_WithFastServers 测试带多个 fastServer 的停止。
func TestServer_StopWithTimeout_WithFastServers(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
s.running = true
// 创建多个 fastServer
s.fastServers = []*fasthttp.Server{
{},
{},
}
// 调用停止
err := s.StopWithTimeout(1 * time.Second)
if err != nil {
t.Errorf("StopWithTimeout failed: %v", err)
}
}
// TestServer_GetProxyCacheStats_WithProxies 测试带代理的缓存统计。
func TestServer_GetProxyCacheStats_WithProxies(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":8080",
}},
}
s := New(cfg)
s.proxies = nil // 确保 proxies 为 nil
// 无代理时应返回空统计
stats := s.getProxyCacheStats()
if stats.Entries != 0 {
t.Errorf("Expected 0 entries, got %d", stats.Entries)
}
}
// TestServer_MultipleListeners 测试多个监听器。
func TestServer_MultipleListeners(t *testing.T) {
cfg := &config.Config{
Servers: []config.ServerConfig{{
Listen: ":0",
}},
}
s := New(cfg)
// 创建多个监听器
ln1, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("failed to create listener: %v", err)
}
ln2, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("failed to create listener: %v", err)
_ = ln1.Close()
}
s.listeners = []net.Listener{ln1, ln2}
// 验证可以获取监听器
got := s.GetListeners()
if len(got) != 2 {
t.Errorf("expected 2 listeners, got %d", len(got))
}
// 清理
_ = s.StopWithTimeout(1 * time.Second)
}