Files
eval/parsingFailure_test.go
zeekay 011df15db5 eval: expression evaluator forked from casbin/govaluate v1.3.0
Module path renamed to github.com/hanzoai/eval and the Go package
renamed from govaluate to eval. Evaluation, parsing, lexing, and
operator behavior are unchanged; MIT license and George Lester
attribution retained. See NOTICE for lineage.
2026-07-18 00:27:32 -07:00

232 lines
5.1 KiB
Go

package eval
import (
"fmt"
"regexp/syntax"
"strings"
"testing"
)
const (
UNEXPECTED_END = "Unexpected end of expression"
INVALID_TOKEN_TRANSITION = "Cannot transition token types"
INVALID_TOKEN_KIND = "Invalid token"
UNCLOSED_QUOTES = "Unclosed string literal"
UNCLOSED_BRACKETS = "Unclosed parameter bracket"
UNBALANCED_PARENTHESIS = "Unbalanced parenthesis"
INVALID_NUMERIC = "Unable to parse numeric value"
UNDEFINED_FUNCTION = "Undefined function"
HANGING_ACCESSOR = "Hanging accessor on token"
INVALID_HEX = "Unable to parse hex value"
)
/*
Represents a test for parsing failures
*/
type ParsingFailureTest struct {
Name string
Input string
Expected string
}
func TestParsingFailure(test *testing.T) {
parsingTests := []ParsingFailureTest{
ParsingFailureTest{
Name: "Invalid equality comparator",
Input: "1 = 1",
Expected: INVALID_TOKEN_KIND,
},
ParsingFailureTest{
Name: "Invalid equality comparator",
Input: "1 === 1",
Expected: INVALID_TOKEN_KIND,
},
ParsingFailureTest{
Name: "Too many characters for logical operator",
Input: "true &&& false",
Expected: INVALID_TOKEN_KIND,
},
ParsingFailureTest{
Name: "Too many characters for logical operator",
Input: "true ||| false",
Expected: INVALID_TOKEN_KIND,
},
ParsingFailureTest{
Name: "Premature end to expression, via modifier",
Input: "10 > 5 +",
Expected: UNEXPECTED_END,
},
ParsingFailureTest{
Name: "Premature end to expression, via comparator",
Input: "10 + 5 >",
Expected: UNEXPECTED_END,
},
ParsingFailureTest{
Name: "Premature end to expression, via logical operator",
Input: "10 > 5 &&",
Expected: UNEXPECTED_END,
},
ParsingFailureTest{
Name: "Premature end to expression, via ternary operator",
Input: "true ?",
Expected: UNEXPECTED_END,
},
ParsingFailureTest{
Name: "Hanging REQ",
Input: "'wat' =~",
Expected: UNEXPECTED_END,
},
ParsingFailureTest{
Name: "Invalid operator change to REQ",
Input: " / =~",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid starting token, comparator",
Input: "> 10",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid starting token, modifier",
Input: "+ 5",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid starting token, logical operator",
Input: "&& 5 < 10",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid NUMERIC transition",
Input: "10 10",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid STRING transition",
Input: "'foo' 'foo'",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid operator transition",
Input: "10 > < 10",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Starting with unbalanced parens",
Input: " ) ( arg2",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Unclosed bracket",
Input: "[foo bar",
Expected: UNCLOSED_BRACKETS,
},
ParsingFailureTest{
Name: "Unclosed quote",
Input: "foo == 'responseTime",
Expected: UNCLOSED_QUOTES,
},
ParsingFailureTest{
Name: "Constant regex pattern fail to compile",
Input: "foo =~ '[abc'",
Expected: string(syntax.ErrMissingBracket),
},
ParsingFailureTest{
Name: "Unbalanced parenthesis",
Input: "10 > (1 + 50",
Expected: UNBALANCED_PARENTHESIS,
},
ParsingFailureTest{
Name: "Multiple radix",
Input: "127.0.0.1",
Expected: INVALID_NUMERIC,
},
ParsingFailureTest{
Name: "Undefined function",
Input: "foobar()",
Expected: UNDEFINED_FUNCTION,
},
ParsingFailureTest{
Name: "Hanging accessor",
Input: "foo.Bar.",
Expected: HANGING_ACCESSOR,
},
ParsingFailureTest{
Name: "Incomplete Hex",
Input: "0x",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Invalid Hex literal",
Input: "0x > 0",
Expected: INVALID_HEX,
},
ParsingFailureTest{
Name: "Hex float (Unsupported)",
Input: "0x1.1",
Expected: INVALID_TOKEN_TRANSITION,
},
ParsingFailureTest{
Name: "Hex invalid letter",
Input: "0x12g1",
Expected: INVALID_TOKEN_TRANSITION,
},
}
runParsingFailureTests(parsingTests, test)
}
func runParsingFailureTests(parsingTests []ParsingFailureTest, test *testing.T) {
var err error
fmt.Printf("Running %d parsing test cases...\n", len(parsingTests))
for _, testCase := range parsingTests {
_, err = NewEvaluableExpression(testCase.Input)
if err == nil {
test.Logf("Test '%s' failed", testCase.Name)
test.Logf("Expected a parsing error, found no error.")
test.Fail()
continue
}
if !strings.Contains(err.Error(), testCase.Expected) {
test.Logf("Test '%s' failed", testCase.Name)
test.Logf("Got error: '%s', expected '%s'", err.Error(), testCase.Expected)
test.Fail()
continue
}
}
}