/* * Copyright 2013 Future Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.araqne.logdb.query.parser; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.araqne.logdb.FunctionRegistry; import org.araqne.logdb.QueryContext; import org.araqne.logdb.QueryParseException; import org.araqne.logdb.Row; import org.araqne.logdb.impl.FunctionRegistryImpl; import org.araqne.logdb.query.expr.Expression; import org.araqne.logdb.query.expr.StringConstant; import org.junit.Test; public class ExpressionParserTest { @Test public void testSimple() { Expression expr = parseExpr("3+4*2/(1-5)"); Object v = expr.eval(null); assertEquals(1.0, v); } private FunctionRegistry funcRegistry = new FunctionRegistryImpl(); private Expression parseExpr(String expr) { return ExpressionParser.parse(null, expr, funcRegistry); } @Test public void testFuncExpr() { Expression expr = parseExpr("1 + abs(1-5*2)"); Object v = expr.eval(null); assertEquals(10L, v); } @Test public void testFuncMultiArgs() { Row log = new Row(); log.put("test", 1); Expression expr = parseExpr("100 + min(3, 7, 2, 5, test) * 2"); Object v = expr.eval(log); assertEquals(102L, v); } @Test public void testNestedFuncExpr() { Expression expr = parseExpr("min(abs(1-9), 3, 10, 5)"); Object v = expr.eval(null); assertEquals(3, v); expr = parseExpr("concat(\"this\", \" \", concat(\"is\", concat(\" \", \"a\", \" \", \"cat\")), \".\")"); v = expr.eval(null); assertEquals("this is a cat.", v); } @Test public void testCommaExpr() { Expression expr = parseExpr("1, 2"); Object v = expr.eval(null); assertEquals("[1, 2]", v.toString()); expr = parseExpr("1, 2, (3, 4), 5"); v = expr.eval(null); assertEquals("[1, 2, [3, 4], 5]", v.toString()); expr = parseExpr("(1, 2), (3, 4), 5"); v = expr.eval(null); assertEquals("[[1, 2], [3, 4], 5]", v.toString()); expr = parseExpr("(1, 2, 3, (4, 5, 6), 7), 5"); v = expr.eval(null); assertEquals("[[1, 2, 3, [4, 5, 6], 7], 5]", v.toString()); } @Test public void testNegation() { Expression expr = parseExpr("-abs(1-9) * 2"); Object v = expr.eval(null); assertEquals(-16L, v); expr = parseExpr("--2"); Number n = (Number) expr.eval(null); assertEquals(2L, n.longValue()); expr = parseExpr("1+-2"); v = expr.eval(null); assertEquals(-1L, v); expr = parseExpr("3--5"); v = expr.eval(null); assertEquals(8L, v); expr = parseExpr("3*-5"); v = expr.eval(null); assertEquals(-15L, v); } @Test public void testBrokenExpr() { String invalid = "3+4*2/"; try { parseExpr(invalid); fail(); } catch (QueryParseException e) { if(e.isDebugMode()){ System.out.println("query " + invalid); System.out.println(e.getMessage()); } assertEquals("90100", e.getType()); assertEquals(invalid, e.getParams().get("value")); } invalid = "3 4*2"; try { parseExpr(invalid); fail(); } catch (QueryParseException e) { if(e.isDebugMode()){ System.out.println("query " + invalid); System.out.println(e.getMessage()); } assertEquals("90201", e.getType()); assertEquals(invalid, e.getParams().get("value")); } } @Test public void testGreaterThanEqual() { Expression exp = parseExpr("10 >= 3"); assertTrue((Boolean) exp.eval(null)); exp = parseExpr("3 >= 3"); assertTrue((Boolean) exp.eval(null)); } @Test public void testGreaterThan() { Expression exp = parseExpr("10 > 3"); assertTrue((Boolean) exp.eval(null)); exp = parseExpr("3 > 3"); assertFalse((Boolean) exp.eval(null)); } @Test public void testLesserThanEqual() { Expression exp = parseExpr("3 <= 5"); assertTrue((Boolean) exp.eval(null)); exp = parseExpr("3 <= 3"); assertTrue((Boolean) exp.eval(null)); } @Test public void testLesserThan() { Expression exp = parseExpr("3 < 5"); assertTrue((Boolean) exp.eval(null)); exp = parseExpr("3 < 3"); assertFalse((Boolean) exp.eval(null)); } @Test public void testBooleanArithmeticPrecendence() { Expression exp = parseExpr("1 == 3-2 or 2 == 2"); assertTrue((Boolean) exp.eval(null)); } @Test public void testEq() { Expression exp = parseExpr("1 == 0"); assertFalse((Boolean) exp.eval(null)); } @Test public void testAnd() { Expression exp = parseExpr("10 >= 3 and 1 == 0"); assertFalse((Boolean) exp.eval(null)); } @Test public void testAndOr() { Expression exp = parseExpr("10 >= 3 and (1 == 0 or 2 == 2)"); assertTrue((Boolean) exp.eval(null)); } @Test public void testIf() { Expression exp = parseExpr("if(field >= 10, 10, field)"); Row m1 = new Row(); m1.put("field", 15); assertEquals(10, exp.eval(m1)); Row m2 = new Row(); m2.put("field", 3); assertEquals(3, exp.eval(m2)); } @Test public void testCase() { Expression exp = parseExpr("case(field >= 10, 10, field < 10, field)"); Row m1 = new Row(); m1.put("field", 15); assertEquals(10, exp.eval(m1)); Row m2 = new Row(); m2.put("field", 3); assertEquals(3, exp.eval(m2)); } @Test public void testConcat() { Expression exp = parseExpr("concat(\"hello\", \"world\")"); assertEquals("helloworld", exp.eval(null)); } @Test public void testToDate() { Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR, 2013); c.set(Calendar.MONTH, 1); c.set(Calendar.DAY_OF_MONTH, 6); c.set(Calendar.HOUR_OF_DAY, 11); c.set(Calendar.MINUTE, 26); c.set(Calendar.SECOND, 33); c.set(Calendar.MILLISECOND, 0); Row m = new Row(); m.put("date", "2013-02-06 11:26:33"); Expression exp = parseExpr("date(date, \"yyyy-MM-dd HH:mm:ss\")"); Object v = exp.eval(m); assertEquals(c.getTime(), v); } @Test public void testSubstr() { String s = "abcdefg"; Row m = new Row(); m.put("line", s); Expression exp = parseExpr("substr(line,0,7)"); assertEquals("abcdefg", exp.eval(m)); exp = parseExpr("substr(line,0,0)"); assertEquals("", exp.eval(m)); exp = parseExpr("substr(line,8,10)"); assertNull(exp.eval(m)); exp = parseExpr("substr(line,3,6)"); assertEquals("def", exp.eval(m)); } @Test public void testMatch() { String s = "210.119.122.32"; Row m = new Row(); m.put("line", s); Expression exp = parseExpr("match(line, \"210.*\")"); assertTrue((Boolean) exp.eval(m)); exp = parseExpr("match(line, \"192.*\")"); assertFalse((Boolean) exp.eval(m)); } @Test public void testWildcard() { Expression exp = parseExpr("\"210.119.122.32\" == \"210*\""); assertTrue((Boolean) exp.eval(null)); exp = parseExpr("\"210.119.122.32\" == \"*32\""); assertTrue((Boolean) exp.eval(null)); exp = parseExpr("\"210.119.122.32\" == \"119*\""); assertFalse((Boolean) exp.eval(null)); exp = parseExpr("\"210.119.122.32\" == \"119\""); assertFalse((Boolean) exp.eval(null)); } @Test public void testBooleanConstants() { Expression exp1 = parseExpr("field == true"); Row m = new Row(); m.put("field", true); assertTrue((Boolean) exp1.eval(m)); m = new Row(); m.put("field", false); assertFalse((Boolean) exp1.eval(m)); Expression exp2 = parseExpr("field == false"); m = new Row(); m.put("field", false); assertTrue((Boolean) exp2.eval(m)); } @Test public void testInIntegers() { Expression expr = parseExpr("in(field, 1, 2, 3)"); Row m = new Row(); m.put("field", 1); assertTrue((Boolean) expr.eval(m)); m.put("field", 2); assertTrue((Boolean) expr.eval(m)); m.put("field", 3); assertTrue((Boolean) expr.eval(m)); m.put("field", 4); assertFalse((Boolean) expr.eval(m)); m.put("field", null); assertFalse((Boolean) expr.eval(m)); } @Test public void testInStrings() { Expression expr = parseExpr("in(field, \"a\", \"b\", \"c\")"); Row m = new Row(); m.put("field", "a"); assertTrue((Boolean) expr.eval(m)); m.put("field", "b"); assertTrue((Boolean) expr.eval(m)); m.put("field", "c"); assertTrue((Boolean) expr.eval(m)); m.put("field", "d"); assertFalse((Boolean) expr.eval(m)); } @Test public void testInStringWildcards() { Expression expr = parseExpr("in(field, \"*74.86.*\")"); Row m = new Row(); m.put("field", "ip = 74.86.1.2"); assertTrue((Boolean) expr.eval(m)); m.put("field", "ip = 75.81.1.2"); assertFalse((Boolean) expr.eval(m)); } @Test public void testBracket() { { Expression expr = parseExpr("a == \"*[GameStart REP]*\""); Row m = new Row(); m.put("a", "22:27:05.235(tid=4436)[Q=0:1:0:0]I[10.1.119.86-997014784-8439] [0 ms][GameStart REP]=126:200:3111 0073875:61.111.10.21:59930:2:1:0:101:qa161새롱 1:2:2718376:3:2000015:0"); assertTrue((Boolean) expr.eval(m)); } { Expression expr = parseExpr("a == \"*[GameStart REP]*\""); Row m = new Row(); m.put("a", "22:27:05.235(tid=4436)[Q=0:1:0:0]I[10.1.119.86-997014784-8439] [0 ms][GameStrt REP]=126:200:3111 0073875:61.111.10.21:59930:2:1:0:101:qa161새롱 1:2:2718376:3:2000015:0"); assertFalse((Boolean) expr.eval(m)); } } @Test public void testStringEscape() { String newline = "\"hello\\nworld\""; StringConstant expr = (StringConstant) parseExpr(newline); assertEquals("hello\nworld", expr.getConstant()); String tab = "\"hello\\tworld\\\\\""; StringConstant expr2 = (StringConstant) parseExpr(tab); assertEquals("hello\tworld\\", expr2.getConstant()); String invalid = "\"hello\\tworld\\i\""; try { parseExpr(invalid); fail(); } catch (QueryParseException e) { if(e.isDebugMode()){ System.out.println(invalid); System.out.println(e.getMessage()); } assertEquals("90205", e.getType()); assertEquals("\\i", e.getParams().get("escape")); assertEquals(invalid, e.getParams().get("value")); } } @Test public void testFuncNoArg() { QueryContext context = new QueryContext(null); Expression expr = ExpressionParser.parse(context, "string(now(), \"yyyyMMdd\")", funcRegistry); assertEquals(expr.eval(null), new SimpleDateFormat("yyyyMMdd").format(new Date())); expr = ExpressionParser.parse(context, "concat(\"a\",string(now(), \"yyyyMMdd\"))", funcRegistry); assertEquals(expr.eval(null), "a" + new SimpleDateFormat("yyyyMMdd").format(new Date())); } }