This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch WW-3530-visitor-validator-cache-key in repository https://gitbox.apache.org/repos/asf/struts.git
commit 92c1804c367f1f5f08fbc67b9d37ae50f0f768df Author: Lukasz Lenart <[email protected]> AuthorDate: Sat Jul 25 09:12:33 2026 +0200 WW-3530 test(core): cover visitor-validator cache-key context handling under wildcard actions Co-Authored-By: Claude Opus 4.8 <[email protected]> --- .../AnnotationActionValidatorManagerTest.java | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/src/test/java/org/apache/struts2/validator/AnnotationActionValidatorManagerTest.java b/core/src/test/java/org/apache/struts2/validator/AnnotationActionValidatorManagerTest.java index 029606409..bf8e67675 100644 --- a/core/src/test/java/org/apache/struts2/validator/AnnotationActionValidatorManagerTest.java +++ b/core/src/test/java/org/apache/struts2/validator/AnnotationActionValidatorManagerTest.java @@ -92,11 +92,50 @@ public class AnnotationActionValidatorManagerTest extends XWorkTestCase { super.tearDown(); } + private void installInvocation(String configName, Object action) { + ActionConfig config = new ActionConfig.Builder("packageName", configName, "").build(); + ActionInvocation invocation = EasyMock.createNiceMock(ActionInvocation.class); + ActionProxy proxy = EasyMock.createNiceMock(ActionProxy.class); + + EasyMock.expect(invocation.getProxy()).andReturn(proxy).anyTimes(); + EasyMock.expect(invocation.getAction()).andReturn(action).anyTimes(); + EasyMock.expect(proxy.getMethod()).andReturn("execute").anyTimes(); + EasyMock.expect(proxy.getConfig()).andReturn(config).anyTimes(); + + EasyMock.replay(invocation, proxy); + ActionContext.getContext().withActionInvocation(invocation); + } + public void testBuildValidatorKey() { String validatorKey = annotationActionValidatorManager.buildValidatorKey(SimpleAnnotationAction.class, "name"); assertEquals(SimpleAnnotationAction.class.getName() + "/packageName/name", validatorKey); } + public void testBuildValidatorKeyKeepsContextForVisitedClassUnderWildcardAction() { + // Action is wildcard-mapped; the validated class is a visited model object + // (not the action class), so its explicit, stable context must be preserved. + installInvocation("*", new SimpleAnnotationAction()); + + String basicKey = annotationActionValidatorManager.buildValidatorKey(AnnotatedTestBean.class, "basic"); + String additionalKey = annotationActionValidatorManager.buildValidatorKey(AnnotatedTestBean.class, "additional"); + + assertEquals(AnnotatedTestBean.class.getName() + "/packageName/basic", basicKey); + assertEquals(AnnotatedTestBean.class.getName() + "/packageName/additional", additionalKey); + assertFalse("visited-object keys must differ per context", basicKey.equals(additionalKey)); + } + + public void testBuildValidatorKeyIgnoresContextForActionClassUnderWildcardAction() { + installInvocation("*", new SimpleAnnotationAction()); + + String key1 = annotationActionValidatorManager.buildValidatorKey(SimpleAnnotationAction.class, "foo"); + String key2 = annotationActionValidatorManager.buildValidatorKey(SimpleAnnotationAction.class, "bar"); + + // WW-2996: a wildcard action's own validators share one cache entry across + // all resolved names, so the volatile context must NOT be part of the key. + assertEquals(key1, key2); + assertEquals(SimpleAnnotationAction.class.getName() + "/packageName/*|execute", key1); + } + public void testBuildsValidatorsForAlias() { List validatorList = annotationActionValidatorManager.getValidators(SimpleAnnotationAction.class, alias);
