- 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
260 lines
5.9 KiB
Go
260 lines
5.9 KiB
Go
// Package http2 提供 HTTP/2 集成测试。
|
||
//
|
||
// 该文件包含 HTTP/2 的端到端集成测试:
|
||
// - HTTP/2 请求处理
|
||
// - ALPN 协商
|
||
// - HTTP/1.1 fallback
|
||
//
|
||
// 运行方式: go test -tags=integration ./internal/http2/...
|
||
//
|
||
// 作者:xfy
|
||
package http2
|
||
|
||
import (
|
||
"bytes"
|
||
"net"
|
||
"net/http"
|
||
"net/http/httptest"
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/valyala/fasthttp"
|
||
"rua.plus/lolly/internal/config"
|
||
)
|
||
|
||
// TestIntegrationHTTP2Request 测试 HTTP/2 请求处理(需要 TLS 证书)。
|
||
func TestIntegrationHTTP2Request(t *testing.T) {
|
||
// 跳过集成测试,除非显式启用
|
||
if testing.Short() {
|
||
t.Skip("Skipping integration test in short mode")
|
||
}
|
||
|
||
// 注意:这需要有效的 TLS 证书才能完整测试
|
||
// 这里使用非 TLS 模式测试基本功能
|
||
|
||
handler := func(ctx *fasthttp.RequestCtx) {
|
||
ctx.WriteString("Hello HTTP/2")
|
||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||
}
|
||
|
||
cfg := &config.HTTP2Config{
|
||
Enabled: true,
|
||
MaxConcurrentStreams: 100,
|
||
}
|
||
|
||
server, err := NewServer(cfg, handler, nil)
|
||
if err != nil {
|
||
t.Fatalf("Failed to create server: %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() {
|
||
if err := server.Serve(ln); err != nil {
|
||
t.Logf("Server serve error: %v", err)
|
||
}
|
||
}()
|
||
|
||
// 等待服务器启动
|
||
time.Sleep(100 * time.Millisecond)
|
||
|
||
// 停止服务器
|
||
if err := server.Stop(); err != nil {
|
||
t.Errorf("Failed to stop server: %v", err)
|
||
}
|
||
}
|
||
|
||
// TestIntegrationHTTP1Fallback 测试 HTTP/1.1 回退。
|
||
func TestIntegrationHTTP1Fallback(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("Skipping integration test in short mode")
|
||
}
|
||
|
||
handler := func(ctx *fasthttp.RequestCtx) {
|
||
ctx.WriteString("Fallback to HTTP/1.1")
|
||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||
}
|
||
|
||
cfg := &config.HTTP2Config{
|
||
Enabled: true,
|
||
MaxConcurrentStreams: 100,
|
||
}
|
||
|
||
server, err := NewServer(cfg, handler, nil)
|
||
if err != nil {
|
||
t.Fatalf("Failed to create server: %v", err)
|
||
}
|
||
|
||
// 验证服务器支持 HTTP/1.1 回退
|
||
if server.handler == nil {
|
||
t.Error("Server handler should be set for HTTP/1.1 fallback")
|
||
}
|
||
}
|
||
|
||
// TestIntegrationConcurrentStreams 测试并发流处理。
|
||
func TestIntegrationConcurrentStreams(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("Skipping integration test in short mode")
|
||
}
|
||
|
||
requestCount := 0
|
||
handler := func(ctx *fasthttp.RequestCtx) {
|
||
requestCount++
|
||
ctx.WriteString("OK")
|
||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||
}
|
||
|
||
cfg := &config.HTTP2Config{
|
||
Enabled: true,
|
||
MaxConcurrentStreams: 10,
|
||
}
|
||
|
||
server, err := NewServer(cfg, handler, nil)
|
||
if err != nil {
|
||
t.Fatalf("Failed to create server: %v", err)
|
||
}
|
||
|
||
// 验证并发流限制
|
||
if server.http2Server.MaxConcurrentStreams != 10 {
|
||
t.Errorf("Expected MaxConcurrentStreams 10, got %d",
|
||
server.http2Server.MaxConcurrentStreams)
|
||
}
|
||
}
|
||
|
||
// TestIntegrationAdapterConversion 测试适配器转换。
|
||
func TestIntegrationAdapterConversion(t *testing.T) {
|
||
handler := func(ctx *fasthttp.RequestCtx) {
|
||
// 设置响应头和体
|
||
ctx.Response.Header.Set("X-Custom-Header", "test-value")
|
||
ctx.WriteString("Converted response")
|
||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||
}
|
||
|
||
adapter := NewFastHTTPHandlerAdapter(handler)
|
||
|
||
// 创建标准 HTTP 请求
|
||
req, err := http.NewRequest(http.MethodGet, "http://example.com/test", nil)
|
||
if err != nil {
|
||
t.Fatalf("Failed to create request: %v", err)
|
||
}
|
||
req.Header.Set("Accept", "application/json")
|
||
|
||
// 使用 httptest 记录响应
|
||
recorder := &testResponseRecorder{
|
||
header: make(http.Header),
|
||
}
|
||
|
||
// 执行适配器
|
||
adapter.ServeHTTP(recorder, req)
|
||
|
||
// 验证响应
|
||
if recorder.statusCode != http.StatusOK {
|
||
t.Errorf("Expected status %d, got %d", http.StatusOK, recorder.statusCode)
|
||
}
|
||
|
||
if recorder.body.String() != "Converted response" {
|
||
t.Errorf("Expected body 'Converted response', got '%s'", recorder.body.String())
|
||
}
|
||
}
|
||
|
||
type testResponseRecorder struct {
|
||
header http.Header
|
||
body testBuffer
|
||
statusCode int
|
||
}
|
||
|
||
func (r *testResponseRecorder) Header() http.Header {
|
||
return r.header
|
||
}
|
||
|
||
func (r *testResponseRecorder) Write(p []byte) (int, error) {
|
||
return r.body.Write(p)
|
||
}
|
||
|
||
func (r *testResponseRecorder) WriteHeader(code int) {
|
||
r.statusCode = code
|
||
}
|
||
|
||
// testBuffer 是一个简单的字节缓冲区。
|
||
type testBuffer struct {
|
||
data []byte
|
||
}
|
||
|
||
func (b *testBuffer) Write(p []byte) (int, error) {
|
||
b.data = append(b.data, p...)
|
||
return len(p), nil
|
||
}
|
||
|
||
func (b *testBuffer) String() string {
|
||
return string(b.data)
|
||
}
|
||
|
||
// BenchmarkAdapterConversion 基准测试适配器转换性能。
|
||
func BenchmarkAdapterConversion(b *testing.B) {
|
||
handler := func(ctx *fasthttp.RequestCtx) {
|
||
ctx.WriteString("Hello")
|
||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||
}
|
||
|
||
adapter := NewFastHTTPHandlerAdapter(handler)
|
||
req := httptest.NewRequest(http.MethodGet, "/test", nil)
|
||
rec := httptest.NewRecorder()
|
||
|
||
b.ResetTimer()
|
||
b.ReportAllocs()
|
||
|
||
for b.Loop() {
|
||
rec.Body.Reset()
|
||
adapter.ServeHTTP(rec, req)
|
||
}
|
||
}
|
||
|
||
// BenchmarkAdapterWithBody 基准测试带请求体的适配器。
|
||
func BenchmarkAdapterWithBody(b *testing.B) {
|
||
handler := func(ctx *fasthttp.RequestCtx) {
|
||
ctx.Write(ctx.PostBody())
|
||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||
}
|
||
|
||
adapter := NewFastHTTPHandlerAdapter(handler)
|
||
body := []byte(`{"test":"data","number":12345}`)
|
||
|
||
b.ResetTimer()
|
||
b.ReportAllocs()
|
||
|
||
for b.Loop() {
|
||
req := httptest.NewRequest(http.MethodPost, "/api", bytes.NewReader(body))
|
||
rec := httptest.NewRecorder()
|
||
adapter.ServeHTTP(rec, req)
|
||
}
|
||
}
|
||
|
||
// BenchmarkServerCreation 基准测试服务器创建。
|
||
func BenchmarkServerCreation(b *testing.B) {
|
||
cfg := &config.HTTP2Config{
|
||
Enabled: true,
|
||
MaxConcurrentStreams: 100,
|
||
}
|
||
handler := func(_ *fasthttp.RequestCtx) {}
|
||
|
||
b.ResetTimer()
|
||
b.ReportAllocs()
|
||
|
||
for b.Loop() {
|
||
_, err := NewServer(cfg, handler, nil)
|
||
if err != nil {
|
||
b.Fatal(err)
|
||
}
|
||
}
|
||
}
|