| package org.apache.velocity.test; |
| |
| import junit.framework.Assert; |
| import org.apache.velocity.VelocityContext; |
| import org.apache.velocity.app.Velocity; |
| |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Properties; |
| |
| public class RenderVelocityTemplateTest |
| { |
| |
| static class RenderVelocityTemplate |
| { |
| static |
| { |
| try |
| { |
| Properties p = new Properties(); |
| p.put("velocimacro.permissions.allow.inline.local.scope", "true"); |
| Velocity.init(p); |
| } |
| catch (Exception e) |
| { |
| throw new AssertionError("Failed to init Velocity"); |
| } |
| } |
| |
| private final VelocityContext velocityContext = new VelocityContext(); |
| |
| private final String template; |
| |
| public RenderVelocityTemplate(String template) |
| { |
| this.template = template; |
| } |
| |
| public String getContent() |
| throws Exception |
| { |
| StringWriter stringWriter = new StringWriter(); |
| Velocity.evaluate(velocityContext, stringWriter, "", template); |
| return stringWriter.toString(); |
| } |
| } |
| |
| |
| private static final String templateString = "" + // |
| "#macro (showhelloworld $foo)\n" + // |
| "Hello, World\n" + // |
| "#end\n" + // |
| "\n" + // |
| "<html>\n" + // |
| "<head>\n" + // |
| "<title>page title</title>\n" + // |
| "</head>\n" + // |
| "<body>\n" + // |
| "<p>This is a test</p>\n" + // |
| "<p>#showhelloworld ($foo)</p>\n" + // |
| "</body>\n" + // |
| "</html>"; |
| |
| public void testMultipleEvals() |
| throws Exception |
| { |
| RenderVelocityTemplate template = new RenderVelocityTemplate(templateString); |
| |
| String result = null; |
| for (int i = 0; i < 1000; ++i) |
| { |
| result = template.getContent(); |
| |
| // Verify that the original macro invocation has been replaced with its result. |
| int index = result.indexOf("#showhelloworld"); |
| if (index != -1) |
| { |
| throw new AssertionError("Failed to substitute macro:\n" + result); |
| } |
| |
| // Verify that the macro did indeed expand. |
| int indexHW = result.indexOf("<p>Hello, World"); |
| Assert.assertTrue(indexHW >= 0); |
| |
| // Assert.assertEquals("", result); // enable to show what we really get |
| } |
| } |
| |
| /** Helper class for testMultiThreadMultipleEvals(). */ |
| static class ExceptionHandler |
| implements Thread.UncaughtExceptionHandler |
| { |
| List<Throwable> errors = new ArrayList<>(); |
| |
| public void uncaughtException(Thread t, Throwable e) |
| { |
| errors.add(e); |
| } |
| } |
| |
| /** Helper class for testMultiThreadMultipleEvals(). */ |
| class RunMultipleEvals |
| extends Thread |
| { |
| @Override |
| public void run() |
| { |
| try |
| { |
| testMultipleEvals(); |
| } |
| catch (Exception e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
| |
| /** |
| * Spawn multiple threads that concurrently call testMultipleEvals. |
| */ |
| public void testMultiThreadMultipleEvals() |
| throws Throwable |
| { |
| int nthreads = 4; |
| ExceptionHandler eh = new ExceptionHandler(); |
| |
| List<Thread> threads = new ArrayList<>(nthreads); |
| for (int i = 0; i < nthreads; ++i) |
| { |
| Thread t = new RunMultipleEvals(); |
| t.setUncaughtExceptionHandler(eh); |
| threads.add(t); |
| } |
| |
| for (Thread t : threads) |
| { |
| t.start(); |
| } |
| |
| for (Thread t : threads) |
| { |
| t.join(); |
| } |
| |
| if (eh.errors.size() > 0) |
| { |
| // Rethrow the first failing exception. |
| System.out.println("Failed " + eh.errors.size() + " out of " + nthreads + " template evaluations"); |
| throw eh.errors.get(0); |
| } |
| } |
| } |