1   package org.apache.velocity.test;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.io.BufferedWriter;
23  import java.io.FileOutputStream;
24  import java.io.OutputStreamWriter;
25  import java.io.StringWriter;
26  import java.io.Writer;
27  
28  import junit.framework.Test;
29  import junit.framework.TestSuite;
30  
31  import org.apache.velocity.Template;
32  import org.apache.velocity.VelocityContext;
33  import org.apache.velocity.app.VelocityEngine;
34  import org.apache.velocity.app.event.implement.EscapeHtmlReference;
35  import org.apache.velocity.context.Context;
36  import org.apache.velocity.exception.ParseErrorException;
37  import org.apache.velocity.runtime.RuntimeConstants;
38  
39  /**
40   * Test #evaluate directive.
41   * 
42   * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
43   * @version $Id: EvaluateTestCase.java 522413 2007-03-26 04:34:15Z wglass $
44   */
45  public class EvaluateTestCase extends BaseTestCase
46  {
47      
48      /**
49      * VTL file extension.
50      */
51     private static final String TMPL_FILE_EXT = "vm";
52  
53     /**
54      * Comparison file extension.
55      */
56     private static final String CMP_FILE_EXT = "cmp";
57  
58     /**
59      * Comparison file extension.
60      */
61     private static final String RESULT_FILE_EXT = "res";
62  
63     /**
64      * Path for templates. This property will override the
65      * value in the default velocity properties file.
66      */
67     private final static String FILE_RESOURCE_LOADER_PATH = TEST_COMPARE_DIR + "/evaluate";
68  
69     /**
70      * Results relative to the build directory.
71      */
72     private static final String RESULTS_DIR = TEST_RESULT_DIR + "/evaluate";
73  
74     /**
75      * Results relative to the build directory.
76      */
77     private static final String COMPARE_DIR = TEST_COMPARE_DIR + "/evaluate/compare";
78  
79      /**
80       * Default constructor.
81       * @param name
82       */
83      public EvaluateTestCase(String name)
84      {
85          super(name);
86      }
87  
88      public void setUp()
89      {
90          assureResultsDirectoryExists(RESULTS_DIR);
91      }
92  
93      public static Test suite()
94      {
95         return new TestSuite(EvaluateTestCase.class);
96      }
97  
98      /**
99       * Test basic functionality.
100      * @throws Exception
101      */
102     public void testEvaluate()
103     throws Exception
104     {
105         testFile("eval1");
106     }
107 
108     /**
109      * Test #stop (since it is attached to context).
110      * @throws Exception
111      */
112     public void testStop()
113     throws Exception
114     {
115         VelocityEngine ve = new VelocityEngine();
116         ve.init();
117         
118         Context context = new VelocityContext();        
119         StringWriter writer = new StringWriter();
120         ve.evaluate(context, writer, "test","test #stop test2 #evaluate('test3')");
121         assertEquals("test ", writer.toString());
122         
123         context = new VelocityContext();        
124         writer = new StringWriter();
125         ve.evaluate(context, writer, "test","test test2 #evaluate('test3 #stop test4') test5");
126         assertEquals("test test2 test3  test5", writer.toString());
127         
128     }
129 
130     /**
131      * Test that the event handlers work in #evaluate (since they are
132      * attached to the context).  Only need to check one - they all 
133      * work the same.
134      * @throws Exception
135      */
136     public void testEventHandler()
137     throws Exception
138     {
139         VelocityEngine ve = new VelocityEngine();
140         ve.setProperty(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION, EscapeHtmlReference.class.getName());
141         ve.init();
142         
143         Context context = new VelocityContext();
144         context.put("lt","<");
145         context.put("gt",">");
146         StringWriter writer = new StringWriter();
147         ve.evaluate(context, writer, "test","${lt}test${gt} #evaluate('${lt}test2${gt}')");
148         assertEquals("&lt;test&gt; &lt;test2&gt;", writer.toString());
149         
150     }
151     
152     
153     /**
154      * Test errors are thrown
155      * @throws Exception
156      */
157     public void testErrors()
158     throws Exception
159     {
160         VelocityEngine ve = new VelocityEngine();
161         ve.init();
162         
163         Context context = new VelocityContext();
164         
165         // no arguments
166         StringWriter writer = new StringWriter();
167         try 
168         {
169             ve.evaluate(context, writer, "test",
170                               "#evaluate()");
171             fail("Expected exception");
172         }
173         catch (ParseErrorException e)
174         {
175             assertEquals("test",e.getTemplateName());
176             assertEquals(1,e.getLineNumber());
177             assertEquals(1,e.getColumnNumber());
178         }
179         
180         // too many arguments
181         writer = new StringWriter();
182         try 
183         {
184             ve.evaluate(context, writer, "test",
185                               "#evaluate('aaa' 'bbb')");
186             fail("Expected exception");
187         }
188         catch (ParseErrorException e)
189         {
190             assertEquals("test",e.getTemplateName());
191             assertEquals(1,e.getLineNumber());
192             assertEquals(17,e.getColumnNumber());
193         }
194         
195         // argument not a string or reference
196         writer = new StringWriter();
197         try 
198         {
199             ve.evaluate(context, writer, "test",
200                               "#evaluate(10)");
201             fail("Expected exception");
202         }
203         catch (ParseErrorException e)
204         {
205             assertEquals("test",e.getTemplateName());
206             assertEquals(1,e.getLineNumber());
207             assertEquals(11,e.getColumnNumber());
208         }
209         
210         // checking line/col for parse error
211         writer = new StringWriter();
212         try 
213         {
214             String eval = "this is a multiline\n\n\n\n\n test #foreach() with an error";
215             context.put("eval",eval);
216             ve.evaluate(context, writer, "test",
217                               "first line\n second line: #evaluate($eval)");
218             fail("Expected exception");
219         }
220         catch (ParseErrorException e)
221         {
222             // should be start of #evaluate
223             assertEquals("test",e.getTemplateName());
224             assertEquals(2,e.getLineNumber());
225             assertEquals(15,e.getColumnNumber());
226         }        
227     }
228     
229     /**
230      * Test a file parses with no errors and compare to existing file.
231      * @param basefilename
232      * @throws Exception
233      */
234     private void testFile(String basefilename)
235     throws Exception
236     {
237         VelocityEngine ve = new VelocityEngine();
238         ve.addProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, FILE_RESOURCE_LOADER_PATH);
239         ve.init();
240         
241         Template template;
242         FileOutputStream fos;
243         Writer fwriter;
244         Context context;
245         
246         template = ve.getTemplate( getFileName(null, basefilename, TMPL_FILE_EXT) );
247         
248         fos = new FileOutputStream (
249                 getFileName(RESULTS_DIR, basefilename, RESULT_FILE_EXT));
250         
251         fwriter = new BufferedWriter( new OutputStreamWriter(fos) );
252         
253         context = new VelocityContext();
254         setupContext(context);
255         template.merge(context, fwriter);
256         fwriter.flush();
257         fwriter.close();
258         
259         if (!isMatch(RESULTS_DIR, COMPARE_DIR, basefilename, RESULT_FILE_EXT, CMP_FILE_EXT))
260         {
261             fail("Output incorrect.");
262         }
263     }
264         
265     public void setupContext(Context context)
266     {
267     } 
268     
269     
270 }