Files
2025-08-29 17:30:58 +08:00

597 lines
15 KiB
Go

package functions
import (
"errors"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
// TestFunction 是用于测试的简单函数实现
type TestFunction struct {
name string
fnType FunctionType
category string
description string
minArgs int
maxArgs int
executor func(ctx *FunctionContext, args []interface{}) (interface{}, error)
}
func (f *TestFunction) GetName() string { return f.name }
func (f *TestFunction) GetType() FunctionType { return f.fnType }
func (f *TestFunction) GetCategory() string { return f.category }
func (f *TestFunction) GetAliases() []string { return []string{} }
func (f *TestFunction) GetDescription() string { return f.description }
func (f *TestFunction) GetMinArgs() int { return f.minArgs }
func (f *TestFunction) GetMaxArgs() int { return f.maxArgs }
func (f *TestFunction) Validate(args []interface{}) error {
if len(args) < f.minArgs {
return fmt.Errorf("not enough arguments: expected at least %d, got %d", f.minArgs, len(args))
}
if f.maxArgs >= 0 && len(args) > f.maxArgs {
return fmt.Errorf("too many arguments: expected at most %d, got %d", f.maxArgs, len(args))
}
return nil
}
func (f *TestFunction) Execute(ctx *FunctionContext, args []interface{}) (interface{}, error) {
if f.executor != nil {
return f.executor(ctx, args)
}
return "test_result", nil
}
func TestRegistryEdgeCases(t *testing.T) {
// 测试注册nil函数
t.Run("Register nil function", func(t *testing.T) {
err := Register(nil)
assert.Error(t, err)
})
// 测试注册重复函数名
t.Run("Register duplicate name", func(t *testing.T) {
testFunc1 := &TestFunction{
name: "duplicate_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
}
testFunc2 := &TestFunction{
name: "duplicate_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
}
// 先注册第一个函数
err := Register(testFunc1)
assert.NoError(t, err)
// 尝试注册同名函数
err = Register(testFunc2)
assert.Error(t, err)
assert.Contains(t, err.Error(), "already registered")
// 清理
Unregister("duplicate_func")
})
}
// TestGetFunctionEdgeCases 测试Get函数的边界情况
func TestGetFunctionEdgeCases(t *testing.T) {
// 测试获取不存在的函数
t.Run("Get non-existent function", func(t *testing.T) {
func_, exists := Get("non_existent_func")
assert.False(t, exists)
assert.Nil(t, func_)
})
// 测试获取空名称函数
t.Run("Get empty name function", func(t *testing.T) {
func_, exists := Get("")
assert.False(t, exists)
assert.Nil(t, func_)
})
// 测试大小写不敏感性(函数名会被转换为小写)
t.Run("Case insensitivity", func(t *testing.T) {
testFunc := &TestFunction{
name: "lowercase_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
}
// 注册小写函数名
err := Register(testFunc)
assert.NoError(t, err)
// 用大写获取应该也能找到(因为内部转换为小写)
func_, exists := Get("LOWERCASE_FUNC")
assert.True(t, exists)
assert.NotNil(t, func_)
// 用正确的小写获取
func_, exists = Get("lowercase_func")
assert.True(t, exists)
assert.NotNil(t, func_)
// 清理
Unregister("lowercase_func")
})
}
// TestUnregisterEdgeCases 测试Unregister函数的边界情况
func TestUnregisterEdgeCases(t *testing.T) {
// 测试注销不存在的函数
t.Run("Unregister non-existent function", func(t *testing.T) {
// 这应该不会引起panic或错误
result := Unregister("non_existent_func")
assert.False(t, result)
// 验证函数确实不存在
func_, exists := Get("non_existent_func")
assert.False(t, exists)
assert.Nil(t, func_)
})
// 测试注销空名称函数
t.Run("Unregister empty name", func(t *testing.T) {
// 这应该不会引起panic或错误
result := Unregister("")
assert.False(t, result)
})
// 测试注销后再次注销
t.Run("Double unregister", func(t *testing.T) {
testFunc := &TestFunction{
name: "double_unregister_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
}
// 注册函数
err := Register(testFunc)
assert.NoError(t, err)
// 第一次注销
result := Unregister("double_unregister_func")
assert.True(t, result)
func_, exists := Get("double_unregister_func")
assert.False(t, exists)
assert.Nil(t, func_)
// 第二次注销(应该不会有问题)
result = Unregister("double_unregister_func")
assert.False(t, result)
})
}
// TestListAllEdgeCases 测试ListAll函数的边界情况
func TestListAllEdgeCases(t *testing.T) {
// 注册一些测试函数
testFunctions := []*TestFunction{
{
name: "test_func1",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
},
{
name: "test_func2",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
},
{
name: "test_func3",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
},
}
for _, fn := range testFunctions {
err := Register(fn)
assert.NoError(t, err)
}
// 测试非空注册表
t.Run("Non-empty registry", func(t *testing.T) {
functions := ListAll()
assert.GreaterOrEqual(t, len(functions), 3) // 至少包含我们注册的3个函数
_, exists1 := functions["test_func1"]
_, exists2 := functions["test_func2"]
_, exists3 := functions["test_func3"]
assert.True(t, exists1)
assert.True(t, exists2)
assert.True(t, exists3)
})
// 清理测试函数
for _, fn := range testFunctions {
Unregister(fn.name)
}
}
// TestExecuteEdgeCases 测试Execute函数的边界情况
func TestExecuteEdgeCases(t *testing.T) {
// 测试执行不存在的函数
t.Run("Execute non-existent function", func(t *testing.T) {
ctx := &FunctionContext{}
result, err := Execute("non_existent_func", ctx, []interface{}{})
assert.Error(t, err)
assert.Nil(t, result)
assert.Contains(t, err.Error(), "not found")
})
// 测试执行返回错误的函数
t.Run("Execute function that returns error", func(t *testing.T) {
errorFunc := &TestFunction{
name: "error_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return nil, errors.New("test error")
},
}
err := Register(errorFunc)
assert.NoError(t, err)
ctx := &FunctionContext{}
result, err := Execute("error_func", ctx, []interface{}{})
assert.Error(t, err)
assert.Nil(t, result)
assert.Contains(t, err.Error(), "test error")
// 清理
Unregister("error_func")
})
// 测试执行带参数的函数
t.Run("Execute function with arguments", func(t *testing.T) {
sumFunc := &TestFunction{
name: "sum_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
if len(args) == 0 {
return 0, nil
}
sum := 0
for _, arg := range args {
if num, ok := arg.(int); ok {
sum += num
}
}
return sum, nil
},
}
err := Register(sumFunc)
assert.NoError(t, err)
ctx := &FunctionContext{}
// 无参数调用
result, err := Execute("sum_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, 0, result)
// 带参数调用
result, err = Execute("sum_func", ctx, []interface{}{1, 2, 3, 4, 5})
assert.NoError(t, err)
assert.Equal(t, 15, result)
// 清理
Unregister("sum_func")
})
// 测试执行panic的函数
t.Run("Execute function that panics", func(t *testing.T) {
panicFunc := &TestFunction{
name: "panic_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
panic("test panic")
},
}
err := Register(panicFunc)
assert.NoError(t, err)
ctx := &FunctionContext{}
// 执行应该捕获panic并返回错误
assert.Panics(t, func() {
Execute("panic_func", ctx, []interface{}{})
})
// 清理
Unregister("panic_func")
})
}
// TestValidateEdgeCases 测试Validate函数的边界情况
func TestValidateEdgeCases(t *testing.T) {
// 测试验证不存在的函数
t.Run("Validate non-existent function", func(t *testing.T) {
err := Validate("non_existent_func")
assert.Error(t, err)
assert.Contains(t, err.Error(), "function 'non_existent_func' not found")
})
// 测试验证空名称函数
t.Run("Validate empty name function", func(t *testing.T) {
err := Validate("")
assert.Error(t, err)
assert.Contains(t, err.Error(), "function '' not found")
})
// 测试验证有效函数
t.Run("Validate valid function", func(t *testing.T) {
validFunc := &TestFunction{
name: "valid_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return "valid", nil
},
}
err := Register(validFunc)
assert.NoError(t, err)
err = Validate("valid_func")
assert.NoError(t, err)
// 清理
Unregister("valid_func")
})
// 测试验证多个函数
t.Run("Validate multiple functions", func(t *testing.T) {
testFunc1 := &TestFunction{
name: "test_func1",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return "test1", nil
},
}
testFunc2 := &TestFunction{
name: "test_func2",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return "test2", nil
},
}
err := Register(testFunc1)
assert.NoError(t, err)
err = Register(testFunc2)
assert.NoError(t, err)
// 验证存在的函数
err = Validate("test_func1")
assert.NoError(t, err)
err = Validate("test_func2")
assert.NoError(t, err)
// 验证不存在的函数
err = Validate("test_func3")
assert.Error(t, err)
// 清理
Unregister("test_func1")
Unregister("test_func2")
})
}
// TestConcurrentAccess 测试并发访问
func TestConcurrentAccess(t *testing.T) {
// 这个测试检查注册表在并发访问时的行为
// 注意:实际的并发安全需要在registry实现中处理
t.Run("Concurrent register and get", func(t *testing.T) {
testFunc := &TestFunction{
name: "concurrent_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return "concurrent_test", nil
},
}
// 注册函数
err := Register(testFunc)
assert.NoError(t, err)
// 获取函数
func_, exists := Get("concurrent_func")
assert.True(t, exists)
assert.NotNil(t, func_)
ctx := &FunctionContext{}
// 执行函数
result, err := Execute("concurrent_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, "concurrent_test", result)
// 清理
Unregister("concurrent_func")
})
}
// TestFunctionSignatureVariations 测试不同函数签名的变化
func TestFunctionSignatureVariations(t *testing.T) {
// 测试无参数函数
t.Run("No parameter function", func(t *testing.T) {
noParamFunc := &TestFunction{
name: "no_param_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: 0,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
if len(args) != 0 {
return nil, errors.New("expected no arguments")
}
return "no_params", nil
},
}
err := Register(noParamFunc)
assert.NoError(t, err)
ctx := &FunctionContext{}
result, err := Execute("no_param_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, "no_params", result)
// 清理
Unregister("no_param_func")
})
// 测试可变参数函数
t.Run("Variadic parameter function", func(t *testing.T) {
variadicFunc := &TestFunction{
name: "variadic_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return len(args), nil
},
}
err := Register(variadicFunc)
assert.NoError(t, err)
ctx := &FunctionContext{}
// 测试不同数量的参数
result, err := Execute("variadic_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, 0, result)
result, err = Execute("variadic_func", ctx, []interface{}{1})
assert.NoError(t, err)
assert.Equal(t, 1, result)
result, err = Execute("variadic_func", ctx, []interface{}{1, 2, 3})
assert.NoError(t, err)
assert.Equal(t, 3, result)
// 清理
Unregister("variadic_func")
})
// 测试返回不同类型的函数
t.Run("Different return types", func(t *testing.T) {
// 返回字符串
stringFunc := &TestFunction{
name: "string_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return "string_result", nil
},
}
// 返回数字
numberFunc := &TestFunction{
name: "number_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return 42, nil
},
}
// 返回布尔值
boolFunc := &TestFunction{
name: "bool_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return true, nil
},
}
// 返回nil
nilFunc := &TestFunction{
name: "nil_func",
fnType: TypeCustom,
category: "test",
minArgs: 0,
maxArgs: -1,
executor: func(ctx *FunctionContext, args []interface{}) (interface{}, error) {
return nil, nil
},
}
// 注册所有函数
assert.NoError(t, Register(stringFunc))
assert.NoError(t, Register(numberFunc))
assert.NoError(t, Register(boolFunc))
assert.NoError(t, Register(nilFunc))
ctx := &FunctionContext{}
// 测试执行
result, err := Execute("string_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, "string_result", result)
result, err = Execute("number_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, 42, result)
result, err = Execute("bool_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Equal(t, true, result)
result, err = Execute("nil_func", ctx, []interface{}{})
assert.NoError(t, err)
assert.Nil(t, result)
// 清理
Unregister("string_func")
Unregister("number_func")
Unregister("bool_func")
Unregister("nil_func")
})
}