This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new 5dc94f6ed [LANG-1835] Ignore synthetic methods in AnnotationUtils 
(#1810)
5dc94f6ed is described below

commit 5dc94f6ed328bf853af92158892aa849d63fb354
Author: Gary Gregory <[email protected]>
AuthorDate: Sat Oct 10 13:40:03 2026 -0400

    [LANG-1835] Ignore synthetic methods in AnnotationUtils (#1810)
    
    Add missing tests.
    
    Test AnnotationUtils with forced accessibility disabled.
    
    Verify that equals(), hashCode(), and toString() work with public
    annotations and preserve access failures for package-private annotations
    when AbstractReflection.forceAccessible is false.
---
 src/changes/changes.xml                            |  1 +
 .../lang3/external/AnnotationEqualsTest.java       | 65 ++++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f4afaf79c..dc1ae9cae 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -50,6 +50,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="fix" dev="ggregory" due-to="alhuda, Gary 
Gregory">Default unbounded WildcardType upper bound to Object in TypeUtils 
(#1807).</action>
     <action                   type="fix" dev="ggregory" due-to="alhuda, Gary 
Gregory">Take FastDatePrinter era names from the locale's calendar 
(#1800).</action>
     <action issue="LANG-1655" type="fix" dev="ggregory" due-to="Efe, Gary 
Gregory">Preserve Korean text in stripAccents (#1799).</action>
+    <action issue="LANG-1835" type="fix" dev="ggregory" due-to="zemiles, Gary 
Gregory">Ignore synthetic methods in AnnotationUtils (#1810).</action>
     <!-- ADD -->
     <!-- UPDATE -->
   </release>
diff --git 
a/src/test/java/org/apache/commons/lang3/external/AnnotationEqualsTest.java 
b/src/test/java/org/apache/commons/lang3/external/AnnotationEqualsTest.java
index 5b6484153..a846bd23b 100644
--- a/src/test/java/org/apache/commons/lang3/external/AnnotationEqualsTest.java
+++ b/src/test/java/org/apache/commons/lang3/external/AnnotationEqualsTest.java
@@ -27,7 +27,9 @@
 import java.lang.reflect.InvocationTargetException;
 
 import org.apache.commons.lang3.AnnotationUtils;
+import org.apache.commons.lang3.exception.UncheckedException;
 import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.SetSystemProperty;
 
 /**
  * Regression test for <a 
href="https://issues.apache.org/jira/browse/LANG-1815";>LANG-1815</a>.
@@ -49,6 +51,19 @@
  * </p>
  */
 public class AnnotationEqualsTest {
+    /**
+     * Declares an annotation accessible without suppressing reflective access 
checks.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface PublicTag {
+        /**
+         * Gets the tag value.
+         *
+         * @return the tag value
+         */
+        String value();
+    }
+
     @Retention(RetentionPolicy.RUNTIME)
     @interface Tag {
         String value();
@@ -66,11 +81,23 @@ public String value() {
         }
     }
 
+    @PublicTag("value")
     @Tag("value")
     private final Object a = new Object();
+
+    @PublicTag("value")
     @Tag("value")
     private final Object b = new Object();
 
+    @Test
+    @SetSystemProperty(key = "AbstractReflection.forceAccessible", value = 
"false")
+    void equalsRejectsPackagePrivateAnnotationsWithoutForcedAccess() throws 
Exception {
+        final Tag tagA = 
getClass().getDeclaredField("a").getAnnotation(Tag.class);
+        final Tag tagB = 
getClass().getDeclaredField("b").getAnnotation(Tag.class);
+        final IllegalStateException ex = 
assertThrows(IllegalStateException.class, () -> AnnotationUtils.equals(tagA, 
tagB));
+        assertInstanceOf(IllegalAccessException.class, ex.getCause());
+    }
+
     @Test
     void equalsWorksOnPackagePrivateAnnotations() throws Exception {
         final Tag tagA = 
getClass().getDeclaredField("a").getAnnotation(Tag.class);
@@ -78,6 +105,14 @@ void equalsWorksOnPackagePrivateAnnotations() throws 
Exception {
         assertTrue(AnnotationUtils.equals(tagA, tagB));
     }
 
+    @Test
+    @SetSystemProperty(key = "AbstractReflection.forceAccessible", value = 
"false")
+    void equalsWorksOnPublicAnnotationsWithoutForcedAccess() throws Exception {
+        final PublicTag tagA = 
getClass().getDeclaredField("a").getAnnotation(PublicTag.class);
+        final PublicTag tagB = 
getClass().getDeclaredField("b").getAnnotation(PublicTag.class);
+        assertTrue(AnnotationUtils.equals(tagA, tagB));
+    }
+
     @Test
     void equalsWrapsReflectiveOperationException() throws Exception {
         final Tag tagA = new ThrowingTag();
@@ -89,12 +124,35 @@ void equalsWrapsReflectiveOperationException() throws 
Exception {
         assertEquals("boom", ((InvocationTargetException) 
ex.getCause()).getTargetException().getMessage());
     }
 
+    @Test
+    @SetSystemProperty(key = "AbstractReflection.forceAccessible", value = 
"false")
+    void hashCodeRejectsPackagePrivateAnnotationsWithoutForcedAccess() throws 
Exception {
+        final Tag tag = 
getClass().getDeclaredField("a").getAnnotation(Tag.class);
+        final UncheckedException ex = assertThrows(UncheckedException.class, 
() -> AnnotationUtils.hashCode(tag));
+        assertInstanceOf(IllegalAccessException.class, ex.getCause());
+    }
+
     @Test
     void hashCodeWorksOnPackagePrivateAnnotations() throws Exception {
         final Tag tag = 
getClass().getDeclaredField("a").getAnnotation(Tag.class);
         assertEquals(tag.hashCode(), AnnotationUtils.hashCode(tag));
     }
 
+    @Test
+    @SetSystemProperty(key = "AbstractReflection.forceAccessible", value = 
"false")
+    void hashCodeWorksOnPublicAnnotationsWithoutForcedAccess() throws 
Exception {
+        final PublicTag tag = 
getClass().getDeclaredField("a").getAnnotation(PublicTag.class);
+        assertEquals(tag.hashCode(), AnnotationUtils.hashCode(tag));
+    }
+
+    @Test
+    @SetSystemProperty(key = "AbstractReflection.forceAccessible", value = 
"false")
+    void toStringRejectsPackagePrivateAnnotationsWithoutForcedAccess() throws 
Exception {
+        final Tag tag = 
getClass().getDeclaredField("a").getAnnotation(Tag.class);
+        final UncheckedException ex = assertThrows(UncheckedException.class, 
() -> AnnotationUtils.toString(tag));
+        assertInstanceOf(IllegalAccessException.class, ex.getCause());
+    }
+
     @Test
     void toStringWorksOnPackagePrivateAnnotations() throws Exception {
         final Tag tag = 
getClass().getDeclaredField("a").getAnnotation(Tag.class);
@@ -102,4 +160,11 @@ void toStringWorksOnPackagePrivateAnnotations() throws 
Exception {
         assertTrue(text.contains("value=value"), text);
     }
 
+    @Test
+    @SetSystemProperty(key = "AbstractReflection.forceAccessible", value = 
"false")
+    void toStringWorksOnPublicAnnotationsWithoutForcedAccess() throws 
Exception {
+        final PublicTag tag = 
getClass().getDeclaredField("a").getAnnotation(PublicTag.class);
+        assertEquals("@" + PublicTag.class.getName() + "(value=value)", 
AnnotationUtils.toString(tag));
+    }
+
 }

Reply via email to