lolly/internal/http2/server_test.go
xfy 2734b04d8f refactor: remove 16.8k lines of dead code across all internal packages
- Delete unused files: tempfile subsystem, matcher variants, server/internal
- Remove 200+ unused functions across proxy, ssl, lua, http2/3, stream, variable
- Fix proxy test type errors (backgroundRefresh ctx→Request)
- Move bench/tools mock backend into internal/testutil
- Remove corresponding test functions for all deleted code
2026-06-03 16:15:43 +08:00

326 lines
7.3 KiB
Go
Raw Permalink 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 http2 提供 HTTP/2 服务器测试。
//
// 该文件包含 HTTP/2 服务器的单元测试和集成测试:
// - 服务器创建和配置测试
// - ALPN 协议协商测试
// - HTTP/1.1 fallback 测试
//
// 作者xfy
package http2
import (
"crypto/tls"
"net"
"testing"
"time"
"github.com/valyala/fasthttp"
"rua.plus/lolly/internal/config"
)
// TestNewServer 测试 HTTP/2 服务器创建。
func TestNewServer(t *testing.T) {
tests := []struct {
cfg *config.HTTP2Config
handler fasthttp.RequestHandler
tlsConfig *tls.Config
name string
wantErr bool
}{
{
name: "有效配置",
cfg: &config.HTTP2Config{
Enabled: true,
MaxConcurrentStreams: 128,
MaxHeaderListSize: 1048576,
IdleTimeout: 120 * time.Second,
PushEnabled: false,
H2CEnabled: false,
},
handler: func(_ *fasthttp.RequestCtx) {},
tlsConfig: nil,
wantErr: false,
},
{
name: "默认配置",
cfg: &config.HTTP2Config{},
handler: func(_ *fasthttp.RequestCtx) {},
wantErr: false,
},
{
name: "nil配置",
cfg: nil,
handler: func(_ *fasthttp.RequestCtx) {},
wantErr: true,
},
{
name: "nil handler",
cfg: &config.HTTP2Config{
Enabled: true,
},
handler: nil,
wantErr: true,
},
{
name: "自定义并发流数量",
cfg: &config.HTTP2Config{
Enabled: true,
MaxConcurrentStreams: 256,
},
handler: func(_ *fasthttp.RequestCtx) {},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
server, err := NewServer(tt.cfg, tt.handler, tt.tlsConfig)
if tt.wantErr {
if err == nil {
t.Errorf("NewServer() expected error, got nil")
}
return
}
if err != nil {
t.Errorf("NewServer() unexpected error: %v", err)
return
}
if server == nil {
t.Error("NewServer() returned nil server")
return
}
// 验证配置正确应用
if server.config != tt.cfg {
t.Error("NewServer() config not set correctly")
}
if server.handler == nil {
t.Error("NewServer() handler not set")
}
})
}
}
// TestServerDefaultValues 测试服务器默认值。
func TestServerDefaultValues(t *testing.T) {
cfg := &config.HTTP2Config{
Enabled: true,
}
handler := func(_ *fasthttp.RequestCtx) {}
server, err := NewServer(cfg, handler, nil)
if err != nil {
t.Fatalf("NewServer() error: %v", err)
}
// 验证默认并发流数量
if server.http2Server.MaxConcurrentStreams == 0 {
t.Error("Expected default MaxConcurrentStreams to be set")
}
// 验证默认空闲超时
if server.http2Server.IdleTimeout == 0 {
t.Error("Expected default IdleTimeout to be set")
}
}
// TestServe_AcceptError 测试 Accept 错误处理。
func TestServe_AcceptError(t *testing.T) {
cfg := &config.HTTP2Config{Enabled: true}
server, err := NewServer(cfg, func(_ *fasthttp.RequestCtx) {}, nil)
if err != nil {
t.Fatalf("NewServer() error: %v", err)
}
// 创建一个已关闭的监听器
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
// 启动服务器
errCh := make(chan error, 1)
go func() {
errCh <- server.Serve(ln)
}()
// 关闭监听器触发 Accept 错误
if err := ln.Close(); err != nil {
t.Logf("Failed to close listener: %v", err)
}
// 停止服务器
_ = server.Stop()
// 服务器应该正常退出
select {
case err := <-errCh:
if err != nil {
t.Errorf("Serve() unexpected error: %v", err)
}
case <-time.After(2 * time.Second):
t.Error("Serve() did not exit in time")
}
}
// TestServe_AlreadyRunning 测试服务器重复启动。
func TestServe_AlreadyRunning(t *testing.T) {
cfg := &config.HTTP2Config{Enabled: true}
server, err := NewServer(cfg, func(_ *fasthttp.RequestCtx) {}, nil)
if err != nil {
t.Fatalf("NewServer() error: %v", err)
}
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
defer func() {
if err := ln.Close(); err != nil {
t.Logf("Failed to close listener: %v", err)
}
}()
// 启动服务器
go func() {
_ = server.Serve(ln)
}()
// 等待服务器启动
time.Sleep(50 * time.Millisecond)
// 尝试再次启动
err = server.Serve(ln)
if err == nil {
t.Error("Serve() should return error when already running")
}
// 停止服务器
_ = server.Stop()
}
// TestStop_GracefulShutdownTimeout 测试优雅关闭超时。
func TestStop_GracefulShutdownTimeout(t *testing.T) {
cfg := &config.HTTP2Config{
Enabled: true,
GracefulShutdownTimeout: 100 * time.Millisecond,
}
handler := func(ctx *fasthttp.RequestCtx) {
// 模拟长时间处理
time.Sleep(2 * time.Second)
ctx.SetStatusCode(fasthttp.StatusOK)
}
server, err := NewServer(cfg, handler, nil)
if err != nil {
t.Fatalf("NewServer() error: %v", err)
}
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
defer func() {
if err := ln.Close(); err != nil {
t.Logf("Failed to close listener: %v", err)
}
}()
// 启动服务器
go func() {
_ = server.Serve(ln)
}()
// 等待服务器启动
time.Sleep(50 * time.Millisecond)
// 停止服务器(应该超时)
start := time.Now()
_ = server.Stop()
elapsed := time.Since(start)
// 应该在超时后返回
if elapsed > 500*time.Millisecond {
t.Errorf("Stop() took too long: %v", elapsed)
}
}
// TestStop_NotRunning 测试停止未运行的服务器。
func TestStop_NotRunning(t *testing.T) {
cfg := &config.HTTP2Config{Enabled: true}
server, err := NewServer(cfg, func(_ *fasthttp.RequestCtx) {}, nil)
if err != nil {
t.Fatalf("NewServer() error: %v", err)
}
// 停止未运行的服务器应该返回 nil
err = server.Stop()
if err != nil {
t.Errorf("Stop() on non-running server should return nil, got: %v", err)
}
}
// TestConnectionPool_CloseAll 测试连接池关闭所有连接。
func TestConnectionPool_CloseAll(t *testing.T) {
pool := newConnectionPool()
// 创建多个连接
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
defer func() {
if err := ln.Close(); err != nil {
t.Logf("Failed to close listener: %v", err)
}
}()
conn1, err := net.Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("Failed to dial: %v", err)
}
conn2, err := net.Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("Failed to dial: %v", err)
}
pool.add("key1", conn1)
pool.add("key1", conn2)
// 关闭所有连接
pool.closeAll()
// 验证连接池已清空
if count := len(pool.conns["key1"]); count != 0 {
t.Errorf("Expected count 0 after closeAll, got %d", count)
}
}
// TestConnectionPool_RemoveNonExistent 测试移除不存在的连接。
func TestConnectionPool_RemoveNonExistent(t *testing.T) {
pool := newConnectionPool()
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Failed to create listener: %v", err)
}
defer func() {
if err := ln.Close(); err != nil {
t.Logf("Failed to close listener: %v", err)
}
}()
conn, err := net.Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("Failed to dial: %v", err)
}
defer func() {
_ = conn.Close()
}()
// 移除不存在的 key/conn 组合不应 panic
pool.remove("nonexistent", conn)
pool.remove("key1", conn)
}