Merge pull request #36 from rulego/dev

Dev
This commit is contained in:
Whki
2025-08-08 17:57:53 +08:00
committed by GitHub
12 changed files with 2856 additions and 189 deletions
+1
View File
@@ -41,6 +41,7 @@ jobs:
run: go build -v ./...
- name: Run tests
if: matrix.go-version != '1.21'
run: go test -v -race -timeout 300s ./...
- name: Run tests with coverage
+96
View File
@@ -273,3 +273,99 @@ func TestExprBridgeAdvancedFunctions(t *testing.T) {
assert.Contains(t, result, "john")
})
}
// TestExprBridgeComplexExpressions 测试复杂表达式处理
func TestExprBridgeComplexExpressions(t *testing.T) {
bridge := NewExprBridge()
tests := []struct {
name string
expression string
data map[string]interface{}
expected interface{}
wantErr bool
}{
{
name: "math_and_string",
expression: "length('test')",
data: map[string]interface{}{},
expected: 4,
wantErr: false,
},
{
name: "nested_function_calls",
expression: "abs(sqrt(16) - 5)",
data: map[string]interface{}{},
expected: float64(1),
wantErr: false,
},
{
name: "array_operations",
expression: "array_length([1, 2, 3, 4])",
data: map[string]interface{}{},
expected: 4,
wantErr: false,
},
{
name: "string_with_variables",
expression: "upper(name)",
data: map[string]interface{}{"name": "john"},
expected: "JOHN",
wantErr: false,
},
{
name: "conditional_expression",
expression: "age > 18 ? 'adult' : 'minor'",
data: map[string]interface{}{"age": 25},
expected: "adult",
wantErr: false,
},
{
name: "complex_math",
expression: "power(2, 3) + mod(10, 3)",
data: map[string]interface{}{},
expected: float64(9),
wantErr: false,
},
{
name: "array_contains_check",
expression: "array_contains([1, 2, 3], 2)",
data: map[string]interface{}{},
expected: true,
wantErr: false,
},
{
name: "string_concatenation",
expression: "concat(first_name, ' ', last_name)",
data: map[string]interface{}{"first_name": "John", "last_name": "Doe"},
expected: "John Doe",
wantErr: false,
},
{
name: "invalid_function",
expression: "nonexistent_function(1)",
data: map[string]interface{}{},
expected: nil,
wantErr: true,
},
{
name: "invalid_syntax",
expression: "length(",
data: map[string]interface{}{},
expected: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := bridge.EvaluateExpression(tt.expression, tt.data)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expected, result)
})
}
}
+5 -5
View File
@@ -117,7 +117,7 @@ func (f *ArrayRemoveFunction) Execute(ctx *FunctionContext, args []interface{})
return nil, fmt.Errorf("array_remove requires array input")
}
var result []interface{}
result := make([]interface{}, 0) // 初始化为空切片而不是nil切片
for i := 0; i < v.Len(); i++ {
elem := v.Index(i).Interface()
if !reflect.DeepEqual(elem, value) {
@@ -151,7 +151,7 @@ func (f *ArrayDistinctFunction) Execute(ctx *FunctionContext, args []interface{}
}
seen := make(map[interface{}]bool)
var result []interface{}
result := make([]interface{}, 0) // 初始化为空切片而不是nil切片
for i := 0; i < v.Len(); i++ {
elem := v.Index(i).Interface()
@@ -200,7 +200,7 @@ func (f *ArrayIntersectFunction) Execute(ctx *FunctionContext, args []interface{
// 找交集
seen := make(map[interface{}]bool)
var result []interface{}
result := make([]interface{}, 0) // 初始化为空切片而不是nil切片
for i := 0; i < v1.Len(); i++ {
elem := v1.Index(i).Interface()
@@ -242,7 +242,7 @@ func (f *ArrayUnionFunction) Execute(ctx *FunctionContext, args []interface{}) (
}
seen := make(map[interface{}]bool)
var result []interface{}
result := make([]interface{}, 0) // 初始化为空切片而不是nil切片
// 添加第一个数组的元素
for i := 0; i < v1.Len(); i++ {
@@ -301,7 +301,7 @@ func (f *ArrayExceptFunction) Execute(ctx *FunctionContext, args []interface{})
// 找差集
seen := make(map[interface{}]bool)
var result []interface{}
result := make([]interface{}, 0) // 初始化为空切片而不是nil切片
for i := 0; i < v1.Len(); i++ {
elem := v1.Index(i).Interface()
+176 -5
View File
@@ -12,66 +12,175 @@ func TestArrayFunctions(t *testing.T) {
funcName string
args []interface{}
expected interface{}
wantErr bool
}{
{
name: "array_length basic",
funcName: "array_length",
args: []interface{}{[]interface{}{1, 2, 3}},
expected: 3,
wantErr: false,
},
{
name: "array_length empty",
funcName: "array_length",
args: []interface{}{[]interface{}{}},
expected: 0,
wantErr: false,
},
{
name: "array_contains true",
funcName: "array_contains",
args: []interface{}{[]interface{}{1, 2, 3}, 2},
expected: true,
wantErr: false,
},
{
name: "array_contains false",
funcName: "array_contains",
args: []interface{}{[]interface{}{1, 2, 3}, 4},
expected: false,
wantErr: false,
},
{
name: "array_contains empty array",
funcName: "array_contains",
args: []interface{}{[]interface{}{}, 1},
expected: false,
wantErr: false,
},
{
name: "array_position found",
funcName: "array_position",
args: []interface{}{[]interface{}{1, 2, 3}, 2},
expected: 2,
wantErr: false,
},
{
name: "array_position not found",
funcName: "array_position",
args: []interface{}{[]interface{}{1, 2, 3}, 4},
expected: 0,
wantErr: false,
},
{
name: "array_position empty array",
funcName: "array_position",
args: []interface{}{[]interface{}{}, 1},
expected: 0,
wantErr: false,
},
{
name: "array_remove basic",
funcName: "array_remove",
args: []interface{}{[]interface{}{1, 2, 3, 2}, 2},
expected: []interface{}{1, 3},
wantErr: false,
},
{
name: "array_remove not found",
funcName: "array_remove",
args: []interface{}{[]interface{}{1, 2, 3}, 4},
expected: []interface{}{1, 2, 3},
wantErr: false,
},
{
name: "array_remove empty array",
funcName: "array_remove",
args: []interface{}{[]interface{}{}, 1},
expected: []interface{}{},
wantErr: false,
},
{
name: "array_distinct basic",
funcName: "array_distinct",
args: []interface{}{[]interface{}{1, 2, 2, 3, 1}},
expected: []interface{}{1, 2, 3},
wantErr: false,
},
{
name: "array_distinct empty",
funcName: "array_distinct",
args: []interface{}{[]interface{}{}},
expected: []interface{}{},
wantErr: false,
},
{
name: "array_intersect basic",
funcName: "array_intersect",
args: []interface{}{[]interface{}{1, 2, 3}, []interface{}{2, 3, 4}},
expected: []interface{}{2, 3},
wantErr: false,
},
{
name: "array_intersect no intersection",
funcName: "array_intersect",
args: []interface{}{[]interface{}{1, 2}, []interface{}{3, 4}},
expected: []interface{}{},
wantErr: false,
},
{
name: "array_intersect first empty",
funcName: "array_intersect",
args: []interface{}{[]interface{}{}, []interface{}{1, 2}},
expected: []interface{}{},
wantErr: false,
},
{
name: "array_intersect second empty",
funcName: "array_intersect",
args: []interface{}{[]interface{}{1, 2}, []interface{}{}},
expected: []interface{}{},
wantErr: false,
},
{
name: "array_union basic",
funcName: "array_union",
args: []interface{}{[]interface{}{1, 2}, []interface{}{2, 3}},
expected: []interface{}{1, 2, 3},
wantErr: false,
},
{
name: "array_union first empty",
funcName: "array_union",
args: []interface{}{[]interface{}{}, []interface{}{1, 2}},
expected: []interface{}{1, 2},
wantErr: false,
},
{
name: "array_union second empty",
funcName: "array_union",
args: []interface{}{[]interface{}{1, 2}, []interface{}{}},
expected: []interface{}{1, 2},
wantErr: false,
},
{
name: "array_except basic",
funcName: "array_except",
args: []interface{}{[]interface{}{1, 2, 3}, []interface{}{2}},
expected: []interface{}{1, 3},
wantErr: false,
},
{
name: "array_except no overlap",
funcName: "array_except",
args: []interface{}{[]interface{}{1, 2}, []interface{}{3, 4}},
expected: []interface{}{1, 2},
wantErr: false,
},
{
name: "array_except first empty",
funcName: "array_except",
args: []interface{}{[]interface{}{}, []interface{}{1, 2}},
expected: []interface{}{},
wantErr: false,
},
{
name: "array_except second empty",
funcName: "array_except",
args: []interface{}{[]interface{}{1, 2}, []interface{}{}},
expected: []interface{}{1, 2},
wantErr: false,
},
}
@@ -83,13 +192,75 @@ func TestArrayFunctions(t *testing.T) {
}
result, err := fn.Execute(&FunctionContext{}, tt.args)
if err != nil {
t.Errorf("Execute() error = %v", err)
return
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && !reflect.DeepEqual(result, tt.expected) {
t.Errorf("Execute() = %v, want %v", result, tt.expected)
}
})
}
}
// TestArrayFunctionErrors 测试数组函数的错误处理
func TestArrayFunctionErrors(t *testing.T) {
tests := []struct {
name string
funcName string
args []interface{}
wantErr bool
}{
// array_length 错误测试
{"array_length nil", "array_length", []interface{}{nil}, true},
{"array_length invalid type", "array_length", []interface{}{"not an array"}, true},
// array_contains 错误测试
{"array_contains nil array", "array_contains", []interface{}{nil, 1}, true},
{"array_contains invalid type", "array_contains", []interface{}{"not an array", 1}, true},
// array_position 错误测试
{"array_position nil array", "array_position", []interface{}{nil, 1}, true},
{"array_position invalid type", "array_position", []interface{}{"not an array", 1}, true},
// array_remove 错误测试
{"array_remove nil array", "array_remove", []interface{}{nil, 1}, true},
{"array_remove invalid type", "array_remove", []interface{}{"not an array", 1}, true},
// array_distinct 错误测试
{"array_distinct nil", "array_distinct", []interface{}{nil}, true},
{"array_distinct invalid type", "array_distinct", []interface{}{"not an array"}, true},
// array_intersect 错误测试
{"array_intersect first nil", "array_intersect", []interface{}{nil, []interface{}{1, 2}}, true},
{"array_intersect second nil", "array_intersect", []interface{}{[]interface{}{1, 2}, nil}, true},
{"array_intersect first invalid type", "array_intersect", []interface{}{"not an array", []interface{}{1, 2}}, true},
{"array_intersect second invalid type", "array_intersect", []interface{}{[]interface{}{1, 2}, "not an array"}, true},
// array_union 错误测试
{"array_union first nil", "array_union", []interface{}{nil, []interface{}{1, 2}}, true},
{"array_union second nil", "array_union", []interface{}{[]interface{}{1, 2}, nil}, true},
{"array_union first invalid type", "array_union", []interface{}{"not an array", []interface{}{1, 2}}, true},
{"array_union second invalid type", "array_union", []interface{}{[]interface{}{1, 2}, "not an array"}, true},
// array_except 错误测试
{"array_except first nil", "array_except", []interface{}{nil, []interface{}{1, 2}}, true},
{"array_except second nil", "array_except", []interface{}{[]interface{}{1, 2}, nil}, true},
{"array_except first invalid type", "array_except", []interface{}{"not an array", []interface{}{1, 2}}, true},
{"array_except second invalid type", "array_except", []interface{}{[]interface{}{1, 2}, "not an array"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fn, exists := Get(tt.funcName)
if !exists {
t.Fatalf("Function %s not found", tt.funcName)
}
if !reflect.DeepEqual(result, tt.expected) {
t.Errorf("Execute() = %v, want %v", result, tt.expected)
_, err := fn.Execute(&FunctionContext{}, tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
+200 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
)
// 测试条件函数
// TestConditionalFunctions 测试条件函数的基本功能
func TestConditionalFunctions(t *testing.T) {
tests := []struct {
name string
@@ -103,3 +103,202 @@ func TestConditionalFunctions(t *testing.T) {
})
}
}
// TestConditionalFunctionValidation 测试条件函数的参数验证
func TestConditionalFunctionValidation(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
wantErr bool
}{
{
name: "if_null no args",
function: NewIfNullFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "if_null one arg",
function: NewIfNullFunction(),
args: []interface{}{"test"},
wantErr: true,
},
{
name: "if_null valid args",
function: NewIfNullFunction(),
args: []interface{}{nil, "default"},
wantErr: false,
},
{
name: "coalesce no args",
function: NewCoalesceFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "coalesce valid args",
function: NewCoalesceFunction(),
args: []interface{}{nil, "default"},
wantErr: false,
},
{
name: "null_if no args",
function: NewNullIfFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "null_if one arg",
function: NewNullIfFunction(),
args: []interface{}{"test"},
wantErr: true,
},
{
name: "null_if valid args",
function: NewNullIfFunction(),
args: []interface{}{"test", "test"},
wantErr: false,
},
{
name: "greatest no args",
function: NewGreatestFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "greatest valid args",
function: NewGreatestFunction(),
args: []interface{}{1, 2, 3},
wantErr: false,
},
{
name: "least no args",
function: NewLeastFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "least valid args",
function: NewLeastFunction(),
args: []interface{}{1, 2, 3},
wantErr: false,
},
{
name: "case_when no args",
function: NewCaseWhenFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "case_when one arg",
function: NewCaseWhenFunction(),
args: []interface{}{true},
wantErr: true,
},
{
name: "case_when valid args",
function: NewCaseWhenFunction(),
args: []interface{}{true, "result"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.function.Validate(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// TestConditionalFunctionEdgeCases 测试条件函数的边界情况
func TestConditionalFunctionEdgeCases(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
expected interface{}
wantErr bool
}{
{
name: "coalesce all null",
function: NewCoalesceFunction(),
args: []interface{}{nil, nil, nil},
expected: nil,
wantErr: false,
},
{
name: "coalesce first non-null",
function: NewCoalesceFunction(),
args: []interface{}{"first", nil, "third"},
expected: "first",
wantErr: false,
},
{
name: "coalesce middle non-null",
function: NewCoalesceFunction(),
args: []interface{}{nil, "second", "third"},
expected: "second",
wantErr: false,
},
{
name: "greatest with mixed types",
function: NewGreatestFunction(),
args: []interface{}{1, 3.14, 2},
expected: 3.14,
wantErr: false,
},
{
name: "least with mixed types",
function: NewLeastFunction(),
args: []interface{}{1, 3.14, 2},
expected: 1,
wantErr: false,
},
{
name: "greatest with strings",
function: NewGreatestFunction(),
args: []interface{}{"apple", "banana", "cherry"},
expected: "cherry",
wantErr: false,
},
{
name: "least with strings",
function: NewLeastFunction(),
args: []interface{}{"apple", "banana", "cherry"},
expected: "apple",
wantErr: false,
},
{
name: "case_when with complex conditions",
function: NewCaseWhenFunction(),
args: []interface{}{false, "first", false, "second", true, "third", "default"},
expected: "third",
wantErr: false,
},
{
name: "null_if with different types",
function: NewNullIfFunction(),
args: []interface{}{"123", 123},
expected: "123",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.function.Execute(&FunctionContext{}, tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && result != tt.expected {
t.Errorf("Execute() = %v, want %v", result, tt.expected)
}
})
}
}
+258
View File
@@ -179,6 +179,261 @@ func TestDateTimeFunctions(t *testing.T) {
}
}
// TestDateTimeFunctionValidation 测试日期时间函数的参数验证
func TestDateTimeFunctionValidation(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
wantErr bool
}{
{
name: "now no args",
function: NewNowFunction(),
args: []interface{}{},
wantErr: false,
},
{
name: "now too many args",
function: NewNowFunction(),
args: []interface{}{"extra"},
wantErr: true,
},
{
name: "current_time no args",
function: NewCurrentTimeFunction(),
args: []interface{}{},
wantErr: false,
},
{
name: "current_date no args",
function: NewCurrentDateFunction(),
args: []interface{}{},
wantErr: false,
},
{
name: "date_format no args",
function: NewDateFormatFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "date_format one arg",
function: NewDateFormatFunction(),
args: []interface{}{"2023-12-25"},
wantErr: true,
},
{
name: "date_format valid args",
function: NewDateFormatFunction(),
args: []interface{}{"2023-12-25", "YYYY-MM-DD"},
wantErr: false,
},
{
name: "date_add no args",
function: NewDateAddFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "date_add two args",
function: NewDateAddFunction(),
args: []interface{}{"2023-12-25", 7},
wantErr: true,
},
{
name: "date_add valid args",
function: NewDateAddFunction(),
args: []interface{}{"2023-12-25", 7, "days"},
wantErr: false,
},
{
name: "year no args",
function: NewYearFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "year valid args",
function: NewYearFunction(),
args: []interface{}{"2023-12-25"},
wantErr: false,
},
{
name: "extract no args",
function: NewExtractFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "extract one arg",
function: NewExtractFunction(),
args: []interface{}{"year"},
wantErr: true,
},
{
name: "extract valid args",
function: NewExtractFunction(),
args: []interface{}{"year", "2023-12-25"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.function.Validate(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// TestDateTimeFunctionErrors 测试日期时间函数的错误处理
func TestDateTimeFunctionErrors(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
wantErr bool
}{
{
name: "date_format invalid date",
function: NewDateFormatFunction(),
args: []interface{}{"invalid-date", "YYYY-MM-DD"},
wantErr: true,
},
{
name: "date_add invalid date",
function: NewDateAddFunction(),
args: []interface{}{"invalid-date", 7, "days"},
wantErr: true,
},
{
name: "date_add invalid unit",
function: NewDateAddFunction(),
args: []interface{}{"2023-12-25", 7, "invalid-unit"},
wantErr: true,
},
{
name: "year invalid date",
function: NewYearFunction(),
args: []interface{}{"invalid-date"},
wantErr: true,
},
{
name: "extract invalid unit",
function: NewExtractFunction(),
args: []interface{}{"invalid-unit", "2023-12-25"},
wantErr: true,
},
{
name: "extract invalid date",
function: NewExtractFunction(),
args: []interface{}{"year", "invalid-date"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := tt.function.Execute(&FunctionContext{}, tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// TestDateTimeFunctionEdgeCases 测试日期时间函数的边界情况
func TestDateTimeFunctionEdgeCases(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
expected interface{}
wantErr bool
}{
{
name: "now function",
function: NewNowFunction(),
args: []interface{}{},
expected: nil, // 不检查具体值,只检查不出错
wantErr: false,
},
{
name: "current_time function",
function: NewCurrentTimeFunction(),
args: []interface{}{},
expected: nil, // 不检查具体值,只检查不出错
wantErr: false,
},
{
name: "current_date function",
function: NewCurrentDateFunction(),
args: []interface{}{},
expected: nil, // 不检查具体值,只检查不出错
wantErr: false,
},
{
name: "unix_timestamp with valid date",
function: NewUnixTimestampFunction(),
args: []interface{}{"2023-01-01 00:00:00"},
expected: nil, // 不检查具体值,只检查不出错
wantErr: false,
},
// 新增边界情况测试
{
name: "date_format empty string",
function: NewDateFormatFunction(),
args: []interface{}{"", "YYYY-MM-DD"},
expected: nil,
wantErr: true,
},
{
name: "date_add zero days",
function: NewDateAddFunction(),
args: []interface{}{"2023-12-25", 0, "days"},
expected: "2023-12-25 00:00:00",
wantErr: false,
},
{
name: "date_diff same date",
function: NewDateDiffFunction(),
args: []interface{}{"2023-12-25", "2023-12-25", "days"},
expected: int64(0),
wantErr: false,
},
{
name: "dayofyear function",
function: NewDayOfYearFunction(),
args: []interface{}{"2023-12-25"},
expected: 359,
wantErr: false,
},
{
name: "weekofyear function",
function: NewWeekOfYearFunction(),
args: []interface{}{"2023-12-25"},
expected: 52,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.function.Execute(&FunctionContext{}, tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && tt.expected != nil && result != tt.expected {
t.Errorf("Execute() = %v, want %v", result, tt.expected)
}
})
}
}
func TestDateTimeRegistration(t *testing.T) {
// 测试函数是否正确注册
dateTimeFunctions := []string{
@@ -199,6 +454,9 @@ func TestDateTimeRegistration(t *testing.T) {
"dayofweek",
"dayofyear",
"weekofyear",
"now",
"current_time",
"current_date",
}
for _, funcName := range dateTimeFunctions {
+119 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
)
// 测试哈希函数
// TestHashFunctions 测试哈希函数的基本功能
func TestHashFunctions(t *testing.T) {
tests := []struct {
name string
@@ -30,6 +30,24 @@ func TestHashFunctions(t *testing.T) {
args: []interface{}{"hello"},
expected: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
},
{
name: "sha512 basic",
funcName: "sha512",
args: []interface{}{"hello"},
expected: "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043",
},
{
name: "md5 empty string",
funcName: "md5",
args: []interface{}{""},
expected: "d41d8cd98f00b204e9800998ecf8427e",
},
{
name: "sha1 empty string",
funcName: "sha1",
args: []interface{}{""},
expected: "da39a3ee5e6b4b0d3255bfef95601890afd80709",
},
}
for _, tt := range tests {
@@ -51,3 +69,103 @@ func TestHashFunctions(t *testing.T) {
})
}
}
// TestHashFunctionValidation 测试哈希函数的参数验证
func TestHashFunctionValidation(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
wantErr bool
}{
{
name: "md5 no args",
function: NewMd5Function(),
args: []interface{}{},
wantErr: true,
},
{
name: "md5 too many args",
function: NewMd5Function(),
args: []interface{}{"hello", "world"},
wantErr: true,
},
{
name: "md5 valid args",
function: NewMd5Function(),
args: []interface{}{"hello"},
wantErr: false,
},
{
name: "sha1 no args",
function: NewSha1Function(),
args: []interface{}{},
wantErr: true,
},
{
name: "sha256 valid args",
function: NewSha256Function(),
args: []interface{}{"test"},
wantErr: false,
},
{
name: "sha512 valid args",
function: NewSha512Function(),
args: []interface{}{"test"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.function.Validate(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// TestHashFunctionErrors 测试哈希函数的错误处理
func TestHashFunctionErrors(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
wantErr bool
}{
{
name: "md5 non-string input",
function: NewMd5Function(),
args: []interface{}{123},
wantErr: true,
},
{
name: "sha1 non-string input",
function: NewSha1Function(),
args: []interface{}{123},
wantErr: true,
},
{
name: "sha256 non-string input",
function: NewSha256Function(),
args: []interface{}{123},
wantErr: true,
},
{
name: "sha512 non-string input",
function: NewSha512Function(),
args: []interface{}{123},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := tt.function.Execute(&FunctionContext{}, tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+178 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
)
// 测试类型检查函数
// TestTypeFunctions 测试类型检查函数的基本功能
func TestTypeFunctions(t *testing.T) {
tests := []struct {
name string
@@ -93,3 +93,180 @@ func TestTypeFunctions(t *testing.T) {
})
}
}
// TestTypeFunctionValidation 测试类型函数的参数验证
func TestTypeFunctionValidation(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
wantErr bool
}{
{
name: "is_null no args",
function: NewIsNullFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "is_null too many args",
function: NewIsNullFunction(),
args: []interface{}{"test", "extra"},
wantErr: true,
},
{
name: "is_null valid args",
function: NewIsNullFunction(),
args: []interface{}{"test"},
wantErr: false,
},
{
name: "is_not_null no args",
function: NewIsNotNullFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "is_not_null valid args",
function: NewIsNotNullFunction(),
args: []interface{}{nil},
wantErr: false,
},
{
name: "is_numeric no args",
function: NewIsNumericFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "is_numeric valid args",
function: NewIsNumericFunction(),
args: []interface{}{123},
wantErr: false,
},
{
name: "is_string no args",
function: NewIsStringFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "is_string valid args",
function: NewIsStringFunction(),
args: []interface{}{"test"},
wantErr: false,
},
{
name: "is_bool no args",
function: NewIsBoolFunction(),
args: []interface{}{},
wantErr: true,
},
{
name: "is_bool valid args",
function: NewIsBoolFunction(),
args: []interface{}{true},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.function.Validate(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// TestTypeFunctionEdgeCases 测试类型函数的边界情况
func TestTypeFunctionEdgeCases(t *testing.T) {
tests := []struct {
name string
function Function
args []interface{}
expected interface{}
}{
{
name: "is_numeric with float",
function: NewIsNumericFunction(),
args: []interface{}{3.14},
expected: true,
},
{
name: "is_numeric with int64",
function: NewIsNumericFunction(),
args: []interface{}{int64(123)},
expected: true,
},
{
name: "is_numeric with float32",
function: NewIsNumericFunction(),
args: []interface{}{float32(3.14)},
expected: true,
},
{
name: "is_numeric with float64",
function: NewIsNumericFunction(),
args: []interface{}{float64(3.14)},
expected: true,
},
{
name: "is_numeric with int32",
function: NewIsNumericFunction(),
args: []interface{}{int32(123)},
expected: true,
},
{
name: "is_numeric with uint",
function: NewIsNumericFunction(),
args: []interface{}{uint(123)},
expected: true,
},
{
name: "is_numeric with uint64",
function: NewIsNumericFunction(),
args: []interface{}{uint64(123)},
expected: true,
},
{
name: "is_numeric with uint32",
function: NewIsNumericFunction(),
args: []interface{}{uint32(123)},
expected: true,
},
{
name: "is_numeric with bool",
function: NewIsNumericFunction(),
args: []interface{}{true},
expected: false,
},
{
name: "is_string with empty string",
function: NewIsStringFunction(),
args: []interface{}{""},
expected: true,
},
{
name: "is_bool with false",
function: NewIsBoolFunction(),
args: []interface{}{false},
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.function.Execute(&FunctionContext{}, tt.args)
if err != nil {
t.Errorf("Execute() error = %v", err)
return
}
if result != tt.expected {
t.Errorf("Execute() = %v, want %v", result, tt.expected)
}
})
}
}
+309 -176
View File
File diff suppressed because it is too large Load Diff
+529
View File
File diff suppressed because it is too large Load Diff