/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.el.core.test; import java.util.List; import java.util.Random; import org.jboss.tools.common.el.core.model.ELInstance; import org.jboss.tools.common.el.core.model.ELModel; import org.jboss.tools.common.el.core.parser.ELParser; import org.jboss.tools.common.el.core.parser.ELParserFactory; import org.jboss.tools.common.el.core.parser.ELParserUtil; import org.jboss.tools.common.el.core.parser.LexicalToken; import org.jboss.tools.common.el.core.parser.SyntaxError; import org.jboss.tools.common.el.core.parser.Tokenizer; import org.jboss.tools.common.el.core.parser.TokenizerFactory; import junit.framework.TestCase; public class ELParserTest extends TestCase { public ELParserTest() { } protected void setUp() throws Exception { } public void testTokenizerOnCorrectEL() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); // 1. One variable checkCorrectEL(t, "#{a}"); // 2. Two EL instances checkCorrectEL(t, "#{a}#{b}"); // 3. Property invocation checkCorrectEL(t, "#{a.b}"); // 4. Argument invocation checkCorrectEL(t, "#{a.b['xxx']}"); // 5a. Method invocation checkCorrectEL(t, "#{a.b()}"); // 5b. Method invocation with one parameter checkCorrectEL(t, "#{a.b(c)}"); // 5c. Method invocation with two parameters checkCorrectEL(t, "#{a.b(c.d , e['u'])}"); // 5d. Method invocation on a string checkCorrectEL(t, "#{'a'.compareTo('c')}"); // 6. Numeric checkCorrectEL(t, "#{a.b(16.900)}"); // 7. Boolean checkCorrectEL(t, "#{a.b(false)}"); // 8. Operators checkCorrectEL(t, "#{a.b(7 + 8) * 4 / 2 - 1}"); // 9. Complex expressions checkCorrectEL(t, "#{a.b(7 + 8) * (4 / 2 - 1)/c.d}"); // 10. Complex expressions checkCorrectEL(t, "#{a.b(7 + 8) * (4 / 2 - 1)/c.d}"); } /** * JBIDE-3132 An OutOfMemory exception is thrown by Code assist for * "#{messages[ " */ public void testJBIDE3132() { ELParser parser = ELParserUtil.getJbossFactory().createParser(); String el = "#{messages["; ELModel model = parser.parse(el); List<ELInstance> is = model.getInstances(); assertEquals(1, is.size()); assertEquals(el, is.get(0).getText()); } public void testElEmptyOperator() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{empty a}"); } public void testElLogicalNotOperators() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{not a == null}"); checkCorrectEL(t, "#{!a eq null}"); } public void testElLogicalAndOperators() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{a!=null and a!=1}"); checkCorrectEL(t, "#{a!=null && a!=1}"); } public void testElLogicalOrOperators() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{a!=null or a!=1}"); checkCorrectEL(t, "#{a!=null || a!=1}"); } public void testElConditionalOperator() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{a?1:2}"); } public void testElRelationalOperator() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{a == b}"); checkCorrectEL(t, "#{a eq b}"); checkCorrectEL(t, "#{a != b}"); checkCorrectEL(t, "#{a ne b}"); checkCorrectEL(t, "#{a < b}"); checkCorrectEL(t, "#{a lt b}"); checkCorrectEL(t, "#{a > b}"); checkCorrectEL(t, "#{a < b}"); checkCorrectEL(t, "#{a <= b}"); checkCorrectEL(t, "#{a ge b}"); checkCorrectEL(t, "#{a >= b}"); checkCorrectEL(t, "#{a le b}"); checkCorrectEL(t, "#{'a' < 'b'}"); } public void testElArithmeticOperators() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{a*b}"); checkCorrectEL(t, "#{a/b}"); checkCorrectEL(t, "#{a div b}"); checkCorrectEL(t, "#{a%b}"); checkCorrectEL(t, "#{a mod b}"); checkCorrectEL(t, "#{a-b}"); checkCorrectEL(t, "#{a+b}"); checkCorrectEL(t, "#{-b+1}"); checkCorrectEL(t, "#{-b}"); } public void testElLiteralExpressions() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{\"#{\"}"); checkCorrectEL(t, "\\#{exprA}"); checkCorrectEL(t, "#{\"\\\"exprA\\\"\"}"); checkCorrectEL(t, "#{\"\\\"#\\\"\"}"); checkCorrectEL(t,"#{'+'}"); // Ask google :) // http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html#indexterm-357 checkCorrectEL(t,"#{'#{'}exprB}"); //Why this is correct? } public void testElReferencesObjectProperties() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{customer.address[\"street\"]}"); checkCorrectEL(t, "#{customer.address['street']}"); checkCorrectEL(t, "#{customer.address[1]}"); checkCorrectEL(t, "#{customer.address[customer.address[customer.address[0]]]}"); checkCorrectEL(t, "#{planets[object.counter].mass}"); } public void testElSimpleTypes() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{\"string\"}"); checkCorrectEL(t, "#{'string'}"); checkCorrectEL(t, "#{11.0}"); checkCorrectEL(t, "#{1.2E4}"); checkCorrectEL(t, "#{null}"); checkCorrectEL(t, "#{1}"); checkCorrectEL(t, "#{true}"); checkCorrectEL(t, "#{false}"); } public void testReservedWordAnd() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"and"); } public void testReservedWordOr() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"or"); } public void testReservedWordNot() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkIncorrectEL(t, "#{"+"not"+"}",5); checkIncorrectEL(t, "#{"+"not"+".method1}", 5); checkIncorrectEL(t, "#{"+"not"+"*"+"not"+"}", 5); } public void testReservedWordEq() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"eq"); } public void testReservedWordNe() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"ne"); } public void testReservedWordLt() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"lt"); } public void testReservedWordGt() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"gt"); } public void testReservedWordLe() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"le"); } public void testReservedWordGe() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"ge"); } public void testReservedWordTrue() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkIncorrectEL(t, "#{true.method1}", 6); } public void testReservedWordFalse() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkIncorrectEL(t, "#{false.method1}", 7); } public void testReservedWordNull() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkIncorrectEL(t, "#{null.method1}", 6); } public void testReservedWordInstanceof() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"instanceof"); } public void testReservedWordEmpty() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkIncorrectEL(t, "#{empty.method1}", 7); } public void testReservedWordDiv() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"div"); } public void testReservedWordMod() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); doReservedWordTest(t,"mod"); } private void doReservedWordTest(Tokenizer t, String keyword) { checkIncorrectEL(t, "#{"+keyword+"}",2); checkIncorrectEL(t, "#{"+keyword+".method1}", 2); checkIncorrectEL(t, "#{"+keyword+"+"+keyword+"}", 2); } public void testComplexMath() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{(7 * (13 + 7.9)) * (a + b.c / d) / (1.3E5) - (1/a.b+8./c.d)}"); } public void testComplexInvocation() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{a.b[a1.b1(a2.b2,a3.b3(x))][y].c(a4.b4,a5.b5[a6(b6)])}"); } public void testSeveralELInstances() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "aaa#{a}bbb#{1}#{c()}"); } public void testElInParenthesis() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{(a + 1).toString()}"); } public void testArray() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkCorrectEL(t, "#{[]}"); checkCorrectEL(t, "#{[1]}"); checkCorrectEL(t, "#{[1,2]}"); checkCorrectEL(t, "#{[1,[2,3]]}"); checkCorrectEL(t, "#{['a','b']}"); } private void checkCorrectEL(Tokenizer t, String test) { LexicalToken token = t.parse(test); assertEquals(test, restore(token)); List<SyntaxError> errors = t.getErrors(); assertEquals("EL '" + test + "' has no syntax problems.", 0, errors .size()); System.out.println("Passed correct EL '" + test + "'"); } public void testTokenizerOnIncorrectEL() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); // 1. Dot unfollowed by name checkIncorrectEL(t, "#{a.}", 4); // 2. Incorrect use of ')' checkIncorrectEL(t, "#{a.b + -c.d + g)}", 16); // 2. Incorrect use of '.' in second EL instance checkIncorrectEL(t, "#{a.b + -c.d + g}#{hh.vv..m()}", 25); // incorrect operation checkIncorrectEL(t, "#{!}", 3); checkIncorrectEL(t, "#{+}", 3); checkIncorrectEL(t, "#{-}", 3); checkIncorrectEL(t, "#{()}", 3); // checkIncorrectEL(t, "#{[1]}", 2); it is a correct array checkIncorrectEL(t, "#{%}", 2); checkIncorrectEL(t, "#{:}", 2); checkIncorrectEL(t, "#{/}", 2); checkIncorrectEL(t, "#{*}", 2); checkIncorrectEL(t, "#{&&}", 2); checkIncorrectEL(t, "#{||}", 2); checkIncorrectEL(t, "#{<}", 2); checkIncorrectEL(t, "#{>}", 2); checkIncorrectEL(t, "#{<=}", 2); checkIncorrectEL(t, "#{>=}", 2); checkIncorrectEL(t, "#{==}", 2); checkIncorrectEL(t, "#{!=}", 3); checkIncorrectEL(t, "#{?}", 2); checkIncorrectEL(t, "#{=}", 2); //unclosed string checkIncorrectEL(t, "#{bean.method('abc)}", 14); checkIncorrectEL(t, "#{bean.method(\"abc)}", 14); //unclosed parenthesis checkIncorrectEL(t, "#{bean.method('abc'}", 19); checkIncorrectEL(t, "#{c.a[1.5E7]}",7); //TODO } public void testLexemas() { Tokenizer t = TokenizerFactory.createJbossTokenizer(); checkIncorrectEL(t, "#{#identifier}", 2); checkIncorrectEL(t, "#{2identifier}", 3); checkIncorrectEL(t, "#{$identifier}", 2); checkIncorrectEL(t, "#{i1.2methodorproperty}", 5); } private void checkIncorrectEL(Tokenizer t, String test, int expectedErrorPosition) { LexicalToken token = t.parse(test); List<SyntaxError> errors = t.getErrors(); assertTrue("EL '" + test + "' has no syntax problems. ", errors.size() > 0); assertEquals(expectedErrorPosition, errors.get(0).getPosition()); String correctPart = test.substring(0, expectedErrorPosition); String parsed = restore(token); assertTrue( "Parsed value should be identical to source at least until first problem.", parsed.startsWith(correctPart)); System.out.println("Passed incorrect EL '" + test + "'"); } private String restore(LexicalToken token) { StringBuffer sb = new StringBuffer(); while (token != null) { sb.append(token.getText()); token = token.getNextToken(); } return sb.toString(); } static int TREAD_NUMBER = 20; static int CALL_NUMBER = 1000; public void testMultiThreadAccess() { final ELParserFactory factory = ELParserUtil.getJbossFactory(); final Random random = new Random(); class Z { int counter = 0; int parserErrors = 0; int syntaxErrors = 0; int expectedSyntaxErrors = 0; synchronized void addParserError() { parserErrors++; } synchronized void addSyntaxError() { syntaxErrors++; } synchronized void addExpectedSyntaxError() { expectedSyntaxErrors++; } synchronized void addCounter() { counter++; } synchronized void removeCounter() { counter--; } synchronized int getCounter() { return counter; } } final Z z = new Z(); for (int i = 0; i < TREAD_NUMBER; i++) { Runnable r = new Runnable() { public void run() { z.addCounter(); try { for (int j = 0; j < CALL_NUMBER; j++) { boolean addError = random.nextInt(100) < 50; if (addError) z.addExpectedSyntaxError(); ELParser parser = factory.createParser(); String el = "#{(a + b(c.d" + random.nextInt(1000) + ") + c().k" + (addError ? "." : "") + ") + 9.7}"; ELModel model = parser.parse(el); LexicalToken t = model.getFirstToken(); if (!el.equals(restore(t))) { z.addParserError(); } if (model.getSyntaxErrors() != null && model.getSyntaxErrors().size() > 0) { z.addSyntaxError(); } } } finally { z.removeCounter(); } } }; new Thread(r).start(); } while (z.getCounter() > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { } } System.out.println("testMultiThreadAccess: Expected syntax errors=" + z.expectedSyntaxErrors); assertEquals(0, z.parserErrors); assertEquals(z.expectedSyntaxErrors, z.syntaxErrors); } }