root/trunk/universe/kauri-template/src/test/java/org/kauriproject/template/TemplateTestBase.java @ 1004

Revision 1004, 9.5 KB (checked in by bruno, 21 months ago)

Templates: allow that expressions which return XML content are streamed as XML. This fits into the work on internationalization, to allow resource bundle messages to contain mixed content.
* Introduced Saxable interface (similar to XMLizable from Cocoon/Daisy)
* TextEvent?: run over individual expression results, streaming them as XML if format is recongized (Saxable, DOM nodes, lists of those).
* Added the DOMStreamer from Cocoon
* TestHandler?:

  • this class is problematic, and should be removed. It reformats white-space (adding & removing), and by doing so, hides whitespace issues, and doesn't work as expected for more complex cases (e.g consecutive character events produced by calling macros). I'll create an issue for this.
  • remove trimming on individual character events, and the related logging that there should be no more than one character event. Due to the introduced changes, this will often not be the case, and I don't see why it should be that way.

* Adjusted some of the testresults because the whitespace stripping does not work anymore as before.
* TemplateTestBase?: if input and output XML is not the same, print it to the stdout, for easy debugging.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/plain
Line 
1/*
2 * Copyright 2008 Outerthought bvba and Schaubroeck nv
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.kauriproject.template;
17
18import java.io.ByteArrayOutputStream;
19import java.util.Date;
20import java.util.HashMap;
21import java.util.Map;
22
23import javax.xml.parsers.SAXParser;
24import javax.xml.parsers.SAXParserFactory;
25
26import junit.framework.TestCase;
27
28import org.apache.commons.logging.Log;
29import org.apache.commons.logging.LogFactory;
30import org.kauriproject.template.source.ClasspathSourceResolver;
31import org.kauriproject.template.source.Source;
32import org.kauriproject.template.source.SourceResolver;
33import org.kauriproject.template.taglib.Taglib;
34import org.kauriproject.xml.sax.XmlConsumer;
35import org.xml.sax.InputSource;
36import org.xml.sax.XMLReader;
37import org.xml.sax.SAXException;
38
39public class TemplateTestBase extends TestCase {
40
41    // development flag - log durations and fail if too slow
42    protected static final boolean TEST_DURATION = false;
43
44    protected static Log log = LogFactory.getLog(TemplateTestBase.class);
45
46    private static final String ENCODING = "UTF-8";
47
48    // Treshold (in seconds) for allowed duration of execution of each test template.
49    protected double executionTreshold;
50
51    // Treshold (in seconds) for allowed duration of building of each test template.
52    protected double buildTreshold;
53
54    // Treshold (in seconds) for allowed duration of entire build/exec/handle process of each template.
55    protected double flowTreshold;
56
57    private SAXParser parser;
58    private SourceResolver sourceResolver;
59
60    @Override
61    protected void setUp() throws Exception {
62        super.setUp();
63        // setup parser
64        SAXParserFactory factory = SAXParserFactory.newInstance();
65        factory.setNamespaceAware(true);
66        factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
67        parser = factory.newSAXParser();
68        sourceResolver = new ClasspathSourceResolver();
69    }
70
71    protected void initTresholds(String template) throws Exception {
72        long start = new Date().getTime();
73        // load template
74        loadXML(template);
75        long end = new Date().getTime();
76        // check duration
77        double duration = getDuration(start, end);
78        log.info("initial loading: " + duration + " sec.");
79
80        executionTreshold = Math.max(0.05, duration);
81        buildTreshold = executionTreshold * 2;
82        flowTreshold = executionTreshold * 3;
83    }
84
85    /**
86     * Test execution of a compiled template.
87     */
88    protected void executeTemplate(CompiledTemplate compiledTemplate, TemplateResult result,
89            Map<String, Object> variables, double treshold) throws SAXException {
90        // setup
91        TemplateContext context = new DefaultTemplateContext();
92        if (variables != null) {
93            context.putAll(variables);
94        }
95        ExecutionContext execContext = new ExecutionContext();
96        execContext.setTemplateContext(context);
97        execContext.setSourceResolver(sourceResolver);
98        DefaultTemplateExecutor executor = new DefaultTemplateExecutor();
99
100        // monitor duration
101        long start = new Date().getTime();
102        // execute template
103        executor.execute(compiledTemplate, null, execContext, result);
104        long end = new Date().getTime();
105
106        // check if there is a templateresult
107        assertNotNull("TemplateResult should not be null.", result);
108
109        // check duration
110        double duration = getDuration(start, end);
111        if (TEST_DURATION) {
112            log.info("duration execution: " + duration + " sec.");
113            assertTrue("Execution was too slow: " + duration + " sec.", duration < treshold);
114        }
115    }
116
117    /**
118     * Test the build/compilation process of a template.
119     */
120    protected CompiledTemplate buildTemplate(String template, double treshold) throws Exception {
121        // setup
122        DefaultTemplateBuilder builder = new DefaultTemplateBuilder(null, new DefaultTemplateService(), false);
123        builder.setTaglibs(loadTaglibs());
124        // load
125        Source resource = sourceResolver.resolve(template);
126        // monitor duration
127        long start = new Date().getTime();
128        // build template
129        CompiledTemplate compiledTemplate = builder.buildTemplate(resource);
130        long end = new Date().getTime();
131
132        // check if there is a compiledTemplate
133        assertNotNull("CompiledTemplate should not be null", compiledTemplate);
134
135        // check duration
136        double duration = getDuration(start, end);
137        if (TEST_DURATION) {
138            log.info("duration build: " + duration + " sec.");
139            assertTrue("Building was too slow: " + duration + " sec.", duration < treshold);
140        }
141
142        return compiledTemplate;
143    }
144
145    /**
146     * Load, build and execute template and optionally check the result.
147     */
148    protected void testFlow(String template, boolean check) throws Exception {
149        testFlow(template, null, check);
150    }
151
152    /**
153     * Load, build and execute template and optionally check the result.
154     */
155    protected void testFlow(String template, Map<String, Object> variables, boolean check) throws Exception {
156        // init tresholds for duration
157        if (TEST_DURATION) {
158            initTresholds(template);
159        }
160        // monitor duration
161        long start = new Date().getTime();
162        // load and build template
163        CompiledTemplate compiledTemplate = buildTemplate(template, buildTreshold);
164        // execute template
165        ByteArrayOutputStream outputResult = new ByteArrayOutputStream();
166        TemplateResult result = new TemplateResultImpl(new KauriSaxHandler.NamespaceAsAttributes(
167                new TestHandler(outputResult)));
168        executeTemplate(compiledTemplate, result, variables, executionTreshold);
169        // flush result
170        result.flush();
171        long end = new Date().getTime();
172
173        // check duration
174        double duration = getDuration(start, end);
175        if (TEST_DURATION) {
176            log.info("duration flow: " + duration + " sec.\n");
177            assertTrue("Flow was too slow: " + duration + " sec.", duration < flowTreshold);
178        }
179
180        // check result
181        if (check) {
182            checkResult(template, outputResult);
183        }
184    }
185
186    /**
187     * Check if the templateresult meets our expectations.
188     */
189    protected void checkResult(String filename, ByteArrayOutputStream bos) throws Exception {
190        String expectedFile = filename.replace(".xml", "_result.xml");
191        String expectedString = loadXML(expectedFile);
192        String actualString = bos.toString(ENCODING);
193        if (!expectedString.equals(actualString)) {
194            System.out.println("=======================================================================");
195            System.out.println("Execution of " + filename + " does not match " + expectedFile);
196            System.out.println("-> Output:");
197            System.out.println(actualString);
198            System.out.println("-> Expected:");
199            System.out.println(expectedString);
200        }
201        assertEquals("Actual XML result does not equal our expected XML.", expectedString, actualString);
202    }
203
204    protected String loadXML(String filename) throws Exception {
205        Source source = sourceResolver.resolve(filename);
206        ByteArrayOutputStream bos = new ByteArrayOutputStream();
207        XmlConsumer consumer = new TestHandler(bos);
208        XMLReader reader = parser.getXMLReader();
209        reader.setContentHandler(consumer);
210        reader.setProperty("http://xml.org/sax/properties/lexical-handler", consumer);
211        reader.parse(new InputSource(source.getInputStream()));
212        String xmlString = bos.toString(ENCODING);
213
214        return xmlString;
215    }
216
217    /**
218     * Compute the difference (in seconds) between two time values (expressed in milliseconds).
219     */
220    protected double getDuration(final long start, final long end) {
221        return ((end - start) / 1000.0);
222    }
223
224    private Map<String, Taglib> loadTaglibs() {
225        Map<String, Taglib> taglibs = new HashMap<String, Taglib>();
226        Class<?> taglibClass;
227        Taglib taglib;
228        try {
229            taglibClass = Class.forName("org.kauriproject.template.taglib.TestTaglib");
230            taglib = (Taglib) taglibClass.newInstance();
231            if (!taglib.getNamespace().equals(TemplateBuilder.NAMESPACE_KTL)) {
232                taglibs.put(taglib.getNamespace(), taglib);
233            } else {
234                log.error("Forbidden to use the default kauri template namespace for taglibs.");
235            }
236
237        } catch (ClassNotFoundException ex) {
238            log.error("error loading taglib: " + ex);
239            ex.printStackTrace();
240        } catch (InstantiationException ex) {
241            log.error("error loading taglib: " + ex);
242            ex.printStackTrace();
243        } catch (IllegalAccessException ex) {
244            log.error("error loading taglib: " + ex);
245            ex.printStackTrace();
246        } catch (ClassCastException ex) {
247            log.error("error loading taglib: " + ex);
248            ex.printStackTrace();
249        }
250        return taglibs;
251
252    }
253
254}
Note: See TracBrowser for help on using the browser.