diff --git a/core/src/main/java/org/apache/struts2/components/Component.java b/core/src/main/java/org/apache/struts2/components/Component.java index 748285b76..4d5c84560 100644 --- a/core/src/main/java/org/apache/struts2/components/Component.java +++ b/core/src/main/java/org/apache/struts2/components/Component.java @@ -72,6 +72,7 @@ public class Component { protected Map parameters; protected ActionMapper actionMapper; protected boolean throwExceptionOnELFailure; + protected boolean performClearTagStateForTagPoolingServers = false; private UrlHelper urlHelper; private NotExcludedAcceptedPatternsChecker notExcludedAcceptedPatterns; @@ -568,6 +569,27 @@ public class Component { return standardAttributes; } + /** + * Request that the tag state be cleared during {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport#doEndTag()} processing, + * which may help with certain edge cases with tag logic running on servers that implement JSP Tag Pooling. + * + * Note: All Tag classes that extend {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport} must implement a setter for + * this attribute (same name), and it must be defined at the Tag class level. + * Defining a setter in the superclass alone is insufficient (results in "Cannot find a setter method for the attribute"). + * + * See {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport#clearTagStateForTagPoolingServers() for additional details. + * + * @param performClearTagStateForTagPoolingServers true if tag state should be cleared, false otherwise. + */ + @StrutsTagAttribute(description="Whether to clear all tag state during doEndTag() processing (if applicable)", type="Boolean", defaultValue="false", required = false) + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + this.performClearTagStateForTagPoolingServers = performClearTagStateForTagPoolingServers; + } + + public boolean getPerformClearTagStateForTagPoolingServers() { + return this.performClearTagStateForTagPoolingServers; + } + /** * Checks if expression doesn't contain vulnerable code * diff --git a/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java b/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java index 5ccc9d64a..1d6981bb1 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/PrepareOperations.java @@ -251,4 +251,15 @@ public class PrepareOperations { return devModeOverride.get(); } + /** + * Clear any override of the static devMode value being applied to the current thread. + * + * This can be useful for any situation where {@link #overrideDevMode(boolean)} might be called + * in a flow where {@link #cleanupRequest(javax.servlet.http.HttpServletRequest)} does not get called. + * May be very situational (such as some unit tests), but may have other utility as well. + */ + public static void clearDevModeOverride() { + devModeOverride.remove(); // Remove current thread's value, enxure next read returns it to initialValue (typically null). + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ActionTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ActionTag.java index 948808bb1..7478a1258 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ActionTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ActionTag.java @@ -39,10 +39,12 @@ public class ActionTag extends ContextBeanTag { protected boolean flush = true; protected boolean rethrowException; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new ActionComponent(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -88,4 +90,26 @@ public class ActionTag extends ContextBeanTag { this.rethrowException = rethrowException; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + this.namespace = null; + this.executeResult = false; + this.ignoreContextParams = false; + this.flush = true; + this.rethrowException = false; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/BeanTag.java b/core/src/main/java/org/apache/struts2/views/jsp/BeanTag.java index 7b2c3a587..363078be3 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/BeanTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/BeanTag.java @@ -39,10 +39,12 @@ public class BeanTag extends ContextBeanTag { protected String name; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Bean(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -52,4 +54,22 @@ public class BeanTag extends ContextBeanTag { public void setName(String name) { this.name = name; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java b/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java index 9dd463cb6..73bba2ea6 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java @@ -35,12 +35,15 @@ public abstract class ComponentTagSupport extends StrutsBodyTagSupport { public abstract Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res); + @Override public int doEndTag() throws JspException { component.end(pageContext.getOut(), getBody()); - component = null; + component = null; // Always clear component reference (since clearTagStateForTagPoolingServers() is conditional). + clearTagStateForTagPoolingServers(); return EVAL_PAGE; } + @Override public int doStartTag() throws JspException { ValueStack stack = getStack(); component = getBean(stack, (HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse()); @@ -57,10 +60,39 @@ public abstract class ComponentTagSupport extends StrutsBodyTagSupport { } } + /** + * Define method to populate component state based on the Tag parameters. + * + * Descendants should override this method for custom behaviour, but should always call the ancestor method when doing so. + */ protected void populateParams() { + populatePerformClearTagStateForTagPoolingServersParam(); + } + + /** + * Specialized method to populate the performClearTagStateForTagPoolingServers state of the Component to match the value set in the Tag. + * + * Generally only unit tests would call this method directly, to avoid calling the whole populateParams() chain again after doStartTag() + * has been called. Doing that can break tag / component state behaviour, but unit tests still need a way to set the + * performClearTagStateForTagPoolingServers state for the component (which only comes into being after doStartTag() is called). + */ + protected void populatePerformClearTagStateForTagPoolingServersParam() { + if (component != null) { + component.setPerformClearTagStateForTagPoolingServers(super.getPerformClearTagStateForTagPoolingServers()); + } } public Component getComponent() { return component; } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + component = null; // Duplicate clear, kept for consistency. + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ContextBeanTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ContextBeanTag.java index 470fae5e0..bfebf6cf7 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ContextBeanTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ContextBeanTag.java @@ -24,6 +24,7 @@ import org.apache.struts2.components.ContextBean; public abstract class ContextBeanTag extends ComponentTagSupport { private String var; + @Override protected void populateParams() { super.populateParams(); @@ -34,4 +35,22 @@ public abstract class ContextBeanTag extends ComponentTagSupport { public void setVar(String var) { this.var = var; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.var = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/DateTag.java b/core/src/main/java/org/apache/struts2/views/jsp/DateTag.java index 73b62f1a7..70681cf98 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/DateTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/DateTag.java @@ -37,10 +37,12 @@ public class DateTag extends ContextBeanTag { protected boolean nice; protected String timezone; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Date(stack); } + @Override protected void populateParams() { super.populateParams(); Date d = (Date)component; @@ -66,4 +68,24 @@ public class DateTag extends ContextBeanTag { this.timezone = timezone; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + this.format = null; + this.nice = false; + this.timezone = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ElseIfTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ElseIfTag.java index 999f8c6ca..659a6cd23 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ElseIfTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ElseIfTag.java @@ -35,15 +35,36 @@ public class ElseIfTag extends ComponentTagSupport { protected String test; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new ElseIf(stack); } + @Override protected void populateParams() { + super.populateParams(); ((ElseIf) getComponent()).setTest(test); } public void setTest(String test) { this.test = test; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.test = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ElseTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ElseTag.java index f15bab78b..343105a83 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ElseTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ElseTag.java @@ -33,7 +33,16 @@ public class ElseTag extends ComponentTagSupport { private static final long serialVersionUID = 8166807953193406785L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Else(stack); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/I18nTag.java b/core/src/main/java/org/apache/struts2/views/jsp/I18nTag.java index de1a1ee16..14b46b7fc 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/I18nTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/I18nTag.java @@ -35,10 +35,12 @@ public class I18nTag extends ComponentTagSupport { protected String name; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new I18n(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -48,4 +50,22 @@ public class I18nTag extends ComponentTagSupport { public void setName(String name) { this.name = name; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/IfTag.java b/core/src/main/java/org/apache/struts2/views/jsp/IfTag.java index 4f4e56eff..7621656c2 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/IfTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/IfTag.java @@ -35,15 +35,36 @@ public class IfTag extends ComponentTagSupport { String test; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new If(stack); } + @Override protected void populateParams() { + super.populateParams(); ((If) getComponent()).setTest(test); } public void setTest(String test) { this.test = test; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.test = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/IncludeTag.java b/core/src/main/java/org/apache/struts2/views/jsp/IncludeTag.java index 1b811bbac..6ebee945a 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/IncludeTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/IncludeTag.java @@ -35,10 +35,12 @@ public class IncludeTag extends ComponentTagSupport { protected String value; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Include(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -48,4 +50,22 @@ public class IncludeTag extends ComponentTagSupport { public void setValue(String value) { this.value = value; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.value = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/IteratorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/IteratorTag.java index 397257ea2..f85875c32 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/IteratorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/IteratorTag.java @@ -39,10 +39,12 @@ public class IteratorTag extends ContextBeanTag { protected String end; protected String step; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new IteratorComponent(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -74,11 +76,14 @@ public class IteratorTag extends ContextBeanTag { this.step = step; } + @Override public int doEndTag() throws JspException { component = null; + clearTagStateForTagPoolingServers(); return EVAL_PAGE; } + @Override public int doAfterBody() throws JspException { boolean again = component.end(pageContext.getOut(), getBody()); @@ -96,4 +101,25 @@ public class IteratorTag extends ContextBeanTag { } } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.statusAttr = null; + this.value = null; + this.begin = null; + this.end = null; + this.step = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/NumberTag.java b/core/src/main/java/org/apache/struts2/views/jsp/NumberTag.java index a74f2aa27..45262c63c 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/NumberTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/NumberTag.java @@ -43,10 +43,12 @@ public class NumberTag extends ContextBeanTag { private Boolean parseIntegerOnly; private String roundingMode; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Number(stack); } + @Override protected void populateParams() { super.populateParams(); Number n = (Number) component; @@ -133,4 +135,30 @@ public class NumberTag extends ContextBeanTag { this.roundingMode = roundingMode; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + this.currency = null; + this.type = null; + this.groupingUsed = null; + this.maximumFractionDigits = null; + this.maximumIntegerDigits = null; + this.minimumFractionDigits = null; + this.minimumIntegerDigits = null; + this.parseIntegerOnly = null; + this.roundingMode = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ParamTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ParamTag.java index 3f1fe6015..019059367 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ParamTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ParamTag.java @@ -36,10 +36,12 @@ public class ParamTag extends ComponentTagSupport { protected String value; protected boolean suppressEmptyParameters; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Param(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -60,4 +62,24 @@ public class ParamTag extends ComponentTagSupport { public void setSuppressEmptyParameters(boolean suppressEmptyParameters) { this.suppressEmptyParameters = suppressEmptyParameters; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + this.value = null; + this.suppressEmptyParameters = false; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/PropertyTag.java b/core/src/main/java/org/apache/struts2/views/jsp/PropertyTag.java index 12abe6bbb..7db42fcf8 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/PropertyTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/PropertyTag.java @@ -40,10 +40,12 @@ public class PropertyTag extends ComponentTagSupport { private boolean escapeXml = false; private boolean escapeCsv = false; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Property(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -83,4 +85,27 @@ public class PropertyTag extends ComponentTagSupport { public void setEscapeXml(boolean escapeXml) { this.escapeXml = escapeXml; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.defaultValue = null; + this.value = null; + this.escapeHtml = true; + this.escapeJavaScript = false; + this.escapeXml = false; + this.escapeCsv = false; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/PushTag.java b/core/src/main/java/org/apache/struts2/views/jsp/PushTag.java index 1a48b767d..f6d647dd3 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/PushTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/PushTag.java @@ -35,10 +35,12 @@ public class PushTag extends ComponentTagSupport { protected String value; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Push(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -48,4 +50,22 @@ public class PushTag extends ComponentTagSupport { public void setValue(String value) { this.value = value; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.value = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/SetTag.java b/core/src/main/java/org/apache/struts2/views/jsp/SetTag.java index 581720300..c76f41cb0 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/SetTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/SetTag.java @@ -37,10 +37,12 @@ public class SetTag extends ContextBeanTag { protected String value; protected boolean trimBody = true; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Set(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -77,4 +79,24 @@ public class SetTag extends ContextBeanTag { return (bodyContent == null ? null : bodyContent.getString()); } } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.scope = null; + this.value = null; + this.trimBody = true; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/StrutsBodyTagSupport.java b/core/src/main/java/org/apache/struts2/views/jsp/StrutsBodyTagSupport.java index 2a89b0e11..2bccb3a25 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/StrutsBodyTagSupport.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/StrutsBodyTagSupport.java @@ -20,11 +20,12 @@ package org.apache.struts2.views.jsp; import com.opensymphony.xwork2.util.TextParseUtil; import com.opensymphony.xwork2.util.ValueStack; +import java.io.PrintWriter; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTagSupport; import org.apache.struts2.util.ComponentUtils; import org.apache.struts2.util.FastByteArrayOutputStream; -import javax.servlet.jsp.tagext.BodyTagSupport; -import java.io.PrintWriter; /** * Contains common functonalities for Struts JSP Tags. @@ -33,6 +34,8 @@ public class StrutsBodyTagSupport extends BodyTagSupport { private static final long serialVersionUID = -1201668454354226175L; + private boolean performClearTagStateForTagPoolingServers = false; + protected ValueStack getStack() { return TagUtils.getStack(pageContext); } @@ -72,4 +75,97 @@ public class StrutsBodyTagSupport extends BodyTagSupport { return bodyContent.getString().trim(); } } + + @Override + public int doEndTag() throws JspException { + clearTagStateForTagPoolingServers(); + return super.doEndTag(); + } + + /** + * Release state for a Struts JSP Tag handler. + * + * According to the JSP API documentation, the page compiler guarantees that the release() method + * will be invoked on the Tag handler before releasing it to the GC (garbage collector). It does + * not specify when the release() call will be made, though, and timing likely depends + * on the implementation of the JSP/servlet engine being used. + */ + @Override + public void release() { + // Ensure release() performs the clearTagStateForTagPoolingServers tag state clearing processing with + // the clear state flag forced to true (if not already set to true), to ensure cleanup. + // The performClearTagStateForTagPoolingServers flag state is preserved for consistency, in case + // release() is called by framework code. + final boolean originalPerformClearTagState = getPerformClearTagStateForTagPoolingServers(); + if (originalPerformClearTagState == true) { + clearTagStateForTagPoolingServers(); + } else { + setPerformClearTagStateForTagPoolingServers(true); + clearTagStateForTagPoolingServers(); + setPerformClearTagStateForTagPoolingServers(originalPerformClearTagState); + } + super.release(); + } + + /** + * Request that the tag state be cleared during {@link StrutsBodyTagSupport#doEndTag()} processing, + * which may help with certain edge cases with tag logic running on servers that implement JSP Tag Pooling. + * + * Note: Even though the Tag classes extend this class {@link StrutsBodyTagSupport}, and this method + * {@link StrutsBodyTagSupport#setPerformClearTagStateForTagPoolingServers(boolean)} exists in the method hierarchy, + * the JSP processing requires us to explicitly override it in every Tag class in order for the Tag handler + * method to be visible to the JSP processing. + * Defining a setter in the superclass alone is insufficient (results in "Cannot find a setter method for the attribute"). + * + * See {@link StrutsBodyTagSupport#clearTagStateForTagPoolingServers()} for additional details. + * + * Warning: Setting this value to true may allow for the desired behaviour, but doing so + * may violate the JSP specification. Set to true at your own risk. + * + * @param performClearTagStateForTagPoolingServers true if tag state should be cleared, false otherwise. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + this.performClearTagStateForTagPoolingServers = performClearTagStateForTagPoolingServers; + } + + /** + * Allow descendant tags to check if the tag state should be cleared during {@link StrutsBodyTagSupport#doEndTag()} processing, + * + * @return true if tag state should be cleared, false (default) otherwise. + */ + protected boolean getPerformClearTagStateForTagPoolingServers() { + return this.performClearTagStateForTagPoolingServers; + } + + /** + * Provide a mechanism to clear tag state, to handle servlet container JSP tag pooling + * behaviour with some servers, such as Glassfish. + * + * Usage: Override this method in descendant classes to clear any state that might cause issues should the + * servlet container re-use a cached instance of the tag object. If the descendant class does not + * declare any new field members then it should not be strictly necessary to call this method there. + * Typically that means calling the ancestor's {@link ComponentTagSupport#clearTagStateForTagPoolingServers()} + * method first, then resetting instance variables at the current level to their default state. + * + * Note: If the descendant overrides {@link StrutsBodyTagSupport#doEndTag()}, and does not call + * super.doEndTag(), then the descendant should call this method in the descendant doEndTag() method + * to ensure consistent clearing of tag state. + */ + protected void clearTagStateForTagPoolingServers() { + // Default implementation. + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + this.setBodyContent(null); // Always clear the tag body (if any) after tag completion. + this.setId(null); // Always clear the tag id (if any) after tag completion. + // Note: The pageContext and parent Tag state are NOT cleared, only the "user-defined" tag state should be cleared. + // Calling setPageContext(null) and setParent(null) appears too dangerous to consider, and the container + // should always set them, even if a tag instance from a pool is re-used. Also, clearing those two + // values likely violates the JSP specification. + // Note: We intentionally do NOT reset performClearTagStateForTagPoolingServers to false here, for two reasons. + // Firstly, if a tag pool re-uses the instance, in order to qualify/match the tag parameters should be + // the same, including performClearTagStateForTagPoolingServers. Secondly, if we change the state of + // the control flag during clearing, it makes unit testing virtually impossible. + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java b/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java index 8f93ad61f..812c81baa 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java @@ -39,10 +39,12 @@ public class TextTag extends ContextBeanTag { private boolean escapeXml = false; private boolean escapeCsv = false; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Text(stack); } + @Override protected void populateParams() { super.populateParams(); @@ -74,4 +76,25 @@ public class TextTag extends ContextBeanTag { this.escapeCsv = escapeCsv; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.name = null; + this.escapeHtml = false; + this.escapeJavaScript = false; + this.escapeXml = false; + this.escapeCsv = false; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java b/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java index baf632340..445777a49 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java @@ -48,10 +48,12 @@ public class URLTag extends ContextBeanTag { protected String anchor; protected String forceAddSchemeHostAndPort; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new URL(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -136,4 +138,35 @@ public class URLTag extends ContextBeanTag { public void setForceAddSchemeHostAndPort(String forceAddSchemeHostAndPort) { this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.includeParams = null; + this.scheme = null; + this.value = null; + this.action = null; + this.namespace = null; + this.method = null; + this.encode = null; + this.includeContext = null; + this.escapeAmp = null; + this.portletMode = null; + this.windowState = null; + this.portletUrlType = null; + this.anchor = null; + this.forceAddSchemeHostAndPort = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/iterator/AppendIteratorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/iterator/AppendIteratorTag.java index e3f754da8..1ea16506d 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/iterator/AppendIteratorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/iterator/AppendIteratorTag.java @@ -37,8 +37,16 @@ public class AppendIteratorTag extends ContextBeanTag { private static final long serialVersionUID = -6017337859763283691L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new AppendIterator(stack); } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/iterator/IteratorGeneratorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/iterator/IteratorGeneratorTag.java index 6255ea98a..f3af5f628 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/iterator/IteratorGeneratorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/iterator/IteratorGeneratorTag.java @@ -176,6 +176,13 @@ public class IteratorGeneratorTag extends StrutsBodyTagSupport { this.var = var; } + @StrutsTagAttribute(description="Whether to clear all tag state during doEndTag() processing", type="Boolean", defaultValue="false", required = false) + @Override + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override public int doStartTag() throws JspException { // value @@ -230,11 +237,27 @@ public class IteratorGeneratorTag extends StrutsBodyTagSupport { return EVAL_BODY_INCLUDE; } + @Override public int doEndTag() throws JspException { // pop resulting iterator from stack at end tag getStack().pop(); iteratorGenerator = null; // clean up + clearTagStateForTagPoolingServers(); // Clean-up, including iteratorGenerator reference. return EVAL_PAGE; } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.countAttr = null; + this.separatorAttr = null; + this.valueAttr = null; + this.converterAttr = null; + this.var = null; + this.iteratorGenerator = null; + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/iterator/MergeIteratorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/iterator/MergeIteratorTag.java index 3cd7fa4f8..839030ca4 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/iterator/MergeIteratorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/iterator/MergeIteratorTag.java @@ -38,8 +38,17 @@ public class MergeIteratorTag extends ContextBeanTag { private static final long serialVersionUID = 4999729472466011218L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new MergeIterator(stack); } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/iterator/SortIteratorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/iterator/SortIteratorTag.java index a268b7fcf..32e13924f 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/iterator/SortIteratorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/iterator/SortIteratorTag.java @@ -110,6 +110,13 @@ public class SortIteratorTag extends StrutsBodyTagSupport { this.var = var; } + @StrutsTagAttribute(description="Whether to clear all tag state during doEndTag() processing", type="Boolean", defaultValue="false", required = false) + @Override + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override public int doStartTag() throws JspException { // Source Object srcToSort; @@ -144,13 +151,28 @@ public class SortIteratorTag extends StrutsBodyTagSupport { return EVAL_BODY_INCLUDE; } + @Override public int doEndTag() throws JspException { int returnVal = super.doEndTag(); // pop sorted list from stack at the end of tag getStack().pop(); sortIteratorFilter = null; + // The super.doEndTag() above should ensure clearTagStateForTagPoolingServers() is called correctly, + // which should clean-up the sortIteratorFilter reference. return returnVal; } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.comparatorAttr = null; + this.sourceAttr = null; + this.var = null; + this.sortIteratorFilter = null; + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/iterator/SubsetIteratorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/iterator/SubsetIteratorTag.java index b1b6dc592..f269a945d 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/iterator/SubsetIteratorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/iterator/SubsetIteratorTag.java @@ -193,6 +193,13 @@ public class SubsetIteratorTag extends StrutsBodyTagSupport { this.var = var; } + @StrutsTagAttribute(description="Whether to clear all tag state during doEndTag() processing", type="Boolean", defaultValue="false", required = false) + @Override + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override public int doStartTag() throws JspException { // source @@ -272,12 +279,27 @@ public class SubsetIteratorTag extends StrutsBodyTagSupport { return EVAL_BODY_INCLUDE; } + @Override public int doEndTag() throws JspException { - + // pop resulting subset iterator from stack at end tag getStack().pop(); - subsetIteratorFilter = null; + clearTagStateForTagPoolingServers(); // Clean-up, including subsetIteratorFilter reference. return EVAL_PAGE; } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.countAttr = null; + this.sourceAttr = null; + this.startAttr = null; + this.deciderAttr = null; + this.var = null; + this.subsetIteratorFilter = null; + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractClosingTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractClosingTag.java index 8fc0834eb..e7949db8a 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractClosingTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractClosingTag.java @@ -23,6 +23,7 @@ import org.apache.struts2.components.ClosingUIBean; public abstract class AbstractClosingTag extends AbstractUITag { protected String openTemplate; + @Override protected void populateParams() { super.populateParams(); @@ -32,4 +33,22 @@ public abstract class AbstractClosingTag extends AbstractUITag { public void setOpenTemplate(String openTemplate) { this.openTemplate = openTemplate; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.openTemplate = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractDoubleListTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractDoubleListTag.java index 83bbdb7f0..efa9db18b 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractDoubleListTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractDoubleListTag.java @@ -66,6 +66,7 @@ public abstract class AbstractDoubleListTag extends AbstractRequiredListTag { protected String doubleAccesskey; + @Override protected void populateParams() { super.populateParams(); @@ -382,4 +383,59 @@ public abstract class AbstractDoubleListTag extends AbstractRequiredListTag { public void setDoubleAccesskey(String doubleAccesskey) { this.doubleAccesskey = doubleAccesskey; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.doubleList = null; + this.doubleListKey = null; + this.doubleListValue = null; + this.doubleListCssClass = null; + this.doubleListCssStyle = null; + this.doubleListTitle = null; + this.doubleName = null; + this.doubleValue = null; + this.formName = null; + this.emptyOption = null; + this.headerKey = null; + this.headerValue = null; + this.multiple = null; + this.size = null; + this.doubleId = null; + this.doubleDisabled = null; + this.doubleMultiple = null; + this.doubleSize = null; + this.doubleHeaderKey = null; + this.doubleHeaderValue = null; + this.doubleEmptyOption = null; + this.doubleCssClass = null; + this.doubleCssStyle = null; + this.doubleOnclick = null; + this.doubleOndblclick = null; + this.doubleOnmousedown = null; + this.doubleOnmouseup = null; + this.doubleOnmouseover = null; + this.doubleOnmousemove = null; + this.doubleOnmouseout = null; + this.doubleOnfocus = null; + this.doubleOnblur = null; + this.doubleOnkeypress = null; + this.doubleOnkeydown = null; + this.doubleOnkeyup = null; + this.doubleOnselect = null; + this.doubleOnchange = null; + this.doubleAccesskey = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractListTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractListTag.java index b357bcbba..a781fd997 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractListTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractListTag.java @@ -30,6 +30,7 @@ public abstract class AbstractListTag extends AbstractUITag { protected String listCssStyle; protected String listTitle; + @Override protected void populateParams() { super.populateParams(); @@ -75,4 +76,29 @@ public abstract class AbstractListTag extends AbstractUITag { public void setListTitle(String listTitle) { this.listTitle = listTitle; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.list = null; + this.listKey = null; + this.listValue = null; + this.listValueKey = null; + this.listLabelKey = null; + this.listCssClass = null; + this.listCssStyle = null; + this.listTitle = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractRequiredListTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractRequiredListTag.java index fd6bb84e1..c407297e0 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractRequiredListTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractRequiredListTag.java @@ -22,6 +22,7 @@ import org.apache.struts2.components.ListUIBean; public abstract class AbstractRequiredListTag extends AbstractListTag { + @Override protected void populateParams() { super.populateParams(); @@ -29,4 +30,11 @@ public abstract class AbstractRequiredListTag extends AbstractListTag { listUIBean.setThrowExceptionOnNullValueAttribute(true); } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java index 6c4323805..345d37254 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java @@ -78,6 +78,7 @@ public abstract class AbstractUITag extends ComponentTagSupport implements Dynam // dynamic attributes. protected Map dynamicAttributes = new HashMap<>(); + @Override protected void populateParams() { super.populateParams(); @@ -127,6 +128,7 @@ public abstract class AbstractUITag extends ComponentTagSupport implements Dynam uiBean.setDynamicAttributes(dynamicAttributes); } + @Override public void setId(String id) { this.id = id; } @@ -312,8 +314,67 @@ public abstract class AbstractUITag extends ComponentTagSupport implements Dynam this.labelSeparator = labelSeparator; } + @Override public void setDynamicAttribute(String uri, String localName, Object value) throws JspException { dynamicAttributes.put(localName, String.valueOf(value)); } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.cssClass = null; + this.cssErrorClass = null; + this.cssStyle = null; + this.cssErrorStyle = null; + this.title = null; + this.disabled = null; + this.label = null; + this.labelSeparator = null; + this.labelPosition = null; + this.requiredPosition = null; + this.errorPosition = null; + this.name = null; + this.requiredLabel = null; + this.tabindex = null; + this.value = null; + this.template = null; + this.theme = null; + this.templateDir = null; + this.onclick = null; + this.ondblclick = null; + this.onmousedown = null; + this.onmouseup = null; + this.onmouseover = null; + this.onmousemove = null; + this.onmouseout = null; + this.onfocus = null; + this.onblur = null; + this.onkeypress = null; + this.onkeydown = null; + this.onkeyup = null; + this.onselect = null; + this.onchange = null; + this.accesskey = null; + this.id = null; + this.key = null; + this.tooltip = null; + this.tooltipConfig = null; + this.javascriptTooltip = null; + this.tooltipDelay = null; + this.tooltipCssClass = null; + this.tooltipIconPath = null; + this.dynamicAttributes.clear(); + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionErrorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionErrorTag.java index e1b7ef63b..02f564c54 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionErrorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionErrorTag.java @@ -36,10 +36,12 @@ public class ActionErrorTag extends AbstractUITag { private boolean escape = true; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new ActionError(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -50,4 +52,22 @@ public class ActionErrorTag extends AbstractUITag { public void setEscape(boolean escape) { this.escape = escape; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.escape = true; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionMessageTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionMessageTag.java index 439f9550e..4ce77bc6c 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionMessageTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionMessageTag.java @@ -23,7 +23,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.struts2.components.ActionMessage; import org.apache.struts2.components.Component; -import org.apache.struts2.components.ActionError; import com.opensymphony.xwork2.util.ValueStack; @@ -37,10 +36,12 @@ public class ActionMessageTag extends AbstractUITag { private boolean escape = true; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new ActionMessage(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -51,4 +52,22 @@ public class ActionMessageTag extends AbstractUITag { public void setEscape(boolean escape) { this.escape = escape; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.escape = true; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AnchorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AnchorTag.java index d3645c169..4f334ada0 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AnchorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AnchorTag.java @@ -49,10 +49,12 @@ public class AnchorTag extends AbstractClosingTag { protected String forceAddSchemeHostAndPort; protected boolean escapeHtmlBody = true; // Default - escape HTML body + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Anchor(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -120,6 +122,7 @@ public class AnchorTag extends AbstractClosingTag { this.scheme = scheme; } + @Override public void setValue(String value) { this.value = value; } @@ -154,6 +157,36 @@ public class AnchorTag extends AbstractClosingTag { public void setEscapeHtmlBody(boolean escapeHtmlBody) { this.escapeHtmlBody = escapeHtmlBody; } + + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + @Override + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.href = null; + this.includeParams = null; + this.scheme = null; + this.action = null; + this.namespace = null; + this.method = null; + this.encode = null; + this.includeContext = null; + this.escapeAmp = null; + this.portletMode = null; + this.windowState = null; + this.portletUrlType = null; + this.anchor = null; + this.forceAddSchemeHostAndPort = null; + } + } - diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxListTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxListTag.java index 40a6ac2f5..2e63b3c62 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxListTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxListTag.java @@ -33,7 +33,16 @@ public class CheckboxListTag extends AbstractRequiredListTag { private static final long serialVersionUID = 4023034029558150010L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new CheckboxList(stack, req, res); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxTag.java index 5cfa22fbc..242aa033b 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxTag.java @@ -35,10 +35,12 @@ public class CheckboxTag extends AbstractUITag { protected String fieldValue; protected String submitUnchecked; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Checkbox(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -53,4 +55,22 @@ public class CheckboxTag extends AbstractUITag { public void setSubmitUnchecked(String aValue) { this.submitUnchecked = aValue; } + + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + @Override + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.fieldValue = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/ComboBoxTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/ComboBoxTag.java index 877ff03e4..29c03a276 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/ComboBoxTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/ComboBoxTag.java @@ -60,10 +60,12 @@ public class ComboBoxTag extends TextFieldTag { this.listValue = listValue; } + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new ComboBox(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -78,4 +80,27 @@ public class ComboBoxTag extends TextFieldTag { public void setList(String list) { this.list = list; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.list = null; + this.listKey = null; + this.listValue = null; + this.headerKey = null; + this.headerValue = null; + this.emptyOption = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/ComponentTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/ComponentTag.java index efbd813ad..48a62d457 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/ComponentTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/ComponentTag.java @@ -33,7 +33,16 @@ public class ComponentTag extends AbstractUITag { private static final long serialVersionUID = 5448365363044104731L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new GenericUIBean(stack, req, res); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/DateTextFieldTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/DateTextFieldTag.java index b4d190757..768864065 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/DateTextFieldTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/DateTextFieldTag.java @@ -35,10 +35,12 @@ public class DateTextFieldTag extends AbstractUITag { protected String format; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new DateTextField(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -46,8 +48,25 @@ public class DateTextFieldTag extends AbstractUITag { textField.setFormat(format); } - public void setFormat(String format) { - this.format = format; - } + public void setFormat(String format) { + this.format = format; + } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.format = null; + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/DebugTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/DebugTag.java index f2a5d0965..c96d53096 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/DebugTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/DebugTag.java @@ -30,8 +30,16 @@ public class DebugTag extends AbstractUITag { private static final long serialVersionUID = 3487684841317160628L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Debug(stack, req, res); } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/DoubleSelectTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/DoubleSelectTag.java index 1241a67d8..ee430c9e5 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/DoubleSelectTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/DoubleSelectTag.java @@ -33,10 +33,12 @@ public class DoubleSelectTag extends AbstractDoubleListTag { private static final long serialVersionUID = 7426011596359509386L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new DoubleSelect(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -48,4 +50,12 @@ public class DoubleSelectTag extends AbstractDoubleListTag { doubleSelect.setSize(size); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/FieldErrorTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/FieldErrorTag.java index b5a834484..1d7a6e363 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/FieldErrorTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/FieldErrorTag.java @@ -37,10 +37,12 @@ public class FieldErrorTag extends AbstractUITag { protected boolean escape = true; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new FieldError(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -56,5 +58,23 @@ public class FieldErrorTag extends AbstractUITag { public void setEscape(boolean escape) { this.escape = escape; } -} + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.fieldName = null; + this.escape = true; + } + +} diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/FileTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/FileTag.java index bbee234e8..ef5171d0d 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/FileTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/FileTag.java @@ -36,10 +36,12 @@ public class FileTag extends AbstractUITag { protected String accept; protected String size; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new File(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -55,4 +57,23 @@ public class FileTag extends AbstractUITag { public void setSize(String size) { this.size = size; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.accept = null; + this.size = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/FormTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/FormTag.java index b7ded8d9c..e765bb569 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/FormTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/FormTag.java @@ -47,10 +47,12 @@ public class FormTag extends AbstractClosingTag { protected String focusElement; protected boolean includeContext = true; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Form(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); Form form = ((Form) component); @@ -121,4 +123,34 @@ public class FormTag extends AbstractClosingTag { public void setIncludeContext(boolean includeContext) { this.includeContext = includeContext; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.action = null; + this.target = null; + this.enctype = null; + this.method = null; + this.namespace = null; + this.validate = null; + this.onsubmit = null; + this.onreset = null; + this.portletMode = null; + this.windowState = null; + this.acceptcharset = null; + this.focusElement = null; + this.includeContext = true; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/HeadTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/HeadTag.java index 49a3b8fa2..b5a457eed 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/HeadTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/HeadTag.java @@ -33,7 +33,16 @@ public class HeadTag extends AbstractUITag { private static final long serialVersionUID = 6876765769175246030L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Head(stack, req, res); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/HiddenTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/HiddenTag.java index 7b8b39618..65f7e49d1 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/HiddenTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/HiddenTag.java @@ -33,7 +33,16 @@ public class HiddenTag extends AbstractUITag { private static final long serialVersionUID = -1124367972048371675L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Hidden(stack, req, res); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java index da8cb2da1..4dbf0070d 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java @@ -53,10 +53,12 @@ public class InputTransferSelectTag extends AbstractListTag { protected String headerKey; protected String headerValue; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new InputTransferSelect(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -200,4 +202,36 @@ public class InputTransferSelectTag extends AbstractListTag { public void setHeaderValue(String headerValue) { this.headerValue = headerValue; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.size = null; + this.multiple = null; + this.allowRemoveAll = null; + this.allowUpDown = null; + this.leftTitle = null; + this.rightTitle = null; + this.buttonCssClass = null; + this.buttonCssStyle = null; + this.addLabel = null; + this.removeLabel = null; + this.removeAllLabel = null; + this.upLabel = null; + this.downLabel = null; + this.headerKey = null; + this.headerValue = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/LabelTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/LabelTag.java index 19611a0fe..b62e50d61 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/LabelTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/LabelTag.java @@ -35,10 +35,12 @@ public class LabelTag extends AbstractUITag { protected String forAttr; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Label(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -48,4 +50,22 @@ public class LabelTag extends AbstractUITag { public void setFor(String aFor) { this.forAttr = aFor; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.forAttr = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/OptGroupTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/OptGroupTag.java index bd90ff5a3..83b6a9de5 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/OptGroupTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/OptGroupTag.java @@ -40,10 +40,12 @@ public class OptGroupTag extends ComponentTagSupport { protected String listCssStyle; protected String listTitle; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new OptGroup(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -89,4 +91,29 @@ public class OptGroupTag extends ComponentTagSupport { public void setListTitle(String listTitle) { this.listTitle = listTitle; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.list = null; + this.label = null; + this.disabled = null; + this.listKey = null; + this.listValue = null; + this.listCssClass = null; + this.listCssStyle = null; + this.listTitle = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTag.java index 73aabc38b..7ad259974 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTag.java @@ -66,10 +66,12 @@ public class OptionTransferSelectTag extends AbstractDoubleListTag { protected String upDownOnRightOnclick; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new OptionTransferSelect(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -342,4 +344,48 @@ public class OptionTransferSelectTag extends AbstractDoubleListTag { public String getSelectAllOnclick() { return this.selectAllOnclick; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.allowAddToLeft = null; + this.allowAddToRight = null; + this.allowAddAllToLeft = null; + this.allowAddAllToRight = null; + this.allowSelectAll = null; + this.allowUpDownOnLeft = null; + this.allowUpDownOnRight = null; + this.leftTitle = null; + this.rightTitle = null; + this.buttonCssClass = null; + this.buttonCssStyle = null; + this.addToLeftLabel = null; + this.addToRightLabel = null; + this.addAllToLeftLabel = null; + this.addAllToRightLabel = null; + this.selectAllLabel = null; + this.leftUpLabel = null; + this.leftDownLabel = null; + this.rightUpLabel = null; + this.rightDownLabel = null; + this.addToLeftOnclick = null; + this.addToRightOnclick = null; + this.addAllToLeftOnclick = null; + this.addAllToRightOnclick = null; + this.selectAllOnclick = null; + this.upDownOnLeftOnclick = null; + this.upDownOnRightOnclick = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/PasswordTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/PasswordTag.java index cf3f73d90..8732135fb 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/PasswordTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/PasswordTag.java @@ -35,10 +35,12 @@ public class PasswordTag extends TextFieldTag { protected String showPassword; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Password(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -52,4 +54,22 @@ public class PasswordTag extends TextFieldTag { public void setShowPassword(String showPassword) { this.showPassword = showPassword; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.showPassword = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/RadioTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/RadioTag.java index 96602979c..a5f4ab1ac 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/RadioTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/RadioTag.java @@ -33,7 +33,16 @@ public class RadioTag extends AbstractRequiredListTag { private static final long serialVersionUID = -6497403399521333624L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Radio(stack, req, res); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/ResetTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/ResetTag.java index 339b0ec08..e623eef7b 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/ResetTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/ResetTag.java @@ -37,10 +37,12 @@ public class ResetTag extends AbstractUITag { protected String type; protected String src; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Reset(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -67,4 +69,24 @@ public class ResetTag extends AbstractUITag { this.src = src; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.action = null; + this.method = null; + this.type = null; + this.src = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/SelectTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/SelectTag.java index cbd71e67e..7659f53a2 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/SelectTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/SelectTag.java @@ -39,10 +39,12 @@ public class SelectTag extends AbstractRequiredListTag { protected String multiple; protected String size; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Select(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -74,4 +76,25 @@ public class SelectTag extends AbstractRequiredListTag { this.size = size; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.emptyOption = null; + this.headerKey = null; + this.headerValue = null; + this.multiple = null; + this.size = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/SubmitTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/SubmitTag.java index a86571051..5250cbe62 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/SubmitTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/SubmitTag.java @@ -39,10 +39,12 @@ public class SubmitTag extends AbstractClosingTag { protected String src; protected boolean escapeHtmlBody = true; // Default - escape HTML body + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Submit(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -84,4 +86,25 @@ public class SubmitTag extends AbstractClosingTag { public void setEscapeHtmlBody(boolean escapeHtmlBody) { this.escapeHtmlBody = escapeHtmlBody; } + + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + @Override + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.action = null; + this.method = null; + this.type = null; + this.src = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/TextFieldTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/TextFieldTag.java index 4f7d2de09..a3325a454 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/TextFieldTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/TextFieldTag.java @@ -37,10 +37,12 @@ public class TextFieldTag extends AbstractUITag { protected String size; protected String type; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new TextField(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -66,4 +68,25 @@ public class TextFieldTag extends AbstractUITag { public void setType(String type) { this.type = type; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.maxlength = null; + this.readonly = null; + this.size = null; + this.type = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/TextareaTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/TextareaTag.java index 0efbe0188..0da6fe8bf 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/TextareaTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/TextareaTag.java @@ -40,10 +40,12 @@ public class TextareaTag extends AbstractUITag { protected String maxlength; protected String minlength; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new TextArea(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -80,4 +82,24 @@ public class TextareaTag extends AbstractUITag { this.minlength = minlength; } + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.cols = null; + this.readonly = null; + this.rows = null; + this.wrap = null; + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/TokenTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/TokenTag.java index 1f9468269..806116c79 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/TokenTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/TokenTag.java @@ -33,7 +33,17 @@ public class TokenTag extends AbstractUITag { private static final long serialVersionUID = 722480798151703457L; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new Token(stack, req, res); } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + } diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/UpDownSelectTag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/UpDownSelectTag.java index 925a6223c..4713c5cf1 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/UpDownSelectTag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/UpDownSelectTag.java @@ -42,10 +42,12 @@ public class UpDownSelectTag extends SelectTag { protected String selectAllLabel; + @Override public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { return new UpDownSelect(stack, req, res); } + @Override protected void populateParams() { super.populateParams(); @@ -118,4 +120,27 @@ public class UpDownSelectTag extends SelectTag { public void setSelectAllLabel(String selectAllLabel) { this.selectAllLabel = selectAllLabel; } + + @Override + /** + * Must declare the setter at the descendant Tag class level in order for the tag handler to locate the method. + */ + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + super.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + } + + @Override + protected void clearTagStateForTagPoolingServers() { + if (getPerformClearTagStateForTagPoolingServers() == false) { + return; // If flag is false (default setting), do not perform any state clearing. + } + super.clearTagStateForTagPoolingServers(); + this.allowMoveUp = null; + this.allowMoveDown = null; + this.allowSelectAll = null; + this.moveUpLabel = null; + this.moveDownLabel = null; + this.selectAllLabel = null; + } + } diff --git a/core/src/test/java/org/apache/struts2/StrutsInternalTestCase.java b/core/src/test/java/org/apache/struts2/StrutsInternalTestCase.java index dfc2dc3a4..30616303f 100644 --- a/core/src/test/java/org/apache/struts2/StrutsInternalTestCase.java +++ b/core/src/test/java/org/apache/struts2/StrutsInternalTestCase.java @@ -19,12 +19,11 @@ package org.apache.struts2; import com.opensymphony.xwork2.XWorkTestCase; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.PrepareOperations; import org.apache.struts2.util.StrutsTestCaseHelper; import org.apache.struts2.views.jsp.StrutsMockServletContext; - -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -39,9 +38,13 @@ public abstract class StrutsInternalTestCase extends XWorkTestCase { /** * Sets up the configuration settings, XWork configuration, and * message resources + * + * @throws java.lang.Exception */ + @Override protected void setUp() throws Exception { super.setUp(); + PrepareOperations.clearDevModeOverride(); // Clear DevMode override every time (consistent ThreadLocal state for tests). initDispatcher(null); } @@ -68,6 +71,7 @@ public abstract class StrutsInternalTestCase extends XWorkTestCase { return initDispatcher(params); } + @Override protected void tearDown() throws Exception { super.tearDown(); // maybe someone else already destroyed Dispatcher @@ -78,4 +82,26 @@ public abstract class StrutsInternalTestCase extends XWorkTestCase { StrutsTestCaseHelper.tearDown(); } + /** + * Compare if two objects are considered equal according to their fields as accessed + * via reflection. + * + * Utilizes {@link EqualsBuilder#reflectionEquals(java.lang.Object, java.lang.Object, boolean)} to perform + * the check, and compares transient fields as well. This may fail when run while a security manager is + * active, due to a need to user reflection. + * + * + * @param obj1 the first {@link Object} to compare against the other. + * @param obj2 the second {@link Object} to compare against the other. + * @return true if the objects are equal based on field comparisons by reflection, false otherwise. + */ + protected boolean objectsAreReflectionEqual(Object obj1, Object obj2) { + boolean result = false; + if (obj1 == obj2) { + result = true; + } else if (obj1 != null && obj2 != null) { + result = EqualsBuilder.reflectionEquals(obj1, obj2, true); + } + return result; + } } diff --git a/core/src/test/java/org/apache/struts2/components/ComponentTest.java b/core/src/test/java/org/apache/struts2/components/ComponentTest.java index 722f6be04..0bc098265 100644 --- a/core/src/test/java/org/apache/struts2/components/ComponentTest.java +++ b/core/src/test/java/org/apache/struts2/components/ComponentTest.java @@ -42,7 +42,8 @@ import org.apache.struts2.views.jsp.iterator.MergeIteratorTag; import org.apache.struts2.views.jsp.ui.TextFieldTag; import org.apache.struts2.views.jsp.ui.UpDownSelectTag; -import com.opensymphony.xwork2.ActionContext; +import java.util.HashMap; +import org.apache.struts2.StrutsException; /** * Test case for method findAncestor(Class) in Component and some commons @@ -542,4 +543,52 @@ public class ComponentTest extends AbstractTagTest { submit.setEscapeHtmlBody(true); assertTrue("Submit htmlEscapeBody not true after set true ?", submit.escapeHtmlBody()); } + + /** + * Attempt some code coverage tests for {@link Component} that can be achieved without + * too much difficulty. + * + * @throws Exception + */ + public void testComponent_coverageTest() throws Exception { + HashMap propertyMap = new HashMap<>(); + Exception exception = new Exception("Generic exception"); + Property property = new Property(stack); + ActionComponent actionComponent = new ActionComponent(stack, request, response); + + try { + actionComponent.setName("componentName"); + // Simulate component attribute with a hyphen in its name. + propertyMap.put("hyphen-keyname-for-coverage", "hyphen-keyname-for-coverage-value"); + propertyMap.put("someKeyName", "someKeyValue"); + actionComponent.copyParams(propertyMap); + actionComponent.addAllParameters(propertyMap); + try { + actionComponent.findString(null, "fieldName", "errorMessage"); + fail("null expr parameter should cause a StrutsException"); + } catch (StrutsException se) { + // expected + } + assertNull("completeExpression of a null expression returned non-null result ?", actionComponent.completeExpression(null)); + try { + actionComponent.findValue(null, "fieldName", "errorMessage"); + fail("null expr parameter should cause a StrutsException"); + } catch (StrutsException se) { + // expected + } + try { + actionComponent.findValue("", "fieldName", "errorMessage"); + fail("empty expr parameter should cause a StrutsException due to finding a null value"); + } catch (StrutsException se) { + // expected + } + assertNotNull("the toString() method with Exception parameter returned null result ?", actionComponent.toString(exception)); + assertFalse("Initial performClearTagStateForTagPoolingServers not false ?", actionComponent.getPerformClearTagStateForTagPoolingServers()); + actionComponent.setPerformClearTagStateForTagPoolingServers(true); + assertTrue("performClearTagStateForTagPoolingServers false after setting to true ?", actionComponent.getPerformClearTagStateForTagPoolingServers()); + } + finally { + property.getComponentStack().pop(); + } + } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java index f31ccc40c..c22f90404 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java @@ -27,6 +27,7 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspWriter; +import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.TestAction; @@ -74,6 +75,7 @@ public abstract class AbstractTagTest extends StrutsInternalTestCase { return new TestAction(); } + @Override protected void setUp() throws Exception { super.setUp(); createMocks(); @@ -129,6 +131,7 @@ public abstract class AbstractTagTest extends StrutsInternalTestCase { .bind(); } + @Override protected void tearDown() throws Exception { super.tearDown(); pageContext.verify(); @@ -144,4 +147,44 @@ public abstract class AbstractTagTest extends StrutsInternalTestCase { servletContext = null; mockContainer = null; } + + /** + * Compare if two component tags are considered equal according to their fields as accessed + * via reflection. + * + * Utilizes {@link EqualsBuilder#reflectionEquals(java.lang.Object, java.lang.Object, boolean)} to perform + * the check, and compares transient fields as well. This may fail when run while a security manager is + * active, due to a need to user reflection. + * + * This method may be useful for checking if the state of a tag is what is expected after a given set of operations, + * or after clearing state such as for calls involving {@link StrutsBodyTagSupport#clearTagStateForTagPoolingServers()} + * has taken place following {@link StrutsBodyTagSupport#doEndTag()} processing. When making comparisons, keep in mind the + * pageContext and parent Tag state are not cleared by clearTagStateForTagPoolingServers(). + * + * @param tag1 the first {@link StrutsBodyTagSupport} to compare against the other. + * @param tag2 the second {@link StrutsBodyTagSupport} to compare against the other. + * @return true if the Tags are equal based on field comparisons by reflection, false otherwise. + */ + protected boolean strutsBodyTagsAreReflectionEqual(StrutsBodyTagSupport tag1, StrutsBodyTagSupport tag2) { + return objectsAreReflectionEqual(tag1, tag2); + } + + /** + * Helper method to simplify setting the performClearTagStateForTagPoolingServers state for a + * {@link ComponentTagSupport} tag's {@link Component} to match expectations for the test. + * + * The component reference is not available to the tag until after the doStartTag() method is called. + * We need to ensure the component's {@link Component#performClearTagStateForTagPoolingServers} state matches + * what we set for the Tag when a non-default (true) value is used, so this method accesses the component instance, + * sets the value specified and forces the tag's parameters to be repopulated again. + * + * @param tag The ComponentTagSupport tag upon whose component we will set the performClearTagStateForTagPoolingServers state. + * @param performClearTagStateForTagPoolingServers true to clear tag state, false otherwise + */ + protected void setComponentTagClearTagState(ComponentTagSupport tag, boolean performClearTagStateForTagPoolingServers) { + tag.component.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + //tag.populateParams(); // Not safe to call after doStartTag() ... breaks some tests. + tag.populatePerformClearTagStateForTagPoolingServersParam(); // Only populate the performClearTagStateForTagPoolingServers parameter for the Tag. + } + } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java index 895639019..dc35e3646 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java @@ -66,6 +66,47 @@ public class ActionTagTest extends AbstractTagTest { ex.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionTagWithNamespace_clearTagStateSet() { + request.setupGetServletPath(TestConfigurationProvider.TEST_NAMESPACE + "/" + "foo.action"); + + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName(TestConfigurationProvider.TEST_NAMESPACE_ACTION); + tag.setVar(TestConfigurationProvider.TEST_NAMESPACE_ACTION); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ActionComponent ac = ((ActionComponent) tag.component); + tag.doEndTag(); + ActionProxy proxy = ac.getProxy(); + + Object o = pageContext.findAttribute(TestConfigurationProvider.TEST_NAMESPACE_ACTION); + assertTrue(o instanceof TestAction); + + assertEquals(TestConfigurationProvider.TEST_NAMESPACE, proxy.getNamespace()); + } catch (JspException ex) { + ex.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimple() { @@ -98,6 +139,57 @@ public class ActionTagTest extends AbstractTagTest { ex.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + } + + public void testSimple_clearTagStateSet() { + request.setupGetServletPath("/foo.action"); + + ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", "testAction"); + container.inject(config.getInterceptors().get(0).getInterceptor()); + + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("testAction"); + tag.setVar("testAction"); + + int stackSize = stack.size(); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.addParameter("foo", "myFoo"); + tag.doEndTag(); + + assertEquals(stack.size(), ActionContext.getContext().getValueStack().size()); + assertEquals("myFoo", stack.findValue("#testAction.foo")); + assertEquals(stackSize, stack.size()); + + Object o = pageContext.findAttribute("testAction"); + assertTrue(o instanceof TestAction); + assertEquals("myFoo", ((TestAction) o).getFoo()); + assertEquals(Action.SUCCESS, ((TestAction) o).getResult()); + } catch (JspException ex) { + ex.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testSimpleWithoutServletActionContext() { @@ -136,6 +228,57 @@ public class ActionTagTest extends AbstractTagTest { ex.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + } + + public void testSimpleWithctionMethodInOriginalURI_clearTagStateSet() { + request.setupGetServletPath("/foo!foo.action"); + + ActionConfig config = configuration.getRuntimeConfiguration().getActionConfig("", "testAction"); + container.inject(config.getInterceptors().get(0).getInterceptor()); + + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("testAction"); + tag.setVar("testAction"); + + int stackSize = stack.size(); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.addParameter("foo", "myFoo"); + tag.doEndTag(); + + assertEquals(stack.size(), ActionContext.getContext().getValueStack().size()); + assertEquals("myFoo", stack.findValue("#testAction.foo")); + assertEquals(stackSize, stack.size()); + + Object o = pageContext.findAttribute("testAction"); + assertTrue(o instanceof TestAction); + assertEquals("myFoo", ((TestAction) o).getFoo()); + assertEquals(Action.SUCCESS, ((TestAction) o).getResult()); + } catch (JspException ex) { + ex.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testActionWithExecuteResult() throws Exception { @@ -157,6 +300,46 @@ public class ActionTagTest extends AbstractTagTest { assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT)); assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT) instanceof PageContext); assertTrue(result.isExecuted()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + } + + public void testActionWithExecuteResult_clearTagStateSet() throws Exception { + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("testActionTagAction"); + tag.setExecuteResult(true); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // tag clear components on doEndTag + ActionComponent component = (ActionComponent) tag.getComponent(); + + tag.doEndTag(); + + TestActionTagResult result = (TestActionTagResult) component.getProxy().getInvocation().getResult(); + + assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT)); + assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT)instanceof PageContext); + assertTrue(result.isExecuted()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testActionWithoutExecuteResult() throws Exception { @@ -178,6 +361,44 @@ public class ActionTagTest extends AbstractTagTest { assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT)); assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT) instanceof PageContext); assertNull(result); // result is never executed, hence never set into invocation + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionWithoutExecuteResult_clearTagStateSet() throws Exception { + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("testActionTagAction"); + tag.setExecuteResult(false); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // tag clear components on doEndTag, so we need to get it here + ActionComponent component = (ActionComponent) tag.getComponent(); + + tag.doEndTag(); + + TestActionTagResult result = (TestActionTagResult) component.getProxy().getInvocation().getResult(); + + assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT)); + assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT)instanceof PageContext); + assertNull(result); // result is never executed, hence never set into invocation + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testExecuteButResetReturnSameInvocation() throws Exception { @@ -199,6 +420,45 @@ public class ActionTagTest extends AbstractTagTest { tag.doEndTag(); assertSame(oldInvocation, ActionContext.getContext().getActionInvocation()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + } + + public void testExecuteButResetReturnSameInvocation_clearTagStateSet() throws Exception { + Mock mockActionInv = new Mock(ActionInvocation.class); + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("testActionTagAction"); + tag.setExecuteResult(true); + ActionContext.getContext().setActionInvocation((ActionInvocation) mockActionInv.proxy()); + + ActionInvocation oldInvocation = ActionContext.getContext().getActionInvocation(); + assertNotNull(oldInvocation); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // tag clear components on doEndTag + ActionComponent component = (ActionComponent) tag.getComponent(); + + tag.doEndTag(); + assertTrue(oldInvocation == ActionContext.getContext().getActionInvocation()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIngoreContextParamsFalse() throws Exception { @@ -224,6 +484,50 @@ public class ActionTagTest extends AbstractTagTest { ActionInvocation ai = component.getProxy().getInvocation(); ActionContext ac = ai.getInvocationContext(); assertEquals(1, ac.getParameters().keySet().size()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + } + + public void testIngoreContextParamsFalse_clearTagStateSet() throws Exception { + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("testActionTagAction"); + tag.setExecuteResult(false); + tag.setIgnoreContextParams(false); + + Map params = new HashMap<>(); + params.put("user", new String[]{"Santa Claus"}); + ActionContext.getContext().setParameters(HttpParameters.create(params).build()); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // tag clear components on doEndTag, so we need to get it here + ActionComponent component = (ActionComponent) tag.getComponent(); + + tag.doEndTag(); + + // check parameters, there should be one + ActionInvocation ai = component.getProxy().getInvocation(); + ActionContext ac = ai.getInvocationContext(); + assertEquals(1, ac.getParameters().keySet().size()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testIngoreContextParamsTrue() throws Exception { @@ -249,6 +553,48 @@ public class ActionTagTest extends AbstractTagTest { ActionInvocation ai = component.getProxy().getInvocation(); ActionContext ac = ai.getInvocationContext(); assertEquals(0, ac.getParameters().keySet().size()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIngoreContextParamsTrue_clearTagStateSet() throws Exception { + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("testActionTagAction"); + tag.setExecuteResult(false); + tag.setIgnoreContextParams(true); + + Map params = new HashMap<>(); + params.put("user", new String[] { "Santa Claus" }); + ActionContext.getContext().setParameters(HttpParameters.create(params).build()); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // tag clear components on doEndTag, so we need to get it here + ActionComponent component = (ActionComponent) tag.getComponent(); + + tag.doEndTag(); + + // check parameters, there should be one + ActionInvocation ai = component.getProxy().getInvocation(); + ActionContext ac = ai.getInvocationContext(); + assertEquals(0, ac.getParameters().keySet().size()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoNameDefined() throws Exception { @@ -265,6 +611,8 @@ public class ActionTagTest extends AbstractTagTest { } catch (StrutsException e) { assertEquals("tag 'actioncomponent', field 'name': Action name is required. Example: updatePerson", e.getMessage()); } + + // The doEndTag() call is expected not to complete. Cannot perform basic sanity check of clearTagStateForTagPoolingServers() behaviour. } // FIXME: Logging the error seems to cause the standard Maven build to fail @@ -278,6 +626,36 @@ public class ActionTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); // will just log it to ERROR but we run the code to test that it works somehow + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + // FIXME: Logging the error seems to cause the standard Maven build to fail + public void testUnknownNameDefined_clearTagStateSet() throws Exception { + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("UNKNOWN_NAME"); + tag.setExecuteResult(false); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + // will just log it to ERROR but we run the code to test that it works somehow + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionMethodWithExecuteResult() throws Exception { @@ -300,8 +678,48 @@ public class ActionTagTest extends AbstractTagTest { assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT)); assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT) instanceof PageContext); assertTrue(result.isExecuted()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testActionMethodWithExecuteResult_clearTagStateSet() throws Exception { + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace(""); + tag.setName("testActionTagAction!input"); + tag.setExecuteResult(true); + ((DefaultActionMapper)container.getInstance(ActionMapper.class)).setAllowDynamicMethodCalls("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // tag clear components on doEndTag + ActionComponent component = (ActionComponent) tag.getComponent(); + + tag.doEndTag(); + + TestActionTagResult result = (TestActionTagResult) component.getProxy().getInvocation().getResult(); + + assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT)); + assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT)instanceof PageContext); + assertTrue(result.isExecuted()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override protected void setUp() throws Exception { super.setUp(); initDispatcher(new HashMap() {{ @@ -310,6 +728,7 @@ public class ActionTagTest extends AbstractTagTest { createMocks(); } + @Override protected void tearDown() throws Exception { super.tearDown(); } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java index acf5d3c65..7d0de563c 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java @@ -30,8 +30,6 @@ import javax.servlet.jsp.JspWriter; import org.apache.struts2.views.jsp.ui.AnchorTag; import org.apache.struts2.views.jsp.ui.StrutsBodyContent; -import org.apache.struts2.components.URL; -import org.apache.struts2.components.Anchor; /** @@ -51,6 +49,35 @@ public class AnchorTagTest extends AbstractUITagTest { ex.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionURL_clearTagStateSet() { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setHref("TestAction.action"); + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertTrue(writer.toString().indexOf("href=\"TestAction.action\"") > -1); + } catch (JspException ex) { + ex.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testAddParameters() { @@ -67,6 +94,39 @@ public class AnchorTagTest extends AbstractUITagTest { ex.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAddParameters_clearTagStateSet() { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setHref("/TestAction.action"); + String bodyText = ""; + try { + StrutsBodyContent bodyContent = new StrutsBodyContent(null); + bodyContent.print(bodyText); + tag.setBodyContent(bodyContent); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + } catch (Exception ex) { + ex.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -147,6 +207,106 @@ public class AnchorTagTest extends AbstractUITagTest { assertEquals(wrapWithAnchor("testAction.action?id1=paramId1&id2=tagId2&" + "amp;tagId=tagValue&urlParam1=urlValue1&urlParam2=urlValue2&param1=param1value&param2=param2value"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * To test priority of parameter passed in to url component though + * various way + * - current request url + * - tag's value attribute + * - tag's nested param tag + *
+ * id1 + * === + * - found in current request url + * - found in tag's value attribute + * - found in tag's param tag + * CONCLUSION: tag's param tag takes precedence (paramId1) + *
+ * id2 + * === + * - found in current request url + * - found in tag's value attribute + * CONCLUSION: tag's value attribute take precedence (tagId2) + *
+ * urlParam1 + * ========= + * - found in current request url + * CONCLUSION: param in current request url will be used (urlValue1) + *
+ * urlParam2 + * ========= + * - found in current request url + * CONCLUSION: param in current request url will be used. (urlValue2) + *
+ * tagId + * ===== + * - found in tag's value attribute + * CONCLUSION: param in tag's value attribute wil; be used. (tagValue) + *
+ * param1 + * ====== + * - found in nested param tag + * CONCLUSION: param in nested param tag will be used. (param1value) + *
+ * param2 + * ====== + * - found in nested param tag + * CONCLUSION: param in nested param tag will be used. (param2value) + */ + public void testParametersPriority_clearTagStateSet() throws Exception { + request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue"); + + ParamTag param1 = new ParamTag(); + param1.setPageContext(pageContext); + param1.setName("param1"); + param1.setValue("%{'param1value'}"); + + ParamTag param2 = new ParamTag(); + param2.setPageContext(pageContext); + param2.setName("param2"); + param2.setValue("%{'param2value'}"); + + ParamTag param3 = new ParamTag(); + param3.setPageContext(pageContext); + param3.setName("id1"); + param3.setValue("%{'paramId1'}"); + + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + param3.doStartTag(); + setComponentTagClearTagState(param3, true); // Ensure component tag state clearing is set true (to match tag). + param3.doEndTag(); + + tag.doEndTag(); + + assertEquals(wrapWithAnchor("testAction.action?id1=paramId1&id2=tagId2&" + + "amp;tagId=tagValue&urlParam1=urlValue1&urlParam2=urlValue2&param1=param1value&param2=param2value"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -171,6 +331,12 @@ public class AnchorTagTest extends AbstractUITagTest { param1.doStartTag(); param1.doEndTag(); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); //String[] stack.getContext().put("param2value", new String[]{"d", "e"}); @@ -181,6 +347,10 @@ public class AnchorTagTest extends AbstractUITagTest { param2.doStartTag(); param2.doEndTag(); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); //ValueHolder[] stack.getContext().put("param3value", new URLTagTest.ValueHolder[]{ @@ -192,6 +362,11 @@ public class AnchorTagTest extends AbstractUITagTest { param3.doStartTag(); param3.doEndTag(); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + tag.doEndTag(); String result = writer.toString(); @@ -202,6 +377,100 @@ public class AnchorTagTest extends AbstractUITagTest { assertTrue(result.contains("p3=f")); assertTrue(result.contains("p3=g")); assertTrue(result.contains("p0=z")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * Use Iterable values as the value of the param tags + * + * @throws Exception + */ + public void testIterableParameters_clearTagStateSet() throws Exception { + tag.setValue("/TestAction.action?p0=z"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + //Iterable + List list = new ArrayList(); + list.add(new URLTagTest.ValueHolder("a")); + list.add(new URLTagTest.ValueHolder("b")); + stack.getContext().put("param1value", list); + + ParamTag param1 = new ParamTag(); + param1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param1.setPageContext(pageContext); + param1.setName("p1"); + param1.setValue("%{#param1value}"); + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + + //String[] + stack.getContext().put("param2value", new String[]{"d", "e"}); + ParamTag param2 = new ParamTag(); + param2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param2.setPageContext(pageContext); + param2.setName("p2"); + param2.setValue("%{#param2value}"); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + + //ValueHolder[] + stack.getContext().put("param3value", new URLTagTest.ValueHolder[]{ + new URLTagTest.ValueHolder("f"), new URLTagTest.ValueHolder("g")}); + ParamTag param3 = new ParamTag(); + param3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param3.setPageContext(pageContext); + param3.setName("p3"); + param3.setValue("%{#param3value}"); + param3.doStartTag(); + setComponentTagClearTagState(param3, true); // Ensure component tag state clearing is set true (to match tag). + param3.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + tag.doEndTag(); + + String result = writer.toString(); + assertTrue(result.contains("p1=a")); + assertTrue(result.contains("p1=b")); + assertTrue(result.contains("p2=d")); + assertTrue(result.contains("p2=e")); + assertTrue(result.contains("p3=f")); + assertTrue(result.contains("p3=g")); + assertTrue(result.contains("p0=z")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -253,6 +522,107 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("testAction.action?id1=paramId1&id2=tagId2&tagId=tagValue&param1=param1value&param2=param2value"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + *

+ * To test priority of parameter passed in to url component though + * various way, with includeParams="NONE" + *

+ * + * - current request url
+ * - tag's value attribute
+ * - tag's nested param tag
+ * + *

+ * In this case only parameters from the tag itself is taken into account. + * Those from request will not count, only those in tag's value attribute + * and nested param tag. + *

+ * @throws Exception + */ + public void testParametersPriorityWithIncludeParamsAsNONE_clearTagStateSet() throws Exception { + request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue"); + tag.setIncludeParams("NONE"); + + ParamTag param1 = new ParamTag(); + param1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param1.setPageContext(pageContext); + param1.setName("param1"); + param1.setValue("%{'param1value'}"); + + ParamTag param2 = new ParamTag(); + param2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param2.setPageContext(pageContext); + param2.setName("param2"); + param2.setValue("%{'param2value'}"); + + ParamTag param3 = new ParamTag(); + param3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param3.setPageContext(pageContext); + param3.setName("id1"); + param3.setValue("%{'paramId1'}"); + + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + param3.doStartTag(); + setComponentTagClearTagState(param3, true); // Ensure component tag state clearing is set true (to match tag). + param3.doEndTag(); + tag.doEndTag(); + + assertEquals(wrapWithAnchor("testAction.action?id1=paramId1&id2=tagId2&tagId=tagValue&param1=param1value&param2=param2value"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeParamsDefaultToGET() throws Exception { @@ -272,6 +642,42 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("TestAction.acton?one=oneVal&two=twoVal&three=threeVal"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeParamsDefaultToGET_clearTagStateSet() throws Exception { + request.setQueryString("one=oneVal&two=twoVal&three=threeVal"); + + // request parameter map should not have any effect, as includeParams + // default to GET, which get its param from request.getQueryString() + Map tmp = new HashMap(); + tmp.put("one", "aaa"); + tmp.put("two", "bbb"); + tmp.put("three", "ccc"); + request.setParameterMap(tmp); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("TestAction.acton"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("TestAction.acton?one=oneVal&two=twoVal&three=threeVal"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionURL2() throws Exception { @@ -306,7 +712,76 @@ public class AnchorTagTest extends AbstractUITagTest { assertTrue(result.contains("param0=value0")); assertTrue(result.contains("param1=value1")); assertTrue(result.contains("param2=value2")); - assertTrue(result.contains("/TestAction.action")); + assertTrue(result.contains("/TestAction.action")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "For this test, tag only has pageContext set, so it should still be equal.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAddParameters2_clearTagStateSet() throws Exception { + request.setAttribute("struts.request_uri", "/TestAction.action"); + request.setQueryString("param0=value0"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag param1 = new ParamTag(); + param1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param1.setPageContext(pageContext); + param1.setName("param1"); + param1.setValue("%{'value1'}"); + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + + ParamTag param2 = new ParamTag(); + param2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param2.setPageContext(pageContext); + param2.setName("param2"); + param2.setValue("%{'value2'}"); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + + tag.doEndTag(); + String result = writer.toString(); + assertTrue(result.contains("param0=value0")); + assertTrue(result.contains("param1=value1")); + assertTrue(result.contains("param2=value2")); + assertTrue(result.contains("/TestAction.action")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEvaluateValue() throws Exception { @@ -318,6 +793,34 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(wrapWithAnchor("test"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEvaluateValue_clearTagStateSet() throws Exception { + URLTagTest.Foo foo = new URLTagTest.Foo(); + foo.setTitle("test"); + stack.push(foo); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("%{title}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(wrapWithAnchor("test"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testHttps() throws Exception { @@ -330,6 +833,35 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(wrapWithAnchor("list-members.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testHttps_clearTagStateSet() throws Exception { + request.setScheme("https"); + request.setServerName("localhost"); + request.setServerPort(443); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("list-members.action"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(wrapWithAnchor("list-members.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testAnchor() throws Exception { @@ -343,6 +875,36 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(wrapWithAnchor("list-members.action#test"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAnchor_clearTagStateSet() throws Exception { + request.setScheme("https"); + request.setServerName("localhost"); + request.setServerPort(443); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("list-members.action"); + tag.setAnchor("test"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(wrapWithAnchor("list-members.action#test"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testParamPrecedence() throws Exception { @@ -365,6 +927,62 @@ public class AnchorTagTest extends AbstractUITagTest { anchor.doEndTag(); assertEquals(wrapWithAnchor("/context/someAction.action?id=33&name=John"), writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(anchor, freshTag)); + } + + public void testParamPrecedence_clearTagStateSet() throws Exception { + request.setRequestURI("/context/someAction.action"); + request.setQueryString("id=22&name=John"); + + AnchorTag anchor = new AnchorTag(); + anchor.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + anchor.setPageContext(pageContext); + anchor.setIncludeParams("get"); + anchor.setEncode("%{false}"); + + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("id"); + paramTag.setValue("%{'33'}"); + + anchor.doStartTag(); + setComponentTagClearTagState(anchor, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + anchor.doEndTag(); + + assertEquals(wrapWithAnchor("/context/someAction.action?id=33&name=John"), writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(anchor, freshTag)); } public void testParamPrecedenceWithAnchor() throws Exception { @@ -388,14 +1006,94 @@ public class AnchorTagTest extends AbstractUITagTest { anchorTag.doEndTag(); assertEquals(wrapWithAnchor("/context/someAction.action?id=33&name=John#testAnchor"), writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(anchorTag, freshTag)); } + public void testParamPrecedenceWithAnchor_clearTagStateSet() throws Exception { + request.setRequestURI("/context/someAction.action"); + request.setQueryString("id=22&name=John"); + + AnchorTag anchorTag = new AnchorTag(); + anchorTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + anchorTag.setPageContext(pageContext); + anchorTag.setIncludeParams("get"); + anchorTag.setEncode("%{false}"); + anchorTag.setAnchor("testAnchor"); + + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("id"); + paramTag.setValue("%{'33'}"); + + anchorTag.doStartTag(); + setComponentTagClearTagState(anchorTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + anchorTag.doEndTag(); + + assertEquals(wrapWithAnchor("/context/someAction.action?id=33&name=John#testAnchor"), writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(anchorTag, freshTag)); + } public void testUsingValueOnly() throws Exception { tag.setValue("/public/about/team.jsp"); tag.doStartTag(); tag.doEndTag(); assertEquals(wrapWithAnchor("/public/about/team.jsp"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testUsingValueOnly_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("/public/about/team.jsp"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(wrapWithAnchor("/public/about/team.jsp"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeNone() throws Exception { @@ -408,6 +1106,35 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/team.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeNone_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("none"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/team.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeGet() throws Exception { @@ -420,6 +1147,35 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/team.action?section=team&company=acme+inc"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeGet_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("get"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/team.action?section=team&company=acme+inc"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeGetDoNotEscapeAmp() throws Exception { @@ -433,6 +1189,36 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/team.action?section=team&company=acme+inc"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeGetDoNotEscapeAmp_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("get"); + tag.setEscapeAmp("false"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/team.action?section=team&company=acme+inc"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURINoActionIncludeNone() throws Exception { @@ -445,6 +1231,35 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/public/about"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURINoActionIncludeNone_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction(null); + tag.setIncludeParams("none"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/public/about"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoActionIncludeGet() throws Exception { @@ -457,6 +1272,35 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/public/about?section=team&company=acme+inc"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNoActionIncludeGet_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction(null); + tag.setIncludeParams("get"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/public/about?section=team&company=acme+inc"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeAll() throws Exception { @@ -483,6 +1327,66 @@ public class AnchorTagTest extends AbstractUITagTest { assertTrue(result.contains("section=team")); assertTrue(result.contains("company=acme+inc")); assertTrue(result.contains("year=2006")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeAll_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("all"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // include nested param tag + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("year"); + paramTag.setValue("2006"); + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + + tag.doEndTag(); + + String result = writer.toString(); + assertTrue(result.contains("/team.action?")); + assertTrue(result.contains("section=team")); + assertTrue(result.contains("company=acme+inc")); + assertTrue(result.contains("year=2006")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURINoActionIncludeAll() throws Exception { @@ -509,6 +1413,66 @@ public class AnchorTagTest extends AbstractUITagTest { assertTrue(result.contains("section=team")); assertTrue(result.contains("company=acme+inc")); assertTrue(result.contains("year=2006")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURINoActionIncludeAll_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction(null); + tag.setIncludeParams("all"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // include nested param tag + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("year"); + paramTag.setValue("2006"); + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + + tag.doEndTag(); + + String result = writer.toString(); + assertTrue(result.contains("/public/about?")); + assertTrue(result.contains("section=team")); + assertTrue(result.contains("company=acme+inc")); + assertTrue(result.contains("year=2006")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testUnknownIncludeParam() throws Exception { @@ -519,6 +1483,33 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(wrapWithAnchor("/public/about"), writer.toString()); // should not add any request parameters + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testUnknownIncludeParam_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setIncludeParams("unknown"); // will log at WARN level + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(wrapWithAnchor("/public/about"), writer.toString()); // should not add any request parameters + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIWithAnchor() throws Exception { @@ -531,6 +1522,35 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/company.action?company=acme+inc"), writer.toString()); // will always chop anchor if using requestURI + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIWithAnchor_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("company=acme inc#canada"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("company"); + tag.setIncludeParams("get"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/company.action?company=acme+inc"), writer.toString()); // will always chop anchor if using requestURI + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeContext() throws Exception { @@ -542,6 +1562,34 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("/myapp/company.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeContext_clearTagStateSet() throws Exception { + request.setupGetContext("/myapp"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setIncludeContext("true"); + tag.setAction("company"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("/myapp/company.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testForceAddSchemeHostAndPort() throws Exception { @@ -551,12 +1599,39 @@ public class AnchorTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(wrapWithAnchor("http://localhost/company.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testForceAddSchemeHostAndPort_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setForceAddSchemeHostAndPort("true"); + tag.setAction("company"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(wrapWithAnchor("http://localhost/company.action"), writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } private String wrapWithAnchor(String href) { return MessageFormat.format("", href); } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/AppendIteratorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/AppendIteratorTagTest.java index 64112c911..6adb42a82 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/AppendIteratorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/AppendIteratorTagTest.java @@ -82,6 +82,107 @@ public class AppendIteratorTagTest extends AbstractTagTest { assertTrue(appendedIterator.hasNext()); assertEquals(appendedIterator.next(), "C"); assertFalse(appendedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AppendIteratorTag freshTag = new AppendIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAppendingIteratorUsingArrayAsSource_clearTagStateSet() throws Exception { + AppendIteratorTag tag = new AppendIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVar("myAppendedIterator"); + + ParamTag iterator1ParamTag = new ParamTag(); + iterator1ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator1ParamTag.setPageContext(pageContext); + iterator1ParamTag.setValue("%{myArr1}"); + + ParamTag iterator2ParamTag = new ParamTag(); + iterator2ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator2ParamTag.setPageContext(pageContext); + iterator2ParamTag.setValue("%{myArr2}"); + + ParamTag iterator3ParamTag = new ParamTag(); + iterator3ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator3ParamTag.setPageContext(pageContext); + iterator3ParamTag.setValue("%{myArr3}"); + + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doStartTag(); + setComponentTagClearTagState(iterator1ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doEndTag(); + iterator2ParamTag.doStartTag(); + setComponentTagClearTagState(iterator2ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator2ParamTag.doEndTag(); + iterator3ParamTag.doStartTag(); + setComponentTagClearTagState(iterator3ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator3ParamTag.doEndTag(); + tag.doEndTag(); + + Iterator appendedIterator = (Iterator) stack.findValue("#myAppendedIterator"); + + assertNotNull(appendedIterator); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "1"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "2"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "3"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "a"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "b"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "c"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "A"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "B"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "C"); + assertFalse(appendedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AppendIteratorTag freshTag = new AppendIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testAppendingIteratorsUsingListAsSource() throws Exception { @@ -133,10 +234,110 @@ public class AppendIteratorTagTest extends AbstractTagTest { assertTrue(appendedIterator.hasNext()); assertEquals(appendedIterator.next(), "C"); assertFalse(appendedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AppendIteratorTag freshTag = new AppendIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testAppendingIteratorsUsingListAsSource_clearTagStateSet() throws Exception { + AppendIteratorTag tag = new AppendIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVar("myAppendedIterator"); + + ParamTag iterator1ParamTag = new ParamTag(); + iterator1ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator1ParamTag.setPageContext(pageContext); + iterator1ParamTag.setValue("%{myList1}"); + + ParamTag iterator2ParamTag = new ParamTag(); + iterator2ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator2ParamTag.setPageContext(pageContext); + iterator2ParamTag.setValue("%{myList2}"); + + ParamTag iterator3ParamTag = new ParamTag(); + iterator3ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator3ParamTag.setPageContext(pageContext); + iterator3ParamTag.setValue("%{myList3}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doStartTag(); + setComponentTagClearTagState(iterator1ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doEndTag(); + iterator2ParamTag.doStartTag(); + setComponentTagClearTagState(iterator2ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator2ParamTag.doEndTag(); + iterator3ParamTag.doStartTag(); + setComponentTagClearTagState(iterator3ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator3ParamTag.doEndTag(); + tag.doEndTag(); + + Iterator appendedIterator = (Iterator) stack.findValue("#myAppendedIterator"); + + assertNotNull(appendedIterator); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "1"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "2"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "3"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "a"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "b"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "c"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "A"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "B"); + assertTrue(appendedIterator.hasNext()); + assertEquals(appendedIterator.next(), "C"); + assertFalse(appendedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AppendIteratorTag freshTag = new AppendIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override public Action getAction() { return new ActionSupport() { public List getMyList1() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/BeanTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/BeanTagTest.java index 4b72ee03f..f6f9343f9 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/BeanTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/BeanTagTest.java @@ -53,6 +53,46 @@ public class BeanTagTest extends AbstractUITagTest { request.verify(); pageContext.verify(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + BeanTag freshTag = new BeanTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() { + BeanTag tag = new BeanTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("org.apache.struts2.TestAction"); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.component.addParameter("result", "success"); + + assertEquals("success", stack.findValue("result")); + // TestAction from bean tag, Action from execution and DefaultTextProvider + assertEquals(3, stack.size()); + tag.doEndTag(); + assertEquals(2, stack.size()); + } catch (JspException ex) { + ex.printStackTrace(); + fail(); + } + + request.verify(); + pageContext.verify(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + BeanTag freshTag = new BeanTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNotAccepted() throws Exception { @@ -108,4 +148,5 @@ public class BeanTagTest extends AbstractUITagTest { tag.doEndTag(); } + } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ElseIfTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ElseIfTagTest.java index 007cc82e6..487377f7d 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ElseIfTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ElseIfTagTest.java @@ -50,6 +50,36 @@ public class ElseIfTagTest extends StrutsInternalTestCase { tag.doEndTag(); assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testIfIsFalseElseIfIsTrue_clearTagStateSet() throws Exception { + stack.getContext().put(If.ANSWER, Boolean.FALSE); + + ElseIfTag tag = new ElseIfTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTest("true"); + + int result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testIfIsFalseElseIfIsFalse() throws Exception { @@ -63,6 +93,36 @@ public class ElseIfTagTest extends StrutsInternalTestCase { tag.doEndTag(); assertEquals(result, TagSupport.SKIP_BODY); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testIfIsFalseElseIfIsFalse_clearTagStateSet() throws Exception { + stack.getContext().put(If.ANSWER, Boolean.FALSE); + + ElseIfTag tag = new ElseIfTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTest("false"); + + int result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(result, TagSupport.SKIP_BODY); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testIfIsTrueElseIfIsTrue() throws Exception { @@ -76,6 +136,36 @@ public class ElseIfTagTest extends StrutsInternalTestCase { tag.doEndTag(); assertEquals(result, TagSupport.SKIP_BODY); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testIfIsTrueElseIfIsTrue_clearTagStateSet() throws Exception { + stack.getContext().put(If.ANSWER, Boolean.TRUE); + + ElseIfTag tag = new ElseIfTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTest("true"); + + int result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(result, TagSupport.SKIP_BODY); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testIfIsTrueElseIfIsFalse() throws Exception { @@ -89,9 +179,39 @@ public class ElseIfTagTest extends StrutsInternalTestCase { tag.doEndTag(); assertEquals(result, TagSupport.SKIP_BODY); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } + public void testIfIsTrueElseIfIsFalse_clearTagStateSet() throws Exception { + stack.getContext().put(If.ANSWER, Boolean.TRUE); + ElseIfTag tag = new ElseIfTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTest("false"); + + int result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(result, TagSupport.SKIP_BODY); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag = new ElseIfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + @Override protected void setUp() throws Exception { super.setUp(); stack = ActionContext.getContext().getValueStack(); @@ -111,5 +231,22 @@ public class ElseIfTagTest extends StrutsInternalTestCase { request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); } + /** + * Helper method to simplify setting the performClearTagStateForTagPoolingServers state for a + * {@link ComponentTagSupport} tag's {@link Component} to match expectations for the test. + * + * The component reference is not available to the tag until after the doStartTag() method is called. + * We need to ensure the component's {@link Component#performClearTagStateForTagPoolingServers} state matches + * what we set for the Tag when a non-default (true) value is used, so this method accesses the component instance, + * sets the value specified and forces the tag's parameters to be repopulated again. + * + * @param tag The ComponentTagSupport tag upon whose component we will set the performClearTagStateForTagPoolingServers state. + * @param performClearTagStateForTagPoolingServers true to clear tag state, false otherwise + */ + protected void setComponentTagClearTagState(ComponentTagSupport tag, boolean performClearTagStateForTagPoolingServers) { + tag.component.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + //tag.populateParams(); // Not safe to call after doStartTag() ... breaks some tests. + tag.populatePerformClearTagStateForTagPoolingServersParam(); // Only populate the performClearTagStateForTagPoolingServers parameter for the Tag. + } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ElseTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ElseTagTest.java index e39304ab2..4d7d7cfcb 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ElseTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ElseTagTest.java @@ -54,6 +54,40 @@ public class ElseTagTest extends StrutsInternalTestCase { fail(); } assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag = new ElseTag(); + freshTag.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag)); + } + + public void testTestFalse_clearTagStateSet() { + stack.getContext().put(If.ANSWER, new Boolean(false)); + + int result = 0; + + try { + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + result = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + elseTag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag = new ElseTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag)); } public void testTestNull() { @@ -63,12 +97,47 @@ public class ElseTagTest extends StrutsInternalTestCase { try { result = elseTag.doStartTag(); + elseTag.doEndTag(); } catch (JspException e) { e.printStackTrace(); fail(); } assertEquals(TagSupport.SKIP_BODY, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag = new ElseTag(); + freshTag.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag)); + } + + public void testTestNull_clearTagStateSet() { + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + + int result = 0; + + try { + result = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + elseTag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.SKIP_BODY, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag = new ElseTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag)); } public void testTestTrue() { @@ -79,14 +148,69 @@ public class ElseTagTest extends StrutsInternalTestCase { try { result = elseTag.doStartTag(); + elseTag.doEndTag(); } catch (JspException e) { e.printStackTrace(); fail(); } assertEquals(TagSupport.SKIP_BODY, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag = new ElseTag(); + freshTag.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag)); } + public void testTestTrue_clearTagStateSet() { + stack.getContext().put(If.ANSWER, new Boolean(true)); + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + + int result = 0; + + try { + result = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + elseTag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.SKIP_BODY, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag = new ElseTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag)); + } + + /** + * Helper method to simplify setting the performClearTagStateForTagPoolingServers state for a + * {@link ComponentTagSupport} tag's {@link Component} to match expecations for a test. + * + * Since the component is not available to the tag until after the doStartTag() method is called, + * but we need to ensure the component's {@link Component#performClearTagStateForTagPoolingServers} state matches + * what we set for the Tag when a non-default (true) value is used, this method retrieves the component instance, + * sets the value specified and forces the parameters to be repopulated again. + * + * @param tag The ComponentTagSupport tag upon whose component we will set the performClearTagStateForTagPoolingServers state. + * @param performClearTagStateForTagPoolingServers true to clear tag state, false otherwise + */ + protected void setComponentTagClearTagState(ComponentTagSupport tag, boolean performClearTagStateForTagPoolingServers) { + tag.component.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + //tag.populateParams(); // Not safe to call after doStartTag() ... breaks some tests. + tag.populatePerformClearTagStateForTagPoolingServersParam(); // Only populate the performClearTagStateForTagPoolingServers parameter for the Tag. + } + + @Override protected void setUp() throws Exception { super.setUp(); // create the needed objects diff --git a/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java index 6b5ac867a..46a5d4176 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java @@ -35,6 +35,7 @@ public class I18nTagTest extends StrutsInternalTestCase { MockPageContext pageContext; ValueStack stack; + @Override protected void setUp() throws Exception { super.setUp(); // create the needed objects @@ -76,6 +77,65 @@ public class I18nTagTest extends StrutsInternalTestCase { e.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + I18nTag freshTag = new I18nTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + // set the resource bundle + tag.setName("testmessages"); + + int result = 0; + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + I18nTag freshTag = new I18nTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + /** + * Helper method to simplify setting the performClearTagStateForTagPoolingServers state for a + * {@link ComponentTagSupport} tag's {@link Component} to match expecations for a test. + * + * Since the component is not available to the tag until after the doStartTag() method is called, + * but we need to ensure the component's {@link Component#performClearTagStateForTagPoolingServers} state matches + * what we set for the Tag when a non-default (true) value is used, this method retrieves the component instance, + * sets the value specified and forces the parameters to be repopulated again. + * + * @param tag The ComponentTagSupport tag upon whose component we will set the performClearTagStateForTagPoolingServers state. + * @param performClearTagStateForTagPoolingServers true to clear tag state, false otherwise + */ + protected void setComponentTagClearTagState(ComponentTagSupport tag, boolean performClearTagStateForTagPoolingServers) { + tag.component.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + //tag.populateParams(); // Not safe to call after doStartTag() ... breaks some tests. + tag.populatePerformClearTagStateForTagPoolingServersParam(); // Only populate the performClearTagStateForTagPoolingServers parameter for the Tag. } /** diff --git a/core/src/test/java/org/apache/struts2/views/jsp/IfTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/IfTagTest.java index 4537e9a58..29813f8d1 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/IfTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/IfTagTest.java @@ -65,6 +65,51 @@ public class IfTagTest extends StrutsInternalTestCase { e.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testNonBooleanTest_clearTagStateSet() { + // set up the stack + Foo foo = new Foo(); + foo.setNum(1); + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + // set up the test + tag.setTest("num"); + + int result = 0; + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testTestError() { @@ -93,6 +138,51 @@ public class IfTagTest extends StrutsInternalTestCase { e.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testTestError_clearTagStateSet() { + // set up the stack + Foo foo = new Foo(); + foo.setNum(2); + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + // set up the test + tag.setTest("nuuuuum == 2"); + + int result = 0; + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.SKIP_BODY, result); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testTestFalse() { @@ -121,6 +211,51 @@ public class IfTagTest extends StrutsInternalTestCase { e.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testTestFalse_clearTagStateSet() { + // set up the stack + Foo foo = new Foo(); + foo.setNum(2); + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + // set up the test + tag.setTest("num != 2"); + + int result = 0; + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.SKIP_BODY, result); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testTestTrue() { @@ -150,8 +285,53 @@ public class IfTagTest extends StrutsInternalTestCase { e.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } + public void testTestTrue_clearTagStateSet() { + // set up the stack + Foo foo = new Foo(); + foo.setNum(2); + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + // set up the test + tag.setTest("num == 2"); + + int result = 0; + //tag.setPageContext(pageContext); + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } public void testIfElse1() throws Exception { IfTag ifTag = new IfTag(); @@ -168,6 +348,58 @@ public class IfTagTest extends StrutsInternalTestCase { assertEquals(TagSupport.EVAL_BODY_INCLUDE, r1); assertEquals(TagSupport.SKIP_BODY, r2); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); + } + + public void testIfElse1_clearTagStateSet() throws Exception { + IfTag ifTag = new IfTag(); + ifTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + ifTag.setPageContext(pageContext); + ifTag.setTest("true"); + + ElseTag elseTag = new ElseTag(); + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + + int r1 = ifTag.doStartTag(); + setComponentTagClearTagState(ifTag, true); // Ensure component tag state clearing is set true (to match tag). + ifTag.doEndTag(); + int r2 = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + elseTag.doEndTag(); + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r1); + assertEquals(TagSupport.SKIP_BODY, r2); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPerformClearTagStateForTagPoolingServers(true); + freshTag2.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); } public void testIfElse2() throws Exception { @@ -185,6 +417,58 @@ public class IfTagTest extends StrutsInternalTestCase { assertEquals(TagSupport.SKIP_BODY, r1); assertEquals(TagSupport.EVAL_BODY_INCLUDE, r2); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); + } + + public void testIfElse2_clearTagStateSet() throws Exception { + IfTag ifTag = new IfTag(); + ifTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + ifTag.setPageContext(pageContext); + ifTag.setTest("false"); + + ElseTag elseTag = new ElseTag(); + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + + int r1 = ifTag.doStartTag(); + setComponentTagClearTagState(ifTag, true); // Ensure component tag state clearing is set true (to match tag). + ifTag.doEndTag(); + int r2 = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + elseTag.doEndTag(); + + assertEquals(TagSupport.SKIP_BODY, r1); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r2); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPerformClearTagStateForTagPoolingServers(true); + freshTag2.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); } public void testIfElseIf() throws Exception { @@ -217,6 +501,88 @@ public class IfTagTest extends StrutsInternalTestCase { assertEquals(TagSupport.SKIP_BODY, r2); assertEquals(TagSupport.EVAL_BODY_INCLUDE, r3); assertEquals(TagSupport.SKIP_BODY, r4); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag2 = new ElseIfTag(); + freshTag2.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag1, freshTag2)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag2, freshTag2)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag3, freshTag2)); + } + + public void testIfElseIf_clearTagStateSet() throws Exception { + IfTag ifTag = new IfTag(); + ifTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + ifTag.setPageContext(pageContext); + ifTag.setTest("false"); + + ElseIfTag elseIfTag1 = new ElseIfTag(); + elseIfTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseIfTag1.setPageContext(pageContext); + elseIfTag1.setTest("false"); + + ElseIfTag elseIfTag2 = new ElseIfTag(); + elseIfTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseIfTag2.setPageContext(pageContext); + elseIfTag2.setTest("true"); + + ElseIfTag elseIfTag3 = new ElseIfTag(); + elseIfTag3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseIfTag3.setPageContext(pageContext); + elseIfTag3.setTest("true"); + + int r1 = ifTag.doStartTag(); + setComponentTagClearTagState(ifTag, true); // Ensure component tag state clearing is set true (to match tag). + ifTag.doEndTag(); + int r2 = elseIfTag1.doStartTag(); + setComponentTagClearTagState(elseIfTag1, true); // Ensure component tag state clearing is set true (to match tag). + elseIfTag1.doEndTag(); + int r3 = elseIfTag2.doStartTag(); + setComponentTagClearTagState(elseIfTag2, true); // Ensure component tag state clearing is set true (to match tag). + elseIfTag2.doEndTag(); + int r4 = elseIfTag3.doStartTag(); + setComponentTagClearTagState(elseIfTag3, true); // Ensure component tag state clearing is set true (to match tag). + elseIfTag3.doEndTag(); + + assertEquals(TagSupport.SKIP_BODY, r1); + assertEquals(TagSupport.SKIP_BODY, r2); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r3); + assertEquals(TagSupport.SKIP_BODY, r4); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag2 = new ElseIfTag(); + freshTag2.setPerformClearTagStateForTagPoolingServers(true); + freshTag2.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag1, freshTag2)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag2, freshTag2)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag3, freshTag2)); } public void testIfElseIfElse() throws Exception { @@ -255,8 +621,113 @@ public class IfTagTest extends StrutsInternalTestCase { assertEquals(TagSupport.SKIP_BODY, r3); assertEquals(TagSupport.SKIP_BODY, r4); assertEquals(TagSupport.EVAL_BODY_INCLUDE, r5); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag2 = new ElseIfTag(); + freshTag2.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag1, freshTag2)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag2, freshTag2)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag3, freshTag2)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag3 = new ElseTag(); + freshTag3.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag3)); } + public void testIfElseIfElse_clearTagStateSet() throws Exception { + IfTag ifTag = new IfTag(); + ifTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + ifTag.setPageContext(pageContext); + ifTag.setTest("false"); + + ElseIfTag elseIfTag1 = new ElseIfTag(); + elseIfTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseIfTag1.setPageContext(pageContext); + elseIfTag1.setTest("false"); + + ElseIfTag elseIfTag2 = new ElseIfTag(); + elseIfTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseIfTag2.setPageContext(pageContext); + elseIfTag2.setTest("false"); + + ElseIfTag elseIfTag3 = new ElseIfTag(); + elseIfTag3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseIfTag3.setPageContext(pageContext); + elseIfTag3.setTest("false"); + + ElseTag elseTag = new ElseTag(); + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + + int r1 = ifTag.doStartTag(); + setComponentTagClearTagState(ifTag, true); // Ensure component tag state clearing is set true (to match tag). + ifTag.doEndTag(); + int r2 = elseIfTag1.doStartTag(); + setComponentTagClearTagState(elseIfTag1, true); // Ensure component tag state clearing is set true (to match tag). + elseIfTag1.doEndTag(); + int r3 = elseIfTag2.doStartTag(); + setComponentTagClearTagState(elseIfTag2, true); // Ensure component tag state clearing is set true (to match tag). + elseIfTag2.doEndTag(); + int r4 = elseIfTag3.doStartTag(); + setComponentTagClearTagState(elseIfTag3, true); // Ensure component tag state clearing is set true (to match tag). + elseIfTag3.doEndTag(); + int r5 = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + elseTag.doEndTag(); + + assertEquals(TagSupport.SKIP_BODY, r1); + assertEquals(TagSupport.SKIP_BODY, r2); + assertEquals(TagSupport.SKIP_BODY, r3); + assertEquals(TagSupport.SKIP_BODY, r4); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r5); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseIfTag freshTag2 = new ElseIfTag(); + freshTag2.setPerformClearTagStateForTagPoolingServers(true); + freshTag2.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag1, freshTag2)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag2, freshTag2)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseIfTag3, freshTag2)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag3 = new ElseTag(); + freshTag3.setPerformClearTagStateForTagPoolingServers(true); + freshTag3.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag3)); + } public void testNestedIfElse1() throws Exception { IfTag ifTag = new IfTag(); @@ -283,6 +754,76 @@ public class IfTagTest extends StrutsInternalTestCase { assertEquals(TagSupport.EVAL_PAGE, r4); assertEquals(TagSupport.SKIP_BODY, r5); assertEquals(TagSupport.EVAL_PAGE, r6); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(nestedIfTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); + } + + public void testNestedIfElse1_clearTagStateSet() throws Exception { + IfTag ifTag = new IfTag(); + ifTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + ifTag.setPageContext(pageContext); + ifTag.setTest("true"); + + IfTag nestedIfTag = new IfTag(); + nestedIfTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + nestedIfTag.setPageContext(pageContext); + nestedIfTag.setTest("true"); + + ElseTag elseTag = new ElseTag(); + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + + int r1 = ifTag.doStartTag(); + setComponentTagClearTagState(ifTag, true); // Ensure component tag state clearing is set true (to match tag). + int r2 = nestedIfTag.doStartTag(); + setComponentTagClearTagState(nestedIfTag, true); // Ensure component tag state clearing is set true (to match tag). + int r3 = nestedIfTag.doEndTag(); + int r4 = ifTag.doEndTag(); + int r5 = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + int r6 = elseTag.doEndTag(); + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r1); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r2); + assertEquals(TagSupport.EVAL_PAGE, r3); + assertEquals(TagSupport.EVAL_PAGE, r4); + assertEquals(TagSupport.SKIP_BODY, r5); + assertEquals(TagSupport.EVAL_PAGE, r6); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(nestedIfTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPerformClearTagStateForTagPoolingServers(true); + freshTag2.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); } public void testNestedIfElse2() throws Exception { @@ -310,11 +851,97 @@ public class IfTagTest extends StrutsInternalTestCase { assertEquals(TagSupport.EVAL_PAGE, r4); assertEquals(TagSupport.SKIP_BODY, r5); assertEquals(TagSupport.EVAL_PAGE, r6); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(nestedIfTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPageContext(pageContext); + // ElseTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); } + public void testNestedIfElse2_clearTagStateSet() throws Exception { + IfTag ifTag = new IfTag(); + ifTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + ifTag.setPageContext(pageContext); + ifTag.setTest("true"); + IfTag nestedIfTag = new IfTag(); + nestedIfTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + nestedIfTag.setPageContext(pageContext); + nestedIfTag.setTest("false"); + ElseTag elseTag = new ElseTag(); + elseTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + elseTag.setPageContext(pageContext); + int r1 = ifTag.doStartTag(); + setComponentTagClearTagState(ifTag, true); // Ensure component tag state clearing is set true (to match tag). + int r2 = nestedIfTag.doStartTag(); + setComponentTagClearTagState(nestedIfTag, true); // Ensure component tag state clearing is set true (to match tag). + int r3 = nestedIfTag.doEndTag(); + int r4 = ifTag.doEndTag(); + int r5 = elseTag.doStartTag(); + setComponentTagClearTagState(elseTag, true); // Ensure component tag state clearing is set true (to match tag). + int r6 = elseTag.doEndTag(); + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, r1); + assertEquals(TagSupport.SKIP_BODY, r2); + assertEquals(TagSupport.EVAL_PAGE, r3); + assertEquals(TagSupport.EVAL_PAGE, r4); + assertEquals(TagSupport.SKIP_BODY, r5); + assertEquals(TagSupport.EVAL_PAGE, r6); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IfTag freshTag = new IfTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(ifTag, freshTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(nestedIfTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ElseTag freshTag2 = new ElseTag(); + freshTag2.setPerformClearTagStateForTagPoolingServers(true); + freshTag2.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(elseTag, freshTag2)); + } + + /** + * Helper method to simplify setting the performClearTagStateForTagPoolingServers state for a + * {@link ComponentTagSupport} tag's {@link Component} to match expecations for a test. + * + * Since the component is not available to the tag until after the doStartTag() method is called, + * but we need to ensure the component's {@link Component#performClearTagStateForTagPoolingServers} state matches + * what we set for the Tag when a non-default (true) value is used, this method retrieves the component instance, + * sets the value specified and forces the parameters to be repopulated again. + * + * @param tag The ComponentTagSupport tag upon whose component we will set the performClearTagStateForTagPoolingServers state. + * @param performClearTagStateForTagPoolingServers true to clear tag state, false otherwise + */ + protected void setComponentTagClearTagState(ComponentTagSupport tag, boolean performClearTagStateForTagPoolingServers) { + tag.component.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + //tag.populateParams(); // Not safe to call after doStartTag() ... breaks some tests. + tag.populatePerformClearTagStateForTagPoolingServersParam(); // Only populate the performClearTagStateForTagPoolingServers parameter for the Tag. + } + + @Override protected void setUp() throws Exception { super.setUp(); // create the needed objects diff --git a/core/src/test/java/org/apache/struts2/views/jsp/IncludeTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/IncludeTagTest.java index 45830854f..85fe212b1 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/IncludeTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/IncludeTagTest.java @@ -65,6 +65,41 @@ public class IncludeTagTest extends AbstractTagTest { assertEquals("", writer.toString()); verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeNoParam_clearTagStateSet() throws Exception { + + // Use always matcher as we can not determine the exact objects used in mock.include(request, response) call + mockRequestDispatcher.include(anyObject(ServletRequest.class), anyObject(ServletResponse.class)); + expectLastCall().times(1); + + replay(mockRequestDispatcher); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("person/list.jsp"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/person/list.jsp", request.getRequestDispatherString()); + assertEquals("", writer.toString()); + + verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeWithParameters() throws Exception { @@ -86,6 +121,44 @@ public class IncludeTagTest extends AbstractTagTest { assertEquals("", writer.toString()); verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeWithParameters_clearTagStateSet() throws Exception { + + // Use always matcher as we can not determine the exact objects used in mock.include(request, response) call + mockRequestDispatcher.include(anyObject(ServletRequest.class), anyObject(ServletResponse.class)); + expectLastCall().times(1); + + replay(mockRequestDispatcher); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("person/create.jsp"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + // adding param must be done after doStartTag() + Include include = (Include) tag.getComponent(); + include.addParameter("user", "Santa Claus"); + tag.doEndTag(); + + assertEquals("/person/create.jsp?user=Santa+Claus", request.getRequestDispatherString()); + assertEquals("", writer.toString()); + + verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeRelative2Dots() throws Exception { @@ -105,7 +178,44 @@ public class IncludeTagTest extends AbstractTagTest { assertEquals("/car/view.jsp", request.getRequestDispatherString()); assertEquals("", writer.toString()); - verify(mockRequestDispatcher); + verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeRelative2Dots_clearTagStateSet() throws Exception { + // TODO: we should test for .. in unit test - is this test correct? + // Use always matcher as we can not determine the exact objects used in mock.include(request, response) call + mockRequestDispatcher.include(anyObject(ServletRequest.class), anyObject(ServletResponse.class)); + expectLastCall().times(1); + + replay(mockRequestDispatcher); + + request.setupGetServletPath("app/manager"); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("../car/view.jsp"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + + assertEquals("/car/view.jsp", request.getRequestDispatherString()); + assertEquals("", writer.toString()); + + verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeSetUseResponseEncodingTrue() throws Exception { @@ -133,6 +243,50 @@ public class IncludeTagTest extends AbstractTagTest { assertEquals("", writer.toString()); // Nothing gets written for mock-include verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeSetUseResponseEncodingTrue_clearTagStateSet() throws Exception { + // TODO: If possible in future mock-test an actual content-includes with various encodings + // while setting the response encoding to match. Doesn't appear to be possible + // right now in unit-test form. + // Seems that the best we can do is verify the setUseResponseEncoding() doesn't fail... + + // Use always matcher as we can not determine the exact objects used in mock.include(request, response) call + mockRequestDispatcher.include(anyObject(ServletRequest.class), anyObject(ServletResponse.class)); + expectLastCall().times(1); + + replay(mockRequestDispatcher); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("person/create.jsp"); + response.setCharacterEncoding("UTF-8"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + // Manipulate after doStartTag to ensure the tag component has undergone injection + Include include = (Include) tag.getComponent(); + include.setUseResponseEncoding("true"); + tag.doEndTag(); + + assertEquals("UTF-8", response.getCharacterEncoding()); + assertEquals("/person/create.jsp", request.getRequestDispatherString()); + assertEquals("", writer.toString()); // Nothing gets written for mock-include + + verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeSetUseResponseEncodingFalse() throws Exception { @@ -160,8 +314,53 @@ public class IncludeTagTest extends AbstractTagTest { assertEquals("", writer.toString()); // Nothing gets written for mock-include verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testIncludeSetUseResponseEncodingFalse_clearTagStateSet() throws Exception { + // TODO: If possible in future mock-test an actual content-includes with various encodings + // while setting the response encoding to match. Doesn't appear to be possible + // right now in unit-test form. + // Seems that the best we can do is verify the setUseResponseEncoding() doesn't fail... + + // Use always matcher as we can not determine the exact objects used in mock.include(request, response) call + mockRequestDispatcher.include(anyObject(ServletRequest.class), anyObject(ServletResponse.class)); + expectLastCall().times(1); + + replay(mockRequestDispatcher); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("person/create.jsp"); + response.setCharacterEncoding("UTF-8"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + // Manipulate after doStartTag to ensure the tag component has undergone injection + Include include = (Include) tag.getComponent(); + include.setUseResponseEncoding("false"); + tag.doEndTag(); + + assertEquals("UTF-8", response.getCharacterEncoding()); + assertEquals("/person/create.jsp", request.getRequestDispatherString()); + assertEquals("", writer.toString()); // Nothing gets written for mock-include + + verify(mockRequestDispatcher); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IncludeTag freshTag = new IncludeTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override protected void setUp() throws Exception { super.setUp(); request.setupGetRequestDispatcher(new MockRequestDispatcher()); @@ -174,6 +373,7 @@ public class IncludeTagTest extends AbstractTagTest { tag.setPageContext(pageContext); } + @Override protected void tearDown() throws Exception { super.tearDown(); tag = null; diff --git a/core/src/test/java/org/apache/struts2/views/jsp/IteratorGeneratorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/IteratorGeneratorTagTest.java index a5efc523e..d1748e16f 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/IteratorGeneratorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/IteratorGeneratorTagTest.java @@ -65,6 +65,57 @@ public class IteratorGeneratorTagTest extends AbstractTagTest { assertNotSame(afterTopOfStack, topOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testGeneratorBasic_clearTagStateSet() throws Exception { + IteratorGeneratorTag tag = new IteratorGeneratorTag(); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVal("%{'aaa,bbb,ccc,ddd,eee'}"); + tag.doStartTag(); + Object topOfStack = stack.findValue("top"); + + + assertTrue(topOfStack instanceof Iterator); + // 1 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "aaa"); + // 2 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "bbb"); + // 3 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "ccc"); + // 4 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "ddd"); + // 5 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(),"eee"); + + assertFalse(((Iterator)topOfStack).hasNext()); + + tag.doEndTag(); + Object afterTopOfStack = stack.findValue("top"); + + + assertNotSame(afterTopOfStack, topOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGeneratorWithSeparator() throws Exception { @@ -97,6 +148,54 @@ public class IteratorGeneratorTagTest extends AbstractTagTest { assertFalse(((Iterator)topOfStack).hasNext()); assertNotSame(afterTopOfStack, topOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testGeneratorWithSeparator_clearTagStateSet() throws Exception { + IteratorGeneratorTag tag = new IteratorGeneratorTag(); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVal("%{'aaa|bbb|ccc|ddd|eee'}"); + tag.setSeparator("|"); + tag.doStartTag(); + Object topOfStack = stack.findValue("top"); + tag.doEndTag(); + Object afterTopOfStack = stack.findValue("top"); + + assertTrue(topOfStack instanceof Iterator); + // 1 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "aaa"); + // 2 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "bbb"); + // 3 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "ccc"); + // 4 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "ddd"); + // 5 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "eee"); + + assertFalse(((Iterator)topOfStack).hasNext()); + assertNotSame(afterTopOfStack, topOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGeneratorWithConverter() throws Exception { @@ -129,6 +228,54 @@ public class IteratorGeneratorTagTest extends AbstractTagTest { assertFalse(((Iterator)topOfStack).hasNext()); assertNotSame(afterTopOfStack, topOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testGeneratorWithConverter_clearTagStateSet() throws Exception { + IteratorGeneratorTag tag = new IteratorGeneratorTag(); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVal("%{'aaa, bbb, ccc, ddd, eee'}"); + tag.setConverter("myConverter"); + tag.doStartTag(); + Object topOfStack = stack.findValue("top"); + tag.doEndTag(); + Object afterTopOfStack = stack.findValue("top"); + + assertTrue(topOfStack instanceof Iterator); + // 1. + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "myConverter-aaa"); + // 2 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "myConverter-bbb"); + // 3 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "myConverter-ccc"); + // 4. + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "myConverter-ddd"); + // 5. + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "myConverter-eee"); + + assertFalse(((Iterator)topOfStack).hasNext()); + assertNotSame(afterTopOfStack, topOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGeneratorWithId() throws Exception { @@ -159,6 +306,52 @@ public class IteratorGeneratorTagTest extends AbstractTagTest { assertEquals(((Iterator)pageContextIterator).next(), "eee"); assertFalse(((Iterator)pageContextIterator).hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testGeneratorWithId_clearTagStateSet() throws Exception { + IteratorGeneratorTag tag = new IteratorGeneratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVal("%{'aaa,bbb,ccc,ddd,eee'}"); + tag.setVar("myPageContextAttId"); + tag.doStartTag(); + tag.doEndTag(); + + Object pageContextIterator = stack.findValue("myPageContextAttId"); + + assertTrue(pageContextIterator instanceof Iterator); + // 1 + assertTrue(((Iterator)pageContextIterator).hasNext()); + assertEquals(((Iterator)pageContextIterator).next(), "aaa"); + // 2. + assertTrue(((Iterator)pageContextIterator).hasNext()); + assertEquals(((Iterator)pageContextIterator).next(), "bbb"); + // 3. + assertTrue(((Iterator)pageContextIterator).hasNext()); + assertEquals(((Iterator)pageContextIterator).next(), "ccc"); + // 4 + assertTrue(((Iterator)pageContextIterator).hasNext()); + assertEquals(((Iterator)pageContextIterator).next(), "ddd"); + // 5 + assertTrue(((Iterator)pageContextIterator).hasNext()); + assertEquals(((Iterator)pageContextIterator).next(), "eee"); + + assertFalse(((Iterator)pageContextIterator).hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGeneratorWithCount() throws Exception { @@ -186,9 +379,52 @@ public class IteratorGeneratorTagTest extends AbstractTagTest { assertFalse(((Iterator)topOfStack).hasNext()); assertNotSame(topOfStack, afterTopOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testGeneratorWithCount_clearTagStateSet() throws Exception { + IteratorGeneratorTag tag = new IteratorGeneratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVal("%{'aaa,bbb,ccc,ddd,eee'}"); + tag.setCount("myCount"); + tag.doStartTag(); + Object topOfStack = stack.findValue("top"); + tag.doEndTag(); + Object afterTopOfStack = stack.findValue("top"); + + + assertTrue(topOfStack instanceof Iterator); + // 1 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "aaa"); + // 2 + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "bbb"); + // 3. + assertTrue(((Iterator)topOfStack).hasNext()); + assertEquals(((Iterator)topOfStack).next(), "ccc"); + + assertFalse(((Iterator)topOfStack).hasNext()); + assertNotSame(topOfStack, afterTopOfStack); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorGeneratorTag freshTag = new IteratorGeneratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override public Action getAction() { return new ActionSupport() { public Converter getMyConverter() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java index df13f164e..df5022c0a 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java @@ -59,7 +59,7 @@ public class IteratorTagTest extends AbstractUITagTest { // one int result = tag.doStartTag(); - assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); assertEquals(stack.peek(), "one"); assertEquals(stack.getContext().get("myId"), "one"); @@ -68,39 +68,116 @@ public class IteratorTagTest extends AbstractUITagTest { // two result = tag.doAfterBody(); - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals(stack.peek(), "two"); assertEquals(stack.getContext().get("myId"), "two"); // three result = tag.doAfterBody(); - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals(stack.peek(), "three"); assertEquals(stack.getContext().get("myId"), "three"); // four result = tag.doAfterBody(); - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals(stack.peek(), "four"); assertEquals(stack.getContext().get("myId"), "four"); // five result = tag.doAfterBody(); - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals(stack.peek(), "five"); assertEquals(stack.getContext().get("myId"), "five"); result = tag.doAfterBody(); - assertEquals(result, TagSupport.SKIP_BODY); + assertEquals(TagSupport.SKIP_BODY, result); result = tag.doEndTag(); - assertEquals(result, TagSupport.EVAL_PAGE); + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testIteratingWithIdSpecified_clearTagStateSet() throws Exception { + List list = new ArrayList(); + list.add("one"); + list.add("two"); + list.add("three"); + list.add("four"); + list.add("five"); + + Foo foo = new Foo(); + foo.setList(list); + + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("list"); + tag.setVar("myId"); + + // one + int result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + assertEquals(stack.peek(), "one"); + assertEquals(stack.getContext().get("myId"), "one"); + + + tag.doInitBody(); + + // two + result = tag.doAfterBody(); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(stack.peek(), "two"); + assertEquals(stack.getContext().get("myId"), "two"); + + + // three + result = tag.doAfterBody(); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(stack.peek(), "three"); + assertEquals(stack.getContext().get("myId"), "three"); + + + // four + result = tag.doAfterBody(); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(stack.peek(), "four"); + assertEquals(stack.getContext().get("myId"), "four"); + + + // five + result = tag.doAfterBody(); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(stack.peek(), "five"); + assertEquals(stack.getContext().get("myId"), "five"); + + + result = tag.doAfterBody(); + assertEquals(TagSupport.SKIP_BODY, result); + + result = tag.doEndTag(); + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testIteratingWithIdSpecifiedAndNullElementOnCollection() throws Exception { List list = new ArrayList(); list.add("one"); @@ -117,7 +194,7 @@ public class IteratorTagTest extends AbstractUITagTest { // one int result = tag.doStartTag(); - assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); assertEquals(stack.peek(), "one"); assertEquals(stack.getContext().get("myId"), "one"); @@ -126,24 +203,83 @@ public class IteratorTagTest extends AbstractUITagTest { // two result = tag.doAfterBody(); - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertNull(stack.peek()); assertNull(stack.getContext().get("myId")); // three result = tag.doAfterBody(); - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals(stack.peek(), "three"); assertEquals(stack.getContext().get("myId"), "three"); result = tag.doAfterBody(); - assertEquals(result, TagSupport.SKIP_BODY); + assertEquals(TagSupport.SKIP_BODY, result); result = tag.doEndTag(); - assertEquals(result, TagSupport.EVAL_PAGE); + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testIteratingWithIdSpecifiedAndNullElementOnCollection_clearTagStateSet() throws Exception { + List list = new ArrayList(); + list.add("one"); + list.add(null); + list.add("three"); + + Foo foo = new Foo(); + foo.setList(list); + + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("list"); + tag.setVar("myId"); + + // one + int result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + assertEquals(stack.peek(), "one"); + assertEquals(stack.getContext().get("myId"), "one"); + + + tag.doInitBody(); + + // two + result = tag.doAfterBody(); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertNull(stack.peek()); + assertNull(stack.getContext().get("myId")); + + + // three + result = tag.doAfterBody(); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(stack.peek(), "three"); + assertEquals(stack.getContext().get("myId"), "three"); + + result = tag.doAfterBody(); + assertEquals(TagSupport.SKIP_BODY, result); + + result = tag.doEndTag(); + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testArrayIterator() { Foo foo = new Foo(); @@ -232,6 +368,99 @@ public class IteratorTagTest extends AbstractUITagTest { assertEquals(TagSupport.SKIP_BODY, result); assertEquals(3, stack.size()); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMapIterator_clearTagStateSet() { + Foo foo = new Foo(); + HashMap map = new HashMap(); + map.put("test1", "123"); + map.put("test2", "456"); + map.put("test3", "789"); + foo.setMap(map); + + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("map"); + + int result = 0; + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + assertEquals(4, stack.size()); + assertTrue(stack.getRoot().peek() instanceof Map.Entry); + + try { + result = tag.doAfterBody(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(4, stack.size()); + assertTrue(stack.getRoot().peek() instanceof Map.Entry); + + try { + result = tag.doAfterBody(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals(4, stack.size()); + assertTrue(stack.getRoot().peek() instanceof Map.Entry); + + try { + result = tag.doAfterBody(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.SKIP_BODY, result); + assertEquals(3, stack.size()); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testStatus() { @@ -252,7 +481,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); assertEquals("test1", stack.getRoot().peek()); assertEquals(4, stack.size()); @@ -272,7 +501,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals("test2", stack.getRoot().peek()); assertEquals(4, stack.size()); @@ -292,7 +521,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals("test3", stack.getRoot().peek()); assertEquals(4, stack.size()); @@ -304,6 +533,113 @@ public class IteratorTagTest extends AbstractUITagTest { assertEquals(3, status.getCount()); assertTrue(status.isOdd()); assertFalse(status.isEven()); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testStatus_clearTagStateSet() { + Foo foo = new Foo(); + foo.setArray(new String[]{"test1", "test2", "test3"}); + + stack.push(foo); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("array"); + tag.setStatus("fooStatus"); + + int result = 0; + + try { + result = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); + assertEquals("test1", stack.getRoot().peek()); + assertEquals(4, stack.size()); + + IteratorStatus status = (IteratorStatus) context.get("fooStatus"); + assertNotNull(status); + assertFalse(status.isLast()); + assertTrue(status.isFirst()); + assertEquals(0, status.getIndex()); + assertEquals(1, status.getCount()); + assertTrue(status.isOdd()); + assertFalse(status.isEven()); + + try { + result = tag.doAfterBody(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals("test2", stack.getRoot().peek()); + assertEquals(4, stack.size()); + + status = (IteratorStatus) context.get("fooStatus"); + assertNotNull(status); + assertFalse(status.isLast()); + assertFalse(status.isFirst()); + assertEquals(1, status.getIndex()); + assertEquals(2, status.getCount()); + assertFalse(status.isOdd()); + assertTrue(status.isEven()); + + try { + result = tag.doAfterBody(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); + assertEquals("test3", stack.getRoot().peek()); + assertEquals(4, stack.size()); + + status = (IteratorStatus) context.get("fooStatus"); + assertNotNull(status); + assertTrue(status.isLast()); + assertFalse(status.isFirst()); + assertEquals(2, status.getIndex()); + assertEquals(3, status.getCount()); + assertTrue(status.isOdd()); + assertFalse(status.isEven()); + + try { + result = tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEmptyArray() { @@ -661,7 +997,7 @@ public class IteratorTagTest extends AbstractUITagTest { List values = new ArrayList(); try { int result = tag.doStartTag(); - assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); values.add(stack.getRoot().peek()); } catch (JspException e) { e.printStackTrace(); @@ -676,6 +1012,7 @@ public class IteratorTagTest extends AbstractUITagTest { ListUtils.isEqualList(Arrays.asList(expectedValues), values); } + @Override protected void setUp() throws Exception { super.setUp(); @@ -700,7 +1037,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.EVAL_BODY_INCLUDE); + assertEquals(TagSupport.EVAL_BODY_INCLUDE, result); assertEquals("test1", stack.getRoot().peek()); assertEquals(4, stack.size()); @@ -711,7 +1048,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals("test2", stack.getRoot().peek()); assertEquals(4, stack.size()); @@ -722,7 +1059,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.EVAL_BODY_AGAIN); + assertEquals(TagSupport.EVAL_BODY_AGAIN, result); assertEquals("test3", stack.getRoot().peek()); assertEquals(4, stack.size()); @@ -733,7 +1070,7 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.SKIP_BODY); + assertEquals(TagSupport.SKIP_BODY, result); assertEquals(3, stack.size()); } @@ -747,13 +1084,22 @@ public class IteratorTagTest extends AbstractUITagTest { fail(); } - assertEquals(result, TagSupport.SKIP_BODY); + assertEquals(TagSupport.SKIP_BODY, result); try { result = tag.doEndTag(); } catch (JspException e) { e.printStackTrace(); fail(); } + + assertEquals(TagSupport.EVAL_PAGE, result); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + IteratorTag freshTag = new IteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } class Foo { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/MergeIteratorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/MergeIteratorTagTest.java index fd3dad1ec..f4a97842c 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/MergeIteratorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/MergeIteratorTagTest.java @@ -82,8 +82,108 @@ public class MergeIteratorTagTest extends AbstractTagTest { assertTrue(mergedIterator.hasNext()); assertEquals(mergedIterator.next(), "C"); assertFalse(mergedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + MergeIteratorTag freshTag = new MergeIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testMergingIteratorWithArrayAsSource_clearTagStateSet() throws Exception { + MergeIteratorTag tag = new MergeIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVar("myMergedIterator"); + + ParamTag iterator1ParamTag = new ParamTag(); + iterator1ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator1ParamTag.setPageContext(pageContext); + iterator1ParamTag.setValue("myArr1"); + + ParamTag iterator2ParamTag = new ParamTag(); + iterator2ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator2ParamTag.setPageContext(pageContext); + iterator2ParamTag.setValue("myArr2"); + + ParamTag iterator3ParamTag = new ParamTag(); + iterator3ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator3ParamTag.setPageContext(pageContext); + iterator3ParamTag.setValue("myArr3"); + + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doStartTag(); + setComponentTagClearTagState(iterator1ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doEndTag(); + iterator2ParamTag.doStartTag(); + setComponentTagClearTagState(iterator2ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator2ParamTag.doEndTag(); + iterator3ParamTag.doStartTag(); + setComponentTagClearTagState(iterator3ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator3ParamTag.doEndTag(); + tag.doEndTag(); + + Iterator mergedIterator = (Iterator) stack.findValue("#myMergedIterator"); // if not iterator, let CCE surface + + assertNotNull(mergedIterator); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "1"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "a"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "A"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "2"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "b"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "B"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "3"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "c"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "C"); + assertFalse(mergedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + MergeIteratorTag freshTag = new MergeIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testMergingIteratorsWithListAsSource() throws Exception { MergeIteratorTag tag = new MergeIteratorTag(); @@ -134,9 +234,108 @@ public class MergeIteratorTagTest extends AbstractTagTest { assertTrue(mergedIterator.hasNext()); assertEquals(mergedIterator.next(), "C"); assertFalse(mergedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + MergeIteratorTag freshTag = new MergeIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testMergingIteratorsWithListAsSource_clearTagStateSet() throws Exception { + MergeIteratorTag tag = new MergeIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setVar("myMergedIterator"); + ParamTag iterator1ParamTag = new ParamTag(); + iterator1ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator1ParamTag.setPageContext(pageContext); + iterator1ParamTag.setValue("myList1"); + + ParamTag iterator2ParamTag = new ParamTag(); + iterator2ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator2ParamTag.setPageContext(pageContext); + iterator2ParamTag.setValue("myList2"); + + ParamTag iterator3ParamTag = new ParamTag(); + iterator3ParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + iterator3ParamTag.setPageContext(pageContext); + iterator3ParamTag.setValue("myList3"); + + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doStartTag(); + setComponentTagClearTagState(iterator1ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator1ParamTag.doEndTag(); + iterator2ParamTag.doStartTag(); + setComponentTagClearTagState(iterator2ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator2ParamTag.doEndTag(); + iterator3ParamTag.doStartTag(); + setComponentTagClearTagState(iterator3ParamTag, true); // Ensure component tag state clearing is set true (to match tag). + iterator3ParamTag.doEndTag(); + tag.doEndTag(); + + Iterator mergedIterator = (Iterator) stack.findValue("#myMergedIterator"); // if not iterator, let CCE surface + + assertNotNull(mergedIterator); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "1"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "a"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "A"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "2"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "b"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "B"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "3"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "c"); + assertTrue(mergedIterator.hasNext()); + assertEquals(mergedIterator.next(), "C"); + assertFalse(mergedIterator.hasNext()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator1ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator2ParamTag, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(iterator3ParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + MergeIteratorTag freshTag = new MergeIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public Action getAction() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java index 6056a94cd..0390866f6 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/NumberTagTest.java @@ -44,8 +44,44 @@ public class NumberTagTest extends AbstractTagTest { // then assertEquals("120", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + NumberTag freshTag = new NumberTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testSimpleFloatFormat_clearTagStateSet() throws Exception { + // given + context.put(ActionContext.LOCALE, Locale.US); + + TestAction testAction = (TestAction) action; + testAction.setFloatNumber(120.0f); + + NumberTag tag = new NumberTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("floatNumber"); + + // when + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // then + assertEquals("120", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + NumberTag freshTag = new NumberTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testSimpleCurrencyUSFormat() throws Exception { // given context = ActionContext.of(context).withLocale(Locale.US).getContextMap(); @@ -64,8 +100,43 @@ public class NumberTagTest extends AbstractTagTest { // then assertEquals("$120.00", writer.toString()); + + NumberTag freshTag = new NumberTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testSimpleCurrencyUSFormat_clearTagStateSet() throws Exception { + // given + context.put(ActionContext.LOCALE, Locale.US); + + TestAction testAction = (TestAction) action; + testAction.setFloatNumber(120.0f); + + NumberTag tag = new NumberTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("floatNumber"); + tag.setType("currency"); + + // when + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // then + assertEquals("$120.00", writer.toString()); + + NumberTag freshTag = new NumberTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testSimpleCurrencyPLFormat() throws Exception { // given context = ActionContext.of(context).withLocale(new Locale("pl", "PL")).getContextMap(); @@ -89,6 +160,45 @@ public class NumberTagTest extends AbstractTagTest { String expected = format.format(120.0f); assertEquals(expected, writer.toString()); + + NumberTag freshTag = new NumberTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleCurrencyPLFormat_clearTagStateSet() throws Exception { + // given + context.put(ActionContext.LOCALE, new Locale("pl", "PL")); + + TestAction testAction = (TestAction) action; + testAction.setFloatNumber(120.0f); + + NumberTag tag = new NumberTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("floatNumber"); + tag.setType("currency"); + + // when + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // then + NumberFormat format = NumberFormat.getCurrencyInstance((Locale) context.get(ActionContext.LOCALE)); + format.setRoundingMode(RoundingMode.CEILING); + String expected = format.format(120.0f); + + assertEquals(expected, writer.toString()); + + NumberTag freshTag = new NumberTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleRoundingCeiling() throws Exception { @@ -114,6 +224,45 @@ public class NumberTagTest extends AbstractTagTest { String expected = format.format(120.45f); assertEquals(expected, writer.toString()); + + NumberTag freshTag = new NumberTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleRoundingCeiling_clearTagStateSet() throws Exception { + // given + context.put(ActionContext.LOCALE, Locale.US); + + TestAction testAction = (TestAction) action; + testAction.setFloatNumber(120.45f); + + NumberTag tag = new NumberTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("floatNumber"); + tag.setRoundingMode("down"); + + // when + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // then + NumberFormat format = NumberFormat.getInstance((Locale) context.get(ActionContext.LOCALE)); + format.setRoundingMode(RoundingMode.DOWN); + String expected = format.format(120.45f); + + assertEquals(expected, writer.toString()); + + NumberTag freshTag = new NumberTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/PropertyTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/PropertyTagTest.java index f37431af2..621e7fb32 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/PropertyTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/PropertyTagTest.java @@ -65,6 +65,67 @@ public class PropertyTagTest extends StrutsInternalTestCase { request.verify(); jspWriter.verify(); pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testDefaultValue_clearTagStateSet() { + PropertyTag tag = new PropertyTag(); + + Foo foo = new Foo(); + + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("TEST"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("title"); + tag.setDefault("TEST"); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + request.verify(); + jspWriter.verify(); + pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testNull() { @@ -94,6 +155,66 @@ public class PropertyTagTest extends StrutsInternalTestCase { request.verify(); jspWriter.verify(); pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testNull_clearTagStateSet() { + PropertyTag tag = new PropertyTag(); + + Foo foo = new Foo(); + + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData(""); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("title"); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + request.verify(); + jspWriter.verify(); + pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testSimple() { @@ -124,6 +245,67 @@ public class PropertyTagTest extends StrutsInternalTestCase { request.verify(); jspWriter.verify(); pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() { + PropertyTag tag = new PropertyTag(); + + Foo foo = new Foo(); + foo.setTitle("test"); + + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("test"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("title"); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + request.verify(); + jspWriter.verify(); + pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } public void testTopOfStack() { @@ -153,8 +335,68 @@ public class PropertyTagTest extends StrutsInternalTestCase { request.verify(); jspWriter.verify(); pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + // PropertyTag had no explicit values set in this test, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } + public void testTopOfStack_clearTagStateSet() { + PropertyTag tag = new PropertyTag(); + + Foo foo = new Foo(); + foo.setTitle("test"); + + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("Foo is: test"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + request.verify(); + jspWriter.verify(); + pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } public void testWithAltSyntax1() throws Exception { // setups @@ -176,6 +418,51 @@ public class PropertyTagTest extends StrutsInternalTestCase { tag.setValue("%{formatTitle()}"); tag.doStartTag(); tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } + + public void testWithAltSyntax1_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("tm_jee"); + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("Foo is: tm_jee"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + { + PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); } // verify test @@ -198,15 +485,58 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.setRequest(request); // test - { - PropertyTag tag = new PropertyTag(); - tag.setEscapeHtml(false); - tag.setEscapeJavaScript(true); - tag.setPageContext(pageContext); - tag.setValue("%{formatTitle()}"); - tag.doStartTag(); - tag.doEndTag(); - } + {PropertyTag tag = new PropertyTag(); + tag.setEscapeHtml(false); + tag.setEscapeJavaScript(true); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } + + public void testEscapeJavaScript_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("\t\b\n\f\r\"\'/\\"); + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("Foo is: \\t\\b\\n\\f\\r\\\"\\\'\\/\\\\"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + {PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscapeHtml(false); + tag.setEscapeJavaScript(true); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} // verify test request.verify(); @@ -228,15 +558,58 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.setRequest(request); // test - { - PropertyTag tag = new PropertyTag(); - tag.setEscapeHtml(false); - tag.setEscapeXml(true); - tag.setPageContext(pageContext); - tag.setValue("%{formatTitle()}"); - tag.doStartTag(); - tag.doEndTag(); - } + {PropertyTag tag = new PropertyTag(); + tag.setEscapeHtml(false); + tag.setEscapeXml(true); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } + + public void testEscapeXml_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("<>'\"&"); + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("Foo is: <>'"&"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + {PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscapeHtml(false); + tag.setEscapeXml(true); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} // verify test request.verify(); @@ -258,15 +631,58 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.setRequest(request); // test - { - PropertyTag tag = new PropertyTag(); - tag.setEscapeHtml(false); - tag.setEscapeCsv(true); - tag.setPageContext(pageContext); - tag.setValue("%{formatTitle()}"); - tag.doStartTag(); - tag.doEndTag(); - } + {PropertyTag tag = new PropertyTag(); + tag.setEscapeHtml(false); + tag.setEscapeCsv(true); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } + + public void testEscapeCsv_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("\"something,\",\""); + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("\"Foo is: \"\"something,\"\",\"\"\""); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + {PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscapeHtml(false); + tag.setEscapeCsv(true); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} // verify test request.verify(); @@ -288,13 +704,54 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.setRequest(request); // test - { - PropertyTag tag = new PropertyTag(); - tag.setPageContext(pageContext); - tag.setValue("formatTitle()"); - tag.doStartTag(); - tag.doEndTag(); - } + {PropertyTag tag = new PropertyTag(); + tag.setPageContext(pageContext); + tag.setValue("formatTitle()"); + tag.doStartTag(); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } + + public void testWithAltSyntax2_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("tm_jee"); + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("Foo is: tm_jee"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + {PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("formatTitle()"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} // verify test request.verify(); @@ -316,13 +773,18 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.setRequest(request); // test - { - PropertyTag tag = new PropertyTag(); - tag.setPageContext(pageContext); - tag.setValue("formatTitle()"); - tag.doStartTag(); - tag.doEndTag(); - } + {PropertyTag tag = new PropertyTag(); + tag.setPageContext(pageContext); + tag.setValue("formatTitle()"); + tag.doStartTag(); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} // verify test request.verify(); @@ -330,6 +792,41 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.verify(); } + public void testWithoutAltSyntax1_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("tm_jee"); + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("Foo is: tm_jee"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + {PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("formatTitle()"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } public void testWithoutAltSyntax2() throws Exception { // setups @@ -344,13 +841,18 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.setRequest(request); // test - { - PropertyTag tag = new PropertyTag(); - tag.setPageContext(pageContext); - tag.setValue("%{formatTitle()}"); - tag.doStartTag(); - tag.doEndTag(); - } + {PropertyTag tag = new PropertyTag(); + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} // verify test request.verify(); @@ -358,13 +860,168 @@ public class PropertyTagTest extends StrutsInternalTestCase { pageContext.verify(); } + public void testWithoutAltSyntax2_clearTagStateSet() throws Exception { + // setups + Foo foo = new Foo(); + foo.setTitle("tm_jee"); + stack.push(foo); + MockJspWriter jspWriter = new MockJspWriter(); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + // test + {PropertyTag tag = new PropertyTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("%{formatTitle()}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag));} + + // verify test + request.verify(); + jspWriter.verify(); + pageContext.verify(); + } + + public void testSimple_release() { + PropertyTag tag = new PropertyTag(); + + Foo foo = new Foo(); + foo.setTitle("test"); + + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("test"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + tag.setPageContext(pageContext); + tag.setValue("title"); + + try { + tag.doStartTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + request.verify(); + jspWriter.verify(); + pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + + // Test release at least once in unit tests (with clear tag state not set). + tag.release(); + assertTrue("Tag state after release() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() and release() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_release_clearTagStateSet() { + PropertyTag tag = new PropertyTag(); + + Foo foo = new Foo(); + foo.setTitle("test"); + + stack.push(foo); + + MockJspWriter jspWriter = new MockJspWriter(); + jspWriter.setExpectedData("test"); + + MockPageContext pageContext = new MockPageContext(); + pageContext.setJspWriter(jspWriter); + pageContext.setRequest(request); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("title"); + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + request.verify(); + jspWriter.verify(); + pageContext.verify(); + + try { + tag.doEndTag(); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PropertyTag freshTag = new PropertyTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + + // Test release at least once in unit tests (with clear tag state set). + tag.release(); + assertTrue("Tag state after release() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() and release() calls are not working properly.", + objectsAreReflectionEqual(tag, freshTag)); + } + + @Override protected void setUp() throws Exception { super.setUp(); stack = ActionContext.getContext().getValueStack(); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); } + /** + * Helper method to simplify setting the performClearTagStateForTagPoolingServers state for a + * {@link ComponentTagSupport} tag's {@link Component} to match expectations for the test. + * + * The component reference is not available to the tag until after the doStartTag() method is called. + * We need to ensure the component's {@link Component#performClearTagStateForTagPoolingServers} state matches + * what we set for the Tag when a non-default (true) value is used, so this method accesses the component instance, + * sets the value specified and forces the tag's parameters to be repopulated again. + * + * @param tag The ComponentTagSupport tag upon whose component we will set the performClearTagStateForTagPoolingServers state. + * @param performClearTagStateForTagPoolingServers true to clear tag state, false otherwise + */ + protected void setComponentTagClearTagState(ComponentTagSupport tag, boolean performClearTagStateForTagPoolingServers) { + tag.component.setPerformClearTagStateForTagPoolingServers(performClearTagStateForTagPoolingServers); + //tag.populateParams(); // Not safe to call after doStartTag() ... breaks some tests. + tag.populatePerformClearTagStateForTagPoolingServersParam(); // Only populate the performClearTagStateForTagPoolingServers parameter for the Tag. + } public static class Foo { private String title; @@ -381,6 +1038,7 @@ public class PropertyTagTest extends StrutsInternalTestCase { return "Foo is: " + title; } + @Override public String toString() { return formatTitle(); } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/PushTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/PushTagTest.java index 78de86f01..4da1b5ef1 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/PushTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/PushTagTest.java @@ -43,5 +43,42 @@ public class PushTagTest extends AbstractUITagTest { e.printStackTrace(); fail(); } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PushTag freshTag = new PushTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() { + PushTag tag = new PushTag(); + + stack.setValue("foo", "bar"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setValue("foo"); + + try { + assertEquals(2, stack.size()); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + assertEquals(3, stack.size()); + tag.doEndTag(); + assertEquals(2, stack.size()); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PushTag freshTag = new PushTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/SetTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/SetTagTest.java index 5edfae401..9e5c30eb5 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/SetTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/SetTagTest.java @@ -39,6 +39,33 @@ public class SetTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("chewie", servletContext.getAttribute("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testApplicationScope_clearTagStateSet() throws JspException { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setValue("name"); + tag.setScope("application"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("chewie", servletContext.getAttribute("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testPageScope() throws JspException { @@ -49,6 +76,33 @@ public class SetTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("chewie", pageContext.getAttribute("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testPageScope_clearTagStateSet() throws JspException { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setValue("name"); + tag.setScope("page"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("chewie", pageContext.getAttribute("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestScope() throws JspException { @@ -58,6 +112,32 @@ public class SetTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("chewie", request.getAttribute("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestScope_clearTagStateSet() throws JspException { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setValue("name"); + tag.setScope("request"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("chewie", request.getAttribute("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSessionScope() throws JspException { @@ -68,6 +148,33 @@ public class SetTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("chewie", session.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSessionScope_clearTagStateSet() throws JspException { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setValue("name"); + tag.setScope("session"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("chewie", session.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testStrutsScope() throws JspException { @@ -76,6 +183,31 @@ public class SetTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("chewie", context.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testStrutsScope_clearTagStateSet() throws JspException { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setValue("name"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("chewie", context.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testStrutsScope2() throws JspException { @@ -83,6 +215,30 @@ public class SetTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(chewie, context.get("chewie")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testStrutsScope2_clearTagStateSet() throws JspException { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("chewie"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(chewie, context.get("chewie")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSetTrimBody() throws JspException, IOException { @@ -100,6 +256,13 @@ public class SetTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(trimmedBeginEndSpaceString, context.get("foo")); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + tag.setName("foo"); tag.setValue(null); tag.setTrimBody(true); @@ -110,6 +273,11 @@ public class SetTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals(trimmedBeginEndSpaceString, context.get("foo")); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + tag.setName("foo"); tag.setValue(null); tag.setTrimBody(false); @@ -119,6 +287,69 @@ public class SetTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(beginEndSpaceString, context.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSetTrimBody_clearTagStateSet() throws JspException, IOException { + final String beginEndSpaceString = " Preceding and trailing spaces. "; + final String trimmedBeginEndSpaceString = beginEndSpaceString.trim(); + StrutsMockBodyContent mockBodyContent; + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setValue(null); + // Do not set any value - default for tag should be true + mockBodyContent = new StrutsMockBodyContent(new MockJspWriter()); + mockBodyContent.setString(beginEndSpaceString); + tag.setBodyContent(mockBodyContent); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(trimmedBeginEndSpaceString, context.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + tag.setName("foo"); + tag.setValue(null); + tag.setTrimBody(true); + mockBodyContent = new StrutsMockBodyContent(new MockJspWriter()); + mockBodyContent.setString(beginEndSpaceString); + tag.setBodyContent(mockBodyContent); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(trimmedBeginEndSpaceString, context.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + tag.setName("foo"); + tag.setValue(null); + tag.setTrimBody(false); + mockBodyContent = new StrutsMockBodyContent(new MockJspWriter()); + mockBodyContent.setString(beginEndSpaceString); + tag.setBodyContent(mockBodyContent); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(beginEndSpaceString, context.get("foo")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEmptyBody() throws JspException { @@ -133,8 +364,40 @@ public class SetTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(emptyBody, context.get(variableName)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testEmptyBody_clearTagStateSet() throws JspException { + StrutsMockBodyContent mockBodyContent; + String variableName = "foo"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(variableName); + tag.setValue(null); + mockBodyContent = new StrutsMockBodyContent(new MockJspWriter()); + String emptyBody = ""; + mockBodyContent.setString(emptyBody); + tag.setBodyContent(mockBodyContent); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(emptyBody, context.get(variableName)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SetTag freshTag = new SetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/SortIteratorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/SortIteratorTagTest.java index eef012c72..f88c2ae81 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/SortIteratorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/SortIteratorTagTest.java @@ -67,6 +67,55 @@ public class SortIteratorTagTest extends AbstractTagTest { assertFalse(sortedIterator.hasNext()); tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SortIteratorTag freshTag = new SortIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSortWithoutId_clearTagStateSet() throws Exception { + SortIteratorTag tag = new SortIteratorTag(); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setComparator("comparator"); + tag.setSource("source"); + + tag.setPageContext(pageContext); + tag.doStartTag(); + + // if not an Iterator, just let the ClassCastException be thrown as error instead of failure + Iterator sortedIterator = (Iterator) stack.findValue("top"); + + assertNotNull(sortedIterator); + // 1 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(1)); + // 2 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(2)); + // 3. + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(3)); + // 4. + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(4)); + // 5 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(5)); + + assertFalse(sortedIterator.hasNext()); + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SortIteratorTag freshTag = new SortIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSortWithIdIteratorAvailableInStackTop() throws Exception { @@ -104,8 +153,59 @@ public class SortIteratorTagTest extends AbstractTagTest { } tag.doEndTag(); - } + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SortIteratorTag freshTag = new SortIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testSortWithIdIteratorAvailableInStackTop_clearTagStateSet() throws Exception { + + SortIteratorTag tag = new SortIteratorTag(); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setVar("myId"); + tag.setComparator("comparator"); + tag.setSource("source"); + + tag.setPageContext(pageContext); + tag.doStartTag(); + + { + Iterator sortedIterator = (Iterator) stack.findValue("top"); + + assertNotNull(sortedIterator); + // 1 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(1)); + // 2 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(2)); + // 3 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(3)); + // 4 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(4)); + // 5 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(5)); + + assertFalse(sortedIterator.hasNext()); + } + + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SortIteratorTag freshTag = new SortIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testSortWithIdIteratorAvailableInPageContext() throws Exception { SortIteratorTag tag = new SortIteratorTag(); @@ -141,6 +241,58 @@ public class SortIteratorTagTest extends AbstractTagTest { } tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SortIteratorTag freshTag = new SortIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSortWithIdIteratorAvailableInPageContext_clearTagStateSet() throws Exception { + SortIteratorTag tag = new SortIteratorTag(); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setVar("myId"); + tag.setComparator("comparator"); + tag.setSource("source"); + + tag.setPageContext(pageContext); + tag.doStartTag(); + + { + Iterator sortedIterator = (Iterator) pageContext.getAttribute("myId"); + + assertNotNull(sortedIterator); + // 1 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(1)); + // 2 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(2)); + // 3 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(3)); + // 4 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(4)); + // 5 + assertTrue(sortedIterator.hasNext()); + assertEquals(sortedIterator.next(), new Integer(5)); + + assertFalse(sortedIterator.hasNext()); + } + + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SortIteratorTag freshTag = new SortIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSortWithIllegalSource() throws Exception { @@ -159,6 +311,8 @@ public class SortIteratorTagTest extends AbstractTagTest { // ok assertTrue(true); } + + // The doEndTag() call is expected not to complete. Cannot perform basic sanity check of clearTagStateForTagPoolingServers() behaviour. } public void testSortWithIllegalComparator() throws Exception { @@ -178,6 +332,7 @@ public class SortIteratorTagTest extends AbstractTagTest { assertTrue(true); } + // The doEndTag() call is expected not to complete. Cannot perform basic sanity check of clearTagStateForTagPoolingServers() behaviour. } public Action getAction() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/SubsetIteratorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/SubsetIteratorTagTest.java index 2bed2901a..4498124bb 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/SubsetIteratorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/SubsetIteratorTagTest.java @@ -51,6 +51,13 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(3)); assertEquals(subsetIterator.next(), new Integer(4)); assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } { // Array as Source @@ -67,6 +74,65 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(3)); assertEquals(subsetIterator.next(), new Integer(4)); assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } + + public void testBasic_clearTagStateSet() throws Exception { + { // List as Source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(1)); + assertEquals(subsetIterator.next(), new Integer(2)); + assertEquals(subsetIterator.next(), new Integer(3)); + assertEquals(subsetIterator.next(), new Integer(4)); + assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + { // Array as Source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myArray"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(1)); + assertEquals(subsetIterator.next(), new Integer(2)); + assertEquals(subsetIterator.next(), new Integer(3)); + assertEquals(subsetIterator.next(), new Integer(4)); + assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } @@ -83,6 +149,13 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(4)); assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } { // Array as source @@ -97,6 +170,61 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(4)); assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } + + public void testWithStartAttribute_clearTagStateSet() throws Exception { + { // List as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + tag.setStart("3"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(4)); + assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + { // Array as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myArray"); + tag.setStart("3"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(4)); + assertEquals(subsetIterator.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } @@ -114,6 +242,13 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(1)); assertEquals(subsetIterator.next(), new Integer(2)); assertEquals(subsetIterator.next(), new Integer(3)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } { // array as source @@ -129,6 +264,63 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(1)); assertEquals(subsetIterator.next(), new Integer(2)); assertEquals(subsetIterator.next(), new Integer(3)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } + + public void testWithCountAttribute_clearTagStateSet() throws Exception { + { // List as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + tag.setCount("3"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(1)); + assertEquals(subsetIterator.next(), new Integer(2)); + assertEquals(subsetIterator.next(), new Integer(3)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + { // array as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myArray"); + tag.setCount("3"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(1)); + assertEquals(subsetIterator.next(), new Integer(2)); + assertEquals(subsetIterator.next(), new Integer(3)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } @@ -146,6 +338,13 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer("4")); assertEquals(subsetIterator.next(), new Integer("5")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } { // Array as source @@ -161,6 +360,63 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer("4")); assertEquals(subsetIterator.next(), new Integer("5")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } + + public void testWIthStartAndCountAttribute_clearTagStateSet() throws Exception { + { // List as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + tag.setStart("3"); + tag.setCount("3"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer("4")); + assertEquals(subsetIterator.next(), new Integer("5")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + { // Array as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myArray"); + tag.setStart("3"); + tag.setCount("3"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer("4")); + assertEquals(subsetIterator.next(), new Integer("5")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } @@ -185,6 +441,13 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator2.next(), new Integer(3)); assertEquals(subsetIterator2.next(), new Integer(4)); assertEquals(subsetIterator2.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } { // Array as source @@ -207,6 +470,77 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator2.next(), new Integer(3)); assertEquals(subsetIterator2.next(), new Integer(4)); assertEquals(subsetIterator2.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } + + public void testWithId_clearTagStateSet() throws Exception { + { // List as Source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + tag.setVar("myPageContextId1"); + + tag.doStartTag(); + Iterator subsetIterator1 = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + Iterator subsetIterator2 = (Iterator) pageContext.getAttribute("myPageContextId1"); + + assertNotNull(subsetIterator1); + assertNotNull(subsetIterator2); + assertEquals(subsetIterator1, subsetIterator2); + assertEquals(subsetIterator2.next(), new Integer(1)); + assertEquals(subsetIterator2.next(), new Integer(2)); + assertEquals(subsetIterator2.next(), new Integer(3)); + assertEquals(subsetIterator2.next(), new Integer(4)); + assertEquals(subsetIterator2.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + { // Array as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myArray"); + tag.setVar("myPageContextId2"); + + tag.doStartTag(); + Iterator subsetIterator1 = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + Iterator subsetIterator2 = (Iterator) pageContext.getAttribute("myPageContextId2"); + + assertNotNull(subsetIterator1); + assertNotNull(subsetIterator2); + assertEquals(subsetIterator1, subsetIterator2); + assertEquals(subsetIterator2.next(), new Integer(1)); + assertEquals(subsetIterator2.next(), new Integer(2)); + assertEquals(subsetIterator2.next(), new Integer(3)); + assertEquals(subsetIterator2.next(), new Integer(4)); + assertEquals(subsetIterator2.next(), new Integer(5)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } @@ -223,6 +557,13 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(2)); assertEquals(subsetIterator.next(), new Integer(4)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } { // Array As source @@ -237,11 +578,65 @@ public class SubsetIteratorTagTest extends AbstractTagTest { assertEquals(subsetIterator.next(), new Integer(2)); assertEquals(subsetIterator.next(), new Integer(4)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } + public void testWithDecider_clearTagStateSet() throws Exception { + { // List as source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + tag.setDecider("myDecider"); + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + assertEquals(subsetIterator.next(), new Integer(2)); + assertEquals(subsetIterator.next(), new Integer(4)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + { // Array As source + SubsetIteratorTag tag = new SubsetIteratorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setSource("myList"); + tag.setDecider("myDecider"); + + tag.doStartTag(); + Iterator subsetIterator = (Iterator) stack.findValue("top"); + tag.doEndTag(); + + assertEquals(subsetIterator.next(), new Integer(2)); + assertEquals(subsetIterator.next(), new Integer(4)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubsetIteratorTag freshTag = new SubsetIteratorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } + + @Override public Action getAction() { return new ActionSupport() { public List getMyList() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java index 29b56271c..fa153e013 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java @@ -50,6 +50,7 @@ public class TextTagTest extends AbstractTagTest { private TextTag tag; + @Override public Action getAction() { TestAction action = new TestAction(); action.setFoo(fooValue); @@ -71,6 +72,39 @@ public class TextTagTest extends AbstractTagTest { assertEquals(startStatus, BodyTag.EVAL_BODY_BUFFERED); assertEquals("Sample Of Default Message", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDefaultMessageOk_clearTagStateSet() throws Exception { + // NOTE: + // simulate the condition + // My Default Message + + StrutsMockBodyContent mockBodyContent = new StrutsMockBodyContent(new MockJspWriter()); + mockBodyContent.setString("Sample Of Default Message"); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setBodyContent(mockBodyContent); + tag.setName("some.invalid.key.so.we.should.get.the.default.message"); + int startStatus = tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(startStatus, BodyTag.EVAL_BODY_BUFFERED); + assertEquals("Sample Of Default Message", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testExpressionsEvaluated() throws Exception { @@ -80,6 +114,32 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testExpressionsEvaluated_clearTagStateSet() throws Exception { + String key = "expressionKey"; + String value = "Foo is " + fooValue; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCorrectI18NKey() throws Exception { @@ -89,6 +149,32 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCorrectI18NKey_clearTagStateSet() throws Exception { + String key = "foo.bar.baz"; + String value = "This should start with foo"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCorrectI18NKey2() throws Exception { @@ -98,6 +184,32 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCorrectI18NKey2_clearTagStateSet() throws Exception { + String key = "bar.baz"; + String value = "No foo here"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testMessageFormatWorks() throws Exception { @@ -121,6 +233,46 @@ public class TextTagTest extends AbstractTagTest { ((Text) tag.component).addParameter(param3); tag.doEndTag(); assertEquals(expected, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMessageFormatWorks_clearTagStateSet() throws Exception { + String key = "messageFormatKey"; + String pattern = "Params are {0} {1} {2}"; + Object param1 = new Integer(12); + Object param2 = new Date(); + Object param3 = "StringVal"; + List params = new ArrayList(); + params.add(param1); + params.add(param2); + params.add(param3); + + MessageFormat format = new MessageFormat(pattern, ActionContext.getContext().getLocale()); + String expected = format.format(params.toArray()); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ((Text) tag.component).addParameter(param1); + ((Text) tag.component).addParameter(param2); + ((Text) tag.component).addParameter(param3); + tag.doEndTag(); + assertEquals(expected, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleKeyValueWorks() throws JspException { @@ -130,6 +282,32 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleKeyValueWorks_clearTagStateSet() throws JspException { + String key = "simpleKey"; + String value = "Simple Message"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } private Locale getForeignLocale() { @@ -169,6 +347,14 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value1, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + final StringBuffer buffer = writer.getBuffer(); buffer.delete(0, buffer.length()); ValueStack newStack = container.getInstance(ValueStackFactory.class).createValueStack(); @@ -176,10 +362,56 @@ public class TextTagTest extends AbstractTagTest { newStack.push(container.inject(TestAction1.class)); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack); assertNotSame(ActionContext.getContext().getValueStack().peek(), newStack.peek()); - + tag.setName(key); // Required as WW-5124 fix clears tag state. tag.doStartTag(); tag.doEndTag(); assertEquals(value2, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testTextTagUsesValueStackInRequestNotActionContext_clearTagStateSet() throws JspException { + String key = "simpleKey"; + String value1 = "Simple Message"; + Locale foreignLocale = getForeignLocale(); + String value2 = getLocalizedMessage(foreignLocale); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value1, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + final StringBuffer buffer = writer.getBuffer(); + buffer.delete(0, buffer.length()); + ValueStack newStack = container.getInstance(ValueStackFactory.class).createValueStack(); + newStack.getContext().put(ActionContext.LOCALE, foreignLocale); + newStack.getContext().put(ActionContext.CONTAINER, container); + newStack.push(container.inject(TestAction1.class)); + request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack); + assertNotSame(ActionContext.getContext().getValueStack().peek(), newStack.peek()); + tag.setName(key); // Required as WW-5124 fix clears tag state. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value2, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testTextTagUsesLocaleFromValueStack() throws JspException { @@ -198,6 +430,13 @@ public class TextTagTest extends AbstractTagTest { tag.doEndTag(); assertEquals(value_default, writer.toString()); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + final StringBuffer buffer = writer.getBuffer(); buffer.delete(0, buffer.length()); String value_int = getLocalizedMessage(foreignLocale); @@ -207,9 +446,64 @@ public class TextTagTest extends AbstractTagTest { assertNotSame(newStack.getActionContext().getLocale(), ActionContext.getContext().getLocale()); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack); assertEquals(ActionContext.getContext().getValueStack().peek(), newStack.peek()); + tag.setName(key); // Required as WW-5124 fix clears tag state. tag.doStartTag(); tag.doEndTag(); assertEquals(value_int, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testTextTagUsesLocaleFromValueStack_clearTagStateSet() throws JspException { + stack.pop(); + stack.push(container.inject(TestAction1.class)); + + Locale defaultLocale = getDefaultLocale(); + Locale foreignLocale = getForeignLocale(); + assertNotSame(defaultLocale, foreignLocale); + + ActionContext.getContext().setLocale(defaultLocale); + String key = "simpleKey"; + String value_default = getLocalizedMessage(defaultLocale); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value_default, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + final StringBuffer buffer = writer.getBuffer(); + buffer.delete(0, buffer.length()); + String value_int = getLocalizedMessage(foreignLocale); + assertFalse(value_default.equals(value_int)); + ValueStack newStack = container.getInstance(ValueStackFactory.class).createValueStack(stack); + newStack.getContext().put(ActionContext.LOCALE, foreignLocale); + newStack.getContext().put(ActionContext.CONTAINER, container); + assertNotSame(newStack.getContext().get(ActionContext.LOCALE), ActionContext.getContext().getLocale()); + request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, newStack); + assertEquals(ActionContext.getContext().getValueStack().peek(), newStack.peek()); + tag.setName(key); // Required as WW-5124 fix clears tag state. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value_int, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithNoMessageAndBodyIsNotEmptyBodyIsReturned() throws Exception { @@ -223,6 +517,36 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(bodyText, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithNoMessageAndBodyIsNotEmptyBodyIsReturned_clearTagStateSet() throws Exception { + final String key = "key.does.not.exist"; + final String bodyText = "body text"; + tag.setName(key); + + StrutsBodyContent bodyContent = new StrutsBodyContent(null); + bodyContent.print(bodyText); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setBodyContent(bodyContent); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(bodyText, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithNoMessageAndNoDefaultKeyReturned() throws JspException { @@ -231,6 +555,31 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(key, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithNoMessageAndNoDefaultKeyReturned_clearTagStateSet() throws JspException { + final String key = "key.does.not.exist"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(key, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoNameDefined() throws Exception { @@ -242,6 +591,8 @@ public class TextTagTest extends AbstractTagTest { } catch (StrutsException e) { assertEquals(msg, e.getMessage()); } + + // The doEndTag() call is expected not to complete. Cannot perform basic sanity check of clearTagStateForTagPoolingServers() behaviour. } public void testBlankNameDefined() throws Exception { @@ -249,6 +600,30 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testBlankNameDefined_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(""); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testPutId() throws Exception { @@ -259,6 +634,33 @@ public class TextTagTest extends AbstractTagTest { tag.doEndTag(); assertEquals("", writer.toString()); assertEquals("No foo here", stack.findString("myId")); // is in stack now + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testPutId_clearTagStateSet() throws Exception { + assertEquals(null, stack.findString("myId")); // nothing in stack + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setVar("myId"); + tag.setName("bar.baz"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("", writer.toString()); + assertEquals("No foo here", stack.findString("myId")); // is in stack now + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEscapeHtml() throws Exception { @@ -269,6 +671,33 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEscapeHtml_clearTagStateSet() throws Exception { + final String key = "foo.escape.html"; + final String value = "1 < 2"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.setEscapeHtml(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEscapeXml() throws Exception { @@ -279,6 +708,33 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEscapeXml_clearTagStateSet() throws Exception { + final String key = "foo.escape.xml"; + final String value = "<>'"&"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.setEscapeXml(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEscapeJavaScript() throws Exception { @@ -289,6 +745,33 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEscapeJavaScript_clearTagStateSet() throws Exception { + final String key = "foo.escape.javascript"; + final String value = "\\t\\b\\n\\f\\r\\\"\\\'\\/\\\\"; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.setEscapeJavaScript(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEscapeCsv() throws Exception { @@ -299,8 +782,41 @@ public class TextTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testEscapeCsv_clearTagStateSet() throws Exception { + final String key = "foo.escape.csv"; + final String value = "\"something,\"\",\"\"\""; + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName(key); + tag.setEscapeCsv(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(value, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextTag freshTag = new TextTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * todo remove ActionContext set after LocalizedTextUtil is fixed to not use ThreadLocal + * + * @throws Exception + */ + @Override protected void setUp() throws Exception { super.setUp(); tag = new TextTag(); @@ -308,6 +824,7 @@ public class TextTagTest extends AbstractTagTest { ActionContext.of(stack.getContext()).bind(); } + @Override protected void tearDown() throws Exception { super.tearDown(); } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java index 7b6117d27..fdb382f39 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java @@ -144,6 +144,149 @@ public class URLTagTest extends AbstractUITagTest { assertEquals(parameters.get("tagId"), "tagValue"); assertEquals(parameters.get("param1"), "param1value"); assertEquals(parameters.get("param2"), "param2value"); + + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * To test priority of parameter passed in to url component though + * various way + * - current request url + * - tag's value attribute + * - tag's nested param tag + * + * id1 + * === + * - found in current request url + * - found in tag's value attribute + * - found in tag's param tag + * CONCLUSION: tag's param tag takes precedence (paramId1) + * + * id2 + * === + * - found in current request url + * - found in tag's value attribute + * CONCLUSION: tag's value attribute take precedence (tagId2) + * + * urlParam1 + * ========= + * - found in current request url + * CONCLUSION: param in current request url will be used (urlValue1) + * + * urlParam2 + * ========= + * - found in current request url + * CONCLUSION: param in current request url will be used. (urlValue2) + * + * tagId + * ===== + * - found in tag's value attribute + * CONCLUSION: param in tag's value attribute wil; be used. (tagValue) + * + * param1 + * ====== + * - found in nested param tag + * CONCLUSION: param in nested param tag will be used. (param1value) + * + * param2 + * ====== + * - found in nested param tag + * CONCLUSION: param in nested param tag will be used. (param2value) + */ + public void testParametersPriority_clearTagStateSet() throws Exception { + request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue"); + + ParamTag param1 = new ParamTag(); + param1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param1.setPageContext(pageContext); + param1.setName("param1"); + param1.setValue("%{'param1value'}"); + + ParamTag param2 = new ParamTag(); + param2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param2.setPageContext(pageContext); + param2.setName("param2"); + param2.setValue("%{'param2value'}"); + + ParamTag param3 = new ParamTag(); + param3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param3.setPageContext(pageContext); + param3.setName("id1"); + param3.setValue("%{'paramId1'}"); + + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + param3.doStartTag(); + setComponentTagClearTagState(param3, true); // Ensure component tag state clearing is set true (to match tag). + param3.doEndTag(); + + URL url = (URL) tag.getComponent(); + Map parameters = url.getParameters(); + + + assertNotNull(parameters); + assertEquals(parameters.size(), 7); + assertEquals(parameters.get("id1"), "paramId1"); + assertEquals(parameters.get("id2"), "tagId2"); + assertEquals(parameters.get("urlParam1"), "urlValue1"); + assertEquals(parameters.get("urlParam2"), "urlValue2"); + assertEquals(parameters.get("tagId"), "tagValue"); + assertEquals(parameters.get("param1"), "param1value"); + assertEquals(parameters.get("param2"), "param2value"); + + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -168,8 +311,50 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/TestAction.action?p0=z&p1=a&p1=b&p2=d&p2=e&p3=f&p3=g", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + /** + * Use Iterable values as the value of the param tags + * @throws Exception + */ + public void testIterableParameters_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("/TestAction.action?p0=z"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + //Iterable + List list = new ArrayList(); + list.add(new ValueHolder("a")); + list.add(new ValueHolder("b")); + tag.component.addParameter("p1", list); + + //String[] + tag.component.addParameter("p2", new String[] { "d", "e" }); + //ValueHolder[] + tag.component.addParameter("p3", new ValueHolder[] { + new ValueHolder("f"), new ValueHolder("g") }); + + tag.doEndTag(); + + assertEquals("/TestAction.action?p0=z&p1=a&p1=b&p2=d&p2=e&p3=f&p3=g", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + /** * To test priority of parameter passed in to url component though * various way, with includeParams="NONE" @@ -202,7 +387,6 @@ public class URLTagTest extends AbstractUITagTest { param3.setName("id1"); param3.setValue("%{'paramId1'}"); - tag.doStartTag(); param1.doStartTag(); param1.doEndTag(); @@ -220,6 +404,113 @@ public class URLTagTest extends AbstractUITagTest { assertEquals(parameters.get("tagId"), "tagValue"); assertEquals(parameters.get("param1"), "param1value"); assertEquals(parameters.get("param2"), "param2value"); + + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * To test priority of parameter passed in to url component though + * various way, with includeParams="NONE" + * - current request url + * - tag's value attribute + * - tag's nested param tag + * + * In this case only parameters from the tag itself is taken into account. + * Those from request will not count, only those in tag's value attribute + * and nested param tag. + * + * @throws Exception + */ + public void testParametersPriorityWithIncludeParamsAsNONE_clearTagStateSet() throws Exception { + request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue"); + tag.setIncludeParams("NONE"); + + ParamTag param1 = new ParamTag(); + param1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param1.setPageContext(pageContext); + param1.setName("param1"); + param1.setValue("%{'param1value'}"); + + ParamTag param2 = new ParamTag(); + param2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param2.setPageContext(pageContext); + param2.setName("param2"); + param2.setValue("%{'param2value'}"); + + ParamTag param3 = new ParamTag(); + param3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param3.setPageContext(pageContext); + param3.setName("id1"); + param3.setValue("%{'paramId1'}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + param3.doStartTag(); + setComponentTagClearTagState(param3, true); // Ensure component tag state clearing is set true (to match tag). + param3.doEndTag(); + + URL url = (URL) tag.getComponent(); + Map parameters = url.getParameters(); + + assertEquals(parameters.size(), 5); + assertEquals(parameters.get("id1"), "paramId1"); + assertEquals(parameters.get("id2"), "tagId2"); + assertEquals(parameters.get("tagId"), "tagValue"); + assertEquals(parameters.get("param1"), "param1value"); + assertEquals(parameters.get("param2"), "param2value"); + + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeParamsDefaultToGET() throws Exception { @@ -245,6 +536,48 @@ public class URLTagTest extends AbstractUITagTest { assertEquals(parameters.get("one"), "oneVal"); assertEquals(parameters.get("two"), "twoVal"); assertEquals(parameters.get("three"), "threeVal"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeParamsDefaultToGET_clearTagStateSet() throws Exception { + request.setQueryString("one=oneVal&two=twoVal&three=threeVal"); + + // request parameter map should not have any effect, as includeParams + // default to GET, which get its param from request.getQueryString() + Map tmp = new HashMap(); + tmp.put("one", "aaa"); + tmp.put("two", "bbb"); + tmp.put("three", "ccc"); + request.setParameterMap(tmp); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("TestAction.acton"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + URL url = (URL) tag.getComponent(); + Map parameters = url.getParameters(); + + tag.doEndTag(); + + assertEquals(parameters.get("one"), "oneVal"); + assertEquals(parameters.get("two"), "twoVal"); + assertEquals(parameters.get("three"), "threeVal"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionURL() throws Exception { @@ -253,6 +586,31 @@ public class URLTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("TestAction.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionURL_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("TestAction.action"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("TestAction.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testAddParameters() throws Exception { @@ -266,6 +624,37 @@ public class URLTagTest extends AbstractUITagTest { tag.component.addParameter("param2", "value2"); tag.doEndTag(); assertEquals("/TestAction.action?param0=value0&param1=value1&param2=value2", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + // URLTag clears component in doEndTag and has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAddParameters_clearTagStateSet() throws Exception { + request.setAttribute("struts.request_uri", "/Test.action"); + + request.setAttribute("struts.request_uri", "/TestAction.action"); + request.setQueryString("param0=value0"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.component.addParameter("param1", "value1"); + tag.component.addParameter("param2", "value2"); + tag.doEndTag(); + assertEquals("/TestAction.action?param0=value0&param1=value1&param2=value2", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEvaluateValue() throws Exception { @@ -277,6 +666,34 @@ public class URLTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("test", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEvaluateValue_clearTagStateSet() throws Exception { + Foo foo = new Foo(); + foo.setTitle("test"); + stack.push(foo); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("%{title}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("test", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testHttps() throws Exception { @@ -289,6 +706,35 @@ public class URLTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("list-members.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testHttps_clearTagStateSet() throws Exception { + request.setScheme("https"); + request.setServerName("localhost"); + request.setServerPort(443); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("list-members.action"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("list-members.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testAnchor() throws Exception { @@ -302,6 +748,36 @@ public class URLTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("list-members.action#test", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAnchor_clearTagStateSet() throws Exception { + request.setScheme("https"); + request.setServerName("localhost"); + request.setServerPort(443); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("list-members.action"); + tag.setAnchor("test"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("list-members.action#test", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testParamPrecedence() throws Exception { @@ -324,6 +800,62 @@ public class URLTagTest extends AbstractUITagTest { urlTag.doEndTag(); assertEquals("/context/someAction.action?id=33&name=John", writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(urlTag, freshTag)); + } + + public void testParamPrecedence_clearTagStateSet() throws Exception { + request.setRequestURI("/context/someAction.action"); + request.setQueryString("id=22&name=John"); + + URLTag urlTag = new URLTag(); + urlTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + urlTag.setPageContext(pageContext); + urlTag.setIncludeParams("get"); + urlTag.setEncode("%{false}"); + + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("id"); + paramTag.setValue("%{'33'}"); + + urlTag.doStartTag(); + setComponentTagClearTagState(urlTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + urlTag.doEndTag(); + + assertEquals("/context/someAction.action?id=33&name=John", writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(urlTag, freshTag)); } public void testParamPrecedenceWithAnchor() throws Exception { @@ -347,16 +879,100 @@ public class URLTagTest extends AbstractUITagTest { urlTag.doEndTag(); assertEquals("/context/someAction.action?id=33&name=John#testAnchor", writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(urlTag, freshTag)); + } + + public void testParamPrecedenceWithAnchor_clearTagStateSet() throws Exception { + request.setRequestURI("/context/someAction.action"); + request.setQueryString("id=22&name=John"); + + URLTag urlTag = new URLTag(); + urlTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + urlTag.setPageContext(pageContext); + urlTag.setIncludeParams("get"); + urlTag.setEncode("%{false}"); + urlTag.setAnchor("testAnchor"); + + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("id"); + paramTag.setValue("%{'33'}"); + + urlTag.doStartTag(); + setComponentTagClearTagState(urlTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + urlTag.doEndTag(); + + assertEquals("/context/someAction.action?id=33&name=John#testAnchor", writer.getBuffer().toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(urlTag, freshTag)); } public void testPutId() throws Exception { tag.setValue("/public/about"); - assertNull(stack.findString("myId")); // nothing in stack + assertEquals(null, stack.findString("myId")); // nothing in stack tag.setVar("myId"); tag.doStartTag(); tag.doEndTag(); assertEquals("", writer.toString()); assertEquals("/public/about", stack.findString("myId")); // is in stack now + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testPutId_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("/public/about"); + assertEquals(null, stack.findString("myId")); // nothing in stack + tag.setVar("myId"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("", writer.toString()); + assertEquals("/public/about", stack.findString("myId")); // is in stack now + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testUsingValueOnly() throws Exception { @@ -364,6 +980,30 @@ public class URLTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("/public/about/team.jsp", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testUsingValueOnly_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setValue("/public/about/team.jsp"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("/public/about/team.jsp", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeNone() throws Exception { @@ -376,6 +1016,35 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/team.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeNone_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("none"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/team.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeGet() throws Exception { @@ -388,6 +1057,35 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/team.action?section=team&company=acme+inc", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeGet_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("get"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/team.action?section=team&company=acme+inc", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeGetDoNotEscapeAmp() throws Exception { @@ -401,8 +1099,38 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/team.action?section=team&company=acme+inc", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testRequestURIActionIncludeGetDoNotEscapeAmp_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("get"); + tag.setEscapeAmp("false"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/team.action?section=team&company=acme+inc", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testRequestURINoActionIncludeNone() throws Exception { request.setRequestURI("/public/about"); request.setQueryString("section=team&company=acme inc"); @@ -413,6 +1141,35 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/public/about", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURINoActionIncludeNone_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction(null); + tag.setIncludeParams("none"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/public/about", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoActionIncludeGet() throws Exception { @@ -425,6 +1182,35 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/public/about?section=team&company=acme+inc", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNoActionIncludeGet_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction(null); + tag.setIncludeParams("get"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/public/about?section=team&company=acme+inc", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIActionIncludeAll() throws Exception { @@ -447,6 +1233,62 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/team.action?section=team&company=acme+inc&year=2006", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIActionIncludeAll_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("all"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // include nested param tag + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("year"); + paramTag.setValue("2006"); + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + + tag.doEndTag(); + + assertEquals("/team.action?section=team&company=acme+inc&year=2006", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURINoActionIncludeAll() throws Exception { @@ -469,6 +1311,62 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/public/about?section=team&company=acme+inc&year=2006", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURINoActionIncludeAll_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction(null); + tag.setIncludeParams("all"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // include nested param tag + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("year"); + paramTag.setValue("2006"); + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + + tag.doEndTag(); + + assertEquals("/public/about?section=team&company=acme+inc&year=2006", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testUnknownIncludeParam() throws Exception { @@ -479,6 +1377,33 @@ public class URLTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("/public/about", writer.toString()); // should not add any request parameters + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testUnknownIncludeParam_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setIncludeParams("unknown"); // will log at WARN level + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("/public/about", writer.toString()); // should not add any request parameters + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequestURIWithAnchor() throws Exception { @@ -491,6 +1416,35 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/company.action?company=acme+inc", writer.toString()); // will always chop anchor if using requestURI + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequestURIWithAnchor_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("company=acme inc#canada"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("company"); + tag.setIncludeParams("get"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/company.action?company=acme+inc", writer.toString()); // will always chop anchor if using requestURI + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeContext() throws Exception { @@ -502,6 +1456,34 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/myapp/company.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testIncludeContext_clearTagStateSet() throws Exception { + request.setupGetContext("/myapp"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setIncludeContext("true"); + tag.setAction("company"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("/myapp/company.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testForceAddSchemeHostAndPort() throws Exception { @@ -511,8 +1493,34 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("http://localhost/company.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testForceAddSchemeHostAndPort_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setForceAddSchemeHostAndPort("true"); + tag.setAction("company"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("http://localhost/company.action", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testEmptyActionCustomMapper() throws Exception { Map props = new HashMap<>(); props.put("config", "struts-default.xml,struts-plugin.xml,struts.xml,org/apache/struts2/views/jsp/WW3090-struts.xml"); @@ -521,6 +1529,127 @@ public class URLTagTest extends AbstractUITagTest { Dispatcher du = this.initDispatcher(props); + /** + * create our standard mock objects + */ + action = this.getAction(); + stack = ActionContext.getContext().getValueStack(); + context = stack.getContext(); + stack.push(action); + + request = new StrutsMockHttpServletRequest(); + request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); + response = new StrutsMockHttpServletResponse(); + request.setSession(new StrutsMockHttpSession()); + request.setupGetServletPath("/"); + + writer = new StringWriter(); + + servletContext = new StrutsMockServletContext(); + servletContext.setRealPath(new File("nosuchfile.properties").getAbsolutePath()); + servletContext.setServletInfo("Resin"); + + pageContext = new StrutsMockPageContext(); + pageContext.setRequest(request); + pageContext.setResponse(response); + pageContext.setServletContext(servletContext); + + mockContainer = new Mock(Container.class); + + session = new SessionMap(request); + Map extraContext = du.createContextMap(new RequestMap(request), + HttpParameters.create(request.getParameterMap()).build(), + session, + new ApplicationMap(pageContext.getServletContext()), + request, + response); + // let's not set the locale -- there is a test that checks if Dispatcher actually picks this up... + // ... but generally we want to just use no locale (let it stay system default) + extraContext.remove(ActionContext.LOCALE); + stack.getContext().putAll(extraContext); + + context.put(ServletActionContext.HTTP_REQUEST, request); + context.put(ServletActionContext.HTTP_RESPONSE, response); + context.put(ServletActionContext.SERVLET_CONTEXT, servletContext); + + ActionContext actionContext = ActionContext.of(context) + .withServletRequest(request) + .withServletResponse(response) + .withServletContext(servletContext) + .bind(); + + // Make sure we have an action invocation available + ActionContext.getContext().withActionInvocation(new DefaultActionInvocation(null, true)); + DefaultActionProxyFactory apFactory = new DefaultActionProxyFactory(); + apFactory.setContainer(container); + ActionProxy ap = apFactory.createActionProxy("/", "hello", null, null); + ActionContext.getContext().getActionInvocation().init(ap); + + request.setScheme("http"); + request.setServerName("localhost"); + request.setServerPort(80); + + tag = new URLTag(); + tag.setPageContext(pageContext); + JspWriter jspWriter = new StrutsMockJspWriter(writer); + pageContext.setJspWriter(jspWriter); + + request.setRequestURI("/context/someAction.action"); + + tag.setAction(null); + tag.setValue(null); + tag.doStartTag(); + tag.doEndTag(); + + assertEquals("/hello.action-red", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + // URLTag clears component in doEndTag and has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + writer = new StringWriter(); + jspWriter = new StrutsMockJspWriter(writer); + pageContext.setJspWriter(jspWriter); + + tag.doStartTag(); + tag.doEndTag(); + + assertEquals("/hello.action-blue", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + // URLTag clears component in doEndTag and has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + writer = new StringWriter(); + jspWriter = new StrutsMockJspWriter(writer); + pageContext.setJspWriter(jspWriter); + + tag.doStartTag(); + tag.doEndTag(); + + assertEquals("/hello.action-red", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + // URLTag clears component in doEndTag and has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEmptyActionCustomMapper_clearTagStateSet() throws Exception { + Map props = new HashMap(); + props.put("config", "struts-default.xml,struts-plugin.xml,struts.xml,org/apache/struts2/views/jsp/WW3090-struts.xml"); + + this.tearDown(); + + Dispatcher du = this.initDispatcher(props); + action = this.getAction(); stack = ActionContext.getContext().getValueStack(); context = stack.getContext(); @@ -575,6 +1704,7 @@ public class URLTagTest extends AbstractUITagTest { request.setServerPort(80); tag = new URLTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setPageContext(pageContext); JspWriter jspWriter = new StrutsMockJspWriter(writer); pageContext.setJspWriter(jspWriter); @@ -584,29 +1714,48 @@ public class URLTagTest extends AbstractUITagTest { tag.setAction(null); tag.setValue(null); tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). tag.doEndTag(); assertEquals("/hello.action-red", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); writer = new StringWriter(); jspWriter = new StrutsMockJspWriter(writer); pageContext.setJspWriter(jspWriter); tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). tag.doEndTag(); assertEquals("/hello.action-blue", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); writer = new StringWriter(); jspWriter = new StrutsMockJspWriter(writer); pageContext.setJspWriter(jspWriter); tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). tag.doEndTag(); assertEquals("/hello.action-red", writer.toString()); - + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEmbeddedParamTagExpressionGetsEvaluatedCorrectly() throws Exception { @@ -632,6 +1781,65 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/team.action?section=team&company=acme+inc&title=test", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEmbeddedParamTagExpressionGetsEvaluatedCorrectly_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + request.setQueryString("section=team&company=acme inc"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("all"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + Foo foo = new Foo("test"); + stack.push(foo); + + // include nested param tag + ParamTag paramTag = new ParamTag(); + paramTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + paramTag.setPageContext(pageContext); + paramTag.setName("title"); + paramTag.setValue("%{title}"); + paramTag.doStartTag(); + setComponentTagClearTagState(paramTag, true); // Ensure component tag state clearing is set true (to match tag). + paramTag.doEndTag(); + + tag.doEndTag(); + + assertEquals("/team.action?section=team&company=acme+inc&title=test", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(paramTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testAccessToStackInternalsGetsHandledCorrectly() throws Exception { @@ -668,6 +1876,59 @@ public class URLTagTest extends AbstractUITagTest { "aae%24%7B%23session%5B%22bar%22%5D%7D=1%24%7B%23session%5B%22bar%22%5D%7D" , writer.toString() ); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testAccessToStackInternalsGetsHandledCorrectly_clearTagStateSet() throws Exception { + Map params = new LinkedHashMap<>(); + params.put("aaa", new String[] {"1${#session[\"foo\"]='true'}"}); + params.put("aab", new String[]{"1${#session[\"bar\"]}"}); + params.put("aac", new String[]{"1${#_memberAccess[\"allowStaticMethodAccess\"]='true'}"}); + params.put("aad", new String[]{"1${#_memberAccess[\"allowStaticMethodAccess\"]}"}); + + request.setParameterMap(params); + request.setRequestURI("/public/about"); + request.setQueryString("aae${%23session[\"bar\"]}=1%24%7B%23session%5B%22bar%22%5D%7D"); + session.put("bar", "rab"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("team"); + tag.setIncludeParams("all"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + Object allowMethodAccess = stack.findValue("\u0023_memberAccess['allowStaticMethodAccess']"); + assertNull(allowMethodAccess); + + assertNull(session.get("foo")); + + assertEquals("/team.action?aaa=1%24%7B%23session%5B%22foo%22%5D%3D%27true%27%7D" + + "&" + + "aab=1%24%7B%23session%5B%22bar%22%5D%7D" + + "&" + + "aac=1%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3D%27true%27%7D" + + "&" + + "aad=1%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%7D" + + "&" + + "aae%24%7B%23session%5B%22bar%22%5D%7D=1%24%7B%23session%5B%22bar%22%5D%7D" + , writer.toString() + ); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIncludeEmptyParameters() throws Exception { @@ -723,8 +1984,122 @@ public class URLTagTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("/company.action?paramWithSetValue=¶mWithSetBody=", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param4, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testIncludeEmptyParameters_clearTagStateSet() throws Exception { + request.setRequestURI("/public/about"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setAction("company"); + tag.setEscapeAmp("false"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + ParamTag param1 = new ParamTag(); + param1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param1.setPageContext(pageContext); + param1.setName("paramWithSetValue"); + param1.setValue(""); + param1.setSuppressEmptyParameters(false); + param1.doStartTag(); + setComponentTagClearTagState(param1, true); // Ensure component tag state clearing is set true (to match tag). + param1.doEndTag(); + + ParamTag param2 = new ParamTag(); + param2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param2.setPageContext(pageContext); + param2.setName("paramWithSetBody"); + param2.setBodyContent(new MockBodyContent() { + @Override + public String getString() { + return ""; + } + }); + param2.setSuppressEmptyParameters(false); + param2.doStartTag(); + setComponentTagClearTagState(param2, true); // Ensure component tag state clearing is set true (to match tag). + param2.doEndTag(); + + ParamTag param3 = new ParamTag(); + param3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param3.setPageContext(pageContext); + param3.setName("paramWithSetValueSuppressed"); + param3.setValue(""); + param3.setSuppressEmptyParameters(true); + param3.doStartTag(); + setComponentTagClearTagState(param3, true); // Ensure component tag state clearing is set true (to match tag). + param3.doEndTag(); + + ParamTag param4 = new ParamTag(); + param4.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + param4.setPageContext(pageContext); + param4.setName("paramWithSetBodySuppressed"); + param4.setBodyContent(new MockBodyContent() { + @Override + public String getString() { + return ""; + } + }); + param4.setSuppressEmptyParameters(true); + param4.doStartTag(); + setComponentTagClearTagState(param4, true); // Ensure component tag state clearing is set true (to match tag). + param4.doEndTag(); + + tag.doEndTag(); + + assertEquals("/company.action?paramWithSetValue=¶mWithSetBody=", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param2, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param3, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(param4, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + URLTag freshTag = new URLTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionErrorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionErrorTagTest.java index b16e6c847..418533986 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionErrorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionErrorTagTest.java @@ -45,6 +45,35 @@ public class ActionErrorTagTest extends AbstractUITagTest { //assertEquals("", writer.toString()); verify(ActionErrorTagTest.class.getResource("actionerror-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPageContext(pageContext); + // AcionErrorTag has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNoActionErrors_clearTagStateSet() throws Exception { + ActionErrorTag tag = new ActionErrorTag(); + ((InternalActionSupport)action).setHasActionErrors(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //assertEquals("", writer.toString()); + verify(ActionErrorTagTest.class.getResource("actionerror-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionErrorsEscape() throws Exception { @@ -61,6 +90,40 @@ public class ActionErrorTagTest extends AbstractUITagTest { assertEquals(normalize("
  • <p>hey</p>
", true), normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPageContext(pageContext); + // AcionErrorTag sets escape true by default and has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionErrorsEscape_clearTagStateSet() throws Exception { + + ActionErrorTag tag = new ActionErrorTag(); + TestAction testAction = new TestAction(); + testAction.addActionError("

hey

"); + stack.pop(); + stack.push(testAction); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscape(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(normalize("
  • <p>hey</p>
", true), + normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionErrorsDontEscape() throws Exception { @@ -77,6 +140,39 @@ public class ActionErrorTagTest extends AbstractUITagTest { assertEquals(normalize("
  • hey

", true), normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionErrorsDontEscape_clearTagStateSet() throws Exception { + + ActionErrorTag tag = new ActionErrorTag(); + TestAction testAction = new TestAction(); + testAction.addActionError("

hey

"); + stack.pop(); + stack.push(testAction); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscape(false); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(normalize("
  • hey

", true), + normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testHaveActionErrors() throws Exception { @@ -89,6 +185,35 @@ public class ActionErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(ActionErrorTagTest.class.getResource("actionerror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testHaveActionErrors_clearTagStateSet() throws Exception { + + ActionErrorTag tag = new ActionErrorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setId("someid"); + ((InternalActionSupport)action).setHasActionErrors(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ActionErrorTagTest.class.getResource("actionerror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNullError() throws Exception { @@ -102,6 +227,36 @@ public class ActionErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(ActionErrorTagTest.class.getResource("actionerror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNullError_clearTagStateSet() throws Exception { + + ActionErrorTag tag = new ActionErrorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setId("someid"); + ((InternalActionSupport)action).setHasActionErrors(true); + ((InternalActionSupport)action).addActionError(null); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ActionErrorTagTest.class.getResource("actionerror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testEmptyErrorList() throws Exception { @@ -115,9 +270,39 @@ public class ActionErrorTagTest extends AbstractUITagTest { tag.doEndTag(); assertTrue(StringUtils.isBlank(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testEmptyErrorList_clearTagStateSet() throws Exception { + ActionErrorTag tag = new ActionErrorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setId("someid"); + ((InternalActionSupport)action).setHasActionErrors(true); + ((InternalActionSupport)action).setJustNullElement(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertTrue(StringUtils.isBlank(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionErrorTag freshTag = new ActionErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override public Action getAction() { return new InternalActionSupport(); } @@ -138,10 +323,12 @@ public class ActionErrorTagTest extends AbstractUITagTest { yesActionErrors = aYesActionErrors; } + @Override public boolean hasActionErrors() { return yesActionErrors; } + @Override public Collection getActionErrors() { if (justNullElement) { return Arrays.asList(null); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionMessageTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionMessageTagTest.java index 15ec1af13..776880c82 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionMessageTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionMessageTagTest.java @@ -45,6 +45,35 @@ public class ActionMessageTagTest extends AbstractUITagTest { tag.doEndTag(); verify(ActionMessageTagTest.class.getResource("actionmessage-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPageContext(pageContext); + // AcionMessageTag has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNoActionMessages_clearTagStateSet() throws Exception { + + ActionMessageTag tag = new ActionMessageTag(); + ((InternalActionSupport)action).setHasActionMessage(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ActionMessageTagTest.class.getResource("actionmessage-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionMessageEscape() throws Exception { @@ -61,6 +90,40 @@ public class ActionMessageTagTest extends AbstractUITagTest { assertEquals(normalize("
  • <p>hey</p>
", true), normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPageContext(pageContext); + // AcionMessageTag sets escape true by default and has no additional state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testActionMessageEscape_clearTagStateSet() throws Exception { + + ActionMessageTag tag = new ActionMessageTag(); + TestAction testAction = new TestAction(); + testAction.addActionMessage("

hey

"); + stack.pop(); + stack.push(testAction); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscape(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(normalize("
  • <p>hey</p>
", true), + normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testActionErrorsDontEscape() throws Exception { @@ -77,8 +140,40 @@ public class ActionMessageTagTest extends AbstractUITagTest { assertEquals(normalize("
  • hey

", true), normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testActionErrorsDontEscape_clearTagStateSet() throws Exception { + + ActionMessageTag tag = new ActionMessageTag(); + TestAction testAction = new TestAction(); + testAction.addActionMessage("

hey

"); + stack.pop(); + stack.push(testAction); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscape(false); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(normalize("
  • hey

", true), + normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testYesActionMessages() throws Exception { @@ -90,6 +185,35 @@ public class ActionMessageTagTest extends AbstractUITagTest { tag.doEndTag(); verify(ActionMessageTagTest.class.getResource("actionmessage-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testYesActionMessages_clearTagStateSet() throws Exception { + + ActionMessageTag tag = new ActionMessageTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setId("someid"); + ((InternalActionSupport)action).setHasActionMessage(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ActionMessageTagTest.class.getResource("actionmessage-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testYesActionMessagesWithEmptyMessages() throws Exception { @@ -102,7 +226,37 @@ public class ActionMessageTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); - assertTrue(StringUtils.isBlank(writer.toString())); + assertTrue(StringUtils.isBlank(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testYesActionMessagesWithEmptyMessages_clearTagStateSet() throws Exception { + + ActionMessageTag tag = new ActionMessageTag(); + tag.setId("someid"); + InternalActionSupport internalActionSupport = (InternalActionSupport) action; + internalActionSupport.setJustNullElement(true); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertTrue(StringUtils.isBlank(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNullMessage() throws Exception { @@ -116,8 +270,39 @@ public class ActionMessageTagTest extends AbstractUITagTest { tag.doEndTag(); verify(ActionMessageTagTest.class.getResource("actionmessage-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testNullMessage_clearTagStateSet() throws Exception { + + ActionMessageTag tag = new ActionMessageTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setId("someid"); + ((InternalActionSupport)action).setHasActionMessage(true); + ((InternalActionSupport)action).addActionMessage(null); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ActionMessageTagTest.class.getResource("actionmessage-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionMessageTag freshTag = new ActionMessageTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override public Action getAction() { return new InternalActionSupport(); } @@ -142,6 +327,7 @@ public class ActionMessageTagTest extends AbstractUITagTest { this.justNullElement = justNullElement; } + @Override public Collection getActionMessages() { if (justNullElement) { return Arrays.asList(null); @@ -157,6 +343,7 @@ public class ActionMessageTagTest extends AbstractUITagTest { } } + @Override public boolean hasActionMessages() { return canHaveActionMessage; } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/AnchorTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/AnchorTest.java index c031f3945..8101cc8a1 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/AnchorTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/AnchorTest.java @@ -47,6 +47,34 @@ public class AnchorTest extends AbstractUITagTest { tag.doEndTag(); verifyResource("href-1.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + createAction(); + + AnchorTag tag = createTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setHref("a"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verifyResource("href-1.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleBadQuote() throws Exception { @@ -58,6 +86,34 @@ public class AnchorTest extends AbstractUITagTest { tag.doEndTag(); verifyResource("href-2.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleBadQuote_clearTagStateSet() throws Exception { + createAction(); + + AnchorTag tag = createTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setHref("a\""); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verifyResource("href-2.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDynamicAttribute() throws Exception { @@ -72,6 +128,37 @@ public class AnchorTest extends AbstractUITagTest { tag.doEndTag(); verifyResource("Anchor-2.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDynamicAttribute_clearTagStateSet() throws Exception { + createAction(); + + AnchorTag tag = createTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setHref("a"); + + tag.setDynamicAttribute("uri", "dynAttrName", "dynAttrValue"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verifyResource("Anchor-2.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDynamicAttributeAsExpression() throws Exception { @@ -86,6 +173,37 @@ public class AnchorTest extends AbstractUITagTest { tag.doEndTag(); verifyResource("Anchor-3.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDynamicAttributeAsExpression_clearTagStateSet() throws Exception { + createAction(); + + AnchorTag tag = createTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setHref("a"); + + tag.setDynamicAttribute("uri", "placeholder", "%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verifyResource("Anchor-3.txt"); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + AnchorTag freshTag = new AnchorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } private void createAction() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java index 1f72445b9..0ea404aa1 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java @@ -40,6 +40,7 @@ public class CheckboxListTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = super.initializedGenericTagTestProperties(); new PropertyHolder("value", "hello").addToMap(result); @@ -98,6 +99,49 @@ public class CheckboxListTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxListTag.class.getResource("CheckboxList-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMultiple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + Collection collection = new ArrayList(2); + collection.add("hello"); + collection.add("foo"); + testAction.setCollection(collection); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"}, + {"cat", "dog"} + }); + + CheckboxListTag tag = new CheckboxListTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxListTag.class.getResource("CheckboxList-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testMultipleWithDisabledOn() throws Exception { @@ -125,6 +169,50 @@ public class CheckboxListTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxListTag.class.getResource("CheckboxList-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMultipleWithDisabledOn_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + Collection collection = new ArrayList(2); + collection.add("hello"); + collection.add("foo"); + testAction.setCollection(collection); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"}, + {"cat", "dog"} + }); + + CheckboxListTag tag = new CheckboxListTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + tag.setDisabled("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxListTag.class.getResource("CheckboxList-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimple() throws Exception { @@ -150,6 +238,48 @@ public class CheckboxListTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxListTag.class.getResource("CheckboxList-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"}, + {"baz", null} + }); + + CheckboxListTag tag = new CheckboxListTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + tag.setOnchange("alert('foo');"); + tag.setTitle("mytitle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxListTag.class.getResource("CheckboxList-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleWithDisableOn() throws Exception { @@ -174,5 +304,46 @@ public class CheckboxListTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxListTag.class.getResource("CheckboxList-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleWithDisableOn_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"} + }); + + CheckboxListTag tag = new CheckboxListTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + tag.setOnchange("alert('foo');"); + tag.setDisabled("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxListTag.class.getResource("CheckboxList-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxListTag freshTag = new CheckboxListTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java index 256e639b5..778fb19f4 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java @@ -19,8 +19,6 @@ package org.apache.struts2.views.jsp.ui; import java.util.Map; -import java.util.HashMap; -import java.util.Collections; import org.apache.struts2.TestAction; import org.apache.struts2.views.jsp.AbstractUITagTest; @@ -41,6 +39,7 @@ public class CheckboxTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = super.initializedGenericTagTestProperties(); new PropertyHolder("value", "true").addToMap(result); @@ -74,6 +73,42 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testChecked_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("someId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setOnfocus("test();"); + tag.setTitle("mytitle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCheckedWithTopLabelPosition() throws Exception { @@ -94,6 +129,43 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCheckedWithTopLabelPosition_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("someId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setOnfocus("test();"); + tag.setTitle("mytitle"); + tag.setLabelposition("top"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCheckedWithLeftLabelPosition() throws Exception { @@ -114,6 +186,43 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCheckedWithLeftLabelPosition_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("someId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setOnfocus("test();"); + tag.setTitle("mytitle"); + tag.setLabelposition("left"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCheckedWithError() throws Exception { @@ -136,6 +245,45 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCheckedWithError_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + testAction.addFieldError("foo", "Some Foo Error"); + testAction.addFieldError("foo", "Another Foo Error"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setOndblclick("test();"); + tag.setOnclick("test();"); + tag.setTitle("mytitle"); + tag.setCssErrorClass("myErrorClass"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCheckedWithErrorStyle() throws Exception { @@ -158,6 +306,45 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-33.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCheckedWithErrorStyle_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + testAction.addFieldError("foo", "Some Foo Error"); + testAction.addFieldError("foo", "Another Foo Error"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setOndblclick("test();"); + tag.setOnclick("test();"); + tag.setTitle("mytitle"); + tag.setCssErrorStyle("color:red"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-33.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testUnchecked() throws Exception { @@ -175,8 +362,42 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testUnchecked_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("false"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setTitle("mytitle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testDisabled() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("true"); @@ -193,6 +414,41 @@ public class CheckboxTest extends AbstractUITagTest { tag.doEndTag(); verify(CheckboxTag.class.getResource("Checkbox-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDisabled_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + + CheckboxTag tag = new CheckboxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFieldValue("baz"); + tag.setTitle("mytitle"); + tag.setDisabled("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(CheckboxTag.class.getResource("Checkbox-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSubmitUncheckedAsFalse() throws Exception { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java index 03b627e87..e21ca40bc 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java @@ -79,6 +79,48 @@ public class ComboBoxTest extends AbstractUITagTest { tag.doEndTag(); verify(ComboBoxTag.class.getResource("ComboBox-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + + ArrayList collection = new ArrayList(); + collection.add("foo"); + collection.add("bar"); + collection.add("baz"); + testAction.setCollection(collection); + + ComboBoxTag tag = new ComboBoxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setId("cb"); + tag.setList("collection"); + + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComboBoxTag.class.getResource("ComboBox-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithEmptyOptionAndHeader() throws Exception { @@ -106,6 +148,50 @@ public class ComboBoxTest extends AbstractUITagTest { tag.doEndTag(); verify(ComboBoxTag.class.getResource("ComboBox-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithEmptyOptionAndHeader_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("banana"); + + List l = new ArrayList(); + l.add("apple"); + l.add("banana"); + l.add("pineaple"); + l.add("grapes"); + testAction.setCollection(l); + + ComboBoxTag tag = new ComboBoxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("My Favourite Fruit"); + tag.setName("myFavouriteFruit"); + tag.setEmptyOption("true"); + tag.setHeaderKey("-1"); + tag.setHeaderValue("--- Please Select ---"); + tag.setList("collection"); + tag.setValue("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComboBoxTag.class.getResource("ComboBox-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithMap() throws Exception { @@ -133,6 +219,50 @@ public class ComboBoxTest extends AbstractUITagTest { tag.doEndTag(); verify(ComboBoxTag.class.getResource("ComboBox-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithMap_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("banana"); + + Map m = new LinkedHashMap(); + m.put("apple", "apple"); + m.put("banana", "banana"); + m.put("pineaple", "pineaple"); + m.put("grapes", "grapes"); + testAction.setMap(m); + + ComboBoxTag tag = new ComboBoxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("My Favourite Fruit"); + tag.setName("myFavouriteFruit"); + tag.setHeaderKey("-1"); + tag.setHeaderValue("--- Please Select ---"); + tag.setEmptyOption("true"); + tag.setList("map"); + tag.setValue("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComboBoxTag.class.getResource("ComboBox-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testJsCallNamingUsesEscapedId() throws Exception { @@ -154,6 +284,44 @@ public class ComboBoxTest extends AbstractUITagTest { tag.doEndTag(); verify(ComboBoxTag.class.getResource("ComboBox-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testJsCallNamingUsesEscapedId_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + + ArrayList collection = new ArrayList(); + collection.add("foo"); + testAction.setCollection(collection); + + ComboBoxTag tag = new ComboBoxTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setId("cb['\".\"'] = bc(){};//"); + tag.setList("collection"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComboBoxTag.class.getResource("ComboBox-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComboBoxTag freshTag = new ComboBoxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComponentTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComponentTest.java index 78765d89f..7e227ac61 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComponentTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComponentTest.java @@ -19,7 +19,6 @@ package org.apache.struts2.views.jsp.ui; import org.apache.struts2.TestAction; -import org.apache.struts2.components.Component; import org.apache.struts2.views.jsp.AbstractUITagTest; @@ -46,6 +45,44 @@ public class ComponentTest extends AbstractUITagTest { tag.doEndTag(); verify(ComponentTag.class.getResource("Component-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * Test that id attribute is evaludated against the Ognl Stack. + * @throws Exception + */ + public void testIdIsEvaluatedAgainstStack1_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("myFooValue"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("foo"); + tag.setId("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComponentTag.class.getResource("Component-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testIdIsEvaludatedAgainstStack2() throws Exception { @@ -63,8 +100,41 @@ public class ComponentTest extends AbstractUITagTest { tag.doEndTag(); verify(ComponentTag.class.getResource("Component-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testIdIsEvaludatedAgainstStack2_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("myFooValue"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("foo"); + tag.setId("foo"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComponentTag.class.getResource("Component-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } /** * Note -- this test uses empty.vm, so it's basically clear @@ -83,6 +153,42 @@ public class ComponentTest extends AbstractUITagTest { tag.doEndTag(); verify(ComponentTag.class.getResource("Component-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComponentTag freshTag = new ComponentTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * Note -- this test uses empty.vm, so it's basically clear + */ + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ComponentTag tag = new ComponentTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("foo"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ComponentTag.class.getResource("Component-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComponentTag freshTag = new ComponentTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -111,6 +217,51 @@ public class ComponentTest extends AbstractUITagTest { // System.out.println(writer); verify(ComponentTag.class.getResource("Component-param.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComponentTag freshTag = new ComponentTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * executes a component test passing in a custom parameter. it also executes calling a custom template using an + * absolute reference. + */ + public void testWithParam_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ComponentTag tag = new ComponentTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("foo"); + tag.setTheme("test"); + tag.setTemplate("Component"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.getComponent().addParameter("hello", "world"); + tag.getComponent().addParameter("argle", "bargle"); + tag.getComponent().addParameter("glip", "glop"); + tag.getComponent().addParameter("array", new String[]{"a", "b", "c"}); + tag.getComponent().addParameter("objClass", tag.getClass().getName()); + tag.doEndTag(); + + // System.out.println(writer); + verify(ComponentTag.class.getResource("Component-param.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ComponentTag freshTag = new ComponentTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testTagAttributeExclusion() throws Exception { @@ -122,6 +273,9 @@ public class ComponentTest extends AbstractUITagTest { tag.doStartTag(); assertTrue(tag.includeContext); + + // Calling tag.doEndTag() results in an exception. + // Aa a result, a basic sanity check of clearTagStateForTagPoolingServers() cannot be called. } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java index ccf506384..6f6e31ecc 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java @@ -33,6 +33,8 @@ import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; +import org.apache.struts2.components.Component; +import org.apache.struts2.components.DateTextField; /** * Unit test for {@link org.apache.struts2.components.Date}. @@ -54,6 +56,37 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCustomFormat_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Date now = new Date(); + String formatted = new SimpleDateFormat(format).format(now); + context.put("myDate", now); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.setFormat(format); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCustomGlobalFormatFormat() throws Exception { @@ -84,8 +117,43 @@ public class DateTagTest extends AbstractTagTest { tag.setFormat(format); tag.setTimezone("GMT+1"); tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCustomFormatWithTimezone_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+1")).getTime(); + SimpleDateFormat sdf = new SimpleDateFormat(format); + sdf.setTimeZone(TimeZone.getTimeZone("GMT+1")); + String formatted = sdf.format(now); + context.put("myDate", now); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.setFormat(format); + tag.setTimezone("GMT+1"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCustomFormatWithTimezoneAsExpression() throws Exception { @@ -104,6 +172,41 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCustomFormatWithTimezoneAsExpression_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+2")).getTime(); + SimpleDateFormat sdf = new SimpleDateFormat(format); + sdf.setTimeZone(TimeZone.getTimeZone("GMT+2")); + String formatted = sdf.format(now); + context.put("myDate", now); + context.put("myTimezone", "GMT+2"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.setFormat(format); + tag.setTimezone("myTimezone"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCustomFormatCalendar() throws Exception { @@ -118,6 +221,37 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCustomFormatCalendar_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Calendar calendar = Calendar.getInstance(); + String formatted = new SimpleDateFormat(format).format(calendar.getTime()); + context.put("myDate", calendar); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.setFormat(format); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCustomFormatLong() throws Exception { @@ -133,6 +267,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCustomFormatLong_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Date date = new Date(); + String formatted = new SimpleDateFormat(format).format(date); + // long + context.put("myDate", date.getTime()); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.setFormat(format); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCustomFormatLocalDateTime() throws Exception { @@ -174,6 +340,36 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDefaultFormat_clearTagStateSet() throws Exception { + Date now = new Date(); + String formatted = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, + ActionContext.getContext().getLocale()).format(now); + + context.put("myDate", now); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testCustomFormatAndComponent() throws Exception { @@ -197,6 +393,46 @@ public class DateTagTest extends AbstractTagTest { tag.doEndTag(); assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCustomFormatAndComponent_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Date now = new Date(); + String formatted = new SimpleDateFormat(format).format(now); + context.put("myDate", now); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setFormat(format); + tag.setNice(false); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + // component test must be done between start and end tag + org.apache.struts2.components.Date component = (org.apache.struts2.components.Date) tag.getComponent(); + assertEquals("myDate", component.getName()); + assertEquals(format, component.getFormat()); + assertEquals(false, component.isNice()); + + tag.doEndTag(); + + assertEquals(formatted, writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSetId() throws Exception { @@ -212,6 +448,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals(formatted, context.get("myId")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSetId_clearTagStateSet() throws Exception { + String format = "yyyy/MM/dd hh:mm:ss"; + Date now = new Date(); + String formatted = new SimpleDateFormat(format).format(now); + context.put("myDate", now); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(false); + tag.setFormat(format); + tag.setVar("myId"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals(formatted, context.get("myId")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFutureNiceHour() throws Exception { @@ -227,6 +495,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("in one hour", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFutureNiceHour_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.HOUR, 1); + future.add(Calendar.SECOND, 5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("in one hour", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testPastNiceHour() throws Exception { @@ -242,6 +542,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("one hour ago", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testPastNiceHour_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.HOUR, -1); + future.add(Calendar.SECOND, -5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("one hour ago", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFutureNiceHourMinSec() throws Exception { @@ -258,6 +590,39 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("in 2 hours, 33 minutes", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFutureNiceHourMinSec_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.HOUR, 2); + future.add(Calendar.MINUTE, 33); + future.add(Calendar.SECOND, 5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("in 2 hours, 33 minutes", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testPastNiceHourMin() throws Exception { @@ -274,6 +639,39 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("4 hours, 55 minutes ago", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testPastNiceHourMin_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar past = Calendar.getInstance(); + past.setTime(now); + past.add(Calendar.HOUR, -4); + past.add(Calendar.MINUTE, -55); + past.add(Calendar.SECOND, -5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", past.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("4 hours, 55 minutes ago", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFutureLessOneMin() throws Exception { @@ -289,6 +687,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("in an instant", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFutureLessOneMin_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.SECOND, 47); + future.add(Calendar.SECOND, 5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("in an instant", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFutureLessOneHour() throws Exception { @@ -304,6 +734,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("in 36 minutes", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFutureLessOneHour_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.MINUTE, 36); + future.add(Calendar.SECOND, 5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("in 36 minutes", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFutureLessOneYear() throws Exception { @@ -319,6 +781,38 @@ public class DateTagTest extends AbstractTagTest { tag.doStartTag(); tag.doEndTag(); assertEquals("in 40 days", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFutureLessOneYear_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.HOUR, 40 * 24); + future.add(Calendar.SECOND, 5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertEquals("in 40 days", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFutureTwoYears() throws Exception { @@ -338,6 +832,42 @@ public class DateTagTest extends AbstractTagTest { // hmmm the Date component isn't the best to calculate the excat difference so we'll just check // that it starts with in 2 years assertTrue(writer.toString().startsWith("in 2 years")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFutureTwoYears_clearTagStateSet() throws Exception { + Date now = new Date(); + Calendar future = Calendar.getInstance(); + future.setTime(now); + future.add(Calendar.YEAR, 2); + future.add(Calendar.DATE, 1); + future.add(Calendar.SECOND, 5); // always add a little slack otherwise we could calculate wrong + + context.put("myDate", future.getTime()); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // hmmm the Date component isn't the best to calculate the excat difference so we'll just check + // that it starts with in 2 years + assertTrue(writer.toString().startsWith("in 2 years")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoDateObjectInContext() throws Exception { @@ -348,14 +878,96 @@ public class DateTagTest extends AbstractTagTest { tag.doEndTag(); //should return a blank assertEquals("", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testNoDateObjectInContext_clearTagStateSet() throws Exception { + context.put("myDate", "this is not a java.util.Date object"); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myDate"); + tag.setNice(true); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + //should return a blank + assertEquals("", writer.toString()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DateTag freshTag = new DateTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * Artificial code coverage test for {@link DateTextFieldTag} within the DateTagTest + * since that tag does not have its own unit tests, and it also appears to be + * a broken tag. The code coverage tests can be moved if the tag is fixed, or + * removed if the tag is dropped. + * + * @throws Exception + */ + public void testDateTextFieldTag_artificialCoverageTest() throws Exception { + final String format = "yyyy/MM/dd hh:mm:ss"; + DateTextFieldTag dateTextFieldTag = createDateTextFieldTag(); + dateTextFieldTag.setFormat(format); + dateTextFieldTag.doStartTag(); + // Cannot call doEndTag(), as the missing datetextfield.ftl causes an exception. + dateTextFieldTag.populateParams(); + + Component bean = dateTextFieldTag.getBean(stack, request, response); + assertNotNull("DateTextField component instance is null ?", bean); + assertTrue("DateTextField component not a DateTextField ?", bean instanceof DateTextField); + + dateTextFieldTag.setPerformClearTagStateForTagPoolingServers(false); + dateTextFieldTag.clearTagStateForTagPoolingServers(); + dateTextFieldTag.setPerformClearTagStateForTagPoolingServers(true); + dateTextFieldTag.clearTagStateForTagPoolingServers(); + dateTextFieldTag.release(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after forced clearing of tag state. + DateTextFieldTag freshTag = new DateTextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(dateTextFieldTag, freshTag)); + } + + /** + * Utility method to create a new {@link DateTextFieldTag} instance for code coverage tests. + * + * Note: There is no datetextfield.ftl template for the tag, so it does not appear that it can + * actually be used in practice. We can perform basic coverage tests from within this + * unit test class until the {@link DateTextFieldTag} is fixed or removed. + * + * @return a basic {@link DateTextFieldTag} instance + * @throws Exception + */ + private DateTextFieldTag createDateTextFieldTag() throws Exception { + DateTextFieldTag tag = new DateTextFieldTag(); + tag.setPageContext(pageContext); + tag.setName("myDate"); + tag.setId("myDate"); + return tag; + } + + @Override protected void setUp() throws Exception { super.setUp(); tag = new DateTag(); tag.setPageContext(pageContext); } + @Override protected void tearDown() throws Exception { super.tearDown(); tag = null; diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java index fa4729555..7f4b54581 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java @@ -57,6 +57,37 @@ public class DebugTagTest extends AbstractUITagTest { assertTrue("Nonce value not included", result.contains("nonce=\"r4nd0m\"")); assertTrue(StringUtils.isNotEmpty(result)); assertTrue("Property 'checkStackProperty' should be in Debug Tag output", StringUtils.contains(result, "checkStackProperty")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPageContext(pageContext); + // DebugTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDevModeEnabled_clearTagStateSet() throws Exception { + setDevMode(true); + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + String result = writer.toString(); + + assertTrue("Nonce value not included", result.contains("nonce=\"r4nd0m\"")); + assertTrue(StringUtils.isNotEmpty(result)); + assertTrue("Property 'checkStackProperty' should be in Debug Tag output", StringUtils.contains(result, "checkStackProperty")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDevModeDisabled() throws Exception { @@ -65,6 +96,32 @@ public class DebugTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertTrue("nothing to see here, devMode=false", StringUtils.isEmpty(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPageContext(pageContext); + // DebugTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDevModeDisabled_clearTagStateSet() throws Exception { + setDevMode(false); + + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertTrue("nothing to see here, devMode=false", StringUtils.isEmpty(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testTagAttributeOverrideDevModeTrue() throws Exception { @@ -76,6 +133,39 @@ public class DebugTagTest extends AbstractUITagTest { String result = writer.toString(); assertTrue(StringUtils.isNotEmpty(result)); assertTrue("Property 'checkStackProperty' should be in Debug Tag output", StringUtils.contains(result, "checkStackProperty")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPageContext(pageContext); + // DebugTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + PrepareOperations.clearDevModeOverride(); // Clear DevMode override. Avoid ThreadLocal side-effects if test thread re-used. + } + + public void testTagAttributeOverrideDevModeTrue_clearTagStateSet() throws Exception { + setDevMode(false); + + PrepareOperations.overrideDevMode(true); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + String result = writer.toString(); + assertTrue(StringUtils.isNotEmpty(result)); + assertTrue("Property 'checkStackProperty' should be in Debug Tag output", StringUtils.contains(result, "checkStackProperty")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + PrepareOperations.clearDevModeOverride(); // Clear DevMode override. Avoid ThreadLocal side-effects if test thread re-used. } public void testTagAttributeOverrideDevModeFalse() throws Exception { @@ -85,6 +175,37 @@ public class DebugTagTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); assertTrue("nothing to see here, devMode=false and overrideDevMode=false", StringUtils.isEmpty(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPageContext(pageContext); + // DebugTag has no additional state, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + PrepareOperations.clearDevModeOverride(); // Clear DevMode override. Avoid ThreadLocal side-effects if test thread re-used. + } + + public void testTagAttributeOverrideDevModeFalse_clearTagStateSet() throws Exception { + setDevMode(false); + + PrepareOperations.overrideDevMode(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + assertTrue("nothing to see here, devMode=false and overrideDevMode=false", StringUtils.isEmpty(writer.toString())); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DebugTag freshTag = new DebugTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + PrepareOperations.clearDevModeOverride(); // Clear DevMode override. Avoid ThreadLocal side-effects if test thread re-used. } private void setDevMode(final boolean devMode) { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java index 15e0a17cd..ce40fa5ca 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java @@ -94,6 +94,88 @@ public class DoubleSelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("DoubleSelect-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDouble_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + Region antwerp = new Region("Antwerp", "AN"); + Region gent = new Region("Gent", "GN"); + Region brugge = new Region("Brugge", "BRG"); + ArrayList belgiumRegions = new ArrayList(); + belgiumRegions.add(antwerp); + belgiumRegions.add(gent); + belgiumRegions.add(brugge); + Country belgium = new Country("Belgium", "BE", belgiumRegions); + + Region paris = new Region("Paris", "PA"); + Region bordeaux = new Region("Bordeaux", "BOR"); + ArrayList franceRegions = new ArrayList(); + franceRegions.add(paris); + franceRegions.add(bordeaux); + Country france = new Country("France", "FR", franceRegions); + + Collection collection = new ArrayList(2); + collection.add("AN"); + testAction.setCollection(collection); + + List countries = new ArrayList(); + countries.add(belgium); + countries.add(france); + + testAction.setList2(countries); + + DoubleSelectTag tag = new DoubleSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setDoubleName("region"); + + tag.setList("list2"); + tag.setDoubleList("regions"); + + tag.setListKey("iso"); + tag.setDoubleListKey("key"); + tag.setListValue("name"); + tag.setDoubleListValue("name"); + + tag.setFormName("inputForm"); + + tag.setOnmousedown("window.status='onmousedown';"); + tag.setOnmousemove("window.status='onmousemove';"); + tag.setOnmouseout("window.status='onmouseout';"); + tag.setOnmouseover("window.status='onmouseover';"); + tag.setOnmouseup("window.status='onmouseup';"); + + //css style and class + tag.setCssClass("c1"); + tag.setCssStyle("s1"); + tag.setDoubleCssClass("c2"); + tag.setDoubleCssStyle("s2"); + + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("DoubleSelect-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testOnchange() throws Exception { @@ -158,8 +240,88 @@ public class DoubleSelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("DoubleSelect-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testOnchange_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + Region antwerp = new Region("Antwerp", "AN"); + Region gent = new Region("Gent", "GN"); + Region brugge = new Region("Brugge", "BRG"); + ArrayList belgiumRegions = new ArrayList(); + belgiumRegions.add(antwerp); + belgiumRegions.add(gent); + belgiumRegions.add(brugge); + Country belgium = new Country("Belgium", "BE", belgiumRegions); + + Region paris = new Region("Paris", "PA"); + Region bordeaux = new Region("Bordeaux", "BOR"); + ArrayList franceRegions = new ArrayList(); + franceRegions.add(paris); + franceRegions.add(bordeaux); + Country france = new Country("France", "FR", franceRegions); + + Collection collection = new ArrayList(2); + collection.add("AN"); + testAction.setCollection(collection); + + List countries = new ArrayList(); + countries.add(belgium); + countries.add(france); + + testAction.setList2(countries); + + DoubleSelectTag tag = new DoubleSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setDoubleName("region"); + + tag.setList("list2"); + tag.setDoubleList("regions"); + + tag.setListKey("iso"); + tag.setDoubleListKey("key"); + tag.setListValue("name"); + tag.setDoubleListValue("name"); + + tag.setFormName("inputForm"); + + tag.setOnmousedown("window.status='onmousedown';"); + tag.setOnmousemove("window.status='onmousemove';"); + tag.setOnmouseout("window.status='onmouseout';"); + tag.setOnmouseover("window.status='onmouseover';"); + tag.setOnmouseup("window.status='onmouseup';"); + tag.setOnchange("window.status='onchange';"); + + //css style and class + tag.setCssClass("c1"); + tag.setCssStyle("s1"); + tag.setDoubleCssClass("c2"); + tag.setDoubleCssStyle("s2"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("DoubleSelect-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testDoubleWithDefaultSelectedValues() throws Exception { @@ -221,7 +383,83 @@ public class DoubleSelectTest extends AbstractUITagTest { verify(SelectTag.class.getResource("DoubleSelect-2.txt")); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testDoubleWithDefaultSelectedValues_clearTagStateSet() throws Exception { + + TestAction testAction = (TestAction) action; + + Region antwerp = new Region("Antwerp", "AN"); + Region gent = new Region("Gent", "GN"); + Region brugge = new Region("Brugge", "BRG"); + ArrayList belgiumRegions = new ArrayList(); + belgiumRegions.add(antwerp); + belgiumRegions.add(gent); + belgiumRegions.add(brugge); + Country belgium = new Country("Belgium", "BE", belgiumRegions); + + Region paris = new Region("Paris", "PA"); + Region bordeaux = new Region("Bordeaux", "BOR"); + ArrayList franceRegions = new ArrayList(); + franceRegions.add(paris); + franceRegions.add(bordeaux); + Country france = new Country("France", "FR", franceRegions); + + Collection collection = new ArrayList(2); + collection.add("AN"); + testAction.setCollection(collection); + + List countries = new ArrayList(); + countries.add(belgium); + countries.add(france); + + testAction.setList2(countries); + + DoubleSelectTag tag = new DoubleSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setDoubleName("region"); + + tag.setValue("'FR'"); + tag.setDoubleValue("'BOR'"); + + tag.setList("list2"); + tag.setDoubleList("regions"); + + tag.setListKey("iso"); + tag.setDoubleListKey("key"); + tag.setListValue("name"); + tag.setDoubleListValue("name"); + + tag.setFormName("inputForm"); + + tag.setOnmousedown("window.status='onmousedown';"); + tag.setOnmousemove("window.status='onmousemove';"); + tag.setOnmouseout("window.status='onmouseout';"); + tag.setOnmouseover("window.status='onmouseover';"); + tag.setOnmouseup("window.status='onmouseup';"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("DoubleSelect-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDoubleWithDotName() throws Exception { @@ -279,6 +517,80 @@ public class DoubleSelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("DoubleSelect-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDoubleWithDotName_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + Region antwerp = new Region("Antwerp", "AN"); + Region gent = new Region("Gent", "GN"); + Region brugge = new Region("Brugge", "BRG"); + ArrayList belgiumRegions = new ArrayList(); + belgiumRegions.add(antwerp); + belgiumRegions.add(gent); + belgiumRegions.add(brugge); + Country belgium = new Country("Belgium", "BE", belgiumRegions); + + Region paris = new Region("Paris", "PA"); + Region bordeaux = new Region("Bordeaux", "BOR"); + ArrayList franceRegions = new ArrayList(); + franceRegions.add(paris); + franceRegions.add(bordeaux); + Country france = new Country("France", "FR", franceRegions); + + Collection collection = new ArrayList(2); + collection.add("AN"); + testAction.setCollection(collection); + + List countries = new ArrayList(); + countries.add(belgium); + countries.add(france); + + testAction.setList2(countries); + + DoubleSelectTag tag = new DoubleSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo.bar"); + tag.setDoubleName("region"); + + tag.setList("list2"); + tag.setDoubleList("regions"); + + tag.setListKey("iso"); + tag.setDoubleListKey("key"); + tag.setListValue("name"); + tag.setDoubleListValue("name"); + + tag.setFormName("inputForm"); + + tag.setOnmousedown("window.status='onmousedown';"); + tag.setOnmousemove("window.status='onmousemove';"); + tag.setOnmouseout("window.status='onmouseout';"); + tag.setOnmouseover("window.status='onmouseover';"); + tag.setOnmouseup("window.status='onmouseup';"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("DoubleSelect-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + DoubleSelectTag freshTag = new DoubleSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGenericSimple() throws Exception { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FieldErrorTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FieldErrorTagTest.java index b1e9b5bad..f8e611337 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FieldErrorTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FieldErrorTagTest.java @@ -46,6 +46,34 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithoutParamsWithFieldErrors_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(true); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithoutParamsWithoutFieldErrors() throws Exception { @@ -56,6 +84,34 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithoutParamsWithoutFieldErrors_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFieldErrorsEscape() throws Exception { @@ -72,6 +128,40 @@ public class FieldErrorTagTest extends AbstractUITagTest { assertEquals(normalize("
  • <p>hey</p>
", true), normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here and escape is true by default, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFieldErrorsEscape_clearTagStateSet() throws Exception { + + FieldErrorTag tag = new FieldErrorTag(); + TestAction testAction = new TestAction(); + testAction.addFieldError("f", "

hey

"); + stack.pop(); + stack.push(testAction); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscape(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(normalize("
  • <p>hey</p>
", true), + normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFieldErrorsDontEscape() throws Exception { @@ -88,6 +178,39 @@ public class FieldErrorTagTest extends AbstractUITagTest { assertEquals(normalize("
  • hey

", true), normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFieldErrorsDontEscape_clearTagStateSet() throws Exception { + + FieldErrorTag tag = new FieldErrorTag(); + TestAction testAction = new TestAction(); + testAction.addFieldError("f", "

hey

"); + stack.pop(); + stack.push(testAction); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setEscape(false); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals(normalize("
  • hey

", true), + normalize(writer.toString(), true)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithParamsWithFieldErrors1() throws Exception { @@ -111,6 +234,71 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithParamsWithFieldErrors1_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setId("someid"); + ((InternalAction)action).setHaveFieldErrors(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field1'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + + ParamTag pTag2 = new ParamTag(); + pTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag2.setPageContext(pageContext); + pTag2.setValue("%{'field3'}"); + pTag2.doStartTag(); + setComponentTagClearTagState(pTag2, true); // Ensure component tag state clearing is set true (to match tag). + pTag2.doEndTag(); + + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithFieldName() throws Exception { @@ -122,6 +310,34 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithFieldName_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setFieldName("field1"); + ((InternalAction)action).setHaveFieldErrors(true); + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithParamsWithFieldErrors2() throws Exception { @@ -144,8 +360,72 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testWithParamsWithFieldErrors2_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(true); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field1'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + + ParamTag pTag2 = new ParamTag(); + pTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag2.setPageContext(pageContext); + pTag2.setValue("%{'field2'}"); + pTag2.doStartTag(); + setComponentTagClearTagState(pTag2, true); // Ensure component tag state clearing is set true (to match tag). + pTag2.doEndTag(); + + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testWithParamsWithFieldErrors3() throws Exception { FieldErrorTag tag = new FieldErrorTag(); @@ -161,6 +441,57 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithParamsWithFieldErrors3_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(true); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field2'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithParamsWithoutFieldErrors1() throws Exception { @@ -182,6 +513,70 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithParamsWithoutFieldErrors1_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field1'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + + ParamTag pTag2 = new ParamTag(); + pTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag2.setPageContext(pageContext); + pTag2.setValue("%{'field3'}"); + pTag2.doStartTag(); + setComponentTagClearTagState(pTag2, true); // Ensure component tag state clearing is set true (to match tag). + pTag2.doEndTag(); + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithParamsWithoutFieldErrors2() throws Exception { @@ -203,8 +598,71 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testWithParamsWithoutFieldErrors2_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field1'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + + ParamTag pTag2 = new ParamTag(); + pTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag2.setPageContext(pageContext); + pTag2.setValue("%{'field3'}"); + pTag2.doStartTag(); + setComponentTagClearTagState(pTag2, true); // Ensure component tag state clearing is set true (to match tag). + pTag2.doEndTag(); + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag2, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testWithParamsWithoutFieldErrors3() throws Exception { FieldErrorTag tag = new FieldErrorTag(); @@ -220,6 +678,57 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithParamsWithoutFieldErrors3_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(false); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field2'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithNullFieldErrors() throws Exception { @@ -237,9 +746,61 @@ public class FieldErrorTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPageContext(pageContext); + // FieldErrorTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testWithNullFieldErrors_clearTagStateSet() throws Exception { + FieldErrorTag tag = new FieldErrorTag(); + ((InternalAction)action).setHaveFieldErrors(false); + ((InternalAction)action).setReturnNullForFieldErrors(true); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + ParamTag pTag1 = new ParamTag(); + pTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + pTag1.setPageContext(pageContext); + pTag1.setValue("%{'field2'}"); + pTag1.doStartTag(); + setComponentTagClearTagState(pTag1, true); // Ensure component tag state clearing is set true (to match tag). + pTag1.doEndTag(); + tag.doEndTag(); + + verify(FieldErrorTagTest.class.getResource("fielderror-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(pTag1, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FieldErrorTag freshTag = new FieldErrorTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + @Override public Action getAction() { return new InternalAction(); } @@ -258,6 +819,7 @@ public class FieldErrorTagTest extends AbstractUITagTest { this.returnNullForFieldErrors = returnNullForFieldErrors; } + @Override public Map> getFieldErrors() { if (haveFieldErrors) { List err1 = new ArrayList(); @@ -280,6 +842,7 @@ public class FieldErrorTagTest extends AbstractUITagTest { } } + @Override public boolean hasFieldErrors() { return haveFieldErrors; } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java index 3e1a6be13..32b932229 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java @@ -49,6 +49,42 @@ public class FileTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("File-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FileTag freshTag = new FileTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + FileTag tag = new FileTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setAccept("*.txt"); + tag.setValue("%{foo}"); + tag.setSize("10"); + tag.setTitle("mytitle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("File-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FileTag freshTag = new FileTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -59,6 +95,7 @@ public class FileTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = super.initializedGenericTagTestProperties(); new PropertyHolder("accept", "someAccepted").addToMap(result); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java index ef3484c4e..e9fba3ee6 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java @@ -58,6 +58,42 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-26.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithActionAttributeContainingQueryString_clearTagStateSet() throws Exception { + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAcceptcharset("UTF-8"); + tag.setAction("testAction?paramone=one¶mtwo=two"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-26.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithActionAttributeContainingBothActionAndMethod() throws Exception { @@ -74,6 +110,39 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithActionAttributeContainingBothActionAndMethod_clearTagStateSet() throws Exception { + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAcceptcharset("UTF-8"); + tag.setAction("testAction"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithoutContext() throws Exception { @@ -89,6 +158,38 @@ public class FormTagTest extends AbstractUITagTest { verify(FormTag.class.getResource("Formtag-14.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithoutContext_clearTagStateSet() throws Exception { + request.setupGetContext("somecontext"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setTheme("xhtml"); + tag.setPageContext(pageContext); + tag.setAction("testAction"); + tag.setIncludeContext(false); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + + verify(FormTag.class.getResource("Formtag-14.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithContext() throws Exception { @@ -103,10 +204,42 @@ public class FormTagTest extends AbstractUITagTest { verify(FormTag.class.getResource("Formtag-13.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithContext_clearTagStateSet() throws Exception { + request.setupGetContext("/testNamespace"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setTheme("xhtml"); + tag.setPageContext(pageContext); + tag.setAction("testAction"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + + verify(FormTag.class.getResource("Formtag-13.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithActionAttributeContainingBothActionAndDMIMethod() throws Exception { FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setPageContext(pageContext); tag.setName("myForm"); tag.setMethod("post"); @@ -122,10 +255,47 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-23.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithActionAttributeContainingBothActionAndDMIMethod_clearTagStateSet() throws Exception { + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAcceptcharset("UTF-8"); + tag.setAction("testAction!testMethod"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + + ((DefaultActionMapper)container.getInstance(ActionMapper.class)).setAllowDynamicMethodCalls("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-23.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithFocusElement() throws Exception { FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setTheme("xhtml"); tag.setPageContext(pageContext); tag.setAction("testAction"); @@ -134,10 +304,40 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithFocusElement_clearTagStateSet() throws Exception { + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setTheme("xhtml"); + tag.setPageContext(pageContext); + tag.setAction("testAction"); + tag.setFocusElement("felement"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithActionAttributeContainingBothActionAndMethodAndNamespace() throws Exception { FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setPageContext(pageContext); tag.setName("myForm"); tag.setNamespace("/testNamespace"); @@ -152,8 +352,42 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testFormWithActionAttributeContainingBothActionAndMethodAndNamespace_clearTagStateSet() throws Exception { + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setNamespace("/testNamespace"); + tag.setMethod("post"); + tag.setAcceptcharset("UTF-8"); + tag.setAction("testNamespaceAction"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testForm() throws Exception { @@ -163,6 +397,7 @@ public class FormTagTest extends AbstractUITagTest { testAction.setFoo("bar"); FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setPageContext(pageContext); tag.setName("myForm"); tag.setMethod("post"); @@ -177,6 +412,47 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testForm_clearTagStateSet() throws Exception { + + request.setupGetServletPath("/testAction"); + + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAcceptcharset("UTF-8"); + tag.setAction("myAction"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.setId("myid"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormId() throws Exception { @@ -187,6 +463,7 @@ public class FormTagTest extends AbstractUITagTest { testAction.setFoo("bar"); FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setPageContext(pageContext); tag.setMethod("post"); tag.setAction("myAction"); @@ -196,6 +473,42 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-29.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormId_clearTagStateSet() throws Exception { + + request.setupGetServletPath("/testAction"); + + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setMethod("post"); + tag.setAction("myAction"); + tag.setId("myid-%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-29.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormNoNameOrId() throws Exception { @@ -218,6 +531,45 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-25.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormNoNameOrId_clearTagStateSet() throws Exception { + + request.setupGetServletPath("/testAction"); + + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setMethod("post"); + tag.setAcceptcharset("UTF-8"); + tag.setAction("myAction"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-25.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -252,8 +604,75 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + /** + * This test with form tag validation enabled. Js validation script will appear + * cause action submited by the form is intercepted by validation interceptor which + * "include" all methods. + */ + public void testFormWithCustomOnsubmitEnabledWithValidateEnabled1_clearTagStateSet() throws Exception { + + prepareMockInvocation(); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAction("doubleValidationAction"); + tag.setAcceptcharset("UTF-8"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.setValidate("true"); + tag.setNamespace(""); + + UpDownSelectTag t = new UpDownSelectTag(); + t.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + t.setPageContext(pageContext); + t.setName("myUpDownSelectTag"); + t.setList("{}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + t.doStartTag(); + setComponentTagClearTagState(t, true); // Ensure component tag state clearing is set true (to match tag). + t.doEndTag(); + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } /** * This test with form tag validation enabled. Js validation script will not appear @@ -286,6 +705,73 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * This test with form tag validation enabled. Js validation script will not appear + * cause action submited by the form is intercepted by validation interceptor which + * "excludes" all methods. + */ + public void testFormWithCustomOnsubmitEnabledWithValidateEnabled2_clearTagStateSet() throws Exception { + prepareMockInvocation(); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAction("testAction"); + tag.setAcceptcharset("UTF-8"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.setValidate("true"); + tag.setNamespace(""); + + UpDownSelectTag t = new UpDownSelectTag(); + t.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + t.setPageContext(pageContext); + t.setName("myUpDownSelectTag"); + t.setList("{}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + t.doStartTag(); + setComponentTagClearTagState(t, true); // Ensure component tag state clearing is set true (to match tag). + t.doEndTag(); + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -318,9 +804,75 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-22.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** + * Tests the numbers are formatted correctly to not break the javascript + */ + public void testFormWithCustomOnsubmitEnabledWithValidateEnabled3_clearTagStateSet() throws Exception { + + prepareMockInvocation(); + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAction("doubleValidationAction"); + tag.setAcceptcharset("UTF-8"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.setValidate("true"); + tag.setNamespace(""); + + UpDownSelectTag t = new UpDownSelectTag(); + t.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + t.setPageContext(pageContext); + t.setName("myUpDownSelectTag"); + t.setList("{}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.getComponent().getParameters().put("actionClass", IntValidationAction.class); + t.doStartTag(); + setComponentTagClearTagState(t, true); // Ensure component tag state clearing is set true (to match tag). + t.doEndTag(); + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-22.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + +/** * Tests the numbers are formatted correctly to not break the javascript, using doubles */ public void testFormWithCustomOnsubmitEnabledWithValidateEnabled4() throws Exception { @@ -350,6 +902,72 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-24.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + +/** + * Tests the numbers are formatted correctly to not break the javascript, using doubles + */ + public void testFormWithCustomOnsubmitEnabledWithValidateEnabled4_clearTagStateSet() throws Exception { + prepareMockInvocation(); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAction("doubleValidationAction"); + tag.setAcceptcharset("UTF-8"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.setValidate("true"); + tag.setNamespace(""); + + UpDownSelectTag t = new UpDownSelectTag(); + t.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + t.setPageContext(pageContext); + t.setName("myUpDownSelectTag"); + t.setList("{}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.getComponent().getParameters().put("actionClass", DoubleValidationAction.class); + t.doStartTag(); + setComponentTagClearTagState(t, true); // Ensure component tag state clearing is set true (to match tag). + t.doEndTag(); + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-24.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } private void prepareMockInvocation() throws Exception { @@ -394,8 +1012,68 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + /** + * This test with form tag validation disabled. + */ + public void testFormWithCustomOnsubmitEnabledWithValidateDisabled_clearTagStateSet() throws Exception { + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAction("myAction"); + tag.setEnctype("myEncType"); + tag.setTitle("mytitle"); + tag.setOnsubmit("submitMe()"); + tag.setValidate("false"); + + UpDownSelectTag t = new UpDownSelectTag(); + t.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + t.setPageContext(pageContext); + t.setName("myUpDownSelectTag"); + t.setList("{}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + t.doStartTag(); + setComponentTagClearTagState(t, true); // Ensure component tag state clearing is set true (to match tag). + t.doEndTag(); + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshParamTag = new UpDownSelectTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(t, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } /** *

@@ -428,6 +1106,56 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + *

+ * Testing that this: + *

+ *
+     * <a:form name="'myForm'" namespace="'/testNamespace'" action="'testNamespaceAction'" method="'post'">
+     * 
+ *

+ * doesn't create an action of "/testNamespace/testNamespaceAction.action" when the "struts.action.extension" + * config property is set to "jspa". + *

+ */ + public void testFormTagWithDifferentActionExtension_clearTagStateSet() throws Exception { + initDispatcher(new HashMap(){{ + put(StrutsConstants.STRUTS_ACTION_EXTENSION, "jspa"); + put("configProviders", TestConfigurationProvider.class.getName()); + }}); + createMocks(); + request.setupGetServletPath("/testNamespace/testNamespaceAction"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setNamespace("/testNamespace"); + tag.setAction("testNamespaceAction"); + tag.setMethod("post"); + tag.setName("myForm"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -449,6 +1177,44 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * Testing that this:
+ * <a:form name="'myForm'" action="'/testNamespace/testNamespaceAction.jspa'" method="'post'"> + *
+ * doesn't create an action of "/testNamespace/testNamespaceAction.action" + */ + public void testFormTagWithDifferentActionExtensionHardcoded_clearTagStateSet() throws Exception { + request.setupGetServletPath("/testNamespace/testNamespaceAction"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setAction("/testNamespace/testNamespaceAction.jspa"); + tag.setMethod("post"); + tag.setName("myForm"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithNamespaceDefaulting() throws Exception { @@ -467,6 +1233,41 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithNamespaceDefaulting_clearTagStateSet() throws Exception { + request.setupGetServletPath("/testNamespace/testNamespaceAction"); + + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myForm"); + tag.setMethod("post"); + tag.setAction("testNamespaceAction"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormTagForStackOverflowException1() throws Exception { @@ -492,6 +1293,66 @@ public class FormTagTest extends AbstractUITagTest { form1.doEndTag(); assertNull(form1.getComponent()); // component is removed after end tag + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form1, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormTagForStackOverflowException1_clearTagStateSet() throws Exception { + request.setRequestURI("/testAction"); + + FormTag form1 = new FormTag(); + form1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form1.setPageContext(pageContext); + form1.doStartTag(); + setComponentTagClearTagState(form1, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form1.getComponent().getComponentStack().size(), 1); + + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("testAction"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(tag.getComponent().getComponentStack().size(), 2); + + tag.doEndTag(); + + assertEquals(form1.getComponent().getComponentStack().size(), 1); + + form1.doEndTag(); + + assertNull(form1.getComponent()); // component is removed after end tag + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form1, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormTagForStackOverflowException2() throws Exception { @@ -527,8 +1388,86 @@ public class FormTagTest extends AbstractUITagTest { form1.doEndTag(); assertNull(form1.getComponent()); // component is removed after end tag + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form1, freshFormTag)); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form2, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testFormTagForStackOverflowException2_clearTagStateSet() throws Exception { + request.setRequestURI("/requestUri"); + + FormTag form1 = new FormTag(); + form1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form1.setPageContext(pageContext); + form1.doStartTag(); + setComponentTagClearTagState(form1, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form1.getComponent().getComponentStack().size(), 1); + + FormTag form2 = new FormTag(); + form2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form2.setPageContext(pageContext); + form2.doStartTag(); + setComponentTagClearTagState(form2, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form2.getComponent().getComponentStack().size(), 2); + + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("testAction"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(tag.getComponent().getComponentStack().size(), 3); + + tag.doEndTag(); + + assertEquals(form2.getComponent().getComponentStack().size(), 2); + + form2.doEndTag(); + + assertEquals(form1.getComponent().getComponentStack().size(), 1); + + form1.doEndTag(); + + assertNull(form1.getComponent()); // component is removed after end tag + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form1, freshFormTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form2, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testFormTagForStackOverflowException3() throws Exception { request.setRequestURI("/requestUri"); @@ -573,8 +1512,105 @@ public class FormTagTest extends AbstractUITagTest { form1.doEndTag(); assertNull(form1.getComponent()); // component is removed after end tag + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form1, freshFormTag)); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form2, freshFormTag)); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form3, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testFormTagForStackOverflowException3_clearTagStateSet() throws Exception { + request.setRequestURI("/requestUri"); + + FormTag form1 = new FormTag(); + form1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form1.setPageContext(pageContext); + form1.doStartTag(); + setComponentTagClearTagState(form1, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form1.getComponent().getComponentStack().size(), 1); + + FormTag form2 = new FormTag(); + form2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form2.setPageContext(pageContext); + form2.doStartTag(); + setComponentTagClearTagState(form2, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form2.getComponent().getComponentStack().size(), 2); + + FormTag form3 = new FormTag(); + form3.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form3.setPageContext(pageContext); + form3.doStartTag(); + setComponentTagClearTagState(form3, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form3.getComponent().getComponentStack().size(), 3); + + ActionTag tag = new ActionTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("testAction"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(tag.getComponent().getComponentStack().size(), 4); + + tag.doEndTag(); + + assertEquals(form3.getComponent().getComponentStack().size(), 3); + + form3.doEndTag(); + + assertEquals(form2.getComponent().getComponentStack().size(), 2); + + form2.doEndTag(); + + assertEquals(form1.getComponent().getComponentStack().size(), 1); + + form1.doEndTag(); + + assertNull(form1.getComponent()); // component is removed after end tag + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form1, freshFormTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form2, freshFormTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form3, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ActionTag freshTag = new ActionTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testFormComponentIsRemoved() throws Exception { request.setRequestURI("/requestUri"); @@ -588,8 +1624,39 @@ public class FormTagTest extends AbstractUITagTest { form.doEndTag(); assertNull(form.getComponent()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshTag)); } + public void testFormComponentIsRemoved_clearTagStateSet() throws Exception { + request.setRequestURI("/requestUri"); + + FormTag form = new FormTag(); + form.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form.setPageContext(pageContext); + form.doStartTag(); + setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). + + assertEquals(form.getComponent().getComponentStack().size(), 1); + + form.doEndTag(); + + assertNull(form.getComponent()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshTag)); + } public void testFormWithNoAction() throws Exception { request.setupGetServletPath("/"); @@ -602,6 +1669,37 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + // FormTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithNoAction_clearTagStateSet() throws Exception { + request.setupGetServletPath("/"); + request.setupGetContextPath("/"); + request.setRequestURI("/foo.jsp"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithStaticAction() throws Exception { @@ -616,6 +1714,37 @@ public class FormTagTest extends AbstractUITagTest { tag.doEndTag(); verify(FormTag.class.getResource("Formtag-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithStaticAction_clearTagStateSet() throws Exception { + request.setupGetServletPath("/"); + request.setupGetContextPath("/"); + request.setRequestURI("/foo.jsp"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setAction("test.html"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithActionAndExtension() throws Exception { @@ -632,6 +1761,37 @@ public class FormTagTest extends AbstractUITagTest { verify(FormTag.class.getResource("Formtag-8.txt")); + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testFormWithActionAndExtension_clearTagStateSet() throws Exception { + request.setupGetServletPath("/BLA"); + + FormTag tag = new FormTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setAction("/testNamespace/testNamespaceAction.jspa"); + tag.setMethod("post"); + tag.setName("myForm"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(FormTag.class.getResource("Formtag-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshTag = new FormTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testFormWithTopLabelPosition() throws Exception { @@ -652,6 +1812,60 @@ public class FormTagTest extends AbstractUITagTest { form.doEndTag(); verify(FormTag.class.getResource("Formtag-27.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); + } + + public void testFormWithTopLabelPosition_clearTagStateSet() throws Exception { + FormTag form = new FormTag(); + form.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form.setTheme("xhtml"); + form.setAction("testAction"); + form.setPageContext(pageContext); + form.setIncludeContext(false); + form.setLabelposition("top"); + + TextFieldTag text = new TextFieldTag(); + text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + text.setPageContext(pageContext); + text.setLabel("label"); + + form.doStartTag(); + setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). + text.doStartTag(); + setComponentTagClearTagState(text, true); // Ensure component tag state clearing is set true (to match tag). + text.doEndTag(); + form.doEndTag(); + + verify(FormTag.class.getResource("Formtag-27.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); } public void testFormWithTopLabelPositionWithElementOverride() throws Exception { @@ -673,6 +1887,61 @@ public class FormTagTest extends AbstractUITagTest { form.doEndTag(); verify(FormTag.class.getResource("Formtag-27.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); + } + + public void testFormWithTopLabelPositionWithElementOverride_clearTagStateSet() throws Exception { + FormTag form = new FormTag(); + form.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form.setTheme("xhtml"); + form.setAction("testAction"); + form.setPageContext(pageContext); + form.setIncludeContext(false); + form.setLabelposition("left"); + + TextFieldTag text = new TextFieldTag(); + text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + text.setPageContext(pageContext); + text.setLabel("label"); + text.setLabelposition("top"); + + form.doStartTag(); + setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). + text.doStartTag(); + setComponentTagClearTagState(text, true); // Ensure component tag state clearing is set true (to match tag). + text.doEndTag(); + form.doEndTag(); + + verify(FormTag.class.getResource("Formtag-27.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); } public void testFormWithTopLabelPositionCssXhtml() throws Exception { @@ -693,6 +1962,60 @@ public class FormTagTest extends AbstractUITagTest { form.doEndTag(); verify(FormTag.class.getResource("Formtag-28.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); + } + + public void testFormWithTopLabelPositionCssXhtml_clearTagStateSet() throws Exception { + FormTag form = new FormTag(); + form.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form.setTheme("css_xhtml"); + form.setAction("testAction"); + form.setPageContext(pageContext); + form.setIncludeContext(false); + form.setLabelposition("top"); + + TextFieldTag text = new TextFieldTag(); + text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + text.setPageContext(pageContext); + text.setLabel("label"); + + form.doStartTag(); + setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). + text.doStartTag(); + setComponentTagClearTagState(text, true); // Ensure component tag state clearing is set true (to match tag). + text.doEndTag(); + form.doEndTag(); + + verify(FormTag.class.getResource("Formtag-28.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); } public void testFormWithTopLabelPositionWithElementOverrideCssXhtml() throws Exception { @@ -714,6 +2037,61 @@ public class FormTagTest extends AbstractUITagTest { form.doEndTag(); verify(FormTag.class.getResource("Formtag-28.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); + } + + public void testFormWithTopLabelPositionWithElementOverrideCssXhtml_clearTagStateSet() throws Exception { + FormTag form = new FormTag(); + form.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + form.setTheme("css_xhtml"); + form.setAction("testAction"); + form.setPageContext(pageContext); + form.setIncludeContext(false); + form.setLabelposition("left"); + + TextFieldTag text = new TextFieldTag(); + text.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + text.setPageContext(pageContext); + text.setLabel("label"); + text.setLabelposition("top"); + + form.doStartTag(); + setComponentTagClearTagState(form, true); // Ensure component tag state clearing is set true (to match tag). + text.doStartTag(); + setComponentTagClearTagState(text, true); // Ensure component tag state clearing is set true (to match tag). + text.doEndTag(); + form.doEndTag(); + + verify(FormTag.class.getResource("Formtag-28.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(form, freshFormTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(text, freshTag)); } @Override diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java index a0c0ff296..c9e4c7015 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java @@ -39,5 +39,35 @@ public class HeadTagTest extends AbstractUITagTest { tag.doEndTag(); verify(HeadTagTest.class.getResource("HeadTagTest-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HeadTag freshTag = new HeadTag(); + freshTag.setPageContext(pageContext); + // HeadTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testHead1_clearTagStateSet() throws Exception { + HeadTag tag = new HeadTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(HeadTagTest.class.getResource("HeadTagTest-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HeadTag freshTag = new HeadTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java index 41f895045..d6d62e1a0 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java @@ -26,6 +26,8 @@ import org.apache.struts2.views.jsp.AbstractUITagTest; import java.util.HashMap; import java.util.Map; +/** + */ public class HiddenTest extends AbstractUITagTest { public void testSimple() throws Exception { @@ -42,6 +44,39 @@ public class HiddenTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Hidden-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + HiddenTag tag = new HiddenTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Hidden-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDisabled() throws Exception { @@ -59,6 +94,40 @@ public class HiddenTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Hidden-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDisabled_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + HiddenTag tag = new HiddenTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setDisabled("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Hidden-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDynamicAttributesWithActionInvocation() throws Exception { @@ -83,6 +152,47 @@ public class HiddenTest extends AbstractUITagTest { assertNotSame(stack.pop(), tag); verify(TextFieldTag.class.getResource("Hidden-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDynamicAttributesWithActionInvocation_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setId(27357L); + + MockActionInvocation ai = new MockActionInvocation(); + ai.setAction(action); + ActionContext.getContext().setActionInvocation(ai); + + HiddenTag tag = new HiddenTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("einszwei"); + tag.setName("first"); + tag.setValue("%{id}"); + tag.setDynamicAttribute("", "data-wuffmiauww", "%{id}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertSame(stack.pop(), testAction); + assertNotSame(stack.pop(), tag); + + verify(TextFieldTag.class.getResource("Hidden-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDynamicAttributesWithStack() throws Exception { @@ -103,6 +213,43 @@ public class HiddenTest extends AbstractUITagTest { assertNotSame(stack.pop(), tag); verify(TextFieldTag.class.getResource("Hidden-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDynamicAttributesWithStack_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setId(27357L); + + HiddenTag tag = new HiddenTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("einszwei"); + tag.setName("first"); + tag.setValue("%{id}"); + tag.setDynamicAttribute("", "data-wuffmiauww", "%{id}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertSame(stack.pop(), testAction); + assertNotSame(stack.pop(), tag); + + verify(TextFieldTag.class.getResource("Hidden-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + HiddenTag freshTag = new HiddenTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -111,8 +258,9 @@ public class HiddenTest extends AbstractUITagTest { * String, String[])} as properties to verify.
This implementation extends testdata from AbstractUITag. * * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} - * as key. + * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = new HashMap(); new PropertyHolder("name", "someName").addToMap(result); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java index 8a6017239..58471741a 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java @@ -45,6 +45,45 @@ public class InputTransferSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(InputTransferSelectTagTest.class.getResource("inputtransferselect-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + InputTransferSelectTag freshTag = new InputTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithRequired_clearTagStateSet() throws Exception { + List list = new ArrayList(); + list.add("Item One"); + list.add("Item Two"); + + TestAction testaction = (TestAction) action; + testaction.setCollection(list); + + InputTransferSelectTag tag = new InputTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setList("collection"); + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(InputTransferSelectTagTest.class.getResource("inputtransferselect-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + InputTransferSelectTag freshTag = new InputTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDynamicAttributes() throws Exception { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/JspTemplateTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/JspTemplateTest.java index 645343766..f0d98ae1d 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/JspTemplateTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/JspTemplateTest.java @@ -47,5 +47,38 @@ public class JspTemplateTest extends AbstractUITagTest { tag.doStartTag(); tag.doEndTag(); rdMock.verify(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testCheckBox_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("true"); + + CheckboxTag tag = new CheckboxTag(); + Mock rdMock = new Mock(RequestDispatcher.class); + rdMock.expect("include",C.args(C.isA(HttpServletRequest.class), C.isA(HttpServletResponse.class))); + RequestDispatcher dispatcher = (RequestDispatcher) rdMock.proxy(); + request.setupGetRequestDispatcher(dispatcher); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTemplate("/test/checkbox.jsp"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + rdMock.verify(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + CheckboxTag freshTag = new CheckboxTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java index 720358c9d..c277ef9ee 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java @@ -44,6 +44,40 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setTitle("mytitle"); + tag.setValue("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleWithLabelposition() throws Exception { @@ -61,6 +95,40 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleWithLabelposition_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setLabelposition("top"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -71,6 +139,7 @@ public class LabelTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = new HashMap(); new PropertyHolder("title", "someTitle").addToMap(result); @@ -95,6 +164,39 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithNoValue_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("baz"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setFor("for"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGenericSimple() throws Exception { @@ -126,6 +228,44 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithKeyNoValueFromStack_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + final String key = "labelKey"; + final String value = "baz"; + testAction.setText(key, value); + + testAction.setFoo("notToBeOutput"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setFor("for"); + tag.setName("foo2"); + tag.setKey(key); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithKeyValueFromStack() throws Exception { @@ -147,6 +287,44 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithKeyValueFromStack_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + final String key = "labelKey"; + final String value = "baz"; + testAction.setText(key, value); + + testAction.setFoo("output"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setFor("for"); + tag.setName("foo"); + tag.setKey(key); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithJustKeyValueFromStack() throws Exception { @@ -166,6 +344,42 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithJustKeyValueFromStack_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + final String key = "labelKey"; + final String value = "baz"; + + // put key with message in a "resource" + testAction.setText(key, value); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setKey(key); + tag.setTheme("simple"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithCssErrorClass() throws Exception { @@ -186,6 +400,43 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithCssErrorClass_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + testAction.addFieldError("myname", "error"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setTitle("mytitle"); + tag.setValue("%{foo}"); + tag.setCssErrorClass("cssErrorClass1"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithCssErrorStyle() throws Exception { @@ -206,6 +457,43 @@ public class LabelTest extends AbstractUITagTest { tag.doEndTag(); verify(LabelTest.class.getResource("Label-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithCssErrorStyle_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + testAction.addFieldError("myname", "error"); + + LabelTag tag = new LabelTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setTitle("mytitle"); + tag.setValue("%{foo}"); + tag.setCssErrorStyle("cssErrorStyle1"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(LabelTest.class.getResource("Label-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + LabelTag freshTag = new LabelTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptGroupTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptGroupTest.java index 5a2b35153..23ac34c09 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptGroupTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptGroupTest.java @@ -52,8 +52,78 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } + public void testOptGroupSimple_clearTagStateSet() throws Exception { + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("%{#{'ONE':'one','TWO':'two','THREE':'three'}}"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("%{#{'AAA':'aaa','BBB':'bbb','CCC':'ccc'}}"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("%{#{'DDD':'ddd','EEE':'eee','FFF':'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } public void testOptGroupWithSingleSelect() throws Exception { @@ -84,8 +154,80 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } + public void testOptGroupWithSingleSelect_clearTagStateSet() throws Exception { + + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("%{#{'ONE':'one','TWO':'two','THREE':'three'}}"); + selectTag.setValue("%{'EEE'}"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("%{#{'AAA':'aaa','BBB':'bbb','CCC':'ccc'}}"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("%{#{'DDD':'ddd','EEE':'eee','FFF':'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } public void testOptGroupWithMultipleSelect() throws Exception { SelectTag selectTag = new SelectTag(); @@ -116,8 +258,81 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } - + + public void testOptGroupWithMultipleSelect_clearTagStateSet() throws Exception { + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setMultiple("true"); + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("%{#{'ONE':'one','TWO':'two','THREE':'three'}}"); + selectTag.setValue("%{{'EEE','BBB','TWO'}}"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("%{#{'AAA':'aaa','BBB':'bbb','CCC':'ccc'}}"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("%{#{'DDD':'ddd','EEE':'eee','FFF':'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } + public void testOptGroupWithMultipleSelectIntKey() throws Exception { SelectTag selectTag = new SelectTag(); selectTag.setMultiple("true"); @@ -147,8 +362,81 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } - + + public void testOptGroupWithMultipleSelectIntKey_clearTagStateSet() throws Exception { + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setMultiple("true"); + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("%{#{1:'one',2:'two',3:'three'}}"); + selectTag.setValue("%{{22,12,2}}"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("%{#{11:'aaa',12:'bbb',13:'ccc'}}"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("%{#{21:'ddd',22:'eee',23:'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } + public void testOptGroupNumbers() throws Exception { ((TestAction)action).setMap(new LinkedHashMap() {{ @@ -183,6 +471,84 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } + + public void testOptGroupNumbers_clearTagStateSet() throws Exception { + + ((TestAction)action).setMap(new LinkedHashMap() {{ + put("AAA", "aaa"); + put(111111L, "bbb"); + put("CCC", "ccc"); + }}); + + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("%{#{'ONE':'one','TWO':'two','THREE':'three'}}"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("map"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("%{#{'DDD':'ddd','EEE':'eee','FFF':'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } public void testOptGroupForHtmlEncoding() throws Exception { @@ -214,6 +580,79 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } + + public void testOptGroupForHtmlEncoding_clearTagStateSet() throws Exception { + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setMultiple("true"); + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("%{#{'ONE':'one','TWO':'two','THREE':'three'}}"); + selectTag.setValue("%{{'EEE','TWO'}}"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("%{#{'&':'aaa','<':'bbb','CCC':'':'ddd','EEE':'eee','FFF':'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } public void testOptGroupWithValueKey() throws Exception { @@ -251,6 +690,85 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } + + public void testOptGroupWithValueKey_clearTagStateSet() throws Exception { + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("selectValues"); + selectTag.setListValueKey("valueKey"); + + LocaleTestAction localeTestAction = new LocaleTestAction(); + container.inject(localeTestAction); + + localeTestAction.setText("LocaleKeyValueTest.ONE","Edno"); + localeTestAction.setText("LocaleKeyValueTest.TWO","Dve"); + stack.push(localeTestAction); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("%{#{'AAA':'aaa','BBB':'bbb','CCC':'ccc'}}"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("%{#{'DDD':'ddd','EEE':'eee','FFF':'fff'}}"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } public void testOptGroupListAttributes() throws Exception { @@ -263,6 +781,7 @@ public class OptGroupTest extends AbstractUITagTest { selectTag.setListTitle("'option-title' + key"); OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. optGroupTag1.setLabel("My Label 1"); optGroupTag1.setList("#{'AAA':'aaa','BBB':'bbb','CCC':'ccc'}"); optGroupTag1.setListCssClass("'optgroup-option-css-class ' + key"); @@ -270,6 +789,7 @@ public class OptGroupTest extends AbstractUITagTest { optGroupTag1.setListTitle("'optgroup-option-title' + key"); OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. optGroupTag2.setLabel("My Label 2"); optGroupTag2.setList("#{'DDD':'ddd','EEE':'eee','FFF':'fff'}"); optGroupTag2.setListCssClass("notExistingProperty"); @@ -288,5 +808,84 @@ public class OptGroupTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(SelectTag.class.getResource("OptGroup-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); + } + + public void testOptGroupListAttributes_clearTagStateSet() throws Exception { + SelectTag selectTag = new SelectTag(); + selectTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + selectTag.setName("mySelection"); + selectTag.setLabel("My Selection"); + selectTag.setList("#{'ONE':'one','TWO':'two','THREE':'three'}"); + selectTag.setListCssClass("'option-css-class ' + key"); + selectTag.setListCssStyle("'background-color: green; font-family: ' + key"); + selectTag.setListTitle("'option-title' + key"); + + OptGroupTag optGroupTag1 = new OptGroupTag(); + optGroupTag1.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag1.setLabel("My Label 1"); + optGroupTag1.setList("#{'AAA':'aaa','BBB':'bbb','CCC':'ccc'}"); + optGroupTag1.setListCssClass("'optgroup-option-css-class ' + key"); + optGroupTag1.setListCssStyle("'background-color: blue; font-family: ' + key"); + optGroupTag1.setListTitle("'optgroup-option-title' + key"); + + OptGroupTag optGroupTag2 = new OptGroupTag(); + optGroupTag2.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + optGroupTag2.setLabel("My Label 2"); + optGroupTag2.setList("#{'DDD':'ddd','EEE':'eee','FFF':'fff'}"); + optGroupTag2.setListCssClass("notExistingProperty"); + optGroupTag2.setListCssStyle("notExistingProperty"); + optGroupTag2.setListTitle("notExistingProperty"); + + selectTag.setPageContext(pageContext); + selectTag.doStartTag(); + setComponentTagClearTagState(selectTag, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.setPageContext(pageContext); + optGroupTag1.doStartTag(); + setComponentTagClearTagState(optGroupTag1, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag1.doEndTag(); + optGroupTag2.setPageContext(pageContext); + optGroupTag2.doStartTag(); + setComponentTagClearTagState(optGroupTag2, true); // Ensure component tag state clearing is set true (to match tag). + optGroupTag2.doEndTag(); + selectTag.doEndTag(); + + //System.out.println(writer.toString()); + verify(SelectTag.class.getResource("OptGroup-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(selectTag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptGroupTag freshOptGroupTag = new OptGroupTag(); + freshOptGroupTag.setPerformClearTagStateForTagPoolingServers(true); + freshOptGroupTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag1, freshOptGroupTag)); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(optGroupTag2, freshOptGroupTag)); } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java index 9742effe1..97338d5d5 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java @@ -92,6 +92,88 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithAllSelected_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left1"); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right1"); + right.add("Right2"); + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("true"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list2"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("true"); + tag.setDoubleCssClass("c2"); + tag.setDoubleCssStyle("s2"); + + tag.setAllowAddAllToLeft("true"); + tag.setAllowAddAllToRight("true"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("true"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.setHeaderKey("Header Key"); + tag.setHeaderValue("Header Value"); + + tag.setDoubleHeaderKey("Double Header Key"); + tag.setDoubleHeaderValue("Double Header Value"); + + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithPartialSelectedOnBothSides() throws Exception { @@ -165,6 +247,96 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithPartialSelectedOnBothSides_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right2"); + + List leftVal = new ArrayList(); + leftVal.add("Left1"); + leftVal.add("Left2"); + leftVal.add("Left3"); + + List rightVal = new ArrayList(); + rightVal.add("Right1"); + rightVal.add("Right2"); + rightVal.add("Right3"); + + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + testaction.setCollection2(leftVal); + testaction.setList3(rightVal); + + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection2"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("true"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list3"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("true"); + + tag.setAllowAddAllToLeft("true"); + tag.setAllowAddAllToRight("true"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("true"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.setHeaderKey("Header Key"); + tag.setHeaderValue("Header Value"); + + tag.setDoubleHeaderKey("Double Header Key"); + tag.setDoubleHeaderValue("Double Header Value"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithoutHeaderOnBothSides() throws Exception { @@ -232,6 +404,90 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithoutHeaderOnBothSides_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right2"); + + List leftVal = new ArrayList(); + leftVal.add("Left1"); + leftVal.add("Left2"); + leftVal.add("Left3"); + + List rightVal = new ArrayList(); + rightVal.add("Right1"); + rightVal.add("Right2"); + rightVal.add("Right3"); + + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + testaction.setCollection2(leftVal); + testaction.setList3(rightVal); + + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection2"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("true"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list3"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("true"); + + tag.setAllowAddAllToLeft("true"); + tag.setAllowAddAllToRight("true"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("true"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithoutHeaderOnOneSide() throws Exception { @@ -302,6 +558,93 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithoutHeaderOnOneSide_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right2"); + + List leftVal = new ArrayList(); + leftVal.add("Left1"); + leftVal.add("Left2"); + leftVal.add("Left3"); + + List rightVal = new ArrayList(); + rightVal.add("Right1"); + rightVal.add("Right2"); + rightVal.add("Right3"); + + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + testaction.setCollection2(leftVal); + testaction.setList3(rightVal); + + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection2"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("true"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list3"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("true"); + + tag.setAllowAddAllToLeft("true"); + tag.setAllowAddAllToRight("true"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("true"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.setHeaderKey("Header Key"); + tag.setHeaderValue("Header Value"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithoutEmptyOptionOnBothSides() throws Exception { @@ -375,6 +718,96 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithoutEmptyOptionOnBothSides_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right2"); + + List leftVal = new ArrayList(); + leftVal.add("Left1"); + leftVal.add("Left2"); + leftVal.add("Left3"); + + List rightVal = new ArrayList(); + rightVal.add("Right1"); + rightVal.add("Right2"); + rightVal.add("Right3"); + + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + testaction.setCollection2(leftVal); + testaction.setList3(rightVal); + + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection2"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("false"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list3"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("false"); + + tag.setAllowAddAllToLeft("true"); + tag.setAllowAddAllToRight("true"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("true"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.setHeaderKey("Header Key"); + tag.setHeaderValue("Header Value"); + + tag.setDoubleHeaderKey("Double Header Key"); + tag.setDoubleHeaderValue("Double Header Value"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithoutEmptyOptionOnOneSide() throws Exception { @@ -448,6 +881,96 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithoutEmptyOptionOnOneSide_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right2"); + + List leftVal = new ArrayList(); + leftVal.add("Left1"); + leftVal.add("Left2"); + leftVal.add("Left3"); + + List rightVal = new ArrayList(); + rightVal.add("Right1"); + rightVal.add("Right2"); + rightVal.add("Right3"); + + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + testaction.setCollection2(leftVal); + testaction.setList3(rightVal); + + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection2"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("true"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list3"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("false"); + + tag.setAllowAddAllToLeft("true"); + tag.setAllowAddAllToRight("true"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("true"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.setHeaderKey("Header Key"); + tag.setHeaderValue("Header Value"); + + tag.setDoubleHeaderKey("Double Header Key"); + tag.setDoubleHeaderValue("Double Header Value"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDisableSomeButtons() throws Exception { @@ -524,6 +1047,99 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDisableSomeButtons_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right2"); + + List leftVal = new ArrayList(); + leftVal.add("Left1"); + leftVal.add("Left2"); + leftVal.add("Left3"); + + List rightVal = new ArrayList(); + rightVal.add("Right1"); + rightVal.add("Right2"); + rightVal.add("Right3"); + + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + testaction.setCollection2(leftVal); + testaction.setList3(rightVal); + + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setId("id"); + tag.setList("collection2"); + tag.setSize("20"); + tag.setMultiple("true"); + tag.setEmptyOption("true"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list3"); + tag.setDoubleId("doubleId"); + tag.setDoubleSize("20"); + tag.setMultiple("true"); + tag.setDoubleEmptyOption("true"); + + tag.setAllowAddAllToLeft("false"); + tag.setAllowAddAllToRight("false"); + tag.setAllowAddToLeft("true"); + tag.setAllowAddToRight("true"); + tag.setAllowSelectAll("false"); + + tag.setAddAllToLeftLabel("All Left"); + tag.setAddAllToRightLabel("All Right"); + tag.setAddToLeftLabel("Left"); + tag.setAddToRightLabel("Right"); + tag.setSelectAllLabel("Select All"); + + tag.setLeftTitle("Title Left"); + tag.setRightTitle("Title Right"); + + tag.setButtonCssClass("buttonCssClass"); + tag.setButtonCssStyle("buttonCssStyle"); + + tag.setHeaderKey("Header Key"); + tag.setHeaderValue("Header Value"); + + tag.setDoubleHeaderKey("Double Header Key"); + tag.setDoubleHeaderValue("Double Header Value"); + + tag.setAddToLeftOnclick("alert('Moving Left')"); + tag.setAddToRightOnclick("alert('Moving Right')"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDynamicAttributes() throws Exception { @@ -556,5 +1172,55 @@ public class OptionTransferSelectTagTest extends AbstractUITagTest { //System.out.println(writer.toString()); verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + + public void testDynamicAttributes_clearTagStateSet() throws Exception { + List left = new ArrayList(); + left.add("Left1"); + left.add("Left2"); + + List right = new ArrayList(); + right.add("Right1"); + right.add("Right2"); + + TestAction testaction = (TestAction) action; + testaction.setCollection(left); + testaction.setList2(right); + + OptionTransferSelectTag tag = new OptionTransferSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + tag.setName("collection"); + tag.setList("collection"); + + tag.setDoubleName("list2"); + tag.setDoubleList("list2"); + + tag.setDynamicAttribute(null, "collection", "leftName"); + tag.setDynamicAttribute(null, "right-collection", "rightName"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + //System.out.println(writer.toString()); + verify(OptionTransferSelectTagTest.class.getResource("optiontransferselect-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + OptionTransferSelectTag freshTag = new OptionTransferSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java index b3de7e291..a4d5cf236 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java @@ -40,6 +40,39 @@ public class PasswordTest extends AbstractUITagTest { tag.doEndTag(); verify(PasswordTag.class.getResource("Password-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PasswordTag freshTag = new PasswordTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + PasswordTag tag = new PasswordTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setTitle("mytitle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(PasswordTag.class.getResource("Password-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + PasswordTag freshTag = new PasswordTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGenericSimple() throws Exception { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java index 1caa5a5bd..8a8cbaa0f 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java @@ -50,8 +50,46 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testMapWithBooleanAsKey_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + HashMap map = new LinkedHashMap(); + map.put(Boolean.TRUE, "male"); + map.put(Boolean.FALSE, "female"); + testAction.setMap(map); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{true}"); + tag.setList("map"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testMapChecked() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("bar"); @@ -74,8 +112,49 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testMapChecked_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + Map map = new LinkedHashMap<>(); + map.put("1", "One"); + map.put("2", "Two"); + testAction.setMap(map); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("\"1\""); + tag.setList("map"); + tag.setListKey("key"); + tag.setListValue("value"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testMapCheckedNull() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("bar"); @@ -96,6 +175,45 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMapCheckedNull_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + HashMap map = new HashMap(); + map.put("1", "One"); + map.put("2", "Two"); + testAction.setMap(map); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{map['3']}"); + tag.setList("#@java.util.TreeMap@{\"1\":\"One\", \"2\":\"Two\", \"\":\"N/A\"}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimple() throws Exception { @@ -119,6 +237,46 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"} + }); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue(""); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleWithStringMap() throws Exception { @@ -134,6 +292,38 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleWithStringMap_clearTagStateSet() throws Exception { + final Map myMap = new TreeMap(); + myMap.put("name", "Std."); + stack.push(new HashMap() {{ put ("myMap", myMap); }}); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myMap['name']"); + tag.setList("#@java.util.TreeMap@{\"Opt.\":\"Opt.\", \"Std.\":\"Std.\", \"\":\"N/A\"}"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleWithLabelSeparator() throws Exception { @@ -158,6 +348,47 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleWithLabelSeparator_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"} + }); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue(""); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + tag.setLabelSeparator("--"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGenericSimple() throws Exception { @@ -194,6 +425,47 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(RadioTag.class.getResource("Radio-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDynamicAttributes_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"} + }); + + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue(""); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + tag.setDynamicAttribute(null, "dojo", "checked: %{top[0]}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(RadioTag.class.getResource("Radio-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNotExistingListValueKey() throws Exception { @@ -209,6 +481,38 @@ public class RadioTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Radio-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNotExistingListValueKey_clearTagStateSet() throws Exception { + RadioTag tag = new RadioTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setList("#{'a':'aaa', 'b':'bbb', 'c':'ccc'}"); + tag.setListValueKey("notExistingProperty"); + + tag.setPageContext(pageContext); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Radio-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + RadioTag freshTag = new RadioTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } private void prepareTagGeneric(RadioTag tag) { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java index 03ee9e960..c297b86cc 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java @@ -45,6 +45,40 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDefaultValues_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setTitle("mytitle"); + tag.setSrc("/images/test.png"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimple() throws Exception { @@ -62,6 +96,40 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setTabindex("1"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testButtonSimple() throws Exception { @@ -79,6 +147,40 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testButtonSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("button"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setTabindex("1"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testButtonWithLabel() throws Exception { @@ -96,6 +198,40 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testButtonWithLabel_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setType("button"); + tag.setName("myname"); + tag.setValue("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testImageSimple() throws Exception { @@ -113,6 +249,40 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testImageSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("button"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setDisabled("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testImageWithSrc() throws Exception { @@ -131,6 +301,41 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testImageWithSrc_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setValue("%{foo}"); + tag.setSrc("some.gif"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testImageWithExpressionSrc() throws Exception { @@ -149,6 +354,41 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testImageWithExpressionSrc_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setValue("%{foo}"); + tag.setSrc("%{getText(\"some.image.from.properties\")}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeImageUsingActionAndMethod() throws Exception { @@ -168,6 +408,42 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleThemeImageUsingActionAndMethod_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction("manager"); + tag.setMethod("update"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeImageUsingActionOnly() throws Exception { @@ -187,6 +463,42 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleThemeImageUsingActionOnly_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction("manager"); + tag.setMethod(null); // no method + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeImageUsingMethodOnly() throws Exception { @@ -206,8 +518,44 @@ public class ResetTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Reset-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testSimpleThemeImageUsingMethodOnly_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + ResetTag tag = new ResetTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction(null); // no action + tag.setMethod("update"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Reset-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ResetTag freshTag = new ResetTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + /** * Initialize a map of {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder} for generic tag * property testing. Will be used when calling {@link #verifyGenericProperties(AbstractUITag, @@ -216,6 +564,7 @@ public class ResetTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = new HashMap(); new PropertyHolder("title", "someTitle").addToMap(result); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java index c30b8f5ab..e739ffe01 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java @@ -46,6 +46,39 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testHeaderCanBePreselected_clearTagStateSet() throws Exception { + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("myLabel"); + tag.setList("#{1:'Cat',2:'Dog'}"); + tag.setName("myPet"); + tag.setHeaderKey("-1"); + tag.setHeaderValue("--- Please Select ---"); + tag.setValue("%{'-1'}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -87,8 +120,65 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + /** + * Tests WW-1601: Select tag template does not work properly for Object like Byte. + */ + public void testByte_clearTagStateSet() throws Exception { + ByteObject hello = new ByteObject(new Byte((byte)1), "hello"); + ByteObject foo = new ByteObject(new Byte((byte)2), "foo"); + + TestAction testAction = (TestAction) action; + + Collection collection = new ArrayList(2); + // expect strings to be returned, we're still dealing with HTTP here! + collection.add("1"); + collection.add("2"); + testAction.setCollection(collection); + + List list2 = new ArrayList(); + list2.add(hello); + list2.add(foo); + testAction.setList2(list2); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list2"); + tag.setListKey("byte"); + tag.setListValue("name"); + tag.setMultiple("true"); + tag.setTitle("mytitle"); + tag.setOnmousedown("alert('onmousedown');"); + tag.setOnmousemove("alert('onmousemove');"); + tag.setOnmouseout("alert('onmouseout');"); + tag.setOnmouseover("alert('onmouseover');"); + tag.setOnmouseup("alert('onmouseup');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } /** * Tests WW-455: Select tag template does not work properly for Object like BigDecimal. @@ -130,6 +220,65 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * Tests WW-455: Select tag template does not work properly for Object like BigDecimal. + */ + public void testBigDecimal_clearTagStateSet() throws Exception { + BigDecimalObject hello = new BigDecimalObject("hello", new BigDecimal(1)); + BigDecimalObject foo = new BigDecimalObject("foo", new BigDecimal(2)); + + TestAction testAction = (TestAction) action; + + Collection collection = new ArrayList(2); + // expect strings to be returned, we're still dealing with HTTP here! + collection.add("hello"); + collection.add("foo"); + testAction.setCollection(collection); + + List list2 = new ArrayList(); + list2.add(hello); + list2.add(foo); + list2.add(new BigDecimalObject("", new BigDecimal(1.500))); + testAction.setList2(list2); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list2"); + tag.setListKey("name"); + tag.setListValue("bigDecimal"); + tag.setMultiple("true"); + tag.setTitle("mytitle"); + tag.setOnmousedown("alert('onmousedown');"); + tag.setOnmousemove("alert('onmousemove');"); + tag.setOnmouseout("alert('onmouseout');"); + tag.setOnmouseover("alert('onmouseover');"); + tag.setOnmouseup("alert('onmouseup');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testInteger() throws Exception { @@ -169,6 +318,62 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-14.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testInteger_clearTagStateSet() throws Exception { + IntegerObject hello = new IntegerObject("hello", 1); + IntegerObject foo = new IntegerObject("foo", 2); + + TestAction testAction = (TestAction) action; + + Collection collection = new ArrayList(2); + // expect strings to be returned, we're still dealing with HTTP here! + collection.add("hello"); + collection.add("foo"); + testAction.setCollection(collection); + + List list2 = new ArrayList(); + list2.add(hello); + list2.add(foo); + list2.add(new IntegerObject("", 3)); + testAction.setList2(list2); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list2"); + tag.setListKey("name"); + tag.setListValue("integer"); + tag.setMultiple("true"); + tag.setTitle("mytitle"); + tag.setOnmousedown("alert('onmousedown');"); + tag.setOnmousemove("alert('onmousemove');"); + tag.setOnmouseout("alert('onmouseout');"); + tag.setOnmouseover("alert('onmouseover');"); + tag.setOnmouseup("alert('onmouseup');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-14.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNumericString() throws Exception { @@ -209,6 +414,63 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-15.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNumericString_clearTagStateSet() throws Exception { + StringObject hello = new StringObject("hello", "1"); + StringObject foo = new StringObject("foo", "2"); + + TestAction testAction = (TestAction) action; + + Collection collection = new ArrayList(2); + // expect strings to be returned, we're still dealing with HTTP here! + collection.add("hello"); + collection.add("foo"); + testAction.setCollection(collection); + + List list2 = new ArrayList(); + list2.add(hello); + list2.add(foo); + list2.add(new StringObject("", "1.5")); + list2.add(new StringObject("", "2,5")); + testAction.setList2(list2); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list2"); + tag.setListKey("name"); + tag.setListValue("number"); + tag.setMultiple("true"); + tag.setTitle("mytitle"); + tag.setOnmousedown("alert('onmousedown');"); + tag.setOnmousemove("alert('onmousemove');"); + tag.setOnmouseout("alert('onmouseout');"); + tag.setOnmouseover("alert('onmouseover');"); + tag.setOnmouseup("alert('onmouseup');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-15.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public class BigDecimalObject { @@ -345,6 +607,39 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEmptyList_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setList2(new ArrayList()); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("collection"); + tag.setList("list2"); + tag.setLabel("tmjee_name"); + + tag.setPageContext(pageContext); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testMultiple() throws Exception { @@ -377,6 +672,55 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMultiple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + Collection collection = new ArrayList(2); + collection.add("hello"); + collection.add("foo"); + testAction.setCollection(collection); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"}, + {"cat", "dog"} + }); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + tag.setMultiple("true"); + tag.setOnmousedown("alert('onmousedown');"); + tag.setOnmousemove("alert('onmousemove');"); + tag.setOnmouseout("alert('onmouseout');"); + tag.setOnmouseover("alert('onmouseover');"); + tag.setOnmouseup("alert('onmouseup');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -415,6 +759,61 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + /** + * WW-1747 - should be a valid test case for the described issue + * @throws Exception + */ + public void testMultipleWithLists_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + Collection collection = new ArrayList(2); + + collection.add(1l); + collection.add(300000000l); + testAction.setCollection(collection); + + List selectList = new ArrayList(); + selectList.add(new LongObject(1l, "foo")); + selectList.add(new LongObject(2l, "bar")); + selectList.add(new LongObject(300000000l, "foobar")); + testAction.setList2(selectList); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("collection"); + tag.setList("list2"); + tag.setListKey("id"); + tag.setListValue("value"); + tag.setMultiple("true"); + tag.setOnmousedown("alert('onmousedown');"); + tag.setOnmousemove("alert('onmousemove');"); + tag.setOnmouseout("alert('onmouseout');"); + tag.setOnmouseover("alert('onmouseover');"); + tag.setOnmouseup("alert('onmouseup');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimple() throws Exception { @@ -445,8 +844,55 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"} + }); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setEmptyOption("true"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + + // header stuff + tag.setHeaderKey("headerKey"); + tag.setHeaderValue("headerValue"); + + // empty option + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testSimpleWithNulls() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("hello"); @@ -475,6 +921,53 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleWithNulls_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + testAction.setList(new String[][]{ + {"hello", null}, + {null, "bar"} + }); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setEmptyOption("true"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("top[1]"); + + // header stuff + tag.setHeaderKey("headerKey"); + tag.setHeaderValue("headerValue"); + + // empty option + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testExtended() throws Exception { @@ -505,6 +998,53 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testExtended_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("hello"); + testAction.setList(new String[][]{ + {"hello", "world"}, + {"foo", "bar"} + }); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setEmptyOption("true"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setList("list"); + tag.setListKey("top[0]"); + tag.setListValue("%{top[0] + ' - ' + top[1]}"); + + // header stuff + tag.setHeaderKey("headerKey"); + tag.setHeaderValue("%{foo + ': headerValue'}"); + + // empty option + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGenericSimple() throws Exception { @@ -533,6 +1073,39 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testMultipleOn_clearTagStateSet() throws Exception { + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("media1"); + tag.setId("myId"); + tag.setEmptyOption("true"); + tag.setName("myName"); + tag.setMultiple("true"); + tag.setList("{'aaa','bbb'}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testMultipleOff() throws Exception { @@ -549,8 +1122,40 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testMultipleOff_clearTagStateSet() throws Exception { + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("media2"); + tag.setId("myId"); + tag.setEmptyOption("true"); + tag.setName("myName"); + tag.setMultiple("false"); + tag.setList("{'aaa','bbb'}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testSimpleInteger() throws Exception { TestAction testAction = (TestAction) action; @@ -584,6 +1189,57 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleInteger_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + IdName hello = new IdName(new Integer(1), "hello"); + IdName world = new IdName(new Integer(2), "world"); + List list2 = new ArrayList(); + list2.add(hello); + list2.add(world); + testAction.setList2(list2); + + testAction.setFooInt(new Integer(1)); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setEmptyOption("true"); + tag.setLabel("mylabel"); + tag.setName("fooInt"); + tag.setList("list2"); + tag.setListKey("id"); + tag.setListValue("name"); + + // header stuff + tag.setHeaderKey("headerKey"); + tag.setHeaderValue("headerValue"); + + // empty option + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleIntegerWithValueWorkaround() throws Exception { @@ -619,8 +1275,60 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testSimpleIntegerWithValueWorkaround_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + IdName hello = new IdName(new Integer(1), "hello"); + IdName world = new IdName(new Integer(2), "world"); + List list2 = new ArrayList(); + list2.add(hello); + list2.add(world); + testAction.setList2(list2); + + testAction.setFooInt(new Integer(1)); + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setEmptyOption("true"); + tag.setLabel("mylabel"); + tag.setName("fooInt"); + tag.setList("list2"); + tag.setListKey("id"); + tag.setListValue("name"); + tag.setValue("fooInt"); + + // header stuff + tag.setHeaderKey("headerKey"); + tag.setHeaderValue("headerValue"); + + // empty option + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testEnumList() throws Exception { SelectTag tag = new SelectTag(); @@ -635,6 +1343,39 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-13.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testEnumList_clearTagStateSet() throws Exception { + + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("status"); + tag.setList("statusList"); + tag.setListKey("name"); + tag.setListValue("displayName"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-13.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNotExistingListValueKey() throws Exception { @@ -650,6 +1391,38 @@ public class SelectTest extends AbstractUITagTest { tag.doEndTag(); verify(SelectTag.class.getResource("Select-16.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNotExistingListValueKey_clearTagStateSet() throws Exception { + SelectTag tag = new SelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setName("foo"); + tag.setLabel("mylabel"); + tag.setList("#{'a':'aaa', 'b':'bbb', 'c':'ccc'}"); + tag.setListValueKey("notExistingProperty"); + + tag.setPageContext(pageContext); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(SelectTag.class.getResource("Select-16.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SelectTag freshTag = new SelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public class IdName { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java index b1c7da721..6f573ae07 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java @@ -50,6 +50,44 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testButtonSimpleWithBody_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setTheme("simple"); + tag.setPageContext(pageContext); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("yoyoyoyoy"); + tag.setValue("%{foo}"); + + StrutsBodyContent body = new StrutsBodyContent(null); + body.print("foo"); + tag.setBodyContent(body); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDefaultValues() throws Exception { @@ -57,6 +95,7 @@ public class SubmitTest extends AbstractUITagTest { testAction.setFoo("bar"); SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. tag.setPageContext(pageContext); tag.setLabel("mylabel"); tag.setName("myname"); @@ -66,6 +105,39 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDefaultValues_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setTitle("mytitle"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimple() throws Exception { @@ -84,6 +156,41 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setDisabled("true"); + tag.setTabindex("1"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testButtonSimple() throws Exception { @@ -102,6 +209,41 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testButtonSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("button"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setDisabled("true"); + tag.setTabindex("1"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testButtonWithLabel() throws Exception { @@ -119,6 +261,40 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testButtonWithLabel_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setType("button"); + tag.setName("myname"); + tag.setValue("%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testImageSimple() throws Exception { @@ -136,6 +312,40 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testImageSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("image"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setDisabled("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testImageWithSrc() throws Exception { @@ -154,6 +364,41 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testImageWithSrc_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setType("image"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setValue("%{foo}"); + tag.setSrc("some.gif"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeImageUsingActionAndMethod() throws Exception { @@ -173,6 +418,42 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleThemeImageUsingActionAndMethod_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction("manager"); + tag.setMethod("update"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeImageUsingActionOnly() throws Exception { @@ -192,6 +473,42 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleThemeImageUsingActionOnly_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction("manager"); + tag.setMethod(null); // no method + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeImageUsingMethodOnly() throws Exception { @@ -211,6 +528,42 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Submit-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleThemeImageUsingMethodOnly_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("button"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction(null); // no action + tag.setMethod("update"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Submit-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testSimpleThemeInput() throws Exception { @@ -230,6 +583,42 @@ public class SubmitTest extends AbstractUITagTest { tag.doEndTag(); assertEquals("", writer.toString().trim()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimpleThemeInput_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + SubmitTag tag = new SubmitTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setTheme("simple"); + tag.setType("input"); + tag.setName("myname"); + tag.setLabel("mylabel"); + tag.setAction(null); + tag.setMethod(null); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + assertEquals("", writer.toString().trim()); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + SubmitTag freshTag = new SubmitTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } /** @@ -240,6 +629,7 @@ public class SubmitTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = new HashMap(); new PropertyHolder("title", "someTitle").addToMap(result); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java index ddd050608..54fa4787a 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java @@ -52,6 +52,49 @@ public class TextareaTest extends AbstractUITagTest { tag.doEndTag(); verify(TextareaTag.class.getResource("Textarea-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextareaTag freshTag = new TextareaTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextareaTag tag = new TextareaTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setRows("30"); + tag.setCols("20"); + tag.setTitle("mytitle"); + tag.setDisabled("true"); + tag.setTabindex("5"); + tag.setOnchange("alert('goodbye');"); + tag.setOnclick("alert('onclick');"); + tag.setId("the_id"); + tag.setOnkeyup("alert('hello');"); + tag.setReadonly("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextareaTag.class.getResource("Textarea-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextareaTag freshTag = new TextareaTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoColsAndRows() throws Exception { @@ -86,6 +129,7 @@ public class TextareaTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = super.initializedGenericTagTestProperties(); new PropertyHolder("cols", "10").addToMap(result); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java index f1701a86d..cf300e806 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java @@ -39,6 +39,7 @@ public class TextfieldTest extends AbstractUITagTest { * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()} * as key. */ + @Override protected Map initializedGenericTagTestProperties() { Map result = super.initializedGenericTagTestProperties(); new PropertyHolder("maxlength", "10").addToMap(result); @@ -74,6 +75,42 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrors_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setTitle("mytitle"); + + testAction.addFieldError("foo", "bar error message"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoLabelJsp() throws Exception { @@ -91,8 +128,42 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testNoLabelJsp_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setSize("10"); + tag.setOnblur("blahescape('somevalue');"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testLabelSeparatorJsp() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("bar"); @@ -110,6 +181,42 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testLabelSeparatorJsp_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setSize("10"); + tag.setOnblur("blahescape('somevalue');"); + tag.setLabelSeparator("??"); + tag.setLabel("label"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNoLabelFtl() throws Exception { @@ -144,6 +251,40 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setSize("10"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWW5125() throws Exception { @@ -157,6 +298,39 @@ public class TextfieldTest extends AbstractUITagTest { tag.setName(fieldName); tag.doStartTag(); tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + verify(TextFieldTag.class.getResource("Textfield-WW-5125.txt")); + } + + public void testWW5125_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + + for(String fieldName : new String[] {"clone", "size", "clear", "values", "hashCode", "isEmpty", "keySet", "entrySet"}) { + testAction.addFieldError(fieldName, fieldName + " error"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName(fieldName); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } verify(TextFieldTag.class.getResource("Textfield-WW-5125.txt")); @@ -178,8 +352,43 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } - + + public void testSimple_recursionTest_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("%{1+1}"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("myname"); + tag.setValue("%{foo}"); + tag.setSize("10"); + tag.setDynamicAttribute(null, "anotherAttr", "%{foo}"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + public void testSimple_recursionTestNoValue() throws Exception { TestAction testAction = (TestAction) action; testAction.setFoo("%{1+1}"); @@ -194,6 +403,39 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testSimple_recursionTestNoValue_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("%{1+1}"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setSize("10"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testHtml5EmailTag() throws Exception { @@ -211,6 +453,40 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testHtml5EmailTag_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("myemaillabel"); + tag.setName("foo"); + tag.setSize("50"); + tag.setType("email"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testErrorPositionBottom() throws Exception { @@ -231,6 +507,43 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrorPositionBottom_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setTitle("mytitle"); + tag.setErrorPosition("bottom"); + + testAction.addFieldError("foo", "bar error message"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testErrorPositionTop() throws Exception { @@ -251,6 +564,43 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrorPositionTop_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setTitle("mytitle"); + tag.setErrorPosition("top"); + + testAction.addFieldError("foo", "bar error message"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequiredLabelPositionDefault() throws Exception { @@ -269,6 +619,41 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequiredLabelPositionDefault_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setRequiredLabel("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequiredLabelPositionRight() throws Exception { @@ -288,6 +673,42 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testRequiredLabelPositionRight_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setRequiredLabel("true"); + tag.setRequiredPosition("right"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-12.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testRequiredLabelPositionLeft() throws Exception { @@ -307,6 +728,43 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-13.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + + public void testRequiredLabelPositionLeft_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setRequiredLabel("true"); + tag.setRequiredPosition("left"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-13.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testErrorPositionBottomCssXhtmlTheme() throws Exception { @@ -328,6 +786,44 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrorPositionBottomCssXhtmlTheme_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setTitle("mytitle"); + tag.setErrorPosition("bottom"); + tag.setTheme("css_xhtml"); + + testAction.addFieldError("foo", "bar error message"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testErrorPositionTopCssXhtmlTheme() throws Exception { @@ -349,6 +845,44 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrorPositionTopCssXhtmlTheme_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setFoo("bar"); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setLabel("mylabel"); + tag.setName("foo"); + tag.setValue("bar"); + tag.setTitle("mytitle"); + tag.setErrorPosition("top"); + tag.setTheme("css_xhtml"); + + testAction.addFieldError("foo", "bar error message"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testNameEvaluation() throws Exception { @@ -364,7 +898,38 @@ public class TextfieldTest extends AbstractUITagTest { tag.doEndTag(); verify(TextFieldTag.class.getResource("Textfield-14.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testNameEvaluation_clearTagStateSet() throws Exception { + TestAction testAction = (TestAction) action; + testAction.setArray(new String[]{"test", "bar"}); + testAction.setFooInt(1); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setName("array[%{fooInt}]"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(TextFieldTag.class.getResource("Textfield-14.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TokenTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TokenTagTest.java index 1d2b42f3f..d265eacfb 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TokenTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TokenTagTest.java @@ -33,7 +33,8 @@ public class TokenTagTest extends AbstractUITagTest { public void testDefaultName() { String tokenName = TokenHelper.DEFAULT_TOKEN_NAME; TokenTag tag = new TokenTag(); - doTokenTest(tokenName, tag); + doTokenTest(tokenName, tag, false); + doTokenTest_clearTagStateSet(tokenName, tag); } public void testMultipleTagsWithSameName() { @@ -41,13 +42,16 @@ public class TokenTagTest extends AbstractUITagTest { TokenTag tag = new TokenTag(); tag.setName(tokenName); - String token = doTokenTest(tokenName, tag); + String token = doTokenTest(tokenName, tag, true); TokenTag anotherTag = new TokenTag(); anotherTag.setName(tokenName); - String anotherToken = doTokenTest(tokenName, anotherTag); + String anotherToken = doTokenTest(tokenName, anotherTag, true); assertEquals(token, anotherToken); + + doTokenTest_clearTagStateSet(tokenName, tag); + doTokenTest_clearTagStateSet(tokenName, anotherTag); } /** @@ -57,7 +61,7 @@ public class TokenTagTest extends AbstractUITagTest { String tokenName = "foo"; TokenTag tag = new TokenTag(); tag.setName(tokenName); - doTokenTest(tokenName, tag); + doTokenTest(tokenName, tag, true); String s = writer.toString(); assertTrue(s.indexOf("name=\"" + TokenHelper.TOKEN_NAME_FIELD) > -1); @@ -65,16 +69,18 @@ public class TokenTagTest extends AbstractUITagTest { assertTrue(s.indexOf("name=\"" + tokenName + "\"") > -1); //System.out.println(s); + doTokenTest_clearTagStateSet(tokenName, tag); } public void testSuppliedName() { String tokenName = "my.very.long.token.name"; TokenTag tag = new TokenTag(); tag.setName(tokenName); - doTokenTest(tokenName, tag); + doTokenTest(tokenName, tag, true); + doTokenTest_clearTagStateSet(tokenName, tag); } - private String doTokenTest(String tokenName, TokenTag tag) { + private String doTokenTest(String tokenName, TokenTag tag, boolean tagNameWasSet) { tag.setPageContext(pageContext); String token = null; @@ -87,6 +93,20 @@ public class TokenTagTest extends AbstractUITagTest { assertNotNull(token); final String sessionTokenName = TokenHelper.buildTokenSessionAttributeName(tokenName); assertEquals(token, pageContext.getSession().getAttribute(sessionTokenName)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TokenTag freshTag = new TokenTag(); + freshTag.setPageContext(pageContext); + if (tagNameWasSet) { + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } else { + // TokenTag has no non=default state set here, so it compares as equal with the default tag clear state as well. + assertTrue("Tag state after doEndTag() under default tag clear state is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } } catch (JspException e) { e.printStackTrace(); fail(); @@ -94,4 +114,36 @@ public class TokenTagTest extends AbstractUITagTest { return token; } + + private String doTokenTest_clearTagStateSet(String tokenName, TokenTag tag) { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + + String token = null; + + try { + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + token = (String) context.get(tokenName); + assertNotNull(token); + final String sessionTokenName = TokenHelper.buildTokenSessionAttributeName(tokenName); + assertEquals(token, pageContext.getSession().getAttribute(sessionTokenName)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TokenTag freshTag = new TokenTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } catch (JspException e) { + e.printStackTrace(); + fail(); + } + + return token; + } + } diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TooltipTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TooltipTest.java index 8c8d8e1c8..05b117562 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TooltipTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TooltipTest.java @@ -64,6 +64,74 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + + public void testWithoutFormOverriding_clearTagStateSet() throws Exception { + + // we test it on textfield component, but since the tooltip are common to + // all components, it will be the same for other components as well. + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + formTag.setName("myForm"); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + + tag.setTooltip("myTooltip"); + tag.setTooltipConfig( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip.gif', " + + "'tooltipDelay':'500', " + + "'jsTooltipEnabled':'true' "+ + "}" + ); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } public void testWithoutFormOverridingNoJS() throws Exception { @@ -98,8 +166,76 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } - + + public void testWithoutFormOverridingNoJS_clearTagStateSet() throws Exception { + + // we test it on textfield component, but since the tooltip are common to + // all components, it will be the same for other components as well. + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + formTag.setName("myForm"); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + + tag.setTooltip("myTooltip"); + tag.setTooltipConfig( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip.gif', " + + "'tooltipDelay':'500', " + + "'jsTooltipEnabled':'false' "+ + "}" + ); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + public void testWithoutFormOverridingNew() throws Exception { // we test it on textfield component, but since the tooltip are common to @@ -130,6 +266,72 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + + public void testWithoutFormOverridingNew_clearTagStateSet() throws Exception { + + // we test it on textfield component, but since the tooltip are common to + // all components, it will be the same for other components as well. + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + formTag.setName("myForm"); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + + //same parameters as the OGNL map configuration, output must be the same + tag.setTooltip("myTooltip"); + tag.setTooltipIconPath("/static/tooltip/myTooltip.gif"); + tag.setTooltipDelay("500"); + tag.setJavascriptTooltip("true"); + + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } public void testWithFormOverriding() throws Exception { @@ -162,8 +364,74 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } - + + public void testWithFormOverriding_clearTagStateSet() throws Exception { + + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setPageContext(pageContext); + formTag.setName("myForm"); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + + formTag.setTooltipConfig( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip.gif', " + + "'tooltipDelay':'500', " + + "'jsTooltipEnabled':'true' "+ + "}" + ); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + tag.setTooltip("myTooltip"); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + public void testWithFormOverridingNew() throws Exception { FormTag formTag = new FormTag(); @@ -192,6 +460,70 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + + public void testWithFormOverridingNew_clearTagStateSet() throws Exception { + + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setPageContext(pageContext); + formTag.setName("myForm"); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + + // same parameters as the OGNL map configuration, output must be the same + formTag.setTooltip("myTooltip"); + formTag.setTooltipIconPath("/static/tooltip/myTooltip.gif"); + formTag.setTooltipDelay("500"); + formTag.setJavascriptTooltip("true"); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + tag.setTooltip("myTooltip"); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } public void testWithPartialFormOverriding() throws Exception { @@ -230,6 +562,78 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + + public void testWithPartialFormOverriding_clearTagStateSet() throws Exception { + + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setName("myForm"); + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + + formTag.setTooltipConfig( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip.gif', " + + "'tooltipDelay':'500', " + + "'jsTooltipEnabled':'true' "+ + "}" + ); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + tag.setTooltip("myTooltip"); + tag.setTooltipConfig( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip2.gif', " + + "'tooltipDelay':'5000' " + + "}" + ); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } public void testWithPartialFormOverridingNew() throws Exception { @@ -265,6 +669,75 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + + public void testWithPartialFormOverridingNew_clearTagStateSet() throws Exception { + + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setName("myForm"); + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + + // same parameters as the OGNL map configuration, output must be the same + formTag.setTooltip("myTooltip"); + formTag.setTooltipIconPath("/static/tooltip/myTooltip.gif"); + formTag.setTooltipDelay("500"); + formTag.setJavascriptTooltip("true"); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + + + //same parameters as the OGNL map configuration, output must be the same + tag.setTooltip("myTooltip"); + tag.setTooltipIconPath("/static/tooltip/myTooltip2.gif"); + tag.setTooltipDelay("5000"); + tag.setJavascriptTooltip("true"); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } public void testUsingParamValueToSetConfigurations() throws Exception { @@ -313,8 +786,90 @@ public class TooltipTest extends AbstractUITagTest { formTag.doEndTag(); verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } + public void testUsingParamValueToSetConfigurations_clearTagStateSet() throws Exception { + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setName("myForm"); + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + + + ParamTag formParamTag = new ParamTag(); + formParamTag.setPageContext(pageContext); + formParamTag.setName("tooltipConfig"); + formParamTag.setValue( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip.gif', " + + "'tooltipDelay':'500', " + + "'jsTooltipEnabled':'true' "+ + "}" + ); + + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + tag.setTooltip("myTooltip"); + + ParamTag textFieldParamTag = new ParamTag(); + textFieldParamTag.setPageContext(pageContext); + textFieldParamTag.setName("tooltipConfig"); + textFieldParamTag.setValue( + "#{" + + "'tooltipIcon':'/static/tooltip/myTooltip2.gif', " + + "'tooltipDelay':'5000' "+ + "}" + ); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + formParamTag.doStartTag(); + setComponentTagClearTagState(formParamTag, true); // Ensure component tag state clearing is set true (to match tag). + formParamTag.doEndTag(); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + textFieldParamTag.doStartTag(); + textFieldParamTag.doEndTag(); + tag.doEndTag(); + formTag.doEndTag(); + + verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } public void testUsingParamBodyValueToSetConfigurations() throws Exception { @@ -365,8 +920,112 @@ public class TooltipTest extends AbstractUITagTest { System.out.println(writer.toString()); verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(textFieldParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); } + public void testUsingParamBodyValueToSetConfigurations_clearTagStateSet() throws Exception { + + FormTag formTag = new FormTag(); + formTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + formTag.setName("myForm"); + formTag.setPageContext(pageContext); + formTag.setId("myFormId"); + formTag.setAction("testAction"); + + + ParamTag formParamTag = new ParamTag(); + formParamTag.setPageContext(pageContext); + formParamTag.setName("tooltipConfig"); + StrutsMockBodyContent bodyContent = new StrutsMockBodyContent(new MockJspWriter()); + bodyContent.setString( + "tooltipIcon=/static/tooltip/myTooltip.gif| " + + "tooltipDelay=500| " + + "jsTooltipEnabled=true " + ); + formParamTag.setBodyContent(bodyContent); + + TextFieldTag tag = new TextFieldTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setLabel("MyLabel"); + tag.setId("myId"); + tag.setTooltip("myTooltip"); + + + ParamTag textFieldParamTag = new ParamTag(); + textFieldParamTag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + textFieldParamTag.setPageContext(pageContext); + textFieldParamTag.setName("tooltipConfig"); + StrutsMockBodyContent bodyContent2 = new StrutsMockBodyContent(new MockJspWriter()); + bodyContent2.setString( + "tooltipIcon=/static/tooltip/myTooltip2.gif| " + + "tooltipDelay=5000 " + ); + textFieldParamTag.setBodyContent(bodyContent2); + + formTag.doStartTag(); + setComponentTagClearTagState(formTag, true); // Ensure component tag state clearing is set true (to match tag). + formParamTag.doStartTag(); + setComponentTagClearTagState(formParamTag, true); // Ensure component tag state clearing is set true (to match tag). + formParamTag.doEndTag(); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + textFieldParamTag.doStartTag(); + setComponentTagClearTagState(textFieldParamTag, true); // Ensure component tag state clearing is set true (to match tag). + textFieldParamTag.doEndTag(); + tag.doEndTag(); + formTag.doEndTag(); + + System.out.println(writer.toString()); + + verify(TooltipTest.class.getResource("tooltip-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + ParamTag freshParamTag = new ParamTag(); + freshParamTag.setPerformClearTagStateForTagPoolingServers(true); + freshParamTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(textFieldParamTag, freshParamTag)); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + FormTag freshFormTag = new FormTag(); + freshFormTag.setPerformClearTagStateForTagPoolingServers(true); + freshFormTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(formTag, freshFormTag)); + } + + @Override public void setUp() throws Exception { super.setUp(); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java index f35fa18f1..57942c192 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java @@ -48,6 +48,39 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithAllSelected_clearTagStateSet() throws Exception { + + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("myAllSelectedMapIds"); + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithPartialSelected() throws Exception { @@ -66,6 +99,41 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithPartialSelected_clearTagStateSet() throws Exception { + + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("false"); + + stack.getActionContext().getSession().put("nonce", "r4nd0m"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithHeaderAndEmptyOption() throws Exception { @@ -84,6 +152,41 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithHeaderAndEmptyOption_clearTagStateSet() throws Exception { + + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setHeaderKey("-1"); + tag.setHeaderValue("--- Please Order ---"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithHeaderOnly() throws Exception { @@ -102,6 +205,41 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testWithHeaderOnly_clearTagStateSet() throws Exception { + + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("false"); + tag.setHeaderKey("-1"); + tag.setHeaderValue("--- Please Order ---"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-4.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testWithEmptyOptionOnly() throws Exception { @@ -118,8 +256,40 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } + public void testWithEmptyOptionOnly_clearTagStateSet() throws Exception { + + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-5.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } public void testDisableSomeSelectAllButton() throws Exception { @@ -136,6 +306,40 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDisableSomeSelectAllButton_clearTagStateSet() throws Exception { + + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setAllowSelectAll("false"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-6.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDisableMoveUpButton() throws Exception { @@ -152,6 +356,39 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDisableMoveUpButton_clearTagStateSet() throws Exception { + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setAllowMoveUp("false"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-7.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testDisableMoveDownButton() throws Exception { @@ -168,6 +405,39 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testDisableMoveDownButton_clearTagStateSet() throws Exception { + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setAllowMoveDown("false"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-8.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testChangeSelectAllButtonText() throws Exception { @@ -184,6 +454,39 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testChangeSelectAllButtonText_clearTagStateSet() throws Exception { + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setSelectAllLabel("Select All"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-9.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testChangeMoveUpButtonText() throws Exception { @@ -200,6 +503,39 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testChangeMoveUpButtonText_clearTagStateSet() throws Exception { + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setMoveUpLabel("Move Up"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-10.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testChangeMoveDownButtonText() throws Exception { @@ -216,6 +552,39 @@ public class UpDownSelectTagTest extends AbstractUITagTest { tag.doEndTag(); verify(UpDownSelectTagTest.class.getResource("updownselecttag-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testChangeMoveDownButtonText_clearTagStateSet() throws Exception { + UpDownSelectTag tag = new UpDownSelectTag(); + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setPageContext(pageContext); + tag.setId("myId"); + tag.setName("myName"); + tag.setList("myMap"); + tag.setValue("mySelectedMapIds"); + tag.setEmptyOption("true"); + tag.setMoveDownLabel("Move Down"); + + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(UpDownSelectTagTest.class.getResource("updownselecttag-11.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + UpDownSelectTag freshTag = new UpDownSelectTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testGenericSimple() throws Exception { @@ -237,6 +606,7 @@ public class UpDownSelectTagTest extends AbstractUITagTest { // =============================== + @Override public Action getAction() { return new ActionSupport() { diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ValidationStylesTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ValidationStylesTest.java index 07f54916a..3727de771 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ValidationStylesTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ValidationStylesTest.java @@ -30,6 +30,31 @@ public class ValidationStylesTest extends AbstractUITagTest { tag.doEndTag(); verify(ValidationStylesTest.class.getResource("validationstyles-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testNormalStyle_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setCssStyle("style"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ValidationStylesTest.class.getResource("validationstyles-1.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testErrorStyle() throws Exception { @@ -38,6 +63,31 @@ public class ValidationStylesTest extends AbstractUITagTest { tag.doEndTag(); verify(ValidationStylesTest.class.getResource("validationstyles-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrorStyle_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setCssErrorStyle("errstyle"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ValidationStylesTest.class.getResource("validationstyles-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testErrorClass() throws Exception { @@ -46,6 +96,31 @@ public class ValidationStylesTest extends AbstractUITagTest { tag.doEndTag(); verify(ValidationStylesTest.class.getResource("validationstyles-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testErrorClass_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setCssErrorClass("errclass"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ValidationStylesTest.class.getResource("validationstyles-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testStyleAndErrorStyle() throws Exception { @@ -55,6 +130,32 @@ public class ValidationStylesTest extends AbstractUITagTest { tag.doEndTag(); verify(ValidationStylesTest.class.getResource("validationstyles-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testStyleAndErrorStyle_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setCssStyle("style"); + tag.setCssErrorStyle("errstyle"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ValidationStylesTest.class.getResource("validationstyles-2.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } public void testStyleAndErrorClass() throws Exception { @@ -64,6 +165,32 @@ public class ValidationStylesTest extends AbstractUITagTest { tag.doEndTag(); verify(ValidationStylesTest.class.getResource("validationstyles-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPageContext(pageContext); + assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); + } + + public void testStyleAndErrorClass_clearTagStateSet() throws Exception { + tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing. + tag.setCssStyle("style"); + tag.setCssErrorClass("errclass"); + tag.doStartTag(); + setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag). + tag.doEndTag(); + + verify(ValidationStylesTest.class.getResource("validationstyles-3.txt")); + + // Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag(). + TextFieldTag freshTag = new TextFieldTag(); + freshTag.setPerformClearTagStateForTagPoolingServers(true); + freshTag.setPageContext(pageContext); + assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " + + "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.", + strutsBodyTagsAreReflectionEqual(tag, freshTag)); } @Override