diff options
Diffstat (limited to 'velocity-engine-core/src/test/java/org/apache/velocity/test/InvalidEventHandlerTestCase.java')
-rw-r--r-- | velocity-engine-core/src/test/java/org/apache/velocity/test/InvalidEventHandlerTestCase.java | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/velocity-engine-core/src/test/java/org/apache/velocity/test/InvalidEventHandlerTestCase.java b/velocity-engine-core/src/test/java/org/apache/velocity/test/InvalidEventHandlerTestCase.java new file mode 100644 index 00000000..48ba8e61 --- /dev/null +++ b/velocity-engine-core/src/test/java/org/apache/velocity/test/InvalidEventHandlerTestCase.java @@ -0,0 +1,646 @@ +package org.apache.velocity.test; + +/* + * 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. + */ + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.app.event.EventCartridge; +import org.apache.velocity.app.event.InvalidReferenceEventHandler; +import org.apache.velocity.context.Context; +import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.RuntimeServices; +import org.apache.velocity.util.RuntimeServicesAware; +import org.apache.velocity.util.introspection.Info; + +import java.io.StringWriter; +import java.io.Writer; + +/** + * Tests event handling for all event handlers except IncludeEventHandler. This is tested + * separately due to its complexity. + * + * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> + * @version $Id$ + */ +public class InvalidEventHandlerTestCase +extends TestCase +{ + // @@ VELOCITY-553 + public class TestObject { + private String nullValueAttribute = null; + + public String getNullValueAttribute() { + return nullValueAttribute; + } + + public String getRealString() { + return new String("helloFooRealStr"); + } + + public String getString() { + return new String("helloFoo"); + } + + public String getNullString() { + return null; + } + + public java.util.Date getNullDate() { + return null; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("TestObject [nullValueAttribute="); + builder.append(nullValueAttribute); + builder.append("]"); + return builder.toString(); + } + } + // @@ VELOCITY-553 + + + /** + * Default constructor. + */ + public InvalidEventHandlerTestCase(String name) + { + super(name); + } + + public static Test suite () + { + return new TestSuite(InvalidEventHandlerTestCase.class); + } + + public void testManualEventHandlers() + throws Exception + { + TestEventCartridge te = new TestEventCartridge(); + + /* + * Test attaching the event cartridge to the context + */ + VelocityEngine ve = new VelocityEngine(); + ve.init(); + + /* + * lets make a Context and add the event cartridge + */ + + VelocityContext inner = new VelocityContext(); + + /* + * Now make an event cartridge, register all the + * event handlers (at once) and attach it to the + * Context + */ + + EventCartridge ec = new EventCartridge(); + ec.addEventHandler(te); + ec.attachToContext( inner ); + + doTestInvalidReferenceEventHandler0(ve, inner); + doTestInvalidReferenceEventHandler1(ve, inner); + doTestInvalidReferenceEventHandler2(ve, inner); + doTestInvalidReferenceEventHandler3(ve, inner); + doTestInvalidReferenceEventHandler4(ve, inner); + } + + /** + * Test assigning the event handlers via properties + */ + public void testConfigurationEventHandlers() + throws Exception + { + VelocityEngine ve = new VelocityEngine(); + ve.setProperty(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES, TestEventCartridge.class.getName()); + + ve.init(); + doTestInvalidReferenceEventHandler0(ve, null); + doTestInvalidReferenceEventHandler1(ve, null); + doTestInvalidReferenceEventHandler2(ve, null); + doTestInvalidReferenceEventHandler3(ve, null); + doTestInvalidReferenceEventHandler4(ve, null); + } + + /** + * Test deeper structures + * @param ve + * @param vc + * @throws Exception + */ + private void doTestInvalidReferenceEventHandler4(VelocityEngine ve, VelocityContext vc) + throws Exception + { + VelocityContext context = new VelocityContext(vc); + + Tree test = new Tree(); + test.setField("10"); + Tree test2 = new Tree(); + test2.setField("12"); + test.setChild(test2); + + context.put("tree",test); + String s; + Writer w; + + // show work fine + s = "$tree.Field $tree.field $tree.child.Field"; + w = new StringWriter(); + ve.evaluate(context, w, "mystring", s); + + s = "$tree.x $tree.field.x $tree.child.y $tree.child.Field.y"; + w = new StringWriter(); + ve.evaluate(context, w, "mystring", s); + + } + + /** + * Test invalid #set + * @param ve + * @param vc + * @throws Exception + */ + private void doTestInvalidReferenceEventHandler3(VelocityEngine ve, VelocityContext vc) + throws Exception + { + VelocityContext context = new VelocityContext(vc); + context.put("a1", 5); + context.put("a4", 5); + context.put("b1","abc"); + + String s; + Writer w; + + // good object, bad right hand side + s = "#set($xx = $a1.afternoon())"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // good object, bad right hand reference + s = "#set($yy = $q1)"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + } + + /** + * Test invalid method calls + * @param ve + * @param vc + * @throws Exception + */ + private void doTestInvalidReferenceEventHandler2(VelocityEngine ve, VelocityContext vc) + throws Exception + { + VelocityContext context = new VelocityContext(vc); + context.put("a1", 5); + context.put("a4", 5); + context.put("b1","abc"); + + String s; + Writer w; + + // good object, bad method + s = "$a1.afternoon()"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // good object, bad method, quiet reference + s = "$!a1.afternoon()"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("", w.toString()); + + // bad object, bad method -- fails on get + s = "$zz.daylight()"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // bad object, bad method, quiet reference + s = "$!zz.daylight()"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("", w.toString()); + + // change result + s = "$b1.baby()"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("www",w.toString()); + } + + /** + * Test invalid gets/references + * @param ve + * @param vc + * @throws Exception + */ + private void doTestInvalidReferenceEventHandler1(VelocityEngine ve, VelocityContext vc) + throws Exception + { + String result; + + VelocityContext context = new VelocityContext(vc); + context.put("a1", 5); + context.put("a4", 5); + context.put("b1","abc"); + + // normal - should be no calls to handler + String s = "$a1 $a1.intValue() $b1 $b1.length() #set($c1 = '5')"; + Writer w = new StringWriter(); + ve.evaluate(context, w, "mystring", s); + + // good object, bad property + s = "$a1.foobar"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // same one as a quiet reference should not fail + s = "$!a1.foobar"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("",w.toString()); + + // same one inside an #if statement should not fail + s = "#if($a1.foobar)yes#{else}no#end"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("no",w.toString()); + + + // bad object, bad property + s = "$a2.foobar"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // same one as a quiet reference should not fail + s = "$!a2.foobar"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("",w.toString()); + + // same one inside an #if statement should still fail + s = "#if($a2.foobar)yes#{else}no#end"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // except if object is tested first + s = "#if($a2 and $a2.foobar)yes#{else}no#end"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + assertEquals("no", w.toString()); + + // bad object, no property + s = "$a3"; + w = new StringWriter(); + try { + ve.evaluate( context, w, "mystring", s ); + fail("Expected exception."); + } catch (RuntimeException e) {} + + // bad object, no property as quiet reference should not fail + s = "$!a3"; + w = new StringWriter(); + ve.evaluate(context, w, "mystring", s); + result = w.toString(); + assertEquals("", result); + + // bad object, no property as #if condition should not fail + s = "#if($a3)yes#{else}no#end"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + result = w.toString(); + assertEquals("no", result); + + // good object, bad property; change the value + s = "$a4.foobar"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + result = w.toString(); + assertEquals("zzz", result); + + } + + /** + * Test invalidGetMethod + * + * Test behaviour (which should be the same) of + * $objRef.myAttribute and $objRef.getMyAttribute() + * + * @param ve + * @param vc + * @throws Exception + */ + private void doTestInvalidReferenceEventHandler0(VelocityEngine ve, VelocityContext vc) + throws Exception + { + String result; + Writer w; + String s; + boolean rc; + + VelocityContext context = new VelocityContext(vc); + context.put("propertyAccess", new String("lorem ipsum")); + context.put("objRef", new TestObject()); + java.util.ArrayList arrayList = new java.util.ArrayList(); + arrayList.add("firstOne"); + arrayList.add(null); + java.util.HashMap hashMap = new java.util.HashMap(); + hashMap.put(41, "41 is not 42"); + + context.put("objRefArrayList", arrayList); + context.put("objRefHashMap", hashMap); + + // good object, good property (returns non null value) + s = "#set($resultVar = $propertyAccess.bytes)"; // -> getBytes() + w = new StringWriter(); + rc = ve.evaluate( context, w, "mystring", s ); + + // good object, good property accessor method (returns non null value) + s = "#set($resultVar = $propertyAccess.getBytes())"; // -> getBytes() + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + // good object, good property (returns non null value) + s = "$objRef.getRealString()"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + // good object, good property accessor method (returns null value) + // No exception shall be thrown, as returning null should be valid + s = "$objRef.getNullValueAttribute()"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + // good object, good property (returns null value) + // No exception shall be thrown, as returning null should be valid + s = "$objRef.nullValueAttribute"; // -> getNullValueAttribute() + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + // good object, good accessor method which returns a non-null object reference + // Test removing a hashmap element which exists + s = "$objRefHashMap.remove(41)"; + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + + // good object, good accessor method which returns null + // Test removing a hashmap element which DOES NOT exist + // Expected behaviour: Returning null as a value should be + // OK and not result in an exception + s = "$objRefHashMap.remove(42)"; // will return null, as the key does not exist + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + // good object, good method invocation (returns non-null object reference) + s = "$objRefArrayList.get(0)"; // element 0 is NOT NULL + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + + // good object, good method invocation (returns null value) + // Expected behaviour: Returning null as a value should be + // OK and not result in an exception + s = "$objRefArrayList.get(1)"; // element 1 is null + w = new StringWriter(); + ve.evaluate( context, w, "mystring", s ); + + } + + + + /** + * Test assigning the event handlers via properties + */ + + public static class TestEventCartridge + implements InvalidReferenceEventHandler, + RuntimeServicesAware + { + private RuntimeServices rs; + + public TestEventCartridge() + { + } + + /** + * Required by EventHandler + */ + @Override + public void setRuntimeServices(RuntimeServices rs ) + { + // make sure this is only called once + if (this.rs == null) + this.rs = rs; + + else + fail("initialize called more than once."); + } + + + @Override + public Object invalidGetMethod(Context context, String reference, Object object, String property, Info info) + { + // as a test, make sure this EventHandler is initialized + if (rs == null) + fail ("Event handler not initialized!"); + + switch (reference) + { + // good object, bad property + case "$a1.foobar": + assertEquals(Integer.valueOf(5), object); + assertEquals("foobar", property); + throw new RuntimeException("expected exception"); + + // bad object, bad property + case "$a2": + assertNull(object); + assertNull(property); + throw new RuntimeException("expected exception"); + + + // bad object, no property + case "$a3": + assertNull(object); + assertNull(property); + throw new RuntimeException("expected exception"); + + + // good object, bad property; change the value + case "$a4.foobar": + assertEquals(Integer.valueOf(5), object); + assertEquals("foobar", property); + return "zzz"; + + + // bad object, bad method -- fail on the object + case "$zz": + assertNull(object); + assertNull(property); + throw new RuntimeException("expected exception"); + + + // pass q1 through + case "$q1": + + break; + case "$tree.x": + assertEquals("x", property); + break; + case "$tree.field.x": + assertEquals("x", property); + break; + case "$tree.child.y": + assertEquals("y", property); + break; + case "$tree.child.Field.y": + assertEquals("y", property); + break; + default: + fail("invalidGetMethod: unexpected reference: " + reference); + break; + } + return null; + } + + @Override + public Object invalidMethod(Context context, String reference, Object object, String method, Info info) + { + // as a test, make sure this EventHandler is initialized + if (rs == null) + fail ("Event handler not initialized!"); + + // good reference, bad method + if (object.getClass().equals(Integer.class)) + { + assertEquals("$a1.afternoon()",reference); + assertEquals("afternoon",method); + throw new RuntimeException("expected exception"); + } + + else if (object.getClass().equals(String.class) && "baby".equals(method)) + { + return "www"; + } + + else + { + fail("Unexpected invalid method. " + method); + } + + return null; + } + + + @Override + public boolean invalidSetMethod(Context context, String leftreference, String rightreference, Info info) + { + + // as a test, make sure this EventHandler is initialized + if (rs == null) + fail ("Event handler not initialized!"); + + // good object, bad method + if (leftreference.equals("xx")) + { + assertEquals("q1.afternoon()",rightreference); + throw new RuntimeException("expected exception"); + } + if (leftreference.equals("yy")) + { + assertEquals("$q1",rightreference); + throw new RuntimeException("expected exception"); + } + else + { + fail("Unexpected left hand side. " + leftreference); + } + + return false; + } + + } + + public static class Tree + { + String field; + Tree child; + + public Tree() + { + + } + + public String getField() + { + return field; + } + + public void setField(String field) + { + this.field = field; + } + + public Tree getChild() + { + return child; + } + + public void setChild(Tree child) + { + this.child = child; + } + + public String testMethod() + { + return "123"; + } + } + +} |