/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.el; import java.io.File; import java.util.Date; import javax.el.ELException; import javax.el.ValueExpression; import org.junit.Assert; import org.junit.Test; import org.apache.el.lang.ELSupport; import org.apache.jasper.el.ELContextImpl; /** * Tests the EL engine directly. Similar tests may be found in * {@link org.apache.jasper.compiler.TestAttributeParser} and * {@link TestELInJsp}. */ public class TestELEvaluation { /** * Test use of spaces in ternary expressions. This was primarily an EL * parser bug. */ @Test public void testBug42565() { Assert.assertEquals("false", evaluateExpression("${false?true:false}")); Assert.assertEquals("false", evaluateExpression("${false?true: false}")); Assert.assertEquals("false", evaluateExpression("${false?true :false}")); Assert.assertEquals("false", evaluateExpression("${false?true : false}")); Assert.assertEquals("false", evaluateExpression("${false? true:false}")); Assert.assertEquals("false", evaluateExpression("${false? true: false}")); Assert.assertEquals("false", evaluateExpression("${false? true :false}")); Assert.assertEquals("false", evaluateExpression("${false? true : false}")); Assert.assertEquals("false", evaluateExpression("${false ?true:false}")); Assert.assertEquals("false", evaluateExpression("${false ?true: false}")); Assert.assertEquals("false", evaluateExpression("${false ?true :false}")); Assert.assertEquals("false", evaluateExpression("${false ?true : false}")); Assert.assertEquals("false", evaluateExpression("${false ? true:false}")); Assert.assertEquals("false", evaluateExpression("${false ? true: false}")); Assert.assertEquals("false", evaluateExpression("${false ? true :false}")); Assert.assertEquals("false", evaluateExpression("${false ? true : false}")); } /** * Test use nested ternary expressions. This was primarily an EL parser bug. */ @Test public void testBug44994() { Assert.assertEquals("none", evaluateExpression( "${0 lt 0 ? 1 lt 0 ? 'many': 'one': 'none'}")); Assert.assertEquals("one", evaluateExpression( "${0 lt 1 ? 1 lt 1 ? 'many': 'one': 'none'}")); Assert.assertEquals("many", evaluateExpression( "${0 lt 2 ? 1 lt 2 ? 'many': 'one': 'none'}")); } @Test public void testParserBug45511() { // Test cases provided by OP Assert.assertEquals("true", evaluateExpression("${empty ('')}")); Assert.assertEquals("true", evaluateExpression("${empty('')}")); Assert.assertEquals("false", evaluateExpression("${(true) and (false)}")); Assert.assertEquals("false", evaluateExpression("${(true)and(false)}")); } @Test public void testBug48112() { // bug 48112 Assert.assertEquals("{world}", evaluateExpression("${fn:trim('{world}')}")); } @Test public void testParserLiteralExpression() { // Inspired by work on bug 45451, comments from kkolinko on the dev // list and looking at the spec to find some edge cases // '\' is only an escape character inside a StringLiteral Assert.assertEquals("\\\\", evaluateExpression("\\\\")); /* * LiteralExpressions can only contain ${ or #{ if escaped with \ * \ is not an escape character in any other circumstances including \\ */ Assert.assertEquals("\\", evaluateExpression("\\")); Assert.assertEquals("$", evaluateExpression("$")); Assert.assertEquals("#", evaluateExpression("#")); Assert.assertEquals("\\$", evaluateExpression("\\$")); Assert.assertEquals("\\#", evaluateExpression("\\#")); Assert.assertEquals("\\\\$", evaluateExpression("\\\\$")); Assert.assertEquals("\\\\#", evaluateExpression("\\\\#")); Assert.assertEquals("${", evaluateExpression("\\${")); Assert.assertEquals("#{", evaluateExpression("\\#{")); Assert.assertEquals("\\${", evaluateExpression("\\\\${")); Assert.assertEquals("\\#{", evaluateExpression("\\\\#{")); // '\' is only an escape for '${' and '#{'. Assert.assertEquals("\\$", evaluateExpression("\\$")); Assert.assertEquals("${", evaluateExpression("\\${")); Assert.assertEquals("\\$a", evaluateExpression("\\$a")); Assert.assertEquals("\\a", evaluateExpression("\\a")); Assert.assertEquals("\\\\", evaluateExpression("\\\\")); } @Test public void testParserStringLiteral() { // Inspired by work on bug 45451, comments from kkolinko on the dev // list and looking at the spec to find some edge cases // The only characters that can be escaped inside a String literal // are \ " and '. # and $ are not escaped inside a String literal. Assert.assertEquals("\\", evaluateExpression("${'\\\\'}")); Assert.assertEquals("\\", evaluateExpression("${\"\\\\\"}")); Assert.assertEquals("\\\"'$#", evaluateExpression("${'\\\\\\\"\\'$#'}")); Assert.assertEquals("\\\"'$#", evaluateExpression("${\"\\\\\\\"\\'$#\"}")); // Trying to quote # or $ should throw an error Exception e = null; try { evaluateExpression("${'\\$'}"); } catch (ELException el) { e = el; } Assert.assertNotNull(e); Assert.assertEquals("\\$", evaluateExpression("${'\\\\$'}")); Assert.assertEquals("\\\\$", evaluateExpression("${'\\\\\\\\$'}")); // Can use ''' inside '"' when quoting with '"' and vice versa without // escaping Assert.assertEquals("\\\"", evaluateExpression("${'\\\\\"'}")); Assert.assertEquals("\"\\", evaluateExpression("${'\"\\\\'}")); Assert.assertEquals("\\'", evaluateExpression("${'\\\\\\''}")); Assert.assertEquals("'\\", evaluateExpression("${'\\'\\\\'}")); Assert.assertEquals("\\'", evaluateExpression("${\"\\\\'\"}")); Assert.assertEquals("'\\", evaluateExpression("${\"'\\\\\"}")); Assert.assertEquals("\\\"", evaluateExpression("${\"\\\\\\\"\"}")); Assert.assertEquals("\"\\", evaluateExpression("${\"\\\"\\\\\"}")); } @Test public void testMultipleEscaping() throws Exception { Assert.assertEquals("''", evaluateExpression("${\"\'\'\"}")); } private void compareBoth(String msg, int expected, Object o1, Object o2){ int i1 = ELSupport.compare(null, o1, o2); int i2 = ELSupport.compare(null, o2, o1); Assert.assertEquals(msg,expected, i1); Assert.assertEquals(msg,expected, -i2); } @Test public void testElSupportCompare(){ compareBoth("Nulls should compare equal", 0, null, null); compareBoth("Null should compare equal to \"\"", 0, "", null); compareBoth("Null should be less than File()",-1, null, new File("")); compareBoth("Null should be less than Date()",-1, null, new Date()); compareBoth("Date(0) should be less than Date(1)",-1, new Date(0), new Date(1)); try { compareBoth("Should not compare",0, new Date(), new File("")); Assert.fail("Expecting ClassCastException"); } catch (ClassCastException expected) { // Expected } Assert.assertTrue(null == null); } /** * Test mixing ${...} and #{...} in the same expression. */ @Test public void testMixedTypes() { // Mixing types should throw an error Exception e = null; try { evaluateExpression("${1+1}#{1+1}"); } catch (ELException el) { e = el; } Assert.assertNotNull(e); } @Test public void testEscape01() { Assert.assertEquals("$${", evaluateExpression("$\\${")); } @Test public void testBug49081a() { Assert.assertEquals("$2", evaluateExpression("$${1+1}")); } @Test public void testBug49081b() { Assert.assertEquals("#2", evaluateExpression("##{1+1}")); } @Test public void testBug49081c() { Assert.assertEquals("#2", evaluateExpression("#${1+1}")); } @Test public void testBug49081d() { Assert.assertEquals("$2", evaluateExpression("$#{1+1}")); } @Test public void testBug60431a() { Assert.assertEquals("OK", evaluateExpression("${fn:concat('O','K')}")); } @Test public void testBug60431b() { Assert.assertEquals("OK", evaluateExpression("${fn:concat(fn:toArray('O','K'))}")); } @Test public void testBug60431c() { Assert.assertEquals("", evaluateExpression("${fn:concat()}")); } @Test public void testBug60431d() { Assert.assertEquals("OK", evaluateExpression("${fn:concat2('OK')}")); } @Test public void testBug60431e() { Assert.assertEquals("RUOK", evaluateExpression("${fn:concat2('RU', fn:toArray('O','K'))}")); } // ************************************************************************ private String evaluateExpression(String expression) { ExpressionFactoryImpl exprFactory = new ExpressionFactoryImpl(); ELContextImpl ctx = new ELContextImpl(exprFactory); ctx.setFunctionMapper(new TesterFunctions.FMapper()); ValueExpression ve = exprFactory.createValueExpression(ctx, expression, String.class); return (String) ve.getValue(ctx); } }