lolly/internal/server/pool_test.go
xfy f2352ab9cc docs(config,stream,logging,handler,proxy,cache,server,ssl,middleware): 为核心模块添加详细 GoDoc 文档注释
- config: 为 Config 和所有子配置结构添加完整文档,包含使用示例和注意事项
- stream: 为负载均衡器和服务器添加详细的参数、返回值和功能说明
- logging: 为日志格式化和输出函数添加文档,说明支持的变量替换
- handler: 为路由器、静态文件和 sendfile 处理器添加文档
- proxy: 为健康检查器和代理功能添加完整文档
- cache/server/ssl/middleware: 补充相关模块的文档注释
- config.example.yaml: 添加可信代理配置、加密套件示例,更新压缩级别说明

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-07 15:36:09 +08:00

238 lines
4.5 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 提供 Goroutine 池功能的测试。
//
// 该文件测试 Goroutine 池的各项功能,包括:
// - 池的创建和配置
// - 启动和停止控制
// - 任务提交和执行
// - 并发提交处理
// - Handler 包装功能
// - 统计信息收集
//
// 作者xfy
package server
import (
"sync"
"sync/atomic"
"testing"
"time"
"github.com/valyala/fasthttp"
)
func TestNewGoroutinePool(t *testing.T) {
cfg := PoolConfig{
MaxWorkers: 100,
MinWorkers: 10,
IdleTimeout: 30 * time.Second,
QueueSize: 50,
}
p := NewGoroutinePool(cfg)
if p == nil {
t.Fatal("Expected non-nil pool")
}
// 检查配置
if p.maxWorkers != 100 {
t.Errorf("Expected maxWorkers 100, got %d", p.maxWorkers)
}
if p.minWorkers != 10 {
t.Errorf("Expected minWorkers 10, got %d", p.minWorkers)
}
}
func TestPoolDefaults(t *testing.T) {
p := NewGoroutinePool(PoolConfig{})
// 应该使用默认值
if p.maxWorkers != 10000 {
t.Errorf("Expected default maxWorkers 10000, got %d", p.maxWorkers)
}
if p.minWorkers != 100 {
t.Errorf("Expected default minWorkers 100, got %d", p.minWorkers)
}
}
func TestPoolStartStop(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 10,
MinWorkers: 2,
})
p.Start()
if !p.running.Load() {
t.Error("Expected pool to be running")
}
p.Stop()
if p.running.Load() {
t.Error("Expected pool to be stopped")
}
}
func TestPoolSubmit(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 10,
MinWorkers: 2,
QueueSize: 10,
IdleTimeout: 5 * time.Second,
})
p.Start()
defer p.Stop()
var executed atomic.Bool
task := func(ctx *fasthttp.RequestCtx) {
executed.Store(true)
}
err := p.Submit(nil, task)
if err != nil {
t.Errorf("Submit failed: %v", err)
}
// 等待任务执行
time.Sleep(100 * time.Millisecond)
if !executed.Load() {
t.Error("Expected task to be executed")
}
}
func TestPoolStats(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 100,
MinWorkers: 10,
QueueSize: 50,
IdleTimeout: 30 * time.Second,
})
p.Start()
defer p.Stop()
stats := p.Stats()
if stats.MaxWorkers != 100 {
t.Errorf("Expected MaxWorkers 100, got %d", stats.MaxWorkers)
}
if stats.MinWorkers != 10 {
t.Errorf("Expected MinWorkers 10, got %d", stats.MinWorkers)
}
if stats.QueueCap != 50 {
t.Errorf("Expected QueueCap 50, got %d", stats.QueueCap)
}
}
func TestPoolConcurrentSubmit(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 50,
MinWorkers: 5,
QueueSize: 100,
IdleTimeout: 5 * time.Second,
})
p.Start()
defer p.Stop()
var counter atomic.Int32
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
_ = p.Submit(nil, func(ctx *fasthttp.RequestCtx) {
counter.Add(1)
})
}()
}
wg.Wait()
// 等待所有任务执行
time.Sleep(500 * time.Millisecond)
if counter.Load() != 100 {
t.Errorf("Expected 100 executions, got %d", counter.Load())
}
}
func TestPoolSubmitWhenStopped(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 10,
})
// 不启动池
var executed atomic.Bool
task := func(ctx *fasthttp.RequestCtx) {
executed.Store(true)
}
err := p.Submit(nil, task)
if err != nil {
t.Errorf("Submit should not fail when stopped: %v", err)
}
// 任务应该直接执行
if !executed.Load() {
t.Error("Expected task to be executed directly when pool is stopped")
}
}
func TestPoolWrapHandler(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 10,
MinWorkers: 2,
QueueSize: 10,
IdleTimeout: 5 * time.Second,
})
p.Start()
defer p.Stop()
var executed atomic.Bool
originalHandler := func(ctx *fasthttp.RequestCtx) {
executed.Store(true)
ctx.SetBodyString("wrapped response")
}
wrappedHandler := p.WrapHandler(originalHandler)
ctx := &fasthttp.RequestCtx{}
ctx.Init(&fasthttp.Request{}, nil, nil)
wrappedHandler(ctx)
// 等待异步执行
time.Sleep(100 * time.Millisecond)
if !executed.Load() {
t.Error("Expected wrapped handler to be executed")
}
}
func TestPoolWrapHandler_WhenStopped(t *testing.T) {
p := NewGoroutinePool(PoolConfig{
MaxWorkers: 10,
})
// 不启动池
var executed atomic.Bool
originalHandler := func(ctx *fasthttp.RequestCtx) {
executed.Store(true)
}
wrappedHandler := p.WrapHandler(originalHandler)
ctx := &fasthttp.RequestCtx{}
ctx.Init(&fasthttp.Request{}, nil, nil)
wrappedHandler(ctx)
// 池停止时应该直接执行
if !executed.Load() {
t.Error("Expected handler to be executed directly when pool is stopped")
}
}