blob: 0d3bb5a6006e5274a88dcc60b36775a713ebb7cf [file]
package govaluate
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{
{
Name: "Single GT",
Input: "1 > 0",
Expected: "1 > 0",
},
{
Name: "Single LT",
Input: "0 < 1",
Expected: "0 < 1",
},
{
Name: "Single GTE",
Input: "1 >= 0",
Expected: "1 >= 0",
},
{
Name: "Single LTE",
Input: "0 <= 1",
Expected: "0 <= 1",
},
{
Name: "Single EQ",
Input: "1 == 0",
Expected: "1 = 0",
},
{
Name: "Single NEQ",
Input: "1 != 0",
Expected: "1 <> 0",
},
{
Name: "Parameter names",
Input: "foo == bar",
Expected: "[foo] = [bar]",
},
{
Name: "Strings",
Input: "'foo'",
Expected: "'foo'",
},
{
Name: "Date format",
Input: "'2014-07-04T00:00:00Z'",
Expected: "'2014-07-04T00:00:00Z'",
},
{
Name: "Single PLUS",
Input: "10 + 10",
Expected: "10 + 10",
},
{
Name: "Single MINUS",
Input: "10 - 10",
Expected: "10 - 10",
},
{
Name: "Single MULTIPLY",
Input: "10 * 10",
Expected: "10 * 10",
},
{
Name: "Single DIVIDE",
Input: "10 / 10",
Expected: "10 / 10",
},
{
Name: "Single true bool",
Input: "true",
Expected: "1",
},
{
Name: "Single false bool",
Input: "false",
Expected: "0",
},
{
Name: "Single AND",
Input: "true && true",
Expected: "1 AND 1",
},
{
Name: "Single OR",
Input: "true || true",
Expected: "1 OR 1",
},
{
Name: "Clauses",
Input: "10 + (foo + bar)",
Expected: "10 + ( [foo] + [bar] )",
},
{
Name: "Negate prefix",
Input: "foo < -1",
Expected: "[foo] < -1",
},
{
Name: "Invert prefix",
Input: "!(foo > 1)",
Expected: "NOT ( [foo] > 1 )",
},
{
Name: "Exponent",
Input: "1 ** 2",
Expected: "POW(1, 2)",
},
{
Name: "Modulus",
Input: "10 % 2",
Expected: "MOD(10, 2)",
},
{
Name: "Membership operator",
Input: "foo IN (1, 2, 3)",
Expected: "[foo] in ( 1 , 2 , 3 )",
},
{
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)",
},*/
{
Name: "Regex equals",
Input: "'foo' =~ '[fF][oO]+'",
Expected: "'foo' RLIKE '[fF][oO]+'",
},
{
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
}
}
}