1   package org.apache.velocity.test;
2   
3   import org.apache.velocity.app.VelocityEngine;
4   import org.apache.velocity.app.Velocity;
5   import org.apache.velocity.test.misc.TestLogChute;
6   import org.apache.velocity.runtime.RuntimeConstants;
7   import org.apache.velocity.VelocityContext;
8   import org.apache.velocity.Template;
9   import junit.framework.TestSuite;
10  
11  import java.io.*;
12  
13  /*
14   * Licensed to the Apache Software Foundation (ASF) under one
15   * or more contributor license agreements.  See the NOTICE file
16   * distributed with this work for additional information
17   * regarding copyright ownership.  The ASF licenses this file
18   * to you under the Apache License, Version 2.0 (the
19   * "License"); you may not use this file except in compliance
20   * with the License.  You may obtain a copy of the License at
21   *
22   *   http://www.apache.org/licenses/LICENSE-2.0
23   *
24   * Unless required by applicable law or agreed to in writing,
25   * software distributed under the License is distributed on an
26   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
27   * KIND, either express or implied.  See the License for the
28   * specific language governing permissions and limitations
29   * under the License.
30   */
31  
32  /**
33   * Test case for including macro libraries via the #parse method.
34   */
35  public class ParseWithMacroLibsTestCase extends BaseTestCase
36  {
37      private static final String RESULT_DIR = TEST_RESULT_DIR + "/parsemacros";
38  
39      private static final String COMPARE_DIR = TEST_COMPARE_DIR + "/parsemacros/compare";
40  
41      public ParseWithMacroLibsTestCase(String name)
42      {
43          super(name);
44      }
45  
46      public void setUp()
47              throws Exception
48      {
49          super.setUp();
50      }
51  
52      /**
53       * Test suite
54       * @return test suite
55       */
56      public static junit.framework.Test suite()
57      {
58          return new TestSuite(ParseWithMacroLibsTestCase.class);
59      }
60      
61      public void testParseMacroLocalCacheOn()
62      throws Exception
63      {
64          /*
65           *  local scope, cache on
66           */
67          VelocityEngine ve = createEngine(true, true);
68  
69          // render twice to make sure there is no difference with cached templates
70          testParseMacro(ve, "vm_library1.vm", "parseMacro1_1", false);
71          testParseMacro(ve, "vm_library1.vm", "parseMacro1_1", false);
72          
73          // run again with different macro library
74          testParseMacro(ve, "vm_library2.vm", "parseMacro1_1b", false);
75          testParseMacro(ve, "vm_library2.vm", "parseMacro1_1b", false);
76      }
77  
78      /**
79       * Runs the tests with global namespace.
80       */
81      public void testParseMacroLocalCacheOff()
82      throws Exception
83      {
84          /*
85           *  local scope, cache off
86           */
87          VelocityEngine ve = createEngine(false, true);
88  
89          testParseMacro(ve, "vm_library1.vm", "parseMacro1_2", true);
90  
91          // run again with different macro library
92          testParseMacro(ve, "vm_library2.vm", "parseMacro1_2b", true);
93      }
94  
95      public void testParseMacroGlobalCacheOn()
96      throws Exception
97      {
98          /*
99           *  global scope, cache on
100          */
101         VelocityEngine ve = createEngine(true, false);
102 
103         // render twice to make sure there is no difference with cached templates
104         testParseMacro(ve, "vm_library1.vm", "parseMacro1_3", false);
105         testParseMacro(ve, "vm_library1.vm", "parseMacro1_3", false);
106 
107         // run again with different macro library
108         testParseMacro(ve, "vm_library2.vm", "parseMacro1_3b", false);
109         testParseMacro(ve, "vm_library2.vm", "parseMacro1_3b", false);
110     }
111     
112     public void testParseMacroGlobalCacheOff()
113     throws Exception
114     {
115         /*
116          *  global scope, cache off
117          */
118         VelocityEngine ve = createEngine(false, false);
119 
120         testParseMacro(ve, "vm_library1.vm", "parseMacro1_4", true);
121         
122         // run again with different macro library
123         testParseMacro(ve, "vm_library2.vm", "parseMacro1_4b", true);
124 
125     }
126     
127     /**
128      * Test #parse with macros.  Can be used to test different engine configurations
129      * @param ve
130      * @param outputBaseFileName
131      * @param testCachingOff
132      * @throws Exception
133      */
134     private void testParseMacro(VelocityEngine ve, String includeFile, String outputBaseFileName, boolean testCachingOff)
135             throws Exception
136     {
137         assureResultsDirectoryExists(RESULT_DIR);
138 
139         FileOutputStream fos = new FileOutputStream (getFileName(
140                 RESULT_DIR, outputBaseFileName, RESULT_FILE_EXT));
141 
142         VelocityContext context = new VelocityContext();
143         context.put("includefile", includeFile);
144 
145         Writer writer = new BufferedWriter(new OutputStreamWriter(fos));
146 
147         Template template = ve.getTemplate("parseMacro1.vm");
148         template.merge(context, writer);
149 
150         /**
151          * Write to the file
152          */
153         writer.flush();
154         writer.close();
155 
156         if (!isMatch(RESULT_DIR, COMPARE_DIR, outputBaseFileName,
157                 RESULT_FILE_EXT,CMP_FILE_EXT))
158         {
159             String result = getFileContents(RESULT_DIR, outputBaseFileName, RESULT_FILE_EXT);
160             String compare = getFileContents(COMPARE_DIR, outputBaseFileName, CMP_FILE_EXT);
161 
162             String msg = "Processed template did not match expected output\n"+
163                 "-----Result-----\n"+ result +
164                 "----Expected----\n"+ compare +
165                 "----------------";
166             
167             fail(msg);
168         }
169 
170         /*
171          * Show that caching is turned off
172          */
173         if (testCachingOff)
174         {
175             Template t1 = ve.getTemplate("parseMacro1.vm");
176             Template t2 = ve.getTemplate("parseMacro1.vm");
177 
178             assertNotSame("Different objects", t1, t2);
179         }
180     }
181 
182     /**
183      * Return and initialize engine
184      * @return
185      */
186     private VelocityEngine createEngine(boolean cache, boolean local)
187     throws Exception
188     {
189         VelocityEngine ve = new VelocityEngine();
190         ve.setProperty( Velocity.VM_PERM_INLINE_LOCAL, Boolean.TRUE);
191         ve.setProperty("velocimacro.permissions.allow.inline.to.replace.global",
192                 new Boolean(local));
193         ve.setProperty("file.resource.loader.cache", new Boolean(cache));
194         ve.setProperty(
195                 Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, TestLogChute.class.getName());
196         ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
197         ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
198                 TEST_COMPARE_DIR + "/parsemacros");
199         ve.init();
200         
201         return ve;
202     }
203     
204     
205     /**
206      * Test whether the literal text is given if a definition cannot be
207      * found for a macro.
208      *
209      * @throws Exception
210      */
211     public void testParseMacrosWithNoDefinition()
212             throws Exception
213     {
214         /*
215          *  ve1: local scope, cache on
216          */
217         VelocityEngine ve1 = new VelocityEngine();
218         
219         ve1.setProperty( Velocity.VM_PERM_INLINE_LOCAL, Boolean.TRUE);
220         ve1.setProperty("velocimacro.permissions.allow.inline.to.replace.global",
221                 Boolean.FALSE);
222         ve1.setProperty("file.resource.loader.cache", Boolean.TRUE);
223         ve1.setProperty(
224                 Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, TestLogChute.class.getName());
225         ve1.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
226         ve1.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
227                 TEST_COMPARE_DIR + "/parsemacros");
228         ve1.init();
229         
230         assureResultsDirectoryExists(RESULT_DIR);
231 
232         FileOutputStream fos = new FileOutputStream (getFileName(
233                 RESULT_DIR, "parseMacro2", RESULT_FILE_EXT));
234 
235         VelocityContext context = new VelocityContext();
236 
237         Writer writer = new BufferedWriter(new OutputStreamWriter(fos));
238 
239         Template template = ve1.getTemplate("parseMacro2.vm");
240         template.merge(context, writer);
241 
242         /**
243          * Write to the file
244          */
245         writer.flush();
246         writer.close();
247 
248         if (!isMatch(RESULT_DIR, COMPARE_DIR, "parseMacro2",
249                 RESULT_FILE_EXT,CMP_FILE_EXT))
250         {
251             fail("Processed template did not match expected output");
252         }
253     }
254 
255 
256     /**
257      * Test that if a macro is duplicated, the second one takes precendence
258      *
259      * @throws Exception
260      */
261     public void testDuplicateDefinitions()
262             throws Exception
263     {
264         /*
265          *  ve1: local scope, cache on
266          */
267         VelocityEngine ve1 = new VelocityEngine();
268         
269         ve1.setProperty( Velocity.VM_PERM_INLINE_LOCAL, Boolean.TRUE);
270         ve1.setProperty("velocimacro.permissions.allow.inline.to.replace.global",
271                 Boolean.FALSE);
272         ve1.setProperty("file.resource.loader.cache", Boolean.TRUE);
273         ve1.setProperty(
274                 Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, TestLogChute.class.getName());
275         ve1.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
276         ve1.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
277                 TEST_COMPARE_DIR + "/parsemacros");
278         ve1.init();
279         
280         assureResultsDirectoryExists(RESULT_DIR);
281 
282         FileOutputStream fos = new FileOutputStream (getFileName(
283                 RESULT_DIR, "parseMacro3", RESULT_FILE_EXT));
284 
285         VelocityContext context = new VelocityContext();
286 
287         Writer writer = new BufferedWriter(new OutputStreamWriter(fos));
288 
289         Template template = ve1.getTemplate("parseMacro3.vm");
290         template.merge(context, writer);
291 
292         /**
293          * Write to the file
294          */
295         writer.flush();
296         writer.close();
297 
298         if (!isMatch(RESULT_DIR, COMPARE_DIR, "parseMacro3",
299                 RESULT_FILE_EXT,CMP_FILE_EXT))
300         {
301             fail("Processed template did not match expected output");
302         }
303     }
304 
305 }