package expr import ( "strings" "testing" "github.com/stretchr/testify/assert" ) // TestValidateExpressionNode 测试表达式节点验证功能 func TestValidateExpressionNode(t *testing.T) { tests := []struct { name string node *ExprNode wantErr bool }{ { "有效数字节点", &ExprNode{Type: TypeNumber, Value: "123"}, false, }, { "有效字段节点", &ExprNode{Type: TypeField, Value: "field1"}, false, }, { "有效字符串节点", &ExprNode{Type: TypeString, Value: "'hello'"}, false, }, { "有效运算符节点", &ExprNode{ Type: TypeOperator, Value: "+", Left: &ExprNode{Type: TypeNumber, Value: "1"}, Right: &ExprNode{Type: TypeNumber, Value: "2"}, }, false, }, { "有效函数节点", &ExprNode{ Type: TypeFunction, Value: "abs", Args: []*ExprNode{{Type: TypeNumber, Value: "1"}}, }, false, }, { "有效CASE节点", &ExprNode{ Type: TypeCase, CaseExpr: &CaseExpression{ WhenClauses: []WhenClause{ { Condition: &ExprNode{ Type: TypeOperator, Value: ">", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, Result: &ExprNode{Type: TypeNumber, Value: "1"}, }, }, ElseResult: &ExprNode{Type: TypeNumber, Value: "0"}, }, }, false, }, // 错误情况 {"空节点", nil, true}, {"无效数字", &ExprNode{Type: TypeNumber, Value: "abc"}, true}, {"无效字段名", &ExprNode{Type: TypeField, Value: "123field"}, true}, {"无效字符串", &ExprNode{Type: TypeString, Value: "hello"}, true}, {"运算符缺少左操作数", &ExprNode{ Type: TypeOperator, Value: "+", Right: &ExprNode{Type: TypeNumber, Value: "1"}, }, true}, {"运算符缺少右操作数", &ExprNode{ Type: TypeOperator, Value: "+", Left: &ExprNode{Type: TypeNumber, Value: "1"}, }, true}, {"无效运算符", &ExprNode{ Type: TypeOperator, Value: "@", Left: &ExprNode{Type: TypeNumber, Value: "1"}, Right: &ExprNode{Type: TypeNumber, Value: "2"}, }, true}, {"无效函数", &ExprNode{ Type: TypeFunction, Value: "unknown", Args: []*ExprNode{{Type: TypeNumber, Value: "1"}}, }, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validateExpression(tt.node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "验证不应该失败") } }) } } // TestValidateExpression 测试公共表达式验证接口 func TestValidateExpression(t *testing.T) { tests := []struct { name string expr string wantErr bool }{ // 有效表达式 {"简单数字", "123", false}, {"简单字段", "field1", false}, {"算术表达式", "1 + 2", false}, {"比较表达式", "field1 > 10", false}, {"函数调用", "abs(-5)", false}, {"复杂表达式", "(field1 + field2) * 2", false}, {"字符串比较", "name = 'test'", false}, {"CASE表达式", "CASE WHEN field1 > 0 THEN 1 ELSE 0 END", false}, {"逻辑表达式", "field1 > 0 AND field2 < 100", false}, {"嵌套函数", "max(abs(field1), abs(field2))", false}, // 无效表达式 {"空表达式", "", true}, {"只有空格", " ", true}, {"括号不匹配1", "(1 + 2", true}, {"括号不匹配2", "1 + 2)", true}, {"连续运算符", "1 + + 2", true}, {"运算符开头", "+ 1 + 2", true}, {"运算符结尾", "1 + 2 +", true}, {"空括号", "()", true}, {"无效数字", "12.34.56", true}, {"无效字符串", "'unclosed string", true}, {"无效函数", "unknown_func(1)", true}, {"无效字段名", "123field", true}, {"tokenize错误", "field with invalid 'quote", true}, {"解析错误", "(((", true}, {"AST验证错误", "123abc", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := ValidateExpression(tt.expr) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "验证不应该失败") } }) } } // TestValidateNumberNode 测试数字节点验证 func TestValidateNumberNode(t *testing.T) { tests := []struct { name string value string wantErr bool }{ {"正整数", "123", false}, {"负整数", "-123", false}, {"零", "0", false}, {"正小数", "3.14", false}, {"负小数", "-3.14", false}, {"科学计数法", "1.5e10", false}, {"负科学计数法", "-1.5e-3", false}, {"小数点开头", ".5", false}, {"小数点结尾", "5.", false}, // 错误情况 {"空字符串", "", true}, {"字母", "abc", true}, {"多个小数点", "3.14.15", true}, {"多个负号", "--5", true}, {"负号在中间", "3-5", true}, {"只有小数点", ".", true}, {"只有负号", "-", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node := &ExprNode{Type: TypeNumber, Value: tt.value} err := validateNumberNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "数字验证不应该失败") } }) } } // TestValidateStringNode 测试字符串节点验证 func TestValidateStringNode(t *testing.T) { tests := []struct { name string value string wantErr bool }{ {"单引号字符串", "'hello'", false}, {"双引号字符串", "\"world\"", false}, {"空字符串", "''", false}, {"空双引号字符串", "\"\"", false}, {"包含转义的字符串", "'hello\\world'", false}, {"包含单引号的双引号字符串", "\"hello'world\"", false}, {"包含双引号的单引号字符串", "'hello\"world'", false}, // 错误情况 {"未闭合单引号", "'hello", true}, {"未闭合双引号", "\"hello", true}, {"没有引号", "hello", true}, {"空值", "", true}, {"只有单引号", "'", true}, {"只有双引号", "\"", true}, {"引号不匹配", "'hello\"", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node := &ExprNode{Type: TypeString, Value: tt.value} err := validateStringNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "字符串验证不应该失败") } }) } } // TestValidateFieldNode 测试字段节点验证 func TestValidateFieldNode(t *testing.T) { tests := []struct { name string value string wantErr bool }{ {"简单字段名", "field1", false}, {"下划线开头", "_field", false}, {"包含数字", "field123", false}, {"驼峰命名", "fieldName", false}, {"蛇形命名", "field_name", false}, {"大写字段", "FIELD", false}, {"反引号字段", "`field name`", false}, {"反引号包含特殊字符", "`user.name`", false}, {"反引号包含空格", "`user name`", false}, // 错误情况 {"空字段名", "", true}, {"数字开头", "123field", true}, {"包含特殊字符", "field-name", true}, {"包含空格", "field name", true}, {"包含点号", "field.name", true}, {"未闭合反引号", "`field", true}, {"只有反引号", "`", true}, {"空反引号", "``", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node := &ExprNode{Type: TypeField, Value: tt.value} err := validateFieldNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "字段验证不应该失败") } }) } } // TestValidateOperatorNode 测试运算符节点验证 func TestValidateOperatorNode(t *testing.T) { tests := []struct { name string operator string left *ExprNode right *ExprNode wantErr bool }{ { "有效加法", "+", &ExprNode{Type: TypeNumber, Value: "1"}, &ExprNode{Type: TypeNumber, Value: "2"}, false, }, { "有效比较", ">", &ExprNode{Type: TypeField, Value: "a"}, &ExprNode{Type: TypeNumber, Value: "0"}, false, }, { "有效逻辑运算", "AND", &ExprNode{ Type: TypeOperator, Value: ">", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, &ExprNode{ Type: TypeOperator, Value: "<", Left: &ExprNode{Type: TypeField, Value: "b"}, Right: &ExprNode{Type: TypeNumber, Value: "10"}, }, false, }, { "有效NOT运算(单操作数)", "NOT", &ExprNode{ Type: TypeOperator, Value: ">", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, nil, false, }, // 错误情况 {"无效运算符", "@", &ExprNode{Type: TypeNumber, Value: "1"}, &ExprNode{Type: TypeNumber, Value: "2"}, true}, {"缺少左操作数", "+", nil, &ExprNode{Type: TypeNumber, Value: "2"}, true}, {"缺少右操作数(双操作数运算符)", "+", &ExprNode{Type: TypeNumber, Value: "1"}, nil, true}, {"NOT运算符有右操作数", "NOT", &ExprNode{Type: TypeNumber, Value: "1"}, &ExprNode{Type: TypeNumber, Value: "2"}, true}, {"左操作数验证失败", "+", &ExprNode{Type: TypeNumber, Value: "abc"}, &ExprNode{Type: TypeNumber, Value: "2"}, true}, {"右操作数验证失败", "+", &ExprNode{Type: TypeNumber, Value: "1"}, &ExprNode{Type: TypeNumber, Value: "abc"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node := &ExprNode{ Type: TypeOperator, Value: tt.operator, Left: tt.left, Right: tt.right, } err := validateOperatorNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "运算符验证不应该失败") } }) } } // TestValidateFunctionNode 测试函数节点验证 func TestValidateFunctionNode(t *testing.T) { // 测试函数Value为空的情况 t.Run("函数名为空", func(t *testing.T) { node := &ExprNode{ Type: TypeFunction, Value: "", Args: []*ExprNode{{Type: TypeNumber, Value: "1"}}, } err := validateFunctionNode(node) assert.Error(t, err, "函数名为空时应该返回错误") assert.Contains(t, err.Error(), "function node has empty value") }) tests := []struct { name string funcName string args []*ExprNode wantErr bool }{ { "ABS函数", "abs", []*ExprNode{{Type: TypeNumber, Value: "1"}}, false, }, { "MAX函数", "max", []*ExprNode{ {Type: TypeNumber, Value: "1"}, {Type: TypeNumber, Value: "2"}, {Type: TypeNumber, Value: "3"}, }, false, }, { "POW函数", "pow", []*ExprNode{ {Type: TypeNumber, Value: "2"}, {Type: TypeNumber, Value: "3"}, }, false, }, { "COUNT函数(无参数)", "count", []*ExprNode{}, false, }, // 错误情况 {"未知函数", "unknown", []*ExprNode{{Type: TypeNumber, Value: "1"}}, true}, {"ABS参数数量错误", "abs", []*ExprNode{}, true}, {"POW参数数量错误", "pow", []*ExprNode{{Type: TypeNumber, Value: "2"}}, true}, {"参数验证失败", "abs", []*ExprNode{{Type: TypeNumber, Value: "abc"}}, true}, {"参数表达式验证失败", "abs", []*ExprNode{{Type: TypeField, Value: "invalid field name!"}}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node := &ExprNode{ Type: TypeFunction, Value: tt.funcName, Args: tt.args, } err := validateFunctionNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "函数验证不应该失败") } }) } } // TestValidateFunctionArgs 测试函数参数验证 func TestValidateFunctionArgs(t *testing.T) { tests := []struct { name string funcName string args []*ExprNode wantErr bool }{ // 单参数函数 {"ABS正确参数", "abs", []*ExprNode{{Type: TypeNumber, Value: "1"}}, false}, {"ABS参数过少", "abs", []*ExprNode{}, true}, {"ABS参数过多", "abs", []*ExprNode{{Type: TypeNumber, Value: "1"}, {Type: TypeNumber, Value: "2"}}, true}, // 双参数函数 {"POW正确参数", "pow", []*ExprNode{{Type: TypeNumber, Value: "2"}, {Type: TypeNumber, Value: "3"}}, false}, {"POW参数过少", "pow", []*ExprNode{{Type: TypeNumber, Value: "2"}}, true}, {"POW参数过多", "pow", []*ExprNode{{Type: TypeNumber, Value: "2"}, {Type: TypeNumber, Value: "3"}, {Type: TypeNumber, Value: "4"}}, true}, // 可变参数函数 {"MAX单参数", "max", []*ExprNode{{Type: TypeNumber, Value: "1"}}, false}, {"MAX多参数", "max", []*ExprNode{{Type: TypeNumber, Value: "1"}, {Type: TypeNumber, Value: "2"}, {Type: TypeNumber, Value: "3"}}, false}, {"MAX无参数", "max", []*ExprNode{}, true}, // 无参数函数(如果有的话) {"COUNT无参数", "count", []*ExprNode{}, false}, {"COUNT有参数", "count", []*ExprNode{{Type: TypeNumber, Value: "1"}}, false}, // COUNT可以有参数 // 未知函数 {"未知函数", "unknown", []*ExprNode{{Type: TypeNumber, Value: "1"}}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 创建一个函数节点来测试 node := &ExprNode{ Type: TypeFunction, Value: tt.funcName, Args: tt.args, } // 使用validateFunctionNode来验证函数名和参数数量 err := validateFunctionNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "函数参数验证不应该失败") } }) } } // TestValidateCaseNode 测试CASE节点验证 func TestValidateCaseNode(t *testing.T) { tests := []struct { name string caseExpr *CaseExpression wantErr bool }{ { "有效CASE表达式", &CaseExpression{ WhenClauses: []WhenClause{ { Condition: &ExprNode{ Type: TypeOperator, Value: ">", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, Result: &ExprNode{Type: TypeNumber, Value: "1"}, }, }, ElseResult: &ExprNode{Type: TypeNumber, Value: "0"}, }, false, }, { "简单CASE表达式(带Value)", &CaseExpression{ Value: &ExprNode{Type: TypeField, Value: "status"}, WhenClauses: []WhenClause{ { Condition: &ExprNode{Type: TypeString, Value: "'active'"}, Result: &ExprNode{Type: TypeNumber, Value: "1"}, }, { Condition: &ExprNode{Type: TypeString, Value: "'inactive'"}, Result: &ExprNode{Type: TypeNumber, Value: "0"}, }, }, ElseResult: &ExprNode{Type: TypeNumber, Value: "-1"}, }, false, }, { "多个WHEN子句", &CaseExpression{ WhenClauses: []WhenClause{ { Condition: &ExprNode{ Type: TypeOperator, Value: ">", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, Result: &ExprNode{Type: TypeNumber, Value: "1"}, }, { Condition: &ExprNode{ Type: TypeOperator, Value: "<", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, Result: &ExprNode{Type: TypeNumber, Value: "-1"}, }, }, ElseResult: &ExprNode{Type: TypeNumber, Value: "0"}, }, false, }, { "没有ELSE子句", &CaseExpression{ WhenClauses: []WhenClause{ { Condition: &ExprNode{ Type: TypeOperator, Value: ">", Left: &ExprNode{Type: TypeField, Value: "a"}, Right: &ExprNode{Type: TypeNumber, Value: "0"}, }, Result: &ExprNode{Type: TypeNumber, Value: "1"}, }, }, ElseResult: nil, }, false, }, // 错误情况 {"没有WHEN子句", &CaseExpression{WhenClauses: []WhenClause{}, ElseResult: &ExprNode{Type: TypeNumber, Value: "0"}}, true}, {"WHEN条件为空", &CaseExpression{ WhenClauses: []WhenClause{ {Condition: nil, Result: &ExprNode{Type: TypeNumber, Value: "1"}}, }, }, true}, {"WHEN结果为空", &CaseExpression{ WhenClauses: []WhenClause{ {Condition: &ExprNode{Type: TypeField, Value: "a"}, Result: nil}, }, }, true}, {"WHEN条件验证失败", &CaseExpression{ WhenClauses: []WhenClause{ {Condition: &ExprNode{Type: TypeNumber, Value: "abc"}, Result: &ExprNode{Type: TypeNumber, Value: "1"}}, }, }, true}, {"WHEN结果验证失败", &CaseExpression{ WhenClauses: []WhenClause{ {Condition: &ExprNode{Type: TypeField, Value: "a"}, Result: &ExprNode{Type: TypeNumber, Value: "abc"}}, }, }, true}, {"ELSE结果验证失败", &CaseExpression{ WhenClauses: []WhenClause{ {Condition: &ExprNode{Type: TypeField, Value: "a"}, Result: &ExprNode{Type: TypeNumber, Value: "1"}}, }, ElseResult: &ExprNode{Type: TypeNumber, Value: "abc"}, }, true}, {"简单CASE的Value验证失败", &CaseExpression{ Value: &ExprNode{Type: TypeNumber, Value: "invalid_number"}, WhenClauses: []WhenClause{ {Condition: &ExprNode{Type: TypeString, Value: "'test'"}, Result: &ExprNode{Type: TypeNumber, Value: "1"}}, }, }, true}, } // 添加CaseExpr为nil的测试用例 t.Run("CaseExpr为nil", func(t *testing.T) { node := &ExprNode{Type: TypeCase, CaseExpr: nil} err := validateCaseNode(node) assert.Error(t, err, "CaseExpr为nil时应该返回错误") assert.Contains(t, err.Error(), "CASE expression is missing") }) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node := &ExprNode{Type: TypeCase, CaseExpr: tt.caseExpr} err := validateCaseNode(node) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "CASE节点验证不应该失败") } }) } } // TestIsValidFieldName 测试字段名验证 func TestIsValidFieldName(t *testing.T) { tests := []struct { name string fieldName string expected bool }{ // 有效情况 {"简单字段名", "field", true}, {"下划线开头", "_field", true}, {"包含数字", "field123", true}, {"驼峰命名", "fieldName", true}, {"蛇形命名", "field_name", true}, {"大写字段", "FIELD", true}, {"单字符字段", "a", true}, {"单下划线", "_", true}, {"反引号字段", "`field name`", true}, {"反引号包含特殊字符", "`user.name`", true}, {"反引号包含数字开头", "`123field`", true}, {"反引号包含连字符", "`field-name`", true}, {"反引号包含各种符号", "`field@#$%^&*()`", true}, // 无效情况 {"空字段名", "", false}, {"数字开头", "123field", false}, {"包含连字符", "field-name", false}, {"包含空格(无反引号)", "field name", false}, {"包含点号(无反引号)", "field.name", false}, {"包含特殊字符@", "field@name", false}, {"包含特殊字符#", "field#name", false}, {"包含特殊字符$", "field$name", false}, {"包含特殊字符%", "field%name", false}, {"未闭合反引号", "`field", false}, {"空反引号", "``", false}, {"反引号内包含反引号", "`field`name`", false}, {"只有反引号开头", "`", false}, {"非ASCII字符", "字段名", false}, {"包含非ASCII字符", "field字段", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := isValidFieldName(tt.fieldName) assert.Equal(t, tt.expected, result, "字段名验证结果应该正确") }) } } // TestValidateTokens 测试标记列表验证 func TestValidateTokens(t *testing.T) { tests := []struct { name string tokens []string wantErr bool }{ {"有效标记列表", []string{"a", "+", "b"}, false}, {"有效函数调用", []string{"abs", "(", "x", ")"}, false}, {"有效CASE表达式", []string{"CASE", "WHEN", "a", ">", "0", "THEN", "1", "ELSE", "0", "END"}, false}, // 错误情况 {"空标记列表", []string{}, true}, {"括号不匹配", []string{"(", "a", "+", "b"}, true}, {"连续运算符", []string{"a", "+", "+", "b"}, true}, {"运算符开头", []string{"+", "a"}, true}, {"运算符结尾", []string{"a", "+"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validateTokens(tt.tokens) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "标记验证不应该失败") } }) } } // TestValidateParentheses 测试括号验证 func TestValidateParentheses(t *testing.T) { tests := []struct { name string tokens []string wantErr bool }{ {"匹配的括号", []string{"(", "a", "+", "b", ")"}, false}, {"嵌套括号", []string{"(", "(", "a", "+", "b", ")", "*", "c", ")"}, false}, {"函数括号", []string{"abs", "(", "x", ")"}, false}, {"无括号", []string{"a", "+", "b"}, false}, // 错误情况 {"缺少右括号", []string{"(", "a", "+", "b"}, true}, {"缺少左括号", []string{"a", "+", "b", ")"}, true}, {"括号顺序错误", []string{")", "a", "+", "b", "("}, true}, {"嵌套不匹配", []string{"(", "(", "a", "+", "b", ")"}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validateParentheses(tt.tokens) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "括号验证不应该失败") } }) } } // TestValidateTokenOrder 测试标记顺序验证 func TestValidateTokenOrder(t *testing.T) { tests := []struct { name string tokens []string wantErr bool }{ {"正确顺序", []string{"a", "+", "b"}, false}, {"函数调用", []string{"abs", "(", "x", ")"}, false}, {"复杂表达式", []string{"a", "+", "b", "*", "c"}, false}, // 错误情况 {"连续运算符", []string{"a", "+", "+", "b"}, true}, {"运算符开头", []string{"+", "a"}, true}, {"运算符结尾", []string{"a", "+"}, true}, {"连续操作数", []string{"a", "b", "+", "c"}, true}, {"CASE关键字组合", []string{"CASE", "WHEN", "field", "THEN", "value", "END"}, false}, {"操作符后跟一元操作符", []string{"a", "AND", "NOT", "b"}, false}, {"连续二元操作符", []string{"a", "+", "*", "b"}, true}, {"以一元操作符开始", []string{"NOT", "a"}, false}, {"以二元操作符开始", []string{"-", "a"}, true}, {"逗号分隔的参数", []string{"func", "(", "a", ",", "b", ")"}, false}, {"括号和操作数混合", []string{"(", "a", ")", "+", "b"}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validateTokenOrder(tt.tokens) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "标记顺序验证不应该失败") } }) } } // TestValidateSyntax 测试语法验证 func TestValidateParenthesisNode(t *testing.T) { tests := []struct { name string node *ExprNode wantErr bool errMsg string }{ { name: "有效的括号表达式", node: &ExprNode{ Type: TypeParenthesis, Left: &ExprNode{ Type: TypeField, Value: "field1", }, }, wantErr: false, }, { name: "括号内为空", node: &ExprNode{ Type: TypeParenthesis, Left: nil, }, wantErr: true, errMsg: "parenthesis node missing inner expression", }, { name: "括号内表达式无效", node: &ExprNode{ Type: TypeParenthesis, Left: &ExprNode{ Type: TypeField, Value: "", // 空字段名 }, }, wantErr: true, errMsg: "field node has empty value", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validateParenthesisNode(tt.node) if tt.wantErr { if err == nil { t.Errorf("validateParenthesisNode() expected error, got nil") } else if !strings.Contains(err.Error(), tt.errMsg) { t.Errorf("validateParenthesisNode() error = %v, want error containing %v", err, tt.errMsg) } } else { if err != nil { t.Errorf("validateParenthesisNode() error = %v, want nil", err) } } }) } } func TestValidateSyntax(t *testing.T) { tests := []struct { name string expr string wantErr bool }{ // 有效表达式 {"有效算术表达式", "a + b", false}, {"有效函数调用", "abs(x)", false}, {"有效CASE表达式", "CASE WHEN a > 0 THEN 1 END", false}, {"有效比较表达式", "field >= 10", false}, {"有效逻辑表达式", "a != b", false}, {"有效不等于表达式", "a <> b", false}, {"有效小于等于表达式", "a <= b", false}, {"复杂表达式", "a + b * c", false}, // 错误情况 {"空表达式", "", true}, {"只有空格", " ", true}, {"空括号", "()", true}, {"括号不匹配1", "(a + b", true}, {"括号不匹配2", "a + b)", true}, {"连续运算符(空格分隔)", "a + + b", true}, {"连续运算符(直接相邻)", "a+-b", true}, {"运算符开头", "+ a + b", true}, {"运算符结尾", "a + b +", true}, {"乘法运算符开头", "* a + b", true}, {"除法运算符结尾", "a + b /", true}, {"模运算符开头", "% a + b", true}, {"幂运算符结尾", "a + b ^", true}, {"等号运算符开头", "= a + b", true}, {"不等号运算符结尾", "a + b !=", true}, {"大于号运算符开头", "> a + b", true}, {"小于号运算符结尾", "a + b <", true}, {"大于等于运算符开头", ">= a + b", true}, {"小于等于运算符结尾", "a + b <=", true}, {"不等于运算符开头", "<> a + b", true}, {"多个连续运算符组合1", "a + * b", true}, {"多个连续运算符组合2", "a / % b", true}, {"多个连续运算符组合3", "a ^ + b", true}, {"多个连续运算符组合4", "a = > b", true}, {"多个连续运算符组合5", "a < = b", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validateSyntax(tt.expr) if tt.wantErr { assert.Error(t, err, "应该返回错误") } else { assert.NoError(t, err, "语法验证不应该失败") } }) } }