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 org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; import java.util.HashMap; /** * This class tests the directive scope controls */ public class ScopeTestCase extends BaseTestCase { public ScopeTestCase(String name) { super(name); } @Override protected void setUpEngine(VelocityEngine engine) { engine.setProperty("a.provide.scope.control", "true"); engine.setProperty("define.provide.scope.control", "true"); engine.setProperty("evaluate.provide.scope.control", "true"); engine.setProperty("foo.provide.scope.control", "true"); engine.setProperty("macro.provide.scope.control", "true"); engine.setProperty("template.provide.scope.control", "true"); engine.setProperty("vm.provide.scope.control", "true"); engine.setProperty("space.gobbling", "bc"); } public void testScopeGetLeakIntoInner() { addTemplate("foo", "#foreach($i in [1..1])#set($foreach.a=$i)"+ "#foreach($j in [2..2])$foreach.a#set($foreach.a=$j)"+ "#foreach($k in [3..3])$foreach.a#end#end$foreach.a#end"); assertTmplEquals("121", "foo"); } public void testScopeGetLeakDoesntHideNullset() { addTemplate("a", "#macro(a)#set($macro.a='a')#b()$macro.a#end"+ "#macro(b)$macro.a#set($macro.a=$null)$!macro.a#end"+ "#a()"); assertTmplEquals("aa", "a"); } public void testRootTemplateMergeScope() { addTemplate("foo", "foo#break($template)bar"); assertTmplEquals("foo", "foo"); assertNull(context.get("template")); } public void testParseScope() { addTemplate("test", "$template.info.depth"+ "$!parse.parent.info.depth"+ "#set( $template.foo = 'bar' )"+ "$template.foo"+ "#break($template)"+ "woogie"); assertEvalEquals("1bar", "#parse( 'test' )"); assertNull(context.get("template")); } public void testNestedParseScope() { HashMap grab = new HashMap(); context.put("grab", grab); addTemplate("inner", "Inner depth: $template.info.depth"+ "#set( $template.foo = '?' )"+ "$!grab.put('inner',$template)"+ "#break($template)$template.foo"); addTemplate("outer", "#set( $template.foo = '!' )"+ "Outer depth: $template.info.depth "+ "#parse('inner')"+ "$!grab.put('outer', $template)"+ "$template.foo"); assertEvalEquals("Outer depth: 1 Inner depth: 2!", "#parse('outer')"); // make extra sure that the outer control was restored after the stop assertFalse(grab.get("inner") == grab.get("outer")); // make sure the outer control was cleaned up assertNull(context.get("template")); addTemplate("3", "$template.topmost.foo#set( $template.topmost.foo = 'bar' )"); addTemplate("2", "#parse( '3' )$!parse.foo"); addTemplate("1", "#set( $template.foo = 'foo' )#parse('2')$template.foo"); assertEvalEquals("foobar", "#parse('1')$!parse"); // make sure the top control was cleaned up assertNull(context.get("template")); } public void testForeachScope() { String template = "#foreach( $i in [0..2] )"+ "#if( $i > 1 )#break($foreach)#end"+ "$foreach.index:$foreach.count:$foreach.hasNext,"+ "#end"; assertEvalEquals("0:1:true,1:2:true,", template); assertNull(context.get("foreach")); } public void testNestedForeachScope() { String template = "#foreach( $i in [1..5] )"+ "#foreach( $j in [1..2] )"+ "#if ( $i > $foreach.count + $foreach.index + $foreach.info.depth )#break($foreach.topmost)#end"+ "#end"+ "$i"+ "#end"; assertEvalEquals("123", template); assertNull(context.get("foreach")); } public void testMacroScope() { String template = "#macro( foo $i )"+ "#if($i > 2 )#break($macro)#end"+ "$i#end"+ "#foo( 0 )#foo( 1 )#foo( 2 )"; assertEvalEquals("012", template); assertNull(context.get("macro")); } public void testRecursiveMacroScope() { String template = "#macro( foo )$macro.info.depth"+ "#if($macro.info.depth > 2 )#break($macro.topmost)#end"+ "#foo()#end#foo()"; assertEvalEquals("123", template); assertNull(context.get("macro")); } public void testNestedMacroScope() { String template = "#macro( a )$macro.info.depth#set($macro.c = 'a')$macro.c#end"+ "#macro( b )#set($macro.c = 'b' )#a()$macro.c#end"+ "#b()"; assertEvalEquals("2ab", template); assertNull(context.get("macro")); } public void testBodyMacroScope() { String template = "#macro( foo $bar )$bodyContent$macro.bar#end"+ "#@foo( 'bar' )#set( $macro.bar = 'foo'+$bar )"+ "#set( $foo.d = $foo.info.depth )$foo.d #end"; assertEvalEquals("1 foobar", template); assertNull(context.get("foo")); assertNull(context.get("macro")); } public void testRecursiveBodyMacroScope() { engine.setProperty(RuntimeConstants.VM_MAX_DEPTH, "5"); String template = "#macro( foo )$bodyContent$macro.i#end"+ "#@foo()#set( $macro.i = \"$!macro.i$foo.info.depth,\" )"+ "$!bodyContent#end"; assertEvalEquals("1,2,3,4,5,", template); assertNull(context.get("foo")); assertNull(context.get("macro")); } public void testDefineScope() { String template = "#define( $foo )#set( $define.bar = 'bar'+$define.info.depth )$define.bar#end$foo"; assertEvalEquals("bar1", template); assertNull(context.get("define")); } public void testNestedDefineScope() { String template = "#define($a)$b c#end"+ "#define($b)$define.info.depth#break($define.topmost)#end"+ "$a"; assertEvalEquals("2", template); assertNull(context.get("define")); } public void testRecursiveDefineScope() { engine.setProperty(RuntimeConstants.DEFINE_DIRECTIVE_MAXDEPTH, "10"); String template = "#define($a)$define.info.depth"+ "#if($define.info.depth == 5)#break($define)#end,$a#end$a"; assertEvalEquals("1,2,3,4,5", template); assertNull(context.get("define")); } public void testRootEvaluateScope() { assertEvalEquals("1", "$evaluate.info.depth"); assertEvalEquals("foo", "foo#break($evaluate)bar"); assertNull(context.get("evaluate")); } public void testEvaluateScope() { context.put("h", "#"); context.put("d", "$"); String template = "${h}set( ${d}evaluate.foo = 'bar' )"+ "${d}evaluate.foo ${d}evaluate.info.depth"; addTemplate("eval", "#evaluate(\""+template+"\")"); assertTmplEquals("bar 1", "eval"); assertNull(context.get("evaluate")); assertNull(context.get("template")); } public void testNestedEvaluateScope() { context.put("h", "#"); context.put("d", "$"); addTemplate("e", "#evaluate(\"${h}evaluate( '${d}evaluate.info.depth${h}stop(${d}evaluate) blah' )\")"); assertTmplEquals("2", "e"); assertNull(context.get("evaluate")); assertNull(context.get("template")); } public void testTurningOffTemplateScope() { engine.setProperty("template."+RuntimeConstants.PROVIDE_SCOPE_CONTROL, "false"); // root addTemplate("test", "$template.info.depth"); assertTmplEquals("$template.info.depth", "test"); // #parse assertEvalEquals("$template.info.depth", "#parse('test')"); } public void testTurningOffEvaluateScope() { engine.setProperty("evaluate."+RuntimeConstants.PROVIDE_SCOPE_CONTROL, "false"); // root assertSchmoo("$evaluate.info.depth"); // #evaluate assertEvalEquals("$evaluate.info.depth", "#evaluate( '$evaluate.info.depth' )"); } public void testTurningOffMacroScope() { engine.setProperty("macro."+RuntimeConstants.PROVIDE_SCOPE_CONTROL, "false"); engine.setProperty("foo."+RuntimeConstants.PROVIDE_SCOPE_CONTROL, "false"); // macro definition assertEvalEquals("$macro", "#macro(a)$macro#end#a()"); // macro body assertEvalEquals("$macro $foo", "#macro(foo)$bodyContent#end#@foo()$macro $foo#end"); } public void testTurningOffDefineScope() { engine.setProperty("define."+RuntimeConstants.PROVIDE_SCOPE_CONTROL, "false"); assertEvalEquals("$define", "#define($a)$define#end$a"); } public void testTurningOffForeachScope() { engine.setProperty("foreach."+RuntimeConstants.PROVIDE_SCOPE_CONTROL, "false"); assertEvalEquals("$foreach$foreach", "#foreach($i in [0..1])$foreach#end"); } public void testTemplateReplaced() { context.put("template", "foo"); addTemplate("test", "$template.replaced"); assertTmplEquals("foo", "test"); assertEvalEquals("foo", "#parse('test')"); assertContextValue("template", "foo"); } public void testEvaluateReplaced() { context.put("evaluate","foo"); assertEvalEquals("foo", "$evaluate.replaced"); assertEvalEquals("foo", "#evaluate('$evaluate.replaced')"); assertContextValue("evaluate", "foo"); } public void testMacroReplaced() { context.put("macro", "foo"); assertEvalEquals("foo foo foo", "$macro #macro(a)$macro.replaced#end#a() $macro"); assertContextValue("macro", "foo"); } public void testForeachReplaced() { context.put("foreach", "foo"); assertEvalEquals("foofoofoo", "$foreach#foreach($i in [1..1])$foreach.replaced#end$foreach"); assertEquals("foo", context.get("foreach")); context.put("foreach", "a"); assertEvalEquals("a", "#foreach($i in [1..1])#foreach($j in [1..1])$foreach.replaced#end#end"); assertContextValue("foreach", "a"); } public void testDefineReplaced() { context.put("define", "a"); assertEvalEquals("a", "#define($a)$define.replaced#end$a"); assertContextValue("define", "a"); } public void testBodyContentReplaced() { context.put("vm", "a"); assertEvalEquals("a", "#macro(vm)$bodyContent#end#@vm()$vm.replaced#end"); assertContextValue("vm", "a"); } public void testInfoDepth() { String template = "#foreach($i in [1..1])"+ "#foreach($j in [0..0])"+ "$foreach.info.depth"+ "#end"+ "#end"; assertEvalEquals("2", template); } public void testInfoName() { String template = "#foreach($i in [1..1])"+ "$foreach.info.name #evaluate('$evaluate.info.name')"+ "#end"; assertEvalEquals("foreach evaluate", template); } public void testInfoType() { addTemplate("info", "#foreach($i in [1..1])"+ "$foreach.info.type"+ "#end "+ "#evaluate('$evaluate.info.type') "+ "$template.info.type"); assertTmplEquals("block line utf-8", "info"); } public void testInfoLineAndColumn() { String template = " #evaluate('$evaluate.info.line, $evaluate.info.column')"; assertEvalEquals(" 1, 2", template); assertEvalEquals("\n\n 3, 4", "\n\n "+template); } public void testInfoTemplate() { addTemplate("test", "#evaluate('$evaluate.info.template')"); assertTmplEquals("test", "test"); assertEvalEquals("test", "#parse('test')"); } }