lolly/internal/lua/middleware_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

404 lines
11 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 lua 提供 Lua 中间件测试
package lua
import (
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/valyala/fasthttp"
)
// TestLuaMiddlewareCreation 测试 LuaMiddleware 创建
func TestLuaMiddlewareCreation(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
// 创建临时脚本文件
tmpDir := t.TempDir()
scriptPath := filepath.Join(tmpDir, "test.lua")
err = os.WriteFile(scriptPath, []byte("ngx.say('hello')"), 0o644)
require.NoError(t, err)
config := LuaMiddlewareConfig{
ScriptPath: scriptPath,
Phase: PhaseContent,
Timeout: 10 * time.Second,
Name: "test-middleware",
Enabled: true,
}
middleware, err := NewLuaMiddleware(engine, config)
require.NoError(t, err)
require.NotNil(t, middleware)
assert.Equal(t, "test-middleware", middleware.Name())
assert.Equal(t, scriptPath, middleware.GetScriptPath())
assert.Equal(t, PhaseContent, middleware.GetPhase())
assert.Equal(t, 10*time.Second, middleware.timeout)
assert.True(t, middleware.IsEnabled())
}
// TestLuaMiddlewareValidation 测试配置验证
func TestLuaMiddlewareValidation(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
// 缺少 engine
config := LuaMiddlewareConfig{ScriptPath: "test.lua"}
middleware, err := NewLuaMiddleware(nil, config)
assert.Error(t, err)
assert.Nil(t, middleware)
assert.Contains(t, err.Error(), "engine is required")
// 缺少 script path
middleware, err = NewLuaMiddleware(engine, LuaMiddlewareConfig{})
assert.Error(t, err)
assert.Nil(t, middleware)
assert.Contains(t, err.Error(), "script path is required")
}
// TestLuaMiddlewareProcess 测试中间件处理
func TestLuaMiddlewareProcess(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
// 创建脚本文件
tmpDir := t.TempDir()
scriptPath := filepath.Join(tmpDir, "test.lua")
err = os.WriteFile(scriptPath, []byte(`ngx.say("hello from lua")`), 0o644)
require.NoError(t, err)
config := LuaMiddlewareConfig{
ScriptPath: scriptPath,
Phase: PhaseContent,
Enabled: true,
EnabledSet: true, // 显式启用
}
middleware, err := NewLuaMiddleware(engine, config)
require.NoError(t, err)
// 创建 RequestCtx
ctx := &fasthttp.RequestCtx{}
// 创建最终处理器
finalHandler := func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("final handler")
}
// 包装处理器
handler := middleware.Process(finalHandler)
// 执行
handler(ctx)
// 验证输出包含 Lua 输出
body := string(ctx.Response.Body())
assert.Contains(t, body, "hello from lua")
}
// TestLuaMiddlewareDisabled 测试禁用的中间件
func TestLuaMiddlewareDisabled(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
// 创建脚本文件
tmpDir := t.TempDir()
scriptPath := filepath.Join(tmpDir, "test.lua")
err = os.WriteFile(scriptPath, []byte(`ngx.say("lua output")`), 0o644)
require.NoError(t, err)
config := LuaMiddlewareConfig{
ScriptPath: scriptPath,
Phase: PhaseContent,
Enabled: false, // 禁用
EnabledSet: true, // 显式设置
}
middleware, err := NewLuaMiddleware(engine, config)
require.NoError(t, err)
// 创建 RequestCtx
ctx := &fasthttp.RequestCtx{}
// 创建最终处理器
finalHandler := func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("final only")
}
// 包装处理器
handler := middleware.Process(finalHandler)
// 执行
handler(ctx)
// 禁用时只执行最终处理器
body := string(ctx.Response.Body())
assert.Equal(t, "final only", body)
assert.NotContains(t, body, "lua output")
}
// TestMultiPhaseLuaMiddlewareCreation 测试多阶段中间件创建
func TestMultiPhaseLuaMiddlewareCreation(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
multi := NewMultiPhaseLuaMiddleware(engine, "multi-test")
assert.Equal(t, "multi-test", multi.Name())
assert.Equal(t, 0, multi.PhaseCount())
}
// TestMultiPhaseLuaMiddlewareAddPhase 测试添加阶段
func TestMultiPhaseLuaMiddlewareAddPhase(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
tmpDir := t.TempDir()
multi := NewMultiPhaseLuaMiddleware(engine, "multi-test")
// 添加 rewrite 阶段
rewriteScript := filepath.Join(tmpDir, "rewrite.lua")
err = os.WriteFile(rewriteScript, []byte("ngx.var.uri = '/rewritten'"), 0o644)
require.NoError(t, err)
err = multi.AddPhase(PhaseRewrite, rewriteScript, 10*time.Second)
require.NoError(t, err)
assert.Equal(t, 1, multi.PhaseCount())
assert.True(t, multi.HasPhase(PhaseRewrite))
// 添加 access 阶段
accessScript := filepath.Join(tmpDir, "access.lua")
err = os.WriteFile(accessScript, []byte("ngx.exit(403)"), 0o644)
require.NoError(t, err)
err = multi.AddPhase(PhaseAccess, accessScript, 10*time.Second)
require.NoError(t, err)
assert.Equal(t, 2, multi.PhaseCount())
assert.True(t, multi.HasPhase(PhaseAccess))
}
// TestMultiPhaseLuaMiddlewareRemovePhase 测试移除阶段
func TestMultiPhaseLuaMiddlewareRemovePhase(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
tmpDir := t.TempDir()
multi := NewMultiPhaseLuaMiddleware(engine, "multi-test")
scriptPath := filepath.Join(tmpDir, "test.lua")
err = os.WriteFile(scriptPath, []byte("return 1"), 0o644)
require.NoError(t, err)
err = multi.AddPhase(PhaseRewrite, scriptPath, 10*time.Second)
require.NoError(t, err)
assert.Equal(t, 1, multi.PhaseCount())
// 移除阶段
multi.RemovePhase(PhaseRewrite)
assert.Equal(t, 0, multi.PhaseCount())
assert.False(t, multi.HasPhase(PhaseRewrite))
}
// TestMultiPhaseLuaMiddlewareProcess 测试多阶段执行
func TestMultiPhaseLuaMiddlewareProcess(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
tmpDir := t.TempDir()
multi := NewMultiPhaseLuaMiddleware(engine, "multi-test")
// rewrite 阎段脚本
rewriteScript := filepath.Join(tmpDir, "rewrite.lua")
err = os.WriteFile(rewriteScript, []byte(`ngx.say("rewrite")`), 0o644)
require.NoError(t, err)
err = multi.AddPhase(PhaseRewrite, rewriteScript, 10*time.Second)
require.NoError(t, err)
// content 阎段脚本
contentScript := filepath.Join(tmpDir, "content.lua")
err = os.WriteFile(contentScript, []byte(`ngx.say("content")`), 0o644)
require.NoError(t, err)
err = multi.AddPhase(PhaseContent, contentScript, 10*time.Second)
require.NoError(t, err)
// 创建 RequestCtx
ctx := &fasthttp.RequestCtx{}
// 创建最终处理器
finalHandler := func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("final")
}
// 包装处理器
handler := multi.Process(finalHandler)
// 执行
handler(ctx)
// 验证执行顺序rewrite -> content -> final
body := string(ctx.Response.Body())
// 注意:由于 Lua 输出会追加到响应体,顺序可能不同
assert.Contains(t, body, "rewrite")
assert.Contains(t, body, "content")
}
// TestMultiPhaseLuaMiddlewareGetPhaseMiddleware 测试获取阶段中间件
func TestMultiPhaseLuaMiddlewareGetPhaseMiddleware(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
tmpDir := t.TempDir()
multi := NewMultiPhaseLuaMiddleware(engine, "multi-test")
scriptPath := filepath.Join(tmpDir, "test.lua")
err = os.WriteFile(scriptPath, []byte("return 1"), 0o644)
require.NoError(t, err)
err = multi.AddPhase(PhaseRewrite, scriptPath, 10*time.Second)
require.NoError(t, err)
// 获取阶段中间件
middleware := multi.GetPhaseMiddleware(PhaseRewrite)
require.NotNil(t, middleware)
assert.Equal(t, PhaseRewrite, middleware.GetPhase())
// 获取不存在的阶段
middleware = multi.GetPhaseMiddleware(PhaseAccess)
assert.Nil(t, middleware)
}
// TestLuaMiddlewareIntegrationWithChain 测试与 middleware chain 集成
func TestLuaMiddlewareIntegrationWithChain(t *testing.T) {
// 这个测试验证 LuaMiddleware 可以与现有的 middleware 链集成
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
tmpDir := t.TempDir()
scriptPath := filepath.Join(tmpDir, "test.lua")
err = os.WriteFile(scriptPath, []byte(`ngx.say("lua middleware")`), 0o644)
require.NoError(t, err)
config := LuaMiddlewareConfig{
ScriptPath: scriptPath,
Phase: PhaseContent,
Name: "lua-content",
}
middleware, err := NewLuaMiddleware(engine, config)
require.NoError(t, err)
// 验证实现了 Middleware 接口
// Name() 和 Process() 方法已实现
assert.Equal(t, "lua-content", middleware.Name())
// 创建 RequestCtx
ctx := &fasthttp.RequestCtx{}
// 创建处理器
handler := middleware.Process(func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("next")
})
// 执行
handler(ctx)
// 验证输出
body := string(ctx.Response.Body())
assert.Contains(t, body, "lua middleware")
}
// TestLuaMiddlewareExecutionError 测试执行错误处理
func TestLuaMiddlewareExecutionError(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
// 创建有语法错误的脚本
tmpDir := t.TempDir()
scriptPath := filepath.Join(tmpDir, "error.lua")
err = os.WriteFile(scriptPath, []byte("invalid lua syntax !!!"), 0o644)
require.NoError(t, err)
config := LuaMiddlewareConfig{
ScriptPath: scriptPath,
Phase: PhaseContent,
}
middleware, err := NewLuaMiddleware(engine, config)
require.NoError(t, err)
ctx := &fasthttp.RequestCtx{}
handler := middleware.Process(func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("final")
})
handler(ctx)
// 执行错误时返回 500
assert.Equal(t, fasthttp.StatusInternalServerError, ctx.Response.StatusCode())
}
// TestLuaMiddlewareExit 测试 ngx.exit() 终止执行
func TestLuaMiddlewareExit(t *testing.T) {
engine, err := NewEngine(DefaultConfig())
require.NoError(t, err)
defer engine.Close()
tmpDir := t.TempDir()
scriptPath := filepath.Join(tmpDir, "exit.lua")
err = os.WriteFile(scriptPath, []byte(`ngx.say("before exit"); ngx.exit(200)`), 0o644)
require.NoError(t, err)
config := LuaMiddlewareConfig{
ScriptPath: scriptPath,
Phase: PhaseContent,
}
middleware, err := NewLuaMiddleware(engine, config)
require.NoError(t, err)
ctx := &fasthttp.RequestCtx{}
nextCalled := false
handler := middleware.Process(func(ctx *fasthttp.RequestCtx) {
nextCalled = true
ctx.WriteString("next handler")
})
handler(ctx)
// ngx.exit() 终止执行next handler 不应被调用
assert.False(t, nextCalled)
// 状态码应为 200
assert.Equal(t, 200, ctx.Response.StatusCode())
// 输出包含 Lua 输出
body := string(ctx.Response.Body())
assert.Contains(t, body, "before exit")
}