/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. * * * This file incorporates work covered by the following copyright and * permission notice: * * Copyright 2004 The Apache Software Foundation * * 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 com.sun.faces.el.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.faces.context.ExternalContext; import javax.faces.el.ValueBinding; import com.sun.faces.el.impl.beans.Factory; import com.sun.faces.cactus.ServletFacesTestCase; /** * @author jhook */ public class TestELImpl extends ServletFacesTestCase { /** * */ public TestELImpl() { super(); } /** * @param name */ public TestELImpl(String name) { super(name); } protected Object evaluate(String ref) throws Exception { ValueBinding vb = this.getFacesContext().getApplication().createValueBinding(ref); return vb.getValue(this.getFacesContext()); } public void testELEvaluation() throws Exception { /* setup our test date */ Bean1 b = this.createBean1(); getExternalContext().getRequestMap().put("bean1a", b); getExternalContext().getSessionMap().put("val1c", "session-scoped1"); getExternalContext().getRequestMap().put("val1b", "request-scoped1"); getExternalContext().getApplicationMap().put("val1d", "app-scoped1"); Map m = new HashMap(); m.put("emptyArray", new Object[0]); m.put("nonemptyArray", new Object[] { "abc" }); m.put("emptyList", new ArrayList()); { List l = new ArrayList(); l.add("hello"); m.put("nonemptyList", l); } m.put("emptyMap", new HashMap()); { Map m2 = new HashMap(); m2.put("a", "a"); m.put("nonemptyMap", m2); } m.put("emptySet", new HashSet()); { Set s = new HashSet(); s.add("hello"); m.put("nonemptySet", s); } getExternalContext().getRequestMap().put("emptyTests", m); getExternalContext().getRequestMap().put("pbean1", Factory.createBean1()); getExternalContext().getRequestMap().put("pbean2", Factory.createBean2()); getExternalContext().getRequestMap().put("pbean3", Factory.createBean3()); getExternalContext().getRequestMap().put("pbean4", Factory.createBean4()); getExternalContext().getRequestMap().put("pbean5", Factory.createBean5()); getExternalContext().getRequestMap().put("pbean6", Factory.createBean6()); getExternalContext().getRequestMap().put("pbean7", Factory.createBean7()); /* testing mixture of strings and expressions */ evaluateTest("abc", "abc"); evaluateTest("#{ 3}", new Long(3)); evaluateTestFailure("a#{"); evaluateTest("a#{ 5 }", "a5"); evaluateTest("#{ 3 }b", "3b"); evaluateTest("#{ 1 }#{ 2 }", "12"); evaluateTest("abc #{ 1} #{ 2} def", "abc 1 2 def"); /* testing values that end with or contain "#" */ evaluateTest("#", "#"); evaluateTest("\\#", "#"); evaluateTest("# ", "# "); evaluateTest("test#", "test#"); evaluateTest("#test", "#test"); evaluateTest("test#test", "test#test"); evaluateTest("test###", "test###"); evaluateTest("test###{ 34 }", "test##34"); evaluateTest("test###{ 34 }##", "test##34##"); evaluateTest("test##{ 34 }", "test#34"); evaluateTest("##{ 34 }", "#34"); evaluateTest("##", "##"); evaluateTest("test##", "test##"); evaluateTest("test##test", "test##test"); evaluateTest("#{ 34 }##{ 34 }", "34#34"); /* basic literals */ evaluateTest("#{1}", new Long(1)); evaluateTest("#{-12}", new Long(-12)); evaluateTest("#{true}", Boolean.TRUE); evaluateTest("#{false}", Boolean.FALSE); evaluateTest("#{null}", null); evaluateTest("#{4.2}", new Double(4.2)); evaluateTest("#{-21.3}", new Double(-21.3)); evaluateTest("#{4.}", new Double(4.0)); evaluateTest("#{.21}", new Double(0.21)); evaluateTest("#{3e-1}", new Double(0.3)); evaluateTest("#{.2222222222}", new Double(0.2222222222)); /* basic relationals between literals */ evaluateTest("#{1 < 2}", Boolean.TRUE); evaluateTest("#{1 > 2}", Boolean.FALSE); evaluateTest("#{1 >= 2}", Boolean.FALSE); evaluateTest("#{1 <= 2}", Boolean.TRUE); evaluateTest("#{1 == 2}", Boolean.FALSE); evaluateTest("#{1 != 2}", Boolean.TRUE); evaluateTest("#{3 >= 3}", Boolean.TRUE); evaluateTest("#{3 <= 3}", Boolean.TRUE); evaluateTest("#{3 == 3}", Boolean.TRUE); evaluateTest("#{3 < 3}", Boolean.FALSE); evaluateTest("#{3 > 3}", Boolean.FALSE); evaluateTest("#{3 != 3}", Boolean.FALSE); // PENDING (visvan) check with Kinman/Jacob /* relationals between booleans evaluateTestFailure("#{false < true}"); evaluateTestFailure("#{false > true}"); evaluateTest("#{true >= true}", Boolean.TRUE); evaluateTest("#{true <= true}", Boolean.TRUE); evaluateTest("#{true == true}", Boolean.TRUE); evaluateTest("#{true != true}", Boolean.FALSE); */ /* looking up objects in scopes */ evaluateTest("#{requestScope.val1b}", "request-scoped1"); evaluateTest("#{sessionScope.val1b}", null); evaluateTest("#{applicationScope.val1b}", null); evaluateTest("#{val1b}", "request-scoped1"); evaluateTest("#{requestScope.val1c}", null); evaluateTest("#{sessionScope.val1c}", "session-scoped1"); evaluateTest("#{applicationScope.val1c}", null); evaluateTest("#{val1c}", "session-scoped1"); evaluateTest("#{requestScope.val1d}", null); evaluateTest("#{sessionScope.val1d}", null); evaluateTest("#{applicationScope.val1d}", "app-scoped1"); evaluateTest("#{val1d}", "app-scoped1"); /* accessing properties */ evaluateTest("#{bean1a.int1}", new Integer(b.getInt1())); evaluateTest("#{bean1a.boolean1}", Boolean.valueOf(b.getBoolean1())); evaluateTest("#{bean1a.string1}", b.getString1()); evaluateTest("#{bean1a.bean1.int2}", b.getBean1().getInt2()); evaluateTest("#{bean1a.bean1.bean2.string2}", b.getBean1().getBean2() .getString2()); evaluateTest("#{bean1a.byte1}", new Byte(b.getByte1())); evaluateTest("#{bean1a.char1}", new Character(b.getChar1())); evaluateTest("#{bean1a.short1}", new Short(b.getShort1())); evaluateTest("#{bean1a.long1}", new Long(b.getLong1())); evaluateTest("#{bean1a.float1}", new Float(b.getFloat1())); evaluateTest("#{bean1a.double1}", new Double(b.getDouble1())); /* test the entire relational comparison type promotion matrix */ evaluateTest("#{bean1a.byte1 < bean1a.byte1}", Boolean.FALSE); evaluateTest("#{bean1a.byte1 < bean1a.char1}", Boolean.TRUE); evaluateTest("#{bean1a.byte1 < bean1a.short1}", Boolean.TRUE); evaluateTest("#{bean1a.byte1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.byte1 < bean1a.long1}", Boolean.TRUE); evaluateTest("#{bean1a.byte1 < bean1a.float1}", Boolean.TRUE); evaluateTest("#{bean1a.byte1 < bean1a.double1}", Boolean.TRUE); evaluateTest("#{bean1a.char1 < bean1a.byte1}", Boolean.FALSE); evaluateTest("#{bean1a.char1 < bean1a.char1}", Boolean.FALSE); evaluateTest("#{bean1a.char1 < bean1a.short1}", Boolean.FALSE); evaluateTest("#{bean1a.char1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.char1 < bean1a.long1}", Boolean.FALSE); evaluateTest("#{bean1a.char1 < bean1a.float1}", Boolean.FALSE); evaluateTest("#{bean1a.char1 < bean1a.double1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.byte1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.char1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.short1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.float1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.long1}", Boolean.FALSE); evaluateTest("#{bean1a.short1 < bean1a.double1}", Boolean.FALSE); evaluateTest("#{bean1a.int1 < bean1a.byte1}", Boolean.TRUE); evaluateTest("#{bean1a.int1 < bean1a.char1}", Boolean.TRUE); evaluateTest("#{bean1a.int1 < bean1a.short1}", Boolean.TRUE); evaluateTest("#{bean1a.int1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.int1 < bean1a.long1}", Boolean.TRUE); evaluateTest("#{bean1a.int1 < bean1a.float1}", Boolean.TRUE); evaluateTest("#{bean1a.int1 < bean1a.double1}", Boolean.TRUE); evaluateTest("#{bean1a.long1 < bean1a.byte1}", Boolean.FALSE); evaluateTest("#{bean1a.long1 < bean1a.char1}", Boolean.FALSE); evaluateTest("#{bean1a.long1 < bean1a.short1}", Boolean.FALSE); evaluateTest("#{bean1a.long1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.long1 < bean1a.long1}", Boolean.FALSE); evaluateTest("#{bean1a.long1 < bean1a.float1}", Boolean.FALSE); evaluateTest("#{bean1a.long1 < bean1a.double1}", Boolean.FALSE); evaluateTest("#{bean1a.float1 < bean1a.byte1}", Boolean.FALSE); evaluateTest("#{bean1a.float1 < bean1a.char1}", Boolean.TRUE); evaluateTest("#{bean1a.float1 < bean1a.short1}", Boolean.TRUE); evaluateTest("#{bean1a.float1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.float1 < bean1a.long1}", Boolean.TRUE); evaluateTest("#{bean1a.float1 < bean1a.float1}", Boolean.FALSE); evaluateTest("#{bean1a.float1 < bean1a.double1}", Boolean.TRUE); evaluateTest("#{bean1a.double1 < bean1a.byte1}", Boolean.FALSE); evaluateTest("#{bean1a.double1 < bean1a.char1}", Boolean.TRUE); evaluateTest("#{bean1a.double1 < bean1a.short1}", Boolean.TRUE); evaluateTest("#{bean1a.double1 < bean1a.int1}", Boolean.FALSE); evaluateTest("#{bean1a.double1 < bean1a.long1}", Boolean.TRUE); evaluateTest("#{bean1a.double1 < bean1a.float1}", Boolean.FALSE); evaluateTest("#{bean1a.double1 < bean1a.double1}", Boolean.FALSE); /* test other relational comparison rules */ evaluateTest("#{null == null}", Boolean.TRUE); evaluateTest("#{noSuchAttribute == noSuchAttribute}", Boolean.TRUE); evaluateTest("#{noSuchAttribute == null}", Boolean.TRUE); evaluateTest("#{null == noSuchAttribute}", Boolean.TRUE); evaluateTest("#{bean1a == null}", Boolean.FALSE); evaluateTest("#{null == bean1a}", Boolean.FALSE); evaluateTest("#{bean1a == bean1a}", Boolean.TRUE); // JSF1.2 BI: This test used to fail with JSF 1.1 EL. With unified EL // the first portion of the expression is coerced to a string, so // the expression evaluates to true. evaluateTest("#{bean1a > \"hello\"}", Boolean.FALSE); evaluateTestFailure("#{bean1a.bean1 < 14}"); evaluateTest("#{bean1a.bean1 == \"hello\"}", Boolean.FALSE); /* test String comparisons */ evaluateTest("#{bean1a.string1 == \"hello\"}", Boolean.TRUE); evaluateTest("#{bean1a.string1 != \"hello\"}", Boolean.FALSE); evaluateTest("#{bean1a.string1 == \"goodbye\"}", Boolean.FALSE); evaluateTest("#{bean1a.string1 != \"goodbye\"}", Boolean.TRUE); evaluateTest("#{bean1a.string1 > \"goodbye\"}", Boolean.TRUE); evaluateTest("#{\"hello\" == bean1a.string1}", Boolean.TRUE); evaluateTest("#{\"goodbye\" > bean1a.string1}", Boolean.FALSE); /* test errors in property traversal */ evaluateTest("#{noSuchAttribute.abc}", null); evaluateTest("#{bean1a.bean2.byte1}", null); evaluateTestFailure("#{bean1a.noProperty}"); evaluateTestFailure("#{bean1a.noGetter}"); evaluateTestFailure("#{bean1a.errorInGetter}"); evaluateTest("#{bean1a.bean2.string2}", null); /* test accessing public properties from private classes */ evaluateTest("#{pbean1.value}", "got the value"); evaluateTest("#{pbean2.value}", "got the value"); evaluateTest("#{pbean3.value}", "got the value"); evaluateTest("#{pbean4.value}", "got the value"); evaluateTest("#{pbean5.value}", "got the value"); evaluateTest("#{pbean6.value}", "got the value"); evaluateTest("#{pbean7.value}", "got the value"); /* test reserved words as identifiers */ evaluateTestFailure("#{and}"); evaluateTestFailure("#{or}"); evaluateTestFailure("#{not}"); evaluateTestFailure("#{eq}"); evaluateTestFailure("#{ne}"); evaluateTestFailure("#{lt}"); evaluateTestFailure("#{gt}"); evaluateTestFailure("#{le}"); evaluateTestFailure("#{ge}"); evaluateTest("#{true}", Boolean.TRUE); evaluateTest("#{false}", Boolean.FALSE); evaluateTest("#{null}", null); /* test reserved words as property names */ evaluateTestFailure("#{bean1a.and}"); evaluateTestFailure("#{bean1a.or}"); evaluateTestFailure("#{bean1a.not}"); evaluateTestFailure("#{bean1a.eq}"); evaluateTestFailure("#{bean1a.ne}"); evaluateTestFailure("#{bean1a.lt}"); evaluateTestFailure("#{bean1a.gt}"); evaluateTestFailure("#{bean1a.le}"); evaluateTestFailure("#{bean1a.ge}"); evaluateTestFailure("#{bean1a.instanceof}"); evaluateTestFailure("#{bean1a.page}"); evaluateTestFailure("#{bean1a.request}"); evaluateTestFailure("#{bean1a.session}"); evaluateTestFailure("#{bean1a.application}"); evaluateTestFailure("#{bean1a.true}"); evaluateTestFailure("#{bean1a.false}"); evaluateTestFailure("#{bean1a.null}"); /* test arithmetic */ evaluateTest("#{3+5}", new Long(8)); evaluateTest("#{3-5}", new Long(-2)); evaluateTest("#{3/5}", new Double(0.6)); evaluateTest("#{3*5}", new Long(15)); evaluateTest("#{3*5.0}", new Double(15.0)); evaluateTest("#{3.0*5}", new Double(15.0)); evaluateTest("#{3.0*5.0}", new Double(15.0)); evaluateTest("#{225 % 17}", new Long(4)); evaluateTest("#{ 1 + 2 + 3 * 5 + 6}", new Long(24)); evaluateTest("#{ 1 + (2 + 3) * 5 + 6}", new Long(32)); /* test logical operators */ evaluateTest("#{ true}", Boolean.TRUE); evaluateTest("#{ not true}", Boolean.FALSE); evaluateTest("#{ not false}", Boolean.TRUE); evaluateTest("#{ not not true}", Boolean.TRUE); evaluateTest("#{ not not false}", Boolean.FALSE); evaluateTest("#{ true and false}", Boolean.FALSE); evaluateTest("#{ true and true}", Boolean.TRUE); evaluateTest("#{ false and true}", Boolean.FALSE); evaluateTest("#{ false and false}", Boolean.FALSE); evaluateTest("#{ true or false}", Boolean.TRUE); evaluateTest("#{ true or true}", Boolean.TRUE); evaluateTest("#{ false or true}", Boolean.TRUE); evaluateTest("#{ false or false}", Boolean.FALSE); evaluateTest("#{ false or false or false or true and false}", Boolean.FALSE); evaluateTest("#{ false or false or false or true and false or true}", Boolean.TRUE); /* test indexed access operator */ evaluateTest("#{ bean1a[\"double1\"] }", new Double(b.getDouble1())); evaluateTest("#{ bean1a[\"double1\"].class }", Double.class); evaluateTest("#{ bean1a.stringArray1[-1]}", null); evaluateTest("#{ bean1a.stringArray1[0]}", b.getStringArray1()[0]); evaluateTest("#{ bean1a.stringArray1[1]}", b.getStringArray1()[1]); evaluateTest("#{ bean1a.stringArray1[2]}", b.getStringArray1()[2]); evaluateTest("#{ bean1a.stringArray1[3]}", b.getStringArray1()[3]); evaluateTest("#{ bean1a.stringArray1[4]}", null); /* Test as list accessor */ evaluateTest("#{ bean1a.list1 [0] }", b.getList1().get(0)); evaluateTest("#{ bean1a.list1 [1] }", b.getList1().get(1)); evaluateTest("#{ bean1a.list1 [2][2] }", "string3"); /* Test as indexed property accessor */ evaluateTestFailure("#{ bean1a.indexed1[-1]}"); evaluateTestFailure("#{ bean1a.indexed1[0]}"); evaluateTestFailure("#{ bean1a.indexed1[1]}"); evaluateTestFailure("#{ bean1a.indexed1[2]}"); evaluateTestFailure("#{ bean1a.indexed1[3]}"); evaluateTestFailure("#{ bean1a.indexed1[4]}"); /* Test as map accessor */ evaluateTest("#{ bean1a.map1.noKey }", null); evaluateTest("#{ bean1a.map1.key1 }", b.getMap1().get("key1")); evaluateTest("#{ bean1a.map1 [\"key1\"] }", b.getMap1().get("key1")); evaluateTest("#{ bean1a.map1 [14] }", "value3"); evaluateTest("#{ bean1a.map1 [2 * 7] }", "value3"); evaluateTest("#{ bean1a.map1.recurse.list1[0] }", new Integer(14)); /* Test UIComponent as bean evaluateTest("#{view.rendered}", Boolean.TRUE); evaluateTest("#{view.attributes.rendered}", Boolean.TRUE); evaluateTest("#{view.children[0].value}", "inputValue"); evaluateTest("#{view.children[0].rendered}", Boolean.TRUE); */ /* test String concatenation */ evaluateTestFailure("#{ \"a\" + \"bcd\" }"); evaluateTestFailure("#{ \"a\" + (4*3) }"); evaluateTestFailure("#{ bean1a.map1 [\"key\" + (5-4)] }"); /* test String comparisons */ evaluateTest("#{ \"30\" < \"4\" }", Boolean.TRUE); evaluateTest("#{ 30 < \"4\" }", Boolean.FALSE); evaluateTest("#{ 30 > \"4\" }", Boolean.TRUE); evaluateTest("#{ \"0004\" == \"4\" }", Boolean.FALSE); /* test relational comparison with alternate symbols */ evaluateTest("#{ 4 eq 3}", Boolean.FALSE); evaluateTest("#{ 4 ne 3}", Boolean.TRUE); evaluateTest("#{ 4 eq 4}", Boolean.TRUE); evaluateTest("#{ 4 ne 4}", Boolean.FALSE); evaluateTest("#{ 4 lt 3}", Boolean.FALSE); evaluateTest("#{ 4 gt 3}", Boolean.TRUE); evaluateTest("#{ 4 le 3}", Boolean.FALSE); evaluateTest("#{ 4 ge 3}", Boolean.TRUE); evaluateTest("#{ 4 le 4}", Boolean.TRUE); evaluateTest("#{ 4 ge 4}", Boolean.TRUE); /* test expressions on the left side of a value suffix */ evaluateTest("#{(3).class}", Long.class); evaluateTest("#{(bean1a.map1)[\"key1\"]}", "value1"); /* test String/boolean logical operators */ evaluateTest("#{'true' and false}", Boolean.FALSE); evaluateTest("#{'true' or true}", Boolean.TRUE); evaluateTest("#{false and 'true'}", Boolean.FALSE); evaluateTest("#{false or 'true'}", Boolean.TRUE); /* test empty operator */ evaluateTest("#{ empty \"A\"}", Boolean.FALSE); evaluateTest("#{ empty \"\" }", Boolean.TRUE); evaluateTest("#{ empty null }", Boolean.TRUE); evaluateTest("#{ empty false}", Boolean.FALSE); evaluateTest("#{ empty 0}", Boolean.FALSE); evaluateTest("#{ not empty 0}", Boolean.TRUE); evaluateTest("#{ not empty empty 0}", Boolean.TRUE); evaluateTest("#{ empty emptyTests.emptyArray }", Boolean.TRUE); evaluateTest("#{ empty emptyTests.nonemptyArray }", Boolean.FALSE); evaluateTest("#{ empty emptyTests.emptyList }", Boolean.TRUE); evaluateTest("#{ empty emptyTests.nonemptyList }", Boolean.FALSE); evaluateTest("#{ empty emptyTests.emptyMap }", Boolean.TRUE); evaluateTest("#{ empty emptyTests.nonemptyMap }", Boolean.FALSE); evaluateTest("#{ empty emptyTests.emptySet }", Boolean.TRUE); evaluateTest("#{ empty emptyTests.nonemptySet }", Boolean.FALSE); /* test String arithmetic */ evaluateTest("#{ \"6\" / \"3\" }", new Double(2.0)); evaluateTest("#{ 3 + \"4\" }", new Long(7)); evaluateTest("#{ \"4\" + 3 }", new Long(7)); evaluateTest("#{ 3 + \"4.5\" }", new Double(7.5)); evaluateTest("#{ \"4.5\" + 3 }", new Double(7.5)); evaluateTest("#{ 3.0 + 6.0}", new Double(9.0)); evaluateTest("#{ 31121.0 * 61553.0 }", new Double(1.915590913E9)); evaluateTest("#{ 31121 * 61553 }", new Long(1915590913)); evaluateTest("#{ 65536 * 65536 * 65536 * 32759 }", new Long("9220838762064379904")); evaluateTest("#{ 9220838762064379904.0 - 9220838762064379900.0 }", new Double(0.0)); evaluateTest("#{ 9220838762064379904 - 9220838762064379900 }", new Long(4)); /* test relational operators involving null */ evaluateTest("#{ null == null }", Boolean.TRUE); evaluateTest("#{ null != null }", Boolean.FALSE); evaluateTest("#{ null > null }", Boolean.FALSE); evaluateTest("#{ null < null }", Boolean.FALSE); evaluateTest("#{ null >= null }", Boolean.TRUE); evaluateTest("#{ null <= null }", Boolean.TRUE); evaluateTest("#{ null == 3 }", Boolean.FALSE); evaluateTest("#{ null != 3 }", Boolean.TRUE); evaluateTest("#{ null > 3 }", Boolean.FALSE); evaluateTest("#{ null < 3 }", Boolean.FALSE); evaluateTest("#{ null >= 3 }", Boolean.FALSE); evaluateTest("#{ null <= 3 }", Boolean.FALSE); evaluateTest("#{ 3 == null }", Boolean.FALSE); evaluateTest("#{ 3 != null }", Boolean.TRUE); evaluateTest("#{ 3 > null }", Boolean.FALSE); evaluateTest("#{ 3 < null }", Boolean.FALSE); evaluateTest("#{ 3 >= null }", Boolean.FALSE); evaluateTest("#{ 3 <= null }", Boolean.FALSE); evaluateTest("#{ null == \"\" }", Boolean.FALSE); evaluateTest("#{ null != \"\" }", Boolean.TRUE); evaluateTest("#{ \"\" == null }", Boolean.FALSE); evaluateTest("#{ \"\" != null }", Boolean.TRUE); /* arithmetic operators involving Strings */ evaluateTest("#{ 4 + 3 }", new Long(7)); evaluateTest("#{ 4.0 + 3 }", new Double(7.0)); evaluateTest("#{ 4 + 3.0 }", new Double(7.0)); evaluateTest("#{ 4.0 + 3.0 }", new Double(7.0)); evaluateTest("#{ \"4\" + 3 }", new Long(7)); evaluateTest("#{ \"4.0\" + 3 }", new Double(7.0)); evaluateTest("#{ \"4\" + 3.0 }", new Double(7.0)); evaluateTest("#{ \"4.0\" + 3.0 }", new Double(7.0)); evaluateTest("#{ 4 + \"3\" }", new Long(7)); evaluateTest("#{ 4.0 + \"3\" }", new Double(7.0)); evaluateTest("#{ 4 + \"3.0\" }", new Double(7.0)); evaluateTest("#{ 4.0 + \"3.0\" }", new Double(7.0)); evaluateTest("#{ \"4\" + \"3\" }", new Long(7)); evaluateTest("#{ \"4.0\" + \"3\" }", new Double(7.0)); evaluateTest("#{ \"4\" + \"3.0\" }", new Double(7.0)); evaluateTest("#{ \"4.0\" + \"3.0\" }", new Double(7.0)); evaluateTest("#{ 4 - 3 }", new Long(1)); evaluateTest("#{ 4.0 - 3 }", new Double(1.0)); evaluateTest("#{ 4 - 3.0 }", new Double(1.0)); evaluateTest("#{ 4.0 - 3.0 }", new Double(1.0)); evaluateTest("#{ \"4\" - 3 }", new Long(1)); evaluateTest("#{ \"4.0\" - 3 }", new Double(1.0)); evaluateTest("#{ \"4\" - 3.0 }", new Double(1.0)); evaluateTest("#{ \"4.0\" - 3.0 }", new Double(1.0)); evaluateTest("#{ 4 - \"3\" }", new Long(1)); evaluateTest("#{ 4.0 - \"3\" }", new Double(1.0)); evaluateTest("#{ 4 - \"3.0\" }", new Double(1.0)); evaluateTest("#{ 4.0 - \"3.0\" }", new Double(1.0)); evaluateTest("#{ \"4\" - \"3\" }", new Long(1)); evaluateTest("#{ \"4.0\" - \"3\" }", new Double(1.0)); evaluateTest("#{ \"4\" - \"3.0\" }", new Double(1.0)); evaluateTest("#{ \"4.0\" - \"3.0\" }", new Double(1.0)); evaluateTest("#{ 4 * 3 }", new Long(12)); evaluateTest("#{ 4.0 * 3 }", new Double(12.0)); evaluateTest("#{ 4 * 3.0 }", new Double(12.0)); evaluateTest("#{ 4.0 * 3.0 }", new Double(12.0)); evaluateTest("#{ \"4\" * 3 }", new Long(12)); evaluateTest("#{ \"4.0\" * 3 }", new Double(12.0)); evaluateTest("#{ \"4\" * 3.0 }", new Double(12.0)); evaluateTest("#{ \"4.0\" * 3.0 }", new Double(12.0)); evaluateTest("#{ 4 * \"3\" }", new Long(12)); evaluateTest("#{ 4.0 * \"3\" }", new Double(12.0)); evaluateTest("#{ 4 * \"3.0\" }", new Double(12.0)); evaluateTest("#{ 4.0 * \"3.0\" }", new Double(12.0)); evaluateTest("#{ \"4\" * \"3\" }", new Long(12)); evaluateTest("#{ \"4.0\" * \"3\" }", new Double(12.0)); evaluateTest("#{ \"4\" * \"3.0\" }", new Double(12.0)); evaluateTest("#{ \"4.0\" * \"3.0\" }", new Double(12.0)); evaluateTest("#{ 4 / 3 }", new Double(4.0 / 3.0)); evaluateTest("#{ 4.0 / 3 }", new Double(4.0 / 3.0)); evaluateTest("#{ 4 / 3.0 }", new Double(4.0 / 3.0)); evaluateTest("#{ 4.0 / 3.0 }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4\" / 3 }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4.0\" / 3 }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4\" / 3.0 }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4.0\" / 3.0 }", new Double(4.0 / 3.0)); evaluateTest("#{ 4 / \"3\" }", new Double(4.0 / 3.0)); evaluateTest("#{ 4.0 / \"3\" }", new Double(4.0 / 3.0)); evaluateTest("#{ 4 / \"3.0\" }", new Double(4.0 / 3.0)); evaluateTest("#{ 4.0 / \"3.0\" }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4\" / \"3\" }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4.0\" / \"3\" }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4\" / \"3.0\" }", new Double(4.0 / 3.0)); evaluateTest("#{ \"4.0\" / \"3.0\" }", new Double(4.0 / 3.0)); evaluateTest("#{ 4 % 3 }", new Long(1)); evaluateTest("#{ 4.0 % 3 }", new Double(1.0)); evaluateTest("#{ 4 % 3.0 }", new Double(1.0)); evaluateTest("#{ 4.0 % 3.0 }", new Double(1.0)); evaluateTest("#{ \"4\" % 3 }", new Long(1)); evaluateTest("#{ \"4.0\" % 3 }", new Double(1.0)); evaluateTest("#{ \"4\" % 3.0 }", new Double(1.0)); evaluateTest("#{ \"4.0\" % 3.0 }", new Double(1.0)); evaluateTest("#{ 4 % \"3\" }", new Long(1)); evaluateTest("#{ 4.0 % \"3\" }", new Double(1.0)); evaluateTest("#{ 4 % \"3.0\" }", new Double(1.0)); evaluateTest("#{ 4.0 % \"3.0\" }", new Double(1.0)); evaluateTest("#{ \"4\" % \"3\" }", new Long(1)); evaluateTest("#{ \"4.0\" % \"3\" }", new Double(1.0)); evaluateTest("#{ \"4\" % \"3.0\" }", new Double(1.0)); evaluateTest("#{ \"4.0\" % \"3.0\" }", new Double(1.0)); evaluateTest("#{ \"8\" / \"2\" }", new Double(4.0)); evaluateTest("#{ \"4e2\" + \"3\" }", new Double(403)); evaluateTest("#{ \"4\" + \"3e2\" }", new Double(304)); evaluateTest("#{ \"4e2\" + \"3e2\" }", new Double(700)); /* unary minus operator involving Strings */ evaluateTest("#{ -3 }", new Long(-3)); evaluateTest("#{ -3.0 }", new Double(-3.0)); evaluateTest("#{ -\"3\" }", new Long(-3)); evaluateTest("#{ -\"3.0\" }", new Double(-3)); evaluateTest("#{ -\"3e2\" }", new Double(-300)); } protected Bean1 createBean1() { Bean1 b1 = new Bean1(); b1.setBoolean1(true); b1.setByte1((byte) 12); b1.setShort1((short) 98); b1.setChar1('b'); b1.setInt1(4); b1.setLong1(98); b1.setFloat1((float) 12.4); b1.setDouble1(89.224); b1.setString1("hello"); b1.setStringArray1(new String[] { "string1", "string2", "string3", "string4" }); { List l = new ArrayList(); l.add(new Integer(14)); l.add("another value"); l.add(b1.getStringArray1()); b1.setList1(l); } { Map m = new HashMap(); m.put("key1", "value1"); m.put(new Integer(14), "value2"); m.put(new Long(14), "value3"); m.put("recurse", b1); b1.setMap1(m); } Bean1 b2 = new Bean1(); b2.setInt2(new Integer(-224)); b2.setString2("bean2's string"); b1.setBean1(b2); Bean1 b3 = new Bean1(); b3.setDouble1(1422.332); b3.setString2("bean3's string"); b2.setBean2(b3); return b1; } public ExternalContext getExternalContext() { return getFacesContext().getExternalContext(); } public void evaluateTestFailure(String ref) throws Exception { try { this.evaluate(ref); fail("'" + ref + "' should have thrown an exception"); } catch (Exception e) { // do nothing } } public void evaluateTest(String ref, Object expectedValue) throws Exception { Object returnedValue = this.evaluate(ref); if (returnedValue != null) { Class expectedType = expectedValue.getClass(); Class returnedType = returnedValue.getClass(); String msg = "'" + ref + "' expected [" + expectedValue + "] of type " + expectedType.getName() + ", but returned [" + returnedValue + "] of type " + returnedType.getName(); assertTrue(msg, expectedType.isAssignableFrom(returnedType)); assertEquals(msg, expectedValue, returnedValue); } else { String msg = "'" + ref + "' expected value [" + expectedValue + "], but returned [" + returnedValue + "]"; assertEquals(msg, expectedValue, returnedValue); } } }