blob: b777c33b5785467f8263521e6bdca2b1a0f80045 [file] [log] [blame]
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 junit.framework.TestCase;
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.TestLogger;
import org.apache.velocity.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
/**
* 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$
*/
public abstract class BaseTestCase extends TestCase implements TemplateTestBase
{
protected VelocityEngine engine;
protected VelocityContext context;
protected boolean DEBUG = false;
protected TestLogger 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 test = System.getProperty("test");
if (test != null)
{
DEBUG = test.equals(getClass().getSimpleName());
}
}
protected void setUp() throws Exception
{
engine = new VelocityEngine();
//by default, make the engine's log output go to the test-report
log = new TestLogger(false, false);
engine.setProperty(RuntimeConstants.RUNTIME_LOG_INSTANCE, 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)
{
info(msg, null);
}
protected void info(String msg, Throwable t)
{
if (DEBUG)
{
try
{
if (engine == null)
{
Velocity.getLog().info(msg, t);
}
else
{
engine.getLog().info(msg, t);
}
}
catch (Throwable t2)
{
System.out.println("Failed to log: "+msg+(t!=null?" - "+t: ""));
System.out.println("Cause: "+t2);
t2.printStackTrace();
}
}
}
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());
}
else
{
info("Expectation: "+Exception.class.getName());
}
evaluate(evil);
String msg = "Template '"+evil+"' should have thrown an exception.";
info("Fail: "+msg);
fail(msg);
}
catch (Exception e)
{
if (exceptionType != null && !exceptionType.isAssignableFrom(e.getClass()))
{
String msg = "Was expecting template '"+evil+"' to throw "+exceptionType+" not "+e;
info("Fail: "+msg);
fail(msg);
}
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.lang3.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);
}
}
}
/**
* 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.
*
* @return source with all line terminations changed to Unix style
*/
protected String normalizeNewlines (String source)
{
return source.replaceAll("\r\n?", "\n");
}
/**
* 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
{
if (DEBUG)
{
info("Result: "+resultsDir+'/'+baseFileName+'.'+resultExt);
}
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: "+compareDir+'/'+baseFileName+'.'+compareExt);
}
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();
}
}