/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.rendering.internal.macro.cache;
import java.io.StringWriter;
import java.util.List;
import org.junit.Test;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.internal.transformation.macro.MacroTransformation;
import org.xwiki.rendering.macro.Macro;
import org.xwiki.rendering.macro.cache.CacheMacroParameters;
import org.xwiki.rendering.macro.script.ScriptMockSetup;
import org.xwiki.rendering.renderer.PrintRendererFactory;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.transformation.MacroTransformationContext;
import org.xwiki.rendering.transformation.Transformation;
import org.xwiki.test.jmock.AbstractComponentTestCase;
import org.xwiki.velocity.VelocityManager;
import static org.xwiki.rendering.test.BlockAssert.assertBlocks;
import static org.junit.Assert.*;
/**
* Unit tests for {@link CacheMacro}.
*
* @version $Id: b4401376500bd568e0ba2ba3db9743bbbbca6fb9 $
* @since 3.0M1
*/
public class CacheMacroTest extends AbstractComponentTestCase
{
private ScriptMockSetup mockSetup;
private CacheMacro cacheMacro;
private PrintRendererFactory rendererFactory;
@Override
protected void registerComponents() throws Exception
{
super.registerComponents();
this.mockSetup = new ScriptMockSetup(getMockery(), getComponentManager());
this.cacheMacro = getComponentManager().getInstance(Macro.class, "cache");
this.rendererFactory = getComponentManager().getInstance(PrintRendererFactory.class, "event/1.0");
}
@Test
public void executeWhenNoIdAndSameContent() throws Exception
{
String expected = "beginDocument\n"
+ "beginMacroMarkerStandalone [velocity] [] [$var]\n"
+ "beginParagraph\n"
+ "onWord [content]\n"
+ "endParagraph\n"
+ "endMacroMarkerStandalone [velocity] [] [$var]\n"
+ "endDocument";
CacheMacroParameters params = new CacheMacroParameters();
MacroTransformationContext context = createMacroTransformationContext();
VelocityManager velocityManager = getComponentManager().getInstance(VelocityManager.class);
StringWriter writer = new StringWriter();
velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
"#set ($var = 'content')");
List<Block> result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
assertBlocks(expected, result, this.rendererFactory);
// Execute a second time with a different value for the velocity $var variable to ensure the returned result
// is the cached one.
velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
"#set ($var = 'newcontent')");
result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
assertBlocks(expected, result, this.rendererFactory);
}
@Test
public void executeWhenNoIdAndDifferentContent() throws Exception
{
String expected1 = "beginDocument\n"
+ "beginMacroMarkerStandalone [velocity] [] [$var]\n"
+ "beginParagraph\n"
+ "onWord [content]\n"
+ "endParagraph\n"
+ "endMacroMarkerStandalone [velocity] [] [$var]\n"
+ "endDocument";
String expected2 = "beginDocument\n"
+ "beginMacroMarkerStandalone [velocity] [] [$var##]\n"
+ "beginParagraph\n"
+ "onWord [newcontent]\n"
+ "endParagraph\n"
+ "endMacroMarkerStandalone [velocity] [] [$var##]\n"
+ "endDocument";
CacheMacroParameters params = new CacheMacroParameters();
MacroTransformationContext context = createMacroTransformationContext();
VelocityManager velocityManager = getComponentManager().getInstance(VelocityManager.class);
StringWriter writer = new StringWriter();
velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
"#set ($var = 'content')");
List<Block> result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
assertBlocks(expected1, result, this.rendererFactory);
// Execute a second time with a different cache macro content to ensure it's not cached
velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
"#set ($var = 'newcontent')");
result = this.cacheMacro.execute(params, "{{velocity}}$var##{{/velocity}}", context);
assertBlocks(expected2, result, this.rendererFactory);
}
@Test
public void executeWhenSameIdAndDifferentContent() throws Exception
{
String expected = "beginDocument\n"
+ "beginMacroMarkerStandalone [velocity] [] [$var]\n"
+ "beginParagraph\n"
+ "onWord [content]\n"
+ "endParagraph\n"
+ "endMacroMarkerStandalone [velocity] [] [$var]\n"
+ "endDocument";
CacheMacroParameters params = new CacheMacroParameters();
params.setId("uniqueid");
MacroTransformationContext context = createMacroTransformationContext();
VelocityManager velocityManager = getComponentManager().getInstance(VelocityManager.class);
StringWriter writer = new StringWriter();
velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
"#set ($var = 'content')");
List<Block> result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
assertBlocks(expected, result, this.rendererFactory);
// Execute a second time with a different content but with the same id, to ensure the returned result
// is the cached one.
result = this.cacheMacro.execute(params, "whatever here...", context);
assertBlocks(expected, result, this.rendererFactory);
}
@Test
public void executeWithIdGeneratedByVelocityMacro() throws Exception
{
VelocityManager velocityManager = getComponentManager().getInstance(VelocityManager.class);
StringWriter writer = new StringWriter();
velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
"#set ($var = 'generatedid')");
CacheMacroParameters params = new CacheMacroParameters();
params.setId("{{velocity}}$var{{/velocity}}");
MacroTransformationContext context = createMacroTransformationContext();
List<Block> result1 = this.cacheMacro.execute(params, "whatever", context);
// Execute a second time with the same id (specified explicitly this time) and ensures that the returned result
// is the same even the cache macro content is different.
params.setId("generatedid");
List<Block> result2 = this.cacheMacro.execute(params, "something else", context);
assertEquals(result1, result2);
}
@Test
public void executeWithDifferentTimeToLive() throws Exception
{
CacheMacroParameters params = new CacheMacroParameters();
MacroTransformationContext context = createMacroTransformationContext();
params.setId("id");
params.setMaxEntries(10);
params.setTimeToLive(100);
List<Block> result1 = this.cacheMacro.execute(params, "content1", context);
// Execute a second time with different content but with different time to live param. This means another
// cache will be used and thus the first cached content won't be returned.
params.setTimeToLive(200);
List<Block> result2 = this.cacheMacro.execute(params, "content2", context);
assertFalse(result2.equals(result1));
}
@Test
public void executeWithDifferentMaxEntries() throws Exception
{
CacheMacroParameters params = new CacheMacroParameters();
MacroTransformationContext context = createMacroTransformationContext();
params.setId("id");
params.setMaxEntries(10);
params.setTimeToLive(100);
List<Block> result1 = this.cacheMacro.execute(params, "content1", context);
// Execute a second time with different content but with different time to live param. This means another
// cache will be used and thus the first cached content won't be returned.
params.setMaxEntries(11);
List<Block> result2 = this.cacheMacro.execute(params, "content2", context);
assertFalse(result2.equals(result1));
}
private MacroTransformationContext createMacroTransformationContext() throws Exception
{
MacroTransformation macroTransformation = getComponentManager().getInstance(Transformation.class, "macro");
MacroTransformationContext context = new MacroTransformationContext();
context.setTransformation(macroTransformation);
context.setSyntax(Syntax.XWIKI_2_0);
return context;
}
}