1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.velocity.internal

File DefaultVelocityEngineTest.java

 

Code metrics

0
73
14
1
265
173
14
0.19
5.21
14
1

Classes

Class Line # Actions
DefaultVelocityEngineTest 51 73 0% 14 0
1.0100%
 

Contributing tests

This file is covered by 10 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.velocity.internal;
21   
22    import static org.mockito.Mockito.verify;
23    import static org.mockito.Mockito.when;
24   
25    import java.io.StringReader;
26    import java.io.StringWriter;
27    import java.util.ArrayList;
28    import java.util.List;
29    import java.util.Properties;
30    import java.util.concurrent.Callable;
31    import java.util.concurrent.ExecutionException;
32    import java.util.concurrent.ExecutorService;
33    import java.util.concurrent.Executors;
34    import java.util.concurrent.Future;
35   
36    import org.apache.velocity.context.Context;
37    import org.junit.Assert;
38    import org.junit.Before;
39    import org.junit.Rule;
40    import org.junit.Test;
41    import org.xwiki.test.mockito.MockitoComponentMockingRule;
42    import org.xwiki.velocity.VelocityConfiguration;
43    import org.xwiki.velocity.XWikiVelocityException;
44    import org.xwiki.velocity.introspection.ChainingUberspector;
45    import org.xwiki.velocity.introspection.DeprecatedCheckUberspector;
46    import org.xwiki.velocity.introspection.SecureUberspector;
47   
48    /**
49    * Unit tests for {@link DefaultVelocityEngine}.
50    */
 
51    public class DefaultVelocityEngineTest
52    {
53    @Rule
54    public MockitoComponentMockingRule<DefaultVelocityEngine> mocker =
55    new MockitoComponentMockingRule<DefaultVelocityEngine>(DefaultVelocityEngine.class);
56   
57    private DefaultVelocityEngine engine;
58   
 
59  10 toggle @Before
60    public void setUp() throws Exception
61    {
62  10 Properties properties = new Properties();
63  10 properties.put("runtime.introspector.uberspect", ChainingUberspector.class.getName());
64  10 properties.put("runtime.introspector.uberspect.chainClasses", SecureUberspector.class.getName() + ","
65    + DeprecatedCheckUberspector.class.getName());
66  10 properties.put("directive.set.null.allowed", Boolean.TRUE.toString());
67  10 properties.put("velocimacro.permissions.allow.inline.local.scope", Boolean.TRUE.toString());
68   
69  10 VelocityConfiguration configuration = this.mocker.getInstance(VelocityConfiguration.class);
70  10 when(configuration.getProperties()).thenReturn(properties);
71   
72  10 this.engine = this.mocker.getComponentUnderTest();
73    }
74   
 
75  11 toggle private void assertEvaluate(String expected, String content, String template) throws XWikiVelocityException
76    {
77  11 assertEvaluate(expected, content, template, new org.apache.velocity.VelocityContext());
78    }
79   
 
80  12 toggle private void assertEvaluate(String expected, String content, String template, Context context)
81    throws XWikiVelocityException
82    {
83  12 StringWriter writer = new StringWriter();
84  12 this.engine.evaluate(context, writer, template, content);
85  12 Assert.assertEquals(expected, writer.toString());
86    }
87   
 
88  1 toggle @Test
89    public void testEvaluateReader() throws Exception
90    {
91  1 this.engine.initialize(new Properties());
92  1 StringWriter writer = new StringWriter();
93  1 this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", new StringReader(
94    "#set($foo='hello')$foo World"));
95  1 Assert.assertEquals("hello World", writer.toString());
96    }
97   
 
98  1 toggle @Test
99    public void testEvaluateString() throws Exception
100    {
101  1 this.engine.initialize(new Properties());
102   
103  1 assertEvaluate("hello World", "#set($foo='hello')$foo World", "mytemplate");
104    }
105   
106    /**
107    * Verify that the default configuration doesn't allow calling Class.forName.
108    */
 
109  1 toggle @Test
110    public void testSecureUberspectorActiveByDefault() throws Exception
111    {
112  1 this.engine.initialize(new Properties());
113   
114  1 String content =
115    "#set($foo = 'test')#set($object = $foo.class.forName('java.util.ArrayList')"
116    + ".newInstance())$object.size()";
117  1 assertEvaluate("$object.size()", content, "mytemplate");
118   
119    // Verify that we log a warning and verify the message.
120  1 verify(this.mocker.getMockedLogger()).warn(
121    "Cannot retrieve method forName from object of class " + "java.lang.Class due to security restrictions.");
122    }
123   
124    /**
125    * Verify that the default configuration allows #setting existing variables to null.
126    */
 
127  1 toggle @Test
128    public void testSettingNullAllowedByDefault() throws Exception
129    {
130  1 this.engine.initialize(new Properties());
131  1 StringWriter writer = new StringWriter();
132  1 Context context = new org.apache.velocity.VelocityContext();
133  1 context.put("null", null);
134  1 List<String> list = new ArrayList<String>();
135  1 list.add("1");
136  1 list.add(null);
137  1 list.add("3");
138  1 context.put("list", list);
139  1 this.engine.evaluate(context, writer, "mytemplate", "#set($foo = true)${foo}#set($foo = $null)${foo}\n"
140    + "#foreach($i in $list)${velocityCount}=$!{i} #end");
141  1 Assert.assertEquals("true${foo}\n1=1 2= 3=3 ", writer.toString());
142   
143  1 String content =
144    "#set($foo = true)${foo}#set($foo = $null)${foo}\n" + "#foreach($i in $list)${velocityCount}=$!{i} #end";
145   
146  1 assertEvaluate("true${foo}\n1=1 2= 3=3 ", content, "mytemplate", context);
147    }
148   
 
149  1 toggle @Test
150    public void testOverrideConfiguration() throws Exception
151    {
152    // For example try setting a non secure Uberspector.
153  1 Properties properties = new Properties();
154  1 properties
155    .setProperty("runtime.introspector.uberspect", "org.apache.velocity.util.introspection.UberspectImpl");
156  1 this.engine.initialize(properties);
157  1 StringWriter writer = new StringWriter();
158  1 this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate",
159    "#set($foo = 'test')#set($object = $foo.class.forName('java.util.ArrayList')"
160    + ".newInstance())$object.size()");
161  1 Assert.assertEquals("0", writer.toString());
162    }
163   
 
164  1 toggle @Test
165    public void testMacroIsolation() throws Exception
166    {
167  1 this.engine.initialize(new Properties());
168  1 Context context = new org.apache.velocity.VelocityContext();
169  1 this.engine.evaluate(context, new StringWriter(), "template1", "#macro(mymacro)test#end");
170  1 assertEvaluate("#mymacro", "#mymacro", "template2");
171    }
172   
 
173  1 toggle @Test
174    public void testConfigureMacrosToBeGlobal() throws Exception
175    {
176  1 Properties properties = new Properties();
177    // Force macros to be global
178  1 properties.put("velocimacro.permissions.allow.inline.local.scope", "false");
179  1 this.engine.initialize(properties);
180  1 Context context = new org.apache.velocity.VelocityContext();
181  1 this.engine.evaluate(context, new StringWriter(), "template1", "#macro(mymacro)test#end");
182  1 assertEvaluate("test", "#mymacro", "template2");
183    }
184   
185    /**
186    * Verify namespace is properly cleared when not needed anymore.
187    */
 
188  1 toggle @Test
189    public void testMacroNamespaceCleanup() throws Exception
190    {
191  1 this.engine.initialize(new Properties());
192   
193    // Unprotected namespace
194   
195  1 assertEvaluate("#mymacro", "#mymacro", "namespace");
196   
197  1 this.engine.evaluate(new org.apache.velocity.VelocityContext(), new StringWriter(), "namespace",
198    "#macro(mymacro)test#end");
199   
200  1 assertEvaluate("#mymacro", "#mymacro", "namespace");
201   
202    // Protected namespace
203   
204    // Start using namespace "namespace"
205  1 this.engine.startedUsingMacroNamespace("namespace");
206   
207    // Register macro
208  1 this.engine.evaluate(new org.apache.velocity.VelocityContext(), new StringWriter(), "namespace",
209    "#macro(mymacro)test#end");
210   
211  1 assertEvaluate("test", "#mymacro", "namespace");
212   
213    // Mark namespace "namespace" as not used anymore
214  1 this.engine.stoppedUsingMacroNamespace("namespace");
215   
216  1 assertEvaluate("#mymacro", "#mymacro", "namespace");
217    }
218   
219    /**
220    * Make sure several thread that supposedly use the same namespace string don't collide.
221    *
222    * @throws XWikiVelocityException
223    * @throws InterruptedException
224    * @throws ExecutionException
225    */
 
226  1 toggle @Test
227    public void testThreadsafeNamespaces() throws XWikiVelocityException, InterruptedException, ExecutionException
228    {
229  1 this.engine.initialize(new Properties());
230   
231    // Start using namespace "namespace"
232  1 this.engine.startedUsingMacroNamespace("namespace");
233   
234    // Register macro
235  1 Context context = new org.apache.velocity.VelocityContext();
236  1 this.engine.evaluate(context, new StringWriter(), "namespace", "#macro(mymacro)test#end");
237   
238  1 assertEvaluate("test", "#mymacro", "namespace");
239   
240  1 ExecutorService pool = Executors.newSingleThreadExecutor();
241  1 Future<Void> future = pool.submit(new Callable<Void>()
242    {
 
243  1 toggle @Override
244    public Void call() throws Exception
245    {
246    // the macro should not be available in a different thread than the one which registered it
247  1 assertEvaluate("#mymacro", "#mymacro", "namespace");
248   
249  1 return null;
250    }
251    });
252  1 future.get();
253   
254    // Mark namespace "namespace" as not used anymore
255  1 this.engine.stoppedUsingMacroNamespace("namespace");
256    }
257   
 
258  1 toggle @Test
259    public void testEvaluateWithStopCommand() throws Exception
260    {
261  1 this.engine.initialize(new Properties());
262   
263  1 assertEvaluate("hello world", "hello world#stop", "mytemplate");
264    }
265    }