org.apache.velocity.test.BaseTestCase.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.velocity.test.BaseTestCase.java

Source

package org.apache.velocity.test;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;

import junit.framework.TestCase;

import org.apache.oro.text.perl.Perl5Util;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.apache.velocity.test.misc.TestLogChute;
import org.apache.velocity.util.StringUtils;

/**
 * Base test case that provides utility methods for
 * the rest of the tests.
 *
 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 * @author Nathan Bubna
 * @version $Id: BaseTestCase.java 898032 2010-01-11 19:51:03Z nbubna $
 */
public abstract class BaseTestCase extends TestCase implements TemplateTestBase {
    protected VelocityEngine engine;
    protected VelocityContext context;
    protected boolean DEBUG = false;
    protected TestLogChute log;
    protected String stringRepoName = "string.repo";

    public BaseTestCase(String name) {
        super(name);

        // if we're just running one case, then have DEBUG
        // automatically set to true
        String testcase = System.getProperty("testcase");
        if (testcase != null) {
            DEBUG = testcase.equals(getClass().getName());
        }
    }

    protected void setUp() throws Exception {
        engine = new VelocityEngine();

        //by default, make the engine's log output go to the test-report
        log = new TestLogChute(false, false);
        log.setEnabledLevel(TestLogChute.INFO_ID);
        log.setSystemErrLevel(TestLogChute.WARN_ID);
        engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, log);

        // use string resource loader by default, instead of file
        engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file,string");
        engine.addProperty("string.resource.loader.class", StringResourceLoader.class.getName());
        engine.addProperty("string.resource.loader.repository.name", stringRepoName);
        engine.addProperty("string.resource.loader.repository.static", "false");

        setUpEngine(engine);

        context = new VelocityContext();
        setUpContext(context);
    }

    protected void setUpEngine(VelocityEngine engine) {
        // extension hook
    }

    protected void setUpContext(VelocityContext context) {
        // extension hook
    }

    protected StringResourceRepository getStringRepository() {
        StringResourceRepository repo = (StringResourceRepository) engine.getApplicationAttribute(stringRepoName);
        if (repo == null) {
            engine.init();
            repo = (StringResourceRepository) engine.getApplicationAttribute(stringRepoName);
        }
        return repo;
    }

    protected void addTemplate(String name, String template) {
        info("Template '" + name + "':  " + template);
        getStringRepository().putStringResource(name, template);
    }

    protected void removeTemplate(String name) {
        info("Removed: '" + name + "'");
        getStringRepository().removeStringResource(name);
    }

    public void tearDown() {
        engine = null;
        context = null;
    }

    protected void info(String msg) {
        if (DEBUG) {
            if (engine == null) {
                Velocity.getLog().info(msg);
            } else {
                engine.getLog().info(msg);
            }
        }
    }

    protected void info(String msg, Throwable t) {
        if (DEBUG) {
            if (engine == null) {
                Velocity.getLog().info(msg);
            } else {
                engine.getLog().info(msg, t);
            }
        }
    }

    public void testBase() {
        if (DEBUG && engine != null) {
            assertSchmoo("");
            assertSchmoo("abc\n123");
        }
    }

    /**
     * Compare an expected string with the given loaded template
     */
    protected void assertTmplEquals(String expected, String template) {
        info("Expected:  " + expected + " from '" + template + "'");

        StringWriter writer = new StringWriter();
        try {
            engine.mergeTemplate(template, "utf-8", context, writer);
        } catch (RuntimeException re) {
            info("RuntimeException!", re);
            throw re;
        } catch (Exception e) {
            info("Exception!", e);
            throw new RuntimeException(e);
        }

        info("Result:  " + writer.toString());
        assertEquals(expected, writer.toString());
    }

    /**
     * Ensure that a context value is as expected.
     */
    protected void assertContextValue(String key, Object expected) {
        info("Expected value of '" + key + "': " + expected);
        Object value = context.get(key);
        info("Result: " + value);
        assertEquals(expected, value);
    }

    /**
     * Ensure that a template renders as expected.
     */
    protected void assertEvalEquals(String expected, String template) {
        info("Expectation: " + expected);
        assertEquals(expected, evaluate(template));
    }

    /**
     * Ensure that the given string renders as itself when evaluated.
     */
    protected void assertSchmoo(String templateIsExpected) {
        assertEvalEquals(templateIsExpected, templateIsExpected);
    }

    /**
     * Ensure that an exception occurs when the string is evaluated.
     */
    protected Exception assertEvalException(String evil) {
        return assertEvalException(evil, null);
    }

    /**
     * Ensure that a specified type of exception occurs when evaluating the string.
     */
    protected Exception assertEvalException(String evil, Class exceptionType) {
        try {
            if (!DEBUG) {
                log.off();
            }
            if (exceptionType != null) {
                info("Expectation: " + exceptionType.getName());
            }
            evaluate(evil);
            fail("Template '" + evil + "' should have thrown an exception.");
        } catch (Exception e) {
            if (exceptionType != null && !exceptionType.isAssignableFrom(e.getClass())) {
                fail("Was expecting template '" + evil + "' to throw " + exceptionType + " not " + e);
            }
            return e;
        } finally {
            if (!DEBUG) {
                log.on();
            }
        }
        return null;
    }

    /**
     * Ensure that the error message of the expected exception has the proper location info.
     */
    protected Exception assertEvalExceptionAt(String evil, String template, int line, int col) {
        String loc = template + "[line " + line + ", column " + col + "]";
        info("Expectation: Exception at " + loc);
        Exception e = assertEvalException(evil);

        info("Result: " + e.getClass().getName() + " - " + e.getMessage());
        if (e.getMessage().indexOf(loc) < 1) {
            fail("Was expecting exception at " + loc + " instead of " + e.getMessage());
        }
        return e;
    }

    /**
     * Only ensure that the error message of the expected exception
     * has the proper line and column info.
     */
    protected Exception assertEvalExceptionAt(String evil, int line, int col) {
        return assertEvalExceptionAt(evil, "", line, col);
    }

    /**
     * Evaluate the specified String as a template and return the result as a String.
     */
    protected String evaluate(String template) {
        StringWriter writer = new StringWriter();
        try {
            info("Template: " + template);

            // use template as its own name, since our templates are short
            // unless it's not that short, then shorten it...
            String name = (template.length() <= 15) ? template : template.substring(0, 15);
            engine.evaluate(context, writer, name, template);

            String result = writer.toString();
            info("Result: " + result);
            return result;
        } catch (RuntimeException re) {
            info("RuntimeException!", re);
            throw re;
        } catch (Exception e) {
            info("Exception!", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Concatenates the file name parts together appropriately.
     *
     * @return The full path to the file.
     */
    protected String getFileName(final String dir, final String base, final String ext) {
        return getFileName(dir, base, ext, false);
    }

    protected String getFileName(final String dir, final String base, final String ext, final boolean mustExist) {
        StringBuffer buf = new StringBuffer();
        try {
            File baseFile = new File(base);
            if (dir != null) {
                if (!baseFile.isAbsolute()) {
                    baseFile = new File(dir, base);
                }

                buf.append(baseFile.getCanonicalPath());
            } else {
                buf.append(baseFile.getPath());
            }

            if (org.apache.commons.lang.StringUtils.isNotEmpty(ext)) {
                buf.append('.').append(ext);
            }

            if (mustExist) {
                File testFile = new File(buf.toString());

                if (!testFile.exists()) {
                    String msg = "getFileName() result " + testFile.getPath() + " does not exist!";
                    info(msg);
                    fail(msg);
                }

                if (!testFile.isFile()) {
                    String msg = "getFileName() result " + testFile.getPath() + " is not a file!";
                    info(msg);
                    fail(msg);
                }
            }
        } catch (IOException e) {
            fail("IO Exception while running getFileName(" + dir + ", " + base + ", " + ext + ", " + mustExist
                    + "): " + e.getMessage());
        }

        return buf.toString();
    }

    /**
     * Assures that the results directory exists.  If the results directory
     * cannot be created, fails the test.
     */
    protected void assureResultsDirectoryExists(String resultsDirectory) {
        File dir = new File(resultsDirectory);
        if (!dir.exists()) {
            info("Template results directory (" + resultsDirectory + ") does not exist");
            if (dir.mkdirs()) {
                info("Created template results directory");
                if (DEBUG) {
                    info("Created template results directory: " + resultsDirectory);
                }
            } else {
                String errMsg = "Unable to create '" + resultsDirectory + "'";
                info(errMsg);
                fail(errMsg);
            }
        }
    }

    //TODO: drop this for JDK regex once we move to JDK 1.5
    private static Perl5Util perl = new Perl5Util();

    /**
     * Normalizes lines to account for platform differences.  Macs use
     * a single \r, DOS derived operating systems use \r\n, and Unix
     * uses \n.  Replace each with a single \n.
     *
     * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
     * @return source with all line terminations changed to Unix style
     */
    protected String normalizeNewlines(String source) {
        return perl.substitute("s/\r[\r]?[\n]/\n/g", source);
    }

    /**
     * Returns whether the processed template matches the
     * content of the provided comparison file.
     *
     * @return Whether the output matches the contents
     *         of the comparison file.
     *
     * @exception Exception Test failure condition.
     */
    protected boolean isMatch(String resultsDir, String compareDir, String baseFileName, String resultExt,
            String compareExt) throws Exception {
        String result = getFileContents(resultsDir, baseFileName, resultExt);
        return isMatch(result, compareDir, baseFileName, compareExt);
    }

    protected String getFileContents(String dir, String baseFileName, String ext) {
        String fileName = getFileName(dir, baseFileName, ext, true);
        return StringUtils.fileContentsToString(fileName);
    }

    /**
     * Returns whether the processed template matches the
     * content of the provided comparison file.
     *
     * @return Whether the output matches the contents
     *         of the comparison file.
     *
     * @exception Exception Test failure condition.
     */
    protected boolean isMatch(String result, String compareDir, String baseFileName, String compareExt)
            throws Exception {
        String compare = getFileContents(compareDir, baseFileName, compareExt);

        // normalize each wrt newline
        result = normalizeNewlines(result);
        compare = normalizeNewlines(compare);
        if (DEBUG) {
            info("Expection: " + compare);
            info("Result: " + result);
        }
        return result.equals(compare);
    }

    /**
     * Turns a base file name into a test case name.
     *
     * @param s The base file name.
     * @return  The test case name.
     */
    protected static final String getTestCaseName(String s) {
        StringBuffer name = new StringBuffer();
        name.append(Character.toTitleCase(s.charAt(0)));
        name.append(s.substring(1, s.length()).toLowerCase());
        return name.toString();
    }
}