Batch 1 - Crash/data corruption: - Add nil/empty config guards in server and app - Protect against fasthttp buffer mutation in logging - Ensure mimeutil falls back before caching empty MIME - Make proxy health checker and resolver tolerate nil cfg - Prevent Lua EMERG/ALERT/CRIT log levels from killing process Batch 2 - Concurrency/race conditions: - Add focused race tests for compression pool, ssl/ocsp, server proxies slice, Lua timer cancel, and TCP socket connect - Fix Lua timer active race and socket ConnectAsync race Batch 3 - Resource leaks/functional damage: - Track and stop rate limiter cleanup goroutines on shutdown - Add tests for proxy connection count leaks, server pool deadlock, Linux sendfile integrity, WebSocket frame data loss, stream UDP stop deadlock, and upstream name mismatch - Fix stream ListenTCP/upstream lookup and UDP shutdown Batch 4 - High severity technical debt: - Add nil guard in security headers middleware - Validate sliding window divisor and add tests - Protect static handler fields with existing RWMutex - Avoid mutating live HostClient.Addr on DNS updates - Fix slow start Start/Stop and resolver restart - Initialize variable fallback context maps - Add tests for request_id/time_local and logging file handle close Also: - Relax integration variable performance threshold under race detector - Update benchmark plan docs for new stream ListenTCP signature Verification: - make test: pass - go test -race -count=1 ./internal/...: pass - make lint: 0 issues - make build: success
77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
// Package security 提供安全头部功能的测试。
|
||
//
|
||
// 该文件测试安全头部模块的各项功能,包括:
|
||
// - HSTS 值格式化
|
||
// - nil 配置保护
|
||
//
|
||
// 作者:xfy
|
||
package security
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"github.com/valyala/fasthttp"
|
||
)
|
||
|
||
// TestAddHeadersNilConfig 验证配置在运行时被置为 nil 也不会 panic。
|
||
func TestAddHeadersNilConfig(t *testing.T) {
|
||
sh := NewHeadersWithHSTS(nil, nil)
|
||
// 故意将内部配置置为 nil,模拟异常状态
|
||
sh.config = nil
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Request.Header.SetMethod("GET")
|
||
ctx.Request.Header.SetRequestURI("/")
|
||
|
||
// 不应 panic
|
||
sh.addHeaders(ctx)
|
||
|
||
if string(ctx.Response.Header.Peek("X-Frame-Options")) != "DENY" {
|
||
t.Errorf("expected default X-Frame-Options=DENY, got %q", ctx.Response.Header.Peek("X-Frame-Options"))
|
||
}
|
||
if string(ctx.Response.Header.Peek("X-Content-Type-Options")) != "nosniff" {
|
||
t.Errorf("expected default X-Content-Type-Options=nosniff, got %q", ctx.Response.Header.Peek("X-Content-Type-Options"))
|
||
}
|
||
}
|
||
|
||
func TestFormatHSTSValue(t *testing.T) {
|
||
tests := []struct {
|
||
name string
|
||
expected string
|
||
maxAge int
|
||
includeSubDomains bool
|
||
preload bool
|
||
}{
|
||
{
|
||
name: "basic HSTS",
|
||
maxAge: 31536000,
|
||
includeSubDomains: true,
|
||
preload: false,
|
||
expected: "max-age=31536000; includeSubDomains",
|
||
},
|
||
{
|
||
name: "HSTS with preload",
|
||
maxAge: 31536000,
|
||
includeSubDomains: true,
|
||
preload: true,
|
||
expected: "max-age=31536000; includeSubDomains; preload",
|
||
},
|
||
{
|
||
name: "HSTS without subdomains",
|
||
maxAge: 86400,
|
||
includeSubDomains: false,
|
||
preload: false,
|
||
expected: "max-age=86400",
|
||
},
|
||
}
|
||
|
||
for _, tt := range tests {
|
||
t.Run(tt.name, func(t *testing.T) {
|
||
result := formatHSTSValue(tt.maxAge, tt.includeSubDomains, tt.preload)
|
||
if result != tt.expected {
|
||
t.Errorf("formatHSTSValue() = %s, expected %s", result, tt.expected)
|
||
}
|
||
})
|
||
}
|
||
}
|