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
67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
// Package server 提供服务器生命周期相关功能的测试。
|
||
//
|
||
// 该文件测试生命周期管理中的并发安全场景,包括:
|
||
// - 代理缓存统计与代理创建/清理的并发访问
|
||
//
|
||
// 作者:xfy
|
||
package server
|
||
|
||
import (
|
||
"sync"
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/stretchr/testify/require"
|
||
"rua.plus/lolly/internal/config"
|
||
"rua.plus/lolly/internal/proxy"
|
||
"rua.plus/lolly/internal/testutil"
|
||
)
|
||
|
||
// TestGetProxyCacheStats_Concurrent 验证并发统计代理缓存与修改 proxies 切片不产生竞态。
|
||
func TestGetProxyCacheStats_Concurrent(t *testing.T) {
|
||
cfg := &config.Config{
|
||
Servers: []config.ServerConfig{{Listen: ":0"}},
|
||
}
|
||
s := New(cfg)
|
||
|
||
proxyCfg := &config.ProxyConfig{
|
||
Path: "/api",
|
||
LoadBalance: "round_robin",
|
||
Timeout: config.ProxyTimeout{Connect: 5 * time.Second},
|
||
Cache: config.ProxyCacheConfig{
|
||
Enabled: true,
|
||
MaxAge: 10 * time.Second,
|
||
},
|
||
}
|
||
targets := testutil.NewTestTargets("http://localhost:8080")
|
||
p, err := proxy.NewProxy(proxyCfg, targets, nil, nil)
|
||
require.NoError(t, err)
|
||
|
||
s.proxies = []*proxy.Proxy{p}
|
||
|
||
purgeHandler := &PurgeHandler{server: s}
|
||
|
||
var wg sync.WaitGroup
|
||
for range 100 {
|
||
wg.Add(3)
|
||
|
||
go func() {
|
||
defer wg.Done()
|
||
_ = s.getProxyCacheStats()
|
||
}()
|
||
|
||
go func() {
|
||
defer wg.Done()
|
||
_ = purgeHandler.purgeByPath("/api/test", "GET")
|
||
}()
|
||
|
||
go func() {
|
||
defer wg.Done()
|
||
s.proxiesMu.Lock()
|
||
s.proxies = append(s.proxies, p)
|
||
s.proxiesMu.Unlock()
|
||
}()
|
||
}
|
||
wg.Wait()
|
||
}
|