/** * Copyright (C) 2010 dennis zhuang (killme2008@gmail.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * **/ package com.googlecode.aviator.parser; import static org.junit.Assert.*; import java.util.regex.Pattern; import org.junit.Before; import org.junit.Test; import com.googlecode.aviator.exception.ExpressionSyntaxErrorException; import com.googlecode.aviator.lexer.ExpressionLexer; public class ExpressionParserUnitTest { private ExpressionParser parser; private FakeCodeGenerator codeGenerator; @Before public void setUp() { this.codeGenerator = new FakeCodeGenerator(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalIdentifier1() { this.parser = new ExpressionParser(new ExpressionLexer("null"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalIdentifier2() { this.parser = new ExpressionParser(new ExpressionLexer("a.null"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalIdentifier3() { this.parser = new ExpressionParser(new ExpressionLexer("a3.2"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseBlankExpression1() { this.parser = new ExpressionParser(new ExpressionLexer(""), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalExpression1() { this.parser = new ExpressionParser(new ExpressionLexer("a=2"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalExpression2() { this.parser = new ExpressionParser(new ExpressionLexer("!=3"), this.codeGenerator); this.parser.parse(); } @Test public void testBitOr() { this.parser = new ExpressionParser(new ExpressionLexer("3|4"), this.codeGenerator); this.parser.parse(); assertEquals("3 4 |", this.codeGenerator.getPostFixExpression()); } @Test public void testBitAnd() { this.parser = new ExpressionParser(new ExpressionLexer("3&4"), this.codeGenerator); this.parser.parse(); assertEquals("3 4 &", this.codeGenerator.getPostFixExpression()); } @Test public void testBitAndNot() { this.parser = new ExpressionParser(new ExpressionLexer("3&~1"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 ~ &", this.codeGenerator.getPostFixExpression()); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalExpression6() { this.parser = new ExpressionParser(new ExpressionLexer("a!b"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseBlankExpression2() { this.parser = new ExpressionParser(new ExpressionLexer("\t "), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseBlankExpression3() { this.parser = new ExpressionParser(new ExpressionLexer(" "), this.codeGenerator); this.parser.parse(); } @Test public void testSimpleExpression() { this.parser = new ExpressionParser(new ExpressionLexer("1+3"), this.codeGenerator); this.parser.parse(); assertEquals("1 3 +", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("1+3-2"), this.codeGenerator); this.parser.parse(); assertEquals("1 3 + 2 -", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("1+3-2/5"), this.codeGenerator); this.parser.parse(); assertEquals("1 3 + 2 5 / -", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("6==3"), this.codeGenerator); this.parser.parse(); assertEquals("6 3 ==", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("6>=3 && c==d.a"), this.codeGenerator); this.parser.parse(); assertEquals("6 3 >= c d.a == &&", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("6>=3 && c==d.a || 0.3<4"), this.codeGenerator); this.parser.parse(); assertEquals("6 3 >= c d.a == && 0.3 4 < ||", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("!true"), this.codeGenerator); this.parser.parse(); assertEquals("true !", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("!a && 3==1"), this.codeGenerator); this.parser.parse(); assertEquals("a ! 3 1 == &&", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("-a+2010"), this.codeGenerator); this.parser.parse(); assertEquals("a - 2010 +", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("3&2^1|4 == 5"), this.codeGenerator); this.parser.parse(); assertEquals("3 2 & 1 ^ 4 5 == |", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("3^2&3|4&~1"), this.codeGenerator); this.parser.parse(); assertEquals("3 2 3 & ^ 4 1 ~ & |", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("true || 2&1==0 ? 1 :0"), this.codeGenerator); this.parser.parse(); assertEquals("true 2 1 0 == & || 1 0 ?:", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("3+4>>1"), this.codeGenerator); this.parser.parse(); assertEquals("3 4 + 1 >>", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("3-4>>1"), this.codeGenerator); this.parser.parse(); assertEquals("3 4 - 1 >>", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("3-4<<1==0"), this.codeGenerator); this.parser.parse(); assertEquals("3 4 - 1 << 0 ==", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("3-4<<1&3"), this.codeGenerator); this.parser.parse(); assertEquals("3 4 - 1 << 3 &", this.codeGenerator.getPostFixExpression()); } @Test public void testParseExpression_WithOneParen() { this.parser = new ExpressionParser(new ExpressionLexer("(3+1)/5"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 + 5 /", this.codeGenerator.getPostFixExpression()); this.codeGenerator.reset(); this.parser = new ExpressionParser(new ExpressionLexer("3-(5+2)"), this.codeGenerator); this.parser.parse(); assertEquals("3 5 2 + -", this.codeGenerator.getPostFixExpression()); this.resetCodeGenerator(); this.parser = new ExpressionParser(new ExpressionLexer("6>=3 && (c==d.a || 0.3<4)"), this.codeGenerator); this.parser.parse(); assertEquals("6 3 >= c d.a == 0.3 4 < || &&", this.codeGenerator.getPostFixExpression()); } @Test public void testParseExpression_WithManyParens1() { this.parser = new ExpressionParser(new ExpressionLexer("6.3-((3+1)/5+3.14)*600%(2+3-(6+(4.3-9)))"), this.codeGenerator); this.parser.parse(); assertEquals("6.3 3 1 + 5 / 3.14 + 600 * 2 3 + 6 4.3 9 - + - % -", this.codeGenerator.getPostFixExpression()); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseExpression_WithIllegalParen1() { this.parser = new ExpressionParser(new ExpressionLexer("3+4)"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseExpression_WithIllegalParen2() { this.parser = new ExpressionParser(new ExpressionLexer("3+4)"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseExpression_IllegalParens3() { this.parser = new ExpressionParser(new ExpressionLexer("(((((3+4)))"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseExpression_IllegalParens4() { this.parser = new ExpressionParser(new ExpressionLexer("(((((3+4)))+3"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseExpression_IllegalParens2() { this.parser = new ExpressionParser(new ExpressionLexer("3-(5+6/(c+d)"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseExpression_IllegalParens() { this.parser = new ExpressionParser(new ExpressionLexer("3-(5+6/(c+d)"), this.codeGenerator); this.parser.parse(); } @Test public void testParsePattern() { this.parser = new ExpressionParser(new ExpressionLexer("'456.5'=~/[\\d\\.]+/"), this.codeGenerator); this.parser.parse(); assertEquals("456.5 [\\d\\.]+ =~", this.codeGenerator.getPostFixExpression()); } @Test public void testParseComplexPattern() { this.parser = new ExpressionParser(new ExpressionLexer( "'killme2008@gmail.com'=~/[a-zA-Z0-9_]+[@][a-zA-Z0-9]+([\\.com]|[\\.cn])/"), this.codeGenerator); this.parser.parse(); assertEquals("killme2008@gmail.com [a-zA-Z0-9_]+[@][a-zA-Z0-9]+([\\.com]|[\\.cn]) =~", this.codeGenerator.getPostFixExpression()); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalPattern() { this.parser = new ExpressionParser(new ExpressionLexer("/[a-zA-Z0-9_]+[@][a-zA-Z0-9]+([\\.com]|[\\.cn])/cdf/"), this.codeGenerator); this.parser.parse(); } @Test public void testParseMorePattern() { this.parser = new ExpressionParser(new ExpressionLexer("/[a-zA-Z0-9_]+[@][a-zA-Z0-9]+([\\.com]|[\\.cn])/==/hello/"), this.codeGenerator); this.parser.parse(); assertEquals("[a-zA-Z0-9_]+[@][a-zA-Z0-9]+([\\.com]|[\\.cn]) hello ==", this.codeGenerator.getPostFixExpression()); } @Test public void testParsePatternWithOtherExpression() { this.parser = new ExpressionParser(new ExpressionLexer(" !false || '456.5'=~/[\\d\\.]+/"), this.codeGenerator); this.parser.parse(); assertEquals("false ! 456.5 [\\d\\.]+ =~ ||", this.codeGenerator.getPostFixExpression()); } @Test public void testParseExpression_WithManyParens2() { this.parser = new ExpressionParser(new ExpressionLexer("5+(5+(5+a*1.02)*1.02)*1.02-600/(4*b-(c+d))"), this.codeGenerator); this.parser.parse(); assertEquals("5 5 5 a 1.02 * + 1.02 * + 1.02 * + 600 4 b * c d + - / -", this.codeGenerator.getPostFixExpression()); } @Test public void testCommonPattern() { this.matchPattern("^\\d+$"); this.matchPattern("^[0-9]*[1-9][0-9]*$"); this.matchPattern("^((-\\d+) ?(0+))$"); this.matchPattern("^-[0-9]*[1-9][0-9]*$"); this.matchPattern("^-?\\d+$"); this.matchPattern("^\\d+(\\.\\d+)?$"); this.matchPattern("^(([0-9]+\\.[0-9]*[1-9][0-9]*) ?([0-9]*[1-9][0-9]*\\.[0-9]+) ?([0-9]*[1-9][0-9]*))$"); this.matchPattern("^((-\\d+(\\.\\d+)?) ?(0+(\\.0+)?))$"); this.matchPattern("^(-(([0-9]+\\.[0-9]*[1-9][0-9]*) ?([0-9]*[1-9][0-9]*\\.[0-9]+) ?([0-9]*[1-9][0-9]*)))$"); this.matchPattern("^(-?\\d+)(\\.\\d+)?$"); this.matchPattern("^[A-Za-z]+$"); this.matchPattern("^[A-Z]+$"); this.matchPattern("^[a-z]+$"); this.matchPattern("^[A-Za-z0-9]+$"); this.matchPattern("^\\w+$"); this.matchPattern("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$"); this.matchPattern("^[a-zA-z]+:\\/\\/(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$"); this.matchPattern("[\u4e00-\u9fa5]"); this.matchPattern("[^\\x00-\\xff]"); this.matchPattern("^\\x00-\\xff]"); this.matchPattern("\\n[\\s ? ]*\\r"); this.matchPattern("<(.*)>.*<\\/\\1>?<(.*)\\/>"); this.matchPattern("(^\\s*)?(\\s*$)"); this.matchPattern("[A-Z][a-z][a-z] [0-9][0-9]*, [0-9]\\{4\\}"); } @Test public void testComplexLogicExpression() { this.parser = new ExpressionParser(new ExpressionLexer("a>b && (c<=d || e!=3.14) && !f"), this.codeGenerator); this.parser.parse(); assertEquals("a b > c d <= e 3.14 != || && f ! &&", this.codeGenerator.getPostFixExpression()); } private void matchPattern(String pattern) { this.codeGenerator.reset(); this.parser = new ExpressionParser(new ExpressionLexer("/" + pattern + "/"), this.codeGenerator); this.parser.parse(); assertEquals(pattern, this.codeGenerator.getPostFixExpression()); } @Test public void testPattern_Escape() { Pattern.compile("http:\\/\\/www\\.google\\.com"); this.parser = new ExpressionParser(new ExpressionLexer("'http://google.com'=~/http:\\/\\/www\\.google\\.com/"), this.codeGenerator); this.parser.parse(); assertEquals("http://google.com http:\\/\\/www\\.google\\.com =~", this.codeGenerator.getPostFixExpression()); } private void resetCodeGenerator() { this.codeGenerator.reset(); } @Test public void testTernary1() { this.parser = new ExpressionParser(new ExpressionLexer("3>1?1:-3"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 > 1 3 - ?:", this.codeGenerator.getPostFixExpression()); } @Test public void testTernary2() { int d = 3 > 1 ? 6 <= 7 ? 0 : 100 : 3 > 2 ? 9 : 0; this.parser = new ExpressionParser(new ExpressionLexer("3>1?6<=7?0:100:3>2?9:0"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 > 6 7 <= 0 100 ?: 3 2 > 9 0 ?: ?:", this.codeGenerator.getPostFixExpression()); } @Test public void testTernary3() { this.parser = new ExpressionParser(new ExpressionLexer("3>1?true:false?1:0"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 > true false 1 0 ?: ?:", this.codeGenerator.getPostFixExpression()); Object d = 3 > 1 ? true : false ? 1 : 0; System.out.println(d); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalTernary1() { this.parser = new ExpressionParser(new ExpressionLexer("3>1?true"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalTernary2() { this.parser = new ExpressionParser(new ExpressionLexer("3>1?true:"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testIllegalTernary3() { this.parser = new ExpressionParser(new ExpressionLexer("3>1?true:false?9"), this.codeGenerator); this.parser.parse(); } @Test public void testTernaryWithParen1() { this.parser = new ExpressionParser(new ExpressionLexer("3==1?(9.0-3>5?-1:2):(false?9:0)"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 == 9.0 3 - 5 > 1 - 2 ?: false 9 0 ?: ?:", this.codeGenerator.getPostFixExpression()); } @Test public void testTernaryWithParen2() { this.parser = new ExpressionParser(new ExpressionLexer("3==1?(100-(3+1)):(false?9:0)"), this.codeGenerator); this.parser.parse(); assertEquals("3 1 == 100 3 1 + - false 9 0 ?: ?:", this.codeGenerator.getPostFixExpression()); } @Test(expected = ExpressionSyntaxErrorException.class) public void testTernaryWithIllegalParen1() { this.parser = new ExpressionParser(new ExpressionLexer("3==1?(100-(3+1):(false?9:0)"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testTernaryWithIllegalParen2() { this.parser = new ExpressionParser(new ExpressionLexer("3==1?(100-3+1)):(false?9:0)"), this.codeGenerator); this.parser.parse(); } @Test public void testParseGroup() { this.parser = new ExpressionParser(new ExpressionLexer("'3.45'=~/(\\d+)\\.(\\d+)/ ? $2 : $0 "), this.codeGenerator); this.parser.parse(); assertEquals("3.45 (\\d+)\\.(\\d+) =~ $2 $0 ?:", this.codeGenerator.getPostFixExpression()); } @Test(expected = ExpressionSyntaxErrorException.class) public void testParseIllegalGroup1() { this.parser = new ExpressionParser(new ExpressionLexer("'3.45'=~/(\\d+)\\.(\\d+)/ ? $2.3 : $0 "), this.codeGenerator); this.parser.parse(); } @Test public void testParseFunction() { this.parser = new ExpressionParser(new ExpressionLexer("string.contains(\"hello\",'fuck')"), this.codeGenerator); this.parser.parse(); assertEquals("hello fuck method<invoked>", this.codeGenerator.getPostFixExpression()); } @Test public void testParseSeqFunction() { this.parser = new ExpressionParser(new ExpressionLexer("map(list,println)"), this.codeGenerator); this.parser.parse(); assertEquals("list println method<invoked>", this.codeGenerator.getPostFixExpression()); } @Test public void testParseReduceFunction() { this.parser = new ExpressionParser(new ExpressionLexer("reduce(list,-,0)"), this.codeGenerator); this.parser.parse(); assertEquals("list - 0 method<invoked>", this.codeGenerator.getPostFixExpression()); } @Test public void testParseFunctionNested() { this.parser = new ExpressionParser(new ExpressionLexer( "string.contains(string.substring(\"hello\",3,4),string.substring(\"hello\",1)) && 3>2"), this.codeGenerator); this.parser.parse(); assertEquals("hello 3 4 method<invoked> hello 1 method<invoked> method<invoked> 3 2 > &&", this.codeGenerator.getPostFixExpression()); } @Test public void testArrayAccess() { this.parser = new ExpressionParser(new ExpressionLexer("a[2]"), this.codeGenerator); this.parser.parse(); assertEquals("a 2 []", this.codeGenerator.getPostFixExpression()); } @Test public void testMultiDimensionalArrayAccess1() { this.parser = new ExpressionParser(new ExpressionLexer("a[2][3]"), this.codeGenerator); this.parser.parse(); assertEquals("a 2 [] 3 []", this.codeGenerator.getPostFixExpression()); } @Test public void testMultiDimensionalArrayAccess2() { this.parser = new ExpressionParser(new ExpressionLexer("a[1][2] [3] [4]"), this.codeGenerator); this.parser.parse(); assertEquals("a 1 [] 2 [] 3 [] 4 []", this.codeGenerator.getPostFixExpression()); } @Test public void testArrayAccess_IndexIsExp() { this.parser = new ExpressionParser(new ExpressionLexer("a[b+c/2]"), this.codeGenerator); this.parser.parse(); assertEquals("a b c 2 / + []", this.codeGenerator.getPostFixExpression()); } @Test public void testArrayAccessNested1() { this.parser = new ExpressionParser(new ExpressionLexer("a[c[3]]"), this.codeGenerator); this.parser.parse(); assertEquals("a c 3 [] []", this.codeGenerator.getPostFixExpression()); } @Test public void testArrayAccessNested2() { this.parser = new ExpressionParser(new ExpressionLexer("a[c[3+c[y*2]]]"), this.codeGenerator); this.parser.parse(); assertEquals("a c 3 c y 2 * [] + [] []", this.codeGenerator.getPostFixExpression()); } @Test(expected = ExpressionSyntaxErrorException.class) public void testArrayAccess_Illegal1() { this.parser = new ExpressionParser(new ExpressionLexer("ab+c/2]"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testArrayAccess_Illegal2() { this.parser = new ExpressionParser(new ExpressionLexer("a[c[3+c[y*2]]"), this.codeGenerator); this.parser.parse(); } // @Test(expected = ExpressionSyntaxErrorException.class) // public void testArrayAccess_Illegal3() { // this.parser = new ExpressionParser(new // ExpressionLexer("a[c[3+true[y*2]]]"), this.codeGenerator); // this.parser.parse(); // } @Test(expected = ExpressionSyntaxErrorException.class) public void testArrayAccess_Illegal4() { this.parser = new ExpressionParser(new ExpressionLexer("a[c3+c[y*2]]]"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testInvalidExpression1() { this.parser = new ExpressionParser(new ExpressionLexer("4(ss*^^%%$$$$"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testInvalidExpression2() { this.parser = new ExpressionParser(new ExpressionLexer("4(*)**&^^^^^^^^"), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testInvalidExpression3() { this.parser = new ExpressionParser(new ExpressionLexer("4("), this.codeGenerator); this.parser.parse(); } @Test(expected = ExpressionSyntaxErrorException.class) public void testInvalidExpression4() { this.parser = new ExpressionParser(new ExpressionLexer("4(*8^####"), this.codeGenerator); this.parser.parse(); } }