Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: freemarker/testcase/TemplateTestCase.java


1   /*
2    * Copyright (c) 2005 The Visigoth Software Society. All rights
3    * reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    * 1. Redistributions of source code must retain the above copyright
10   *    notice, this list of conditions and the following disclaimer.
11   *
12   * 2. Redistributions in binary form must reproduce the above copyright
13   *    notice, this list of conditions and the following disclaimer in
14   *    the documentation and/or other materials provided with the
15   *    distribution.
16   *
17   * 3. The end-user documentation included with the redistribution, if
18   *    any, must include the following acknowledgement:
19   *       "This product includes software developed by the
20   *        Visigoth Software Society (http://www.visigoths.org/)."
21   *    Alternately, this acknowledgement may appear in the software itself,
22   *    if and wherever such third-party acknowledgements normally appear.
23   *
24   * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
25   *    project contributors may be used to endorse or promote products derived
26   *    from this software without prior written permission. For written
27   *    permission, please contact visigoths@visigoths.org.
28   *
29   * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30   *    nor may "FreeMarker" or "Visigoth" appear in their names
31   *    without prior written permission of the Visigoth Software Society.
32   *
33   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36   * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44   * SUCH DAMAGE.
45   * ====================================================================
46   *
47   * This software consists of voluntary contributions made by many
48   * individuals on behalf of the Visigoth Software Society. For more
49   * information on the Visigoth Software Society, please see
50   * http://www.visigoths.org/
51   */
52  
53  package freemarker.testcase;
54  
55  import freemarker.template.*;
56  import freemarker.ext.beans.*;
57  import freemarker.ext.dom.NodeModel;
58  import freemarker.ext.jdom.NodeListModel;
59  import freemarker.testcase.models.*;
60  import freemarker.template.utility.*;
61  import freemarker.template.utility.NormalizeNewlines;
62  import freemarker.testcase.models.TransformHashWrapper;
63  import junit.framework.*;
64  import java.util.*;
65  import java.io.*;
66  import java.net.URL;
67  import javax.xml.parsers.DocumentBuilder;
68  import javax.xml.parsers.DocumentBuilderFactory;
69  import org.jdom.input.SAXBuilder;
70  import org.xml.sax.InputSource;
71  
72  
73  public class TemplateTestCase extends TestCase {
74      
75      Template template;
76      HashMap dataModel = new HashMap();
77      
78      String filename, testName;
79      String inputDir = "template";
80      String referenceDir = "reference";
81      File outputDir;
82      
83      Configuration conf = new Configuration();
84      
85      public TemplateTestCase(String name, String filename) {
86          super(name);
87          this.filename = filename;
88          this.testName = name;
89      }
90      
91      public void setTemplateDirectory(String dirname) throws IOException {
92          URL url = getClass().getResource("TemplateTestCase.class");
93          File parent = new File(url.getFile()).getParentFile();
94          File dir = new File(parent, dirname);
95          conf.setDirectoryForTemplateLoading(dir);
96          System.out.println("Setting loading directory as: " + dir);
97      }
98      
99      public void setOutputDirectory(String dirname) {
100         URL url = getClass().getResource("TemplateTestCase.class");
101         File parent = new File(url.getFile()).getParentFile();
102         this.outputDir = new File(parent, dirname);
103         System.out.println("Setting reference directory as: " + outputDir);
104     }
105 
106     public void setConfigParam(String param, String value) throws IOException {
107         if ("templatedir".equals(param)) {
108             setTemplateDirectory(value);
109         }
110         else if ("auto_import".equals(param)) {
111             StringTokenizer st = new StringTokenizer(value);
112             if (!st.hasMoreTokens()) fail("Expecting libname");
113             String libname = st.nextToken();
114             if (!st.hasMoreTokens()) fail("Expecting 'as <alias>' in autoimport");
115             String as = st.nextToken();
116             if (!as.equals("as")) fail("Expecting 'as <alias>' in autoimport");
117             if (!st.hasMoreTokens()) fail("Expecting alias after 'as' in autoimport");
118             String alias = st.nextToken();
119             conf.addAutoImport(alias, libname);
120         }
121         else if ("clear_encoding_map".equals(param)) {
122             if (StringUtil.getYesNo(value)) {
123                 conf.clearEncodingMap();
124             }
125         }
126         else if ("input_encoding".equals(param)) {
127             conf.setDefaultEncoding(value);
128         }
129         else if ("outputdir".equals(param)) {
130             setOutputDirectory(value);
131         }
132         else if ("output_encoding".equals(param)) {
133             conf.setOutputEncoding(value);
134         }
135         else if ("locale".equals(param)) {
136             String lang = "", country="", variant="";
137             StringTokenizer st = new StringTokenizer(value,"_", false);
138             if (st.hasMoreTokens()) {
139                 lang = st.nextToken();
140             }
141             if (st.hasMoreTokens()) {
142                 country = st.nextToken();
143             }
144             if (st.hasMoreTokens()){
145                 variant = st.nextToken();
146             }
147             if (lang != "") {
148                 Locale loc = new Locale(lang, country, variant);
149                 conf.setLocale(loc);
150             }
151         }
152         else if ("object_wrapper".equals(param)) {
153             try {
154                 Class cl = Class.forName(value);
155                 ObjectWrapper ow = (ObjectWrapper) cl.newInstance();
156                 conf.setObjectWrapper(ow);
157             } catch (Exception e) {
158                 fail("Error setting object wrapper to " + value + "\n" + e.getMessage());
159             }
160         }
161         else if ("input_encoding".equals(param)) {
162             conf.setDefaultEncoding(value);
163         }
164         else if ("output_encoding".equals(param)) {
165             conf.setOutputEncoding(value);
166         }
167         else if ("strict_syntax".equals(param)) {
168             boolean b = StringUtil.getYesNo(value);
169             conf.setStrictSyntaxMode(b);
170         }
171         else if ("url_escaping_charset".equals(param)) {
172             conf.setURLEscapingCharset(value);
173         }
174     }
175     
176     /*
177      * This method just contains all the code to seed the data model 
178      * ported over from the individual classes. This seems ugly and unnecessary.
179      * We really might as well just expose pretty much 
180      * the same tree to all our tests. (JR)
181      */
182     
183     public void setUp() throws Exception {
184         dataModel.put("message", "Hello, world!");
185         
186         if (testName.equals("bean-maps")) {
187             BeansWrapper w1 = new BeansWrapper();
188             BeansWrapper w2 = new BeansWrapper();
189             BeansWrapper w3 = new BeansWrapper();
190             BeansWrapper w4 = new BeansWrapper();
191             BeansWrapper w5 = new BeansWrapper();
192             BeansWrapper w6 = new BeansWrapper();
193             BeansWrapper w7 = new BeansWrapper();
194     
195             w1.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY);
196             w2.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY);
197             w3.setExposureLevel(BeansWrapper.EXPOSE_NOTHING);
198             w4.setExposureLevel(BeansWrapper.EXPOSE_NOTHING);
199             w5.setExposureLevel(BeansWrapper.EXPOSE_ALL);
200             w6.setExposureLevel(BeansWrapper.EXPOSE_ALL);
201     
202             w1.setMethodsShadowItems(true);
203             w2.setMethodsShadowItems(false);
204             w3.setMethodsShadowItems(true);
205             w4.setMethodsShadowItems(false);
206             w5.setMethodsShadowItems(true);
207             w6.setMethodsShadowItems(false);
208     
209             w7.setSimpleMapWrapper(true);
210     
211             Object test = getTestBean();
212     
213             dataModel.put("m1", w1.wrap(test));
214             dataModel.put("m2", w2.wrap(test));
215             dataModel.put("m3", w3.wrap(test));
216             dataModel.put("m4", w4.wrap(test));
217             dataModel.put("m5", w5.wrap(test));
218             dataModel.put("m6", w6.wrap(test));
219             dataModel.put("m7", w7.wrap(test));
220     
221             dataModel.put("s1", w1.wrap("hello"));
222             dataModel.put("s2", w1.wrap("world"));
223             dataModel.put("s3", w5.wrap("hello"));
224             dataModel.put("s4", w5.wrap("world"));
225         }
226         
227         else if (testName.equals("beans")) {
228             dataModel.put("array", new String[] { "array-0", "array-1"});
229             dataModel.put("list", Arrays.asList(new String[] { "list-0", "list-1", "list-2"}));
230             Map tmap = new HashMap();
231             tmap.put("key", "value");
232             Object objKey = new Object();
233             tmap.put(objKey, "objValue");
234             dataModel.put("map", tmap);
235             dataModel.put("objKey", objKey);
236             dataModel.put("obj", new freemarker.testcase.models.BeanTestClass());
237             dataModel.put("resourceBundle", new ResourceBundleModel(ResourceBundle.getBundle("freemarker.testcase.models.BeansTestResources"), BeansWrapper.getDefaultInstance()));
238             dataModel.put("date", new GregorianCalendar(1974, 10, 14).getTime());
239             dataModel.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
240         }
241         
242         else if (testName.equals("boolean")) {
243             dataModel.put( "boolean1", TemplateBooleanModel.FALSE);
244             dataModel.put( "boolean2", TemplateBooleanModel.TRUE);
245             dataModel.put( "boolean3", TemplateBooleanModel.TRUE);
246             dataModel.put( "boolean4", TemplateBooleanModel.TRUE);
247             dataModel.put( "boolean5", TemplateBooleanModel.FALSE);
248             
249             dataModel.put( "list1", new BooleanList1() );
250             dataModel.put( "list2", new BooleanList2() );
251     
252             dataModel.put( "hash1", new BooleanHash1() );
253             dataModel.put( "hash2", new BooleanHash2() );
254         }
255         
256         else if (testName.equals("dateformat")) {
257             GregorianCalendar cal = new GregorianCalendar(2002, 10, 15, 14, 54, 13);
258             cal.setTimeZone(TimeZone.getTimeZone("GMT"));
259             dataModel.put("date", new SimpleDate(cal.getTime(), TemplateDateModel.DATETIME));
260             dataModel.put("unknownDate", new SimpleDate(cal.getTime(), TemplateDateModel.UNKNOWN));
261         }
262         else if (testName.equals("default-xmlns")) {
263             InputSource is = new InputSource(getClass().getResourceAsStream("test-defaultxmlns1.xml"));
264             NodeModel nm = NodeModel.parse(is);
265             dataModel.put("doc", nm);
266         }
267         
268         else if (testName.equals("multimodels")) {
269             dataModel.put("test", "selftest");
270             dataModel.put("self", "self");
271             dataModel.put("zero", new Integer(0));
272             dataModel.put("data", new MultiModel1());
273         }
274         
275         else if (testName.equals("nodelistmodel")) {
276             org.jdom.Document doc = new SAXBuilder().build(new InputSource(getClass().getResourceAsStream("test-xml.xml")));
277             dataModel.put("doc", new NodeListModel(doc));
278         }
279         
280         else if (testName.equals("string-builtins3")) {
281             dataModel.put("multi", new TestBoolean());
282         }
283         
284         else if (testName.equals("type-builtins")) {
285             dataModel.put("testmethod", new TestMethod());
286             dataModel.put("testnode", new TestNode());
287             dataModel.put("testcollection", new SimpleCollection(new ArrayList()));
288         }
289         
290         else if (testName.equals("var-layers")) {
291             dataModel.put("x", new Integer(4));
292             dataModel.put("z", new Integer(4));
293             conf.setSharedVariable("y", new Integer(7));
294         }
295         
296         else if (testName.equals("xml-fragment")) {
297             DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
298             f.setNamespaceAware(true);
299             DocumentBuilder db = f.newDocumentBuilder();
300             org.w3c.dom.Document doc = db.parse(new InputSource(getClass().getResourceAsStream("test-xmlfragment.xml")));
301             dataModel.put("node", NodeModel.wrap(doc.getDocumentElement().getFirstChild().getFirstChild()));
302         }
303         
304         else if (testName.equals("xmlns1")) {
305             InputSource is = new InputSource(getClass().getResourceAsStream("test-xmlns.xml"));
306             NodeModel nm = NodeModel.parse(is);
307             dataModel.put("doc", nm);
308         }
309         
310         else if (testName.equals("xmlns2")) {
311             InputSource is = new InputSource(getClass().getResourceAsStream("test-xmlns2.xml"));
312             NodeModel nm = NodeModel.parse(is);
313             dataModel.put("doc", nm);
314         }
315         
316         else if (testName.equals("xmlns3") || testName.equals("xmlns4")) {
317             InputSource is = new InputSource(getClass().getResourceAsStream("test-xmlns3.xml"));
318             NodeModel nm = NodeModel.parse(is);
319             dataModel.put("doc", nm);
320         }
321         
322         else if (testName.equals("xmlns5")) {
323             InputSource is = new InputSource(getClass().getResourceAsStream("test-defaultxmlns1.xml"));
324             NodeModel nm = NodeModel.parse(is);
325             dataModel.put("doc", nm);
326         }
327     }
328     
329     public void runTest() {
330         try {
331             template = conf.getTemplate(filename);
332         } catch (Exception e) {
333             StringWriter sw = new StringWriter();
334             PrintWriter pw = new PrintWriter(sw);
335             e.printStackTrace(pw);
336             fail("Could not load template " + filename + "\n" + sw.toString());
337         }
338         File refFile = new File (outputDir, filename);
339         File outFile = new File (outputDir, filename+".out");
340         Writer out = null;
341         String encoding = conf.getOutputEncoding();
342         if (encoding == null) encoding = "UTF-8";
343         try {
344             out = new OutputStreamWriter(new FileOutputStream(outFile), 
345                     encoding);
346         } catch (IOException ioe) {
347             fail("Cannot write to file: " + outFile + "\n" + ioe.getMessage());
348         }
349         try {
350             template.process(dataModel, out);
351             out.close();
352         } catch (Exception e) {
353             StringWriter sw = new StringWriter();
354             PrintWriter pw = new PrintWriter(sw);
355             e.printStackTrace(pw);
356             fail("Could not process template " + filename + "\n" + sw.toString());
357         }
358         try {
359             Reader ref = new InputStreamReader(new FileInputStream(refFile), 
360                     encoding);
361             Reader output = new InputStreamReader(new FileInputStream(outFile), 
362                     encoding);
363             compare(ref, output);
364         } catch (IOException e) {
365             StringWriter sw = new StringWriter();
366             PrintWriter pw = new PrintWriter(sw);
367             e.printStackTrace(pw);
368             fail("Error comparing files " + refFile + " and " + outFile + "\n" + sw.toString());
369         }
370         outFile.delete();
371     }
372 
373     static public void compare(Reader reference, Reader output) throws IOException {
374         LineNumberReader ref = new LineNumberReader(reference);
375         LineNumberReader out = new LineNumberReader(output);
376         String refLine = "", outLine = "";
377         while (refLine != null || outLine != null) {
378             if (refLine == null) {
379                 fail("Output text is longer than reference text");
380             }
381             if (outLine == null) {
382                 fail("Output text is shorter than reference text");
383             }
384             refLine = ref.readLine();
385             outLine = out.readLine();
386             if (refLine != null && outLine != null & !refLine.equals(outLine)) {
387                 fail("Difference found on line " + ref.getLineNumber() + 
388                                             ".\nReference text is: " + refLine +
389                                             "\nOutput text is: " + outLine);
390             }
391         } 
392     }
393     
394     static class TestBoolean implements TemplateBooleanModel, TemplateScalarModel {
395         public boolean getAsBoolean() {
396             return true;
397         }
398         
399         public String getAsString() {
400             return "de";
401         }
402     }
403     
404     static class TestMethod implements TemplateMethodModel {
405       public Object exec(java.util.List arguments) {
406           return "x";
407       }
408     }
409     
410     static class TestNode implements TemplateNodeModel {
411       
412       public String getNodeName() {
413           return "name";
414       }
415                     
416       public TemplateNodeModel getParentNode() {
417           return null;
418       }
419     
420       public String getNodeType() {
421           return "element";
422       }
423     
424       public TemplateSequenceModel getChildNodes() {
425           return null;
426       }
427       
428       public String getNodeNamespace() {
429           return null;
430       }
431     }
432 
433    public Object getTestBean()
434     {
435         Map testBean = new TestBean();
436         testBean.put("name", "Chris");
437         testBean.put("location", "San Francisco");
438         testBean.put("age", new Integer(27));
439         return testBean;
440     }
441 
442     public static class TestBean extends HashMap {
443         public String getName() {
444             return "Christopher";
445         }
446         public int getLuckyNumber() {
447             return 7;
448         }
449     }
450 }