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{ 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 } } }