mirror of
https://github.com/hanzoai/eval.git
synced 2026-09-30 21:47:09 +00:00
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.
248 lines
4.4 KiB
Go
248 lines
4.4 KiB
Go
package eval
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
/*
|
|
Represents a test of correctly creating a SQL query string from an expression.
|
|
*/
|
|
type QueryTest struct {
|
|
Name string
|
|
Input string
|
|
Expected string
|
|
}
|
|
|
|
func TestSQLSerialization(test *testing.T) {
|
|
|
|
testCases := []QueryTest{
|
|
|
|
QueryTest{
|
|
|
|
Name: "Single GT",
|
|
Input: "1 > 0",
|
|
Expected: "1 > 0",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single LT",
|
|
Input: "0 < 1",
|
|
Expected: "0 < 1",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single GTE",
|
|
Input: "1 >= 0",
|
|
Expected: "1 >= 0",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single LTE",
|
|
Input: "0 <= 1",
|
|
Expected: "0 <= 1",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single EQ",
|
|
Input: "1 == 0",
|
|
Expected: "1 = 0",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single NEQ",
|
|
Input: "1 != 0",
|
|
Expected: "1 <> 0",
|
|
},
|
|
|
|
QueryTest{
|
|
|
|
Name: "Parameter names",
|
|
Input: "foo == bar",
|
|
Expected: "[foo] = [bar]",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Strings",
|
|
Input: "'foo'",
|
|
Expected: "'foo'",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Date format",
|
|
Input: "'2014-07-04T00:00:00Z'",
|
|
Expected: "'2014-07-04T00:00:00Z'",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single PLUS",
|
|
Input: "10 + 10",
|
|
Expected: "10 + 10",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single MINUS",
|
|
Input: "10 - 10",
|
|
Expected: "10 - 10",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single MULTIPLY",
|
|
Input: "10 * 10",
|
|
Expected: "10 * 10",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single DIVIDE",
|
|
Input: "10 / 10",
|
|
Expected: "10 / 10",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single true bool",
|
|
Input: "true",
|
|
Expected: "1",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single false bool",
|
|
Input: "false",
|
|
Expected: "0",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single AND",
|
|
Input: "true && true",
|
|
Expected: "1 AND 1",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Single OR",
|
|
Input: "true || true",
|
|
Expected: "1 OR 1",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Clauses",
|
|
Input: "10 + (foo + bar)",
|
|
Expected: "10 + ( [foo] + [bar] )",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Negate prefix",
|
|
Input: "foo < -1",
|
|
Expected: "[foo] < -1",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Invert prefix",
|
|
Input: "!(foo > 1)",
|
|
Expected: "NOT ( [foo] > 1 )",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Exponent",
|
|
Input: "1 ** 2",
|
|
Expected: "POW(1, 2)",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Modulus",
|
|
Input: "10 % 2",
|
|
Expected: "MOD(10, 2)",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Membership operator",
|
|
Input: "foo IN (1, 2, 3)",
|
|
Expected: "[foo] in ( 1 , 2 , 3 )",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Null coalescence",
|
|
Input: "foo ?? bar",
|
|
Expected: "COALESCE([foo], [bar])",
|
|
},
|
|
/*
|
|
// Ternaries don't work yet, because the outputter is not yet sophisticated enough to produce them.
|
|
QueryTest{
|
|
|
|
Name: "Full ternary",
|
|
Input: "[foo] == 5 ? 1 : 2",
|
|
Expected: "IF([foo] = 5, 1, 2)",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Half ternary",
|
|
Input: "[foo] == 5 ? 1",
|
|
Expected: "IF([foo] = 5, 1)",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Full ternary with implicit bool",
|
|
Input: "[foo] ? 1 : 2",
|
|
Expected: "IF([foo] = 0, 1, 2)",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Half ternary with implicit bool",
|
|
Input: "[foo] ? 1",
|
|
Expected: "IF([foo] = 0, 1)",
|
|
},*/
|
|
QueryTest{
|
|
|
|
Name: "Regex equals",
|
|
Input: "'foo' =~ '[fF][oO]+'",
|
|
Expected: "'foo' RLIKE '[fF][oO]+'",
|
|
},
|
|
QueryTest{
|
|
|
|
Name: "Regex not-equals",
|
|
Input: "'foo' !~ '[fF][oO]+'",
|
|
Expected: "'foo' NOT RLIKE '[fF][oO]+'",
|
|
},
|
|
}
|
|
|
|
runQueryTests(testCases, test)
|
|
}
|
|
|
|
func runQueryTests(testCases []QueryTest, test *testing.T) {
|
|
|
|
var expression *EvaluableExpression
|
|
var actualQuery string
|
|
var err error
|
|
|
|
test.Logf("Running %d SQL translation test cases", len(testCases))
|
|
|
|
// Run the test cases.
|
|
for _, testCase := range testCases {
|
|
|
|
expression, err = NewEvaluableExpression(testCase.Input)
|
|
|
|
if err != nil {
|
|
|
|
test.Logf("Test '%s' failed to parse: %s", testCase.Name, err)
|
|
test.Logf("Expression: '%s'", testCase.Input)
|
|
test.Fail()
|
|
continue
|
|
}
|
|
|
|
actualQuery, err = expression.ToSQLQuery()
|
|
|
|
if err != nil {
|
|
|
|
test.Logf("Test '%s' failed to create query: %s", testCase.Name, err)
|
|
test.Logf("Expression: '%s'", testCase.Input)
|
|
test.Fail()
|
|
continue
|
|
}
|
|
|
|
if actualQuery != testCase.Expected {
|
|
|
|
test.Logf("Test '%s' did not create expected query.", testCase.Name)
|
|
test.Logf("Actual: '%s', expected '%s'", actualQuery, testCase.Expected)
|
|
test.Fail()
|
|
continue
|
|
}
|
|
}
|
|
}
|