package org.dcache.util.expression; import org.junit.Before; import org.junit.Test; import org.parboiled.Parboiled; import org.parboiled.parserunners.BasicParseRunner; import org.parboiled.support.ParsingResult; import static org.junit.Assert.assertEquals; public class ExpressionTest { private SymbolTable symbols; @Before public void setup() { symbols = new SymbolTable(); symbols.put("number", 1.0); } private Expression createExpression(String s) { ExpressionParser parser = Parboiled.createParser(ExpressionParser.class); ParsingResult<Expression> result = new BasicParseRunner(parser.Top()).run(s); return result.resultValue; } private Expression createCheckedExpression(String s) throws TypeMismatchException, UnknownIdentifierException { Expression expression = createExpression(s); expression.check(symbols); return expression; } private Object evaluate(String s) throws TypeMismatchException, UnknownIdentifierException { Expression expression = createExpression(s); expression.check(symbols); return expression.evaluate(symbols); } @Test public void testLiterals() throws Exception { assertEquals(-1.0, evaluate("-1")); assertEquals(1.0, evaluate("1")); assertEquals(1.1, evaluate("1.1")); assertEquals(true, evaluate("true")); assertEquals(false, evaluate("false")); assertEquals("foo", evaluate("\"foo\"")); assertEquals("foo", evaluate("'foo'")); assertEquals(1000.0, evaluate("1k")); assertEquals(1000.0, evaluate("1 K")); assertEquals(1000000.0, evaluate("1 M")); assertEquals(1000000000.0, evaluate("1 G")); assertEquals(1000000000000.0, evaluate("1 T")); assertEquals(1000000000000000.0, evaluate("1 P")); assertEquals(Math.scalb(1.0, 10), evaluate("1 Ki")); assertEquals(Math.scalb(1.0, 20), evaluate("1 Mi")); assertEquals(Math.scalb(1.0, 30), evaluate("1 Gi")); assertEquals(Math.scalb(1.0, 40), evaluate("1 Ti")); assertEquals(Math.scalb(1.0, 50), evaluate("1 Pi")); } @Test public void testOperators() throws Exception { assertEquals(2.0, evaluate("1+1")); assertEquals(0.0, evaluate("1-1")); assertEquals(4.0, evaluate("2*2")); assertEquals(2.5, evaluate("5/2")); assertEquals(1.0, evaluate("5%2")); assertEquals(27.0, evaluate("3**3")); assertEquals(true, evaluate("1 < 2")); assertEquals(false, evaluate("2 < 2")); assertEquals(true, evaluate("2 <= 2")); assertEquals(true, evaluate("2 == 2")); assertEquals(false, evaluate("2 != 2")); assertEquals(false, evaluate("2 > 2")); assertEquals(true, evaluate("2 >= 2")); assertEquals(true, evaluate("true == true")); assertEquals(false, evaluate("true != true")); assertEquals(true, evaluate("'bla' == \"bla\"")); assertEquals(false, evaluate("'bla' == 'false'")); assertEquals(false, evaluate("'bla' != \"bla\"")); assertEquals(true, evaluate("'bla' != 'false'")); assertEquals(-1.0, evaluate("--+-++1")); assertEquals(1.0, evaluate("-+-++1")); assertEquals(1.0, evaluate("true ? 1 : 2")); assertEquals(2.0, evaluate("false ? 1 : 2")); assertEquals(true, evaluate("true ? true : false")); assertEquals(false, evaluate("false ? true : false")); assertEquals("a", evaluate("true ? 'a' : 'b'")); assertEquals("b", evaluate("false ? 'a' : 'b'")); assertEquals(true, evaluate("'blabla' =~ '(bla)+'")); assertEquals(false, evaluate("'blabla' !~ '(bla)+'")); assertEquals(true, evaluate("true and true")); assertEquals(false, evaluate("true and false")); assertEquals(true, evaluate("true or false")); assertEquals(false, evaluate("false or false")); assertEquals(true, evaluate("not false")); assertEquals(false, evaluate("not true")); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerIfCondition() throws Exception { evaluate("1 ? 2 :3"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerIfValues() throws Exception { evaluate("true ? 2 : false"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerNumberEqualsString() throws Exception { evaluate("2.1 == '1'"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerNumberAndNumber() throws Exception { evaluate("2.1 and 1"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerNotNumber() throws Exception { evaluate("not 2.1"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerUminusString() throws Exception { evaluate("-'bla'"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerBooleanLEBoolean() throws Exception { evaluate("true <= true"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerNumberPlusBoolean() throws Exception { evaluate("1+false"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerNumberPlusString() throws Exception { evaluate("1+'one'"); } @Test(expected=TypeMismatchException.class) public void testTypeCheckerMatchNumber() throws Exception { evaluate("1 =~ 2"); } @Test public void testIdentifierWithTrailingSpace() throws Exception { assertEquals(1.0, evaluate("number ")); } }