From 9363a2cf0114e04b63cb979fdb2ef0312da06ab1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 10 May 2026 11:39:45 -0400 Subject: [PATCH] Make object accessibility optional --- .../lang3/builder/AbstractReflection.java | 171 ++++++++++++++++++ .../lang3/builder/CompareToBuilder.java | 56 ++++-- .../commons/lang3/builder/EqualsBuilder.java | 60 ++++-- .../lang3/builder/HashCodeBuilder.java | 82 +++++++-- .../builder/ReflectionToStringBuilder.java | 5 +- .../lang3/builder/ToStringBuilder.java | 91 ++++++++-- .../commons/lang3/AbstractLangTest.java | 2 +- .../lang3/builder/AbstractBuilderTest.java | 62 +++++++ .../lang3/builder/AbstractReflectionTest.java | 26 +++ .../builder/CompareToBuilderNoForceTest.java | 28 +++ .../lang3/builder/CompareToBuilderTest.java | 47 +++-- .../lang3/builder/DiffBuilderNoForceTest.java | 28 +++ .../lang3/builder/DiffBuilderTest.java | 5 +- .../builder/EqualsBuilderNoForceTest.java | 44 +++++ ...erReflectJreImplementationNoForceTest.java | 28 +++ ...lsBuilderReflectJreImplementationTest.java | 13 +- .../lang3/builder/EqualsBuilderTest.java | 61 +++---- .../builder/JsonToStringStyleNoForceTest.java | 28 +++ .../lang3/builder/JsonToStringStyleTest.java | 14 +- ...lineRecursiveToStringStyleNoForceTest.java | 28 +++ .../MultilineRecursiveToStringStyleTest.java | 27 ++- .../RecursiveToStringStyleNoForceTest.java | 28 +++ .../builder/RecursiveToStringStyleTest.java | 9 +- ...uilderCustomImplementationNoForceTest.java | 28 +++ ...StringBuilderCustomImplementationTest.java | 10 +- ...tionToStringBuilderExcludeNoForceTest.java | 28 +++ ...ngBuilderExcludeNullValuesNoForceTest.java | 28 +++ ...nToStringBuilderExcludeNullValuesTest.java | 19 +- .../ReflectionToStringBuilderExcludeTest.java | 7 +- ...ilderExcludeWithAnnotationNoForceTest.java | 28 +++ ...tringBuilderExcludeWithAnnotationTest.java | 5 +- ...tionToStringBuilderIncludeNoForceTest.java | 28 +++ .../ReflectionToStringBuilderIncludeTest.java | 5 +- ...tionToStringBuilderSummaryNoForceTest.java | 28 +++ .../ReflectionToStringBuilderSummaryTest.java | 8 +- .../builder/ToStringBuilderNoForceTest.java | 28 +++ .../lang3/builder/ToStringBuilderTest.java | 89 +++++---- 37 files changed, 1062 insertions(+), 220 deletions(-) create mode 100644 src/main/java/org/apache/commons/lang3/builder/AbstractReflection.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/AbstractBuilderTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/AbstractReflectionTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/CompareToBuilderNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/DiffBuilderNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/EqualsBuilderNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryNoForceTest.java create mode 100644 src/test/java/org/apache/commons/lang3/builder/ToStringBuilderNoForceTest.java diff --git a/src/main/java/org/apache/commons/lang3/builder/AbstractReflection.java b/src/main/java/org/apache/commons/lang3/builder/AbstractReflection.java new file mode 100644 index 00000000000..368dc26f613 --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/builder/AbstractReflection.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.function.Supplier; + +import org.apache.commons.lang3.SystemProperties; + +/** + * Abstracts reflection access for reflection-based classes in this package. + *

+ * See {@link AbstractBuilder#setForceAccessible(boolean)} for details. + *

+ * + * @since 3.21.0 + * @see AbstractBuilder#setForceAccessible(boolean) + * @see AccessibleObject#setAccessible(boolean) + */ +public abstract class AbstractReflection { + + /** + * Builds an instance of a subclass of {@link AbstractReflection}. + * + * @param An AbstractBuilder subclass. + */ + public abstract static class AbstractBuilder> implements Supplier { + + /** + * Whether the {@link AbstractReflection} subclass will call {@link AccessibleObject#setAccessible(boolean) AccessibleObject#setAccessible(true)} on + * inaccessible fields. + */ + private boolean forceAccessible = getForceAccessible(); + + /** + * Constructs a new instance for a subclass. + */ + AbstractBuilder() { + // Empty. + } + + /** + * Returns {@code this} instance typed as its subclass. + * + * @return {@code this} instance typed as its subclass. + */ + @SuppressWarnings("unchecked") + protected B asThis() { + return (B) this; + } + + /** + * Whether the {@link AbstractReflection} subclass will call {@link AccessibleObject#setAccessible(boolean) AccessibleObject#setAccessible(true)} on + * inaccessible fields. + *

+ * In general, controls whether the instances built by this builder will force the accessible flag for reflection. + *

+ *

+ * Defaults to {@code getForceAccessible()}, which defaults to true for compatibility. + *

+ *

+ * This default is read from the system property {@code "AbstractReflection.forceAccessible"}, which defaults to true for compatibility. + *

+ *

+ * The parsing rules are as {@link Boolean#parseBoolean(String)}. + *

+ *

+ * See subclassses for specific behavior. + *

+ * + * @param forceAccessible Whether to force accessibility by calling {@link AccessibleObject#setAccessible(boolean) + * AccessibleObject#setAccessible(true)}. + * @return {@code this} instance. + * @see AccessibleObject#setAccessible(boolean) + */ + public B setForceAccessible(final boolean forceAccessible) { + this.forceAccessible = forceAccessible; + return asThis(); + } + } + + /** + * Tests whether the system property {@code "AbstractReflection.forceAccessible"} is set to true. + *

+ * The parsing rules are as {@link Boolean#parseBoolean(String)}. + *

+ *

+ * If the property is not set, return true. + *

+ * + * @return whether the system property {@code "AbstractReflection.forceAccessible"} is set to true with true as the default. + * @see Boolean#parseBoolean(String) + */ + static boolean getForceAccessible() { + return SystemProperties.getBoolean(AbstractReflection.class, "forceAccessible", () -> true); + } + + /** + * If {@code forceAccessible} flag is true, each field in the given array is made accessible by calling {@link AccessibleObject#setAccessible(boolean) + * AccessibleObject#setAccessible(true)} but only if a field is not already accessible. + * + * @param forceAccessible Whether to call {@link AccessibleObject#setAccessible(boolean)} if a field is not already accessible. + * @param fields The fields to set. + * @throws SecurityException Thrown if {@code forceAccessible} flag is true and the request is denied. + * @see AccessibleObject#setAccessible(boolean) + * @see SecurityManager#checkPermission + */ + static void setAccessible(final boolean forceAccessible, final Field... fields) { + if (forceAccessible) { + for (final Field field : fields) { + // Test to avoid the permission check if there is a security manager. + if (field != null && !field.isAccessible()) { + field.setAccessible(true); + } + } + } + } + + /** + * Whether to call {@link AccessibleObject#setAccessible(boolean) AccessibleObject#setAccessible(true)} on inaccessible fields. + */ + private final boolean forceAccessible; + + /** + * Constructs a new instance. + * + * @param The type to build. + * @param builder The builder. + */ + > AbstractReflection(final AbstractBuilder builder) { + this.forceAccessible = builder.forceAccessible; + } + + /** + * Tests whether fields should be made accessible with {@link AccessibleObject#setAccessible(boolean)}. + * + * @return whether fields should be made accessible with {@link AccessibleObject#setAccessible(boolean)}. + */ + protected boolean isForceAccessible() { + return forceAccessible; + } + + /** + * If {@code forceAccessible} flag is true, each field in the given array is made accessible by calling {@link AccessibleObject#setAccessible(boolean) + * AccessibleObject#setAccessible(true)} but only if a field is not already accessible. + * + * @param fields The fields to set. + * @throws SecurityException Thrown if {@code forceAccessible} flag is true and the request is denied. + * @see AccessibleObject#setAccessible(boolean) + * @see SecurityManager#checkPermission + */ + void setAccessible(final Field... fields) { + setAccessible(isForceAccessible(), fields); + } +} diff --git a/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java b/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java index 9a3b419ab0f..512b6b33a72 100644 --- a/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java @@ -16,7 +16,6 @@ */ package org.apache.commons.lang3.builder; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; @@ -94,7 +93,35 @@ * @see HashCodeBuilder * @since 1.0 */ -public class CompareToBuilder implements Builder { +public class CompareToBuilder extends AbstractReflection implements Builder { + + /** + * Builds instances of CompareToBuilder. + */ + public static class Builder extends AbstractBuilder { + + /** + * Constructs a new Builder instance. + */ + private Builder() { + // empty + } + + @Override + public CompareToBuilder get() { + return new CompareToBuilder(this); + } + + } + + /** + * Constructs a new Builder. + * + * @return a new Builder. + */ + public static Builder builder() { + return new Builder(); + } /** * Appends to {@code builder} the comparison of {@code lhs} @@ -106,6 +133,7 @@ public class CompareToBuilder implements Builder { * @param builder {@link CompareToBuilder} to append to * @param useTransients whether to compare transient fields * @param excludeFields fields to exclude + * @param forceAccessible Whether to set fields' accessible flags */ private static void reflectionAppend( final Object lhs, @@ -113,16 +141,19 @@ private static void reflectionAppend( final Class clazz, final CompareToBuilder builder, final boolean useTransients, - final String[] excludeFields) { + final String[] excludeFields, + final boolean forceAccessible) { final Field[] fields = clazz.getDeclaredFields(); - AccessibleObject.setAccessible(fields, true); + setAccessible(forceAccessible, fields); for (int i = 0; i < fields.length && builder.comparison == 0; i++) { final Field field = fields[i]; - if (!ArrayUtils.contains(excludeFields, field.getName()) - && !field.getName().contains("$") + final String name = field.getName(); + if (!ArrayUtils.contains(excludeFields, name) + && !name.contains("$") && (useTransients || !Modifier.isTransient(field.getModifiers())) - && !Modifier.isStatic(field.getModifiers())) { + && !Modifier.isStatic(field.getModifiers()) + && field.isAccessible()) { // IllegalAccessException can't happen. Would get a Security exception instead. // Throw a runtime exception in case the impossible happens. builder.append(Reflection.getUnchecked(field, lhs), Reflection.getUnchecked(field, rhs)); @@ -230,22 +261,20 @@ public static int reflectionCompare( final boolean compareTransients, final Class reflectUpToClass, final String... excludeFields) { - if (lhs == rhs) { return 0; } Objects.requireNonNull(lhs, "lhs"); Objects.requireNonNull(rhs, "rhs"); - Class lhsClazz = lhs.getClass(); if (!lhsClazz.isInstance(rhs)) { throw new ClassCastException(); } final CompareToBuilder compareToBuilder = new CompareToBuilder(); - reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields); + reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields, AbstractReflection.getForceAccessible()); while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) { lhsClazz = lhsClazz.getSuperclass(); - reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields); + reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields, AbstractReflection.getForceAccessible()); } return compareToBuilder.toComparison(); } @@ -329,9 +358,14 @@ public static int reflectionCompare(final Object lhs, final Object rhs, final St * {@link #toComparison} to get the result.

*/ public CompareToBuilder() { + super(builder()); comparison = 0; } + private CompareToBuilder(final Builder builder) { + super(builder); + } + /** * Appends to the {@code builder} the comparison of * two {@code booleans}s. diff --git a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java index d4bbdf55804..04de844bfc1 100644 --- a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java @@ -16,7 +16,6 @@ */ package org.apache.commons.lang3.builder; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -86,7 +85,35 @@ * * @since 1.0 */ -public class EqualsBuilder implements Builder { +public class EqualsBuilder extends AbstractReflection implements Builder { + + /** + * Builds instances of CompareToBuilder. + */ + public static class Builder extends AbstractBuilder { + + /** + * Constructs a new Builder instance. + */ + private Builder() { + // empty + } + + @Override + public EqualsBuilder get() { + return new EqualsBuilder(this); + } + + } + + /** + * Constructs a new Builder. + * + * @return a new Builder. + */ + public static Builder builder() { + return new Builder(); + } /** * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops. @@ -155,7 +182,7 @@ static boolean isRegistered(final Object lhs, final Object rhs) { } /** - * This method uses reflection to determine if the two {@link Object}s + * Uses reflection to determine if the two {@link Object}s * are equal. * *

It uses {@code AccessibleObject.setAccessible} to gain access to private @@ -181,7 +208,7 @@ public static boolean reflectionEquals(final Object lhs, final Object rhs, final } /** - * This method uses reflection to determine if the two {@link Object}s + * Uses reflection to determine if the two {@link Object}s * are equal. * *

It uses {@code AccessibleObject.setAccessible} to gain access to private @@ -235,7 +262,7 @@ public static boolean reflectionEquals(final Object lhs, final Object rhs, final } /** - * This method uses reflection to determine if the two {@link Object}s + * Uses reflection to determine if the two {@link Object}s * are equal. * *

It uses {@code AccessibleObject.setAccessible} to gain access to private @@ -268,7 +295,7 @@ public static boolean reflectionEquals(final Object lhs, final Object rhs, final } /** - * This method uses reflection to determine if the two {@link Object}s + * Uses reflection to determine if the two {@link Object}s * are equal. * *

It uses {@code AccessibleObject.setAccessible} to gain access to private @@ -293,7 +320,7 @@ public static boolean reflectionEquals(final Object lhs, final Object rhs, final } /** - * This method uses reflection to determine if the two {@link Object}s + * Uses reflection to determine if the two {@link Object}s * are equal. * *

It uses {@code AccessibleObject.setAccessible} to gain access to private @@ -371,11 +398,16 @@ private static void unregister(final Object lhs, final Object rhs) { * @see Object#equals(Object) */ public EqualsBuilder() { + super(builder()); // set up default classes to bypass reflection for bypassReflectionClasses = new ArrayList<>(1); bypassReflectionClasses.add(String.class); //hashCode field being lazy but not transient } + private EqualsBuilder(Builder builder) { + super(builder); + } + /** * Test if two {@code booleans}s are equal. * @@ -961,9 +993,8 @@ public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) { try { if (testClass.isArray()) { append(lhs, rhs); - } else //If either class is being excluded, call normal object equals method on lhsClass. - if (bypassReflectionClasses != null - && (bypassReflectionClasses.contains(lhsClass) || bypassReflectionClasses.contains(rhsClass))) { + } else // If either class is being excluded, call normal object equals method on lhsClass. + if (bypassReflectionClasses != null && (bypassReflectionClasses.contains(lhsClass) || bypassReflectionClasses.contains(rhsClass))) { isEquals = lhs.equals(rhs); } else { reflectionAppend(lhs, rhs, testClass); @@ -991,19 +1022,14 @@ public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) { * @param rhs the right-hand side object * @param clazz the class to append details of */ - private void reflectionAppend( - final Object lhs, - final Object rhs, - final Class clazz) { - + private void reflectionAppend(final Object lhs, final Object rhs, final Class clazz) { if (isRegistered(lhs, rhs)) { return; } - try { register(lhs, rhs); final Field[] fields = clazz.getDeclaredFields(); - AccessibleObject.setAccessible(fields, true); + setAccessible(fields); for (int i = 0; i < fields.length && isEquals; i++) { final Field field = fields[i]; if (!ArrayUtils.contains(excludeFields, field.getName()) diff --git a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java index 89610d298e6..d5737b7d65f 100644 --- a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java @@ -17,7 +17,6 @@ package org.apache.commons.lang3.builder; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; @@ -102,7 +101,53 @@ * * @since 1.0 */ -public class HashCodeBuilder implements Builder { +public class HashCodeBuilder extends AbstractReflection implements Builder { + + /** + * Builds instances of CompareToBuilder. + */ + public static class Builder extends AbstractBuilder { + + private int initialOddNumber; + + private int multiplierOddNumber; + + /** + * Constructs a new Builder instance. + */ + private Builder() { + // empty + } + + @Override + public HashCodeBuilder get() { + return new HashCodeBuilder(this); + } + + + /** + * Sets an odd number used as the initial value. + * + * @param initialOddNumber an odd number used as the initial value. + * @return {@code this} instance. + */ + public Builder setInitialOddNumber(final int initialOddNumber) { + this.initialOddNumber = initialOddNumber; + return asThis(); + } + + /** + * Sets an odd number used as the multiplier. + * + * @param multiplierOddNumber an odd number used as the multiplier. + * @return {@code this} instance. + */ + public Builder setMultiplierOddNumber(final int multiplierOddNumber) { + this.multiplierOddNumber = multiplierOddNumber; + return asThis(); + } + + } /** * The default initial value to use in reflection hash code building. @@ -121,6 +166,15 @@ public class HashCodeBuilder implements Builder { */ private static final ThreadLocal> REGISTRY = ThreadLocal.withInitial(HashSet::new); + /** + * Constructs a new Builder. + * + * @return a new Builder. + */ + public static Builder builder() { + return new Builder(); + } + /* * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode() * we are in the process of calculating. @@ -175,9 +229,10 @@ static boolean isRegistered(final Object value) { * whether to use transient fields * @param excludeFields * Collection of String field names to exclude from use in calculation of hash code + * @param setAccessible Whether to set fields' accessible flags */ private static void reflectionAppend(final Object object, final Class clazz, final HashCodeBuilder builder, final boolean useTransients, - final String[] excludeFields) { + final String[] excludeFields, final boolean setAccessible) { if (isRegistered(object)) { return; } @@ -185,7 +240,7 @@ private static void reflectionAppend(final Object object, final Class clazz, register(object); // The elements in the returned array are not sorted and are not in any particular order. final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName)); - AccessibleObject.setAccessible(fields, true); + setAccessible(setAccessible, fields); for (final Field field : fields) { if (!ArrayUtils.contains(excludeFields, field.getName()) && !field.getName().contains("$") @@ -340,10 +395,10 @@ public static int reflectionHashCode(final int initialNonZeroOddNumber, fina Objects.requireNonNull(object, "object"); final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber); Class clazz = object.getClass(); - reflectionAppend(object, clazz, builder, testTransients, excludeFields); + reflectionAppend(object, clazz, builder, testTransients, excludeFields, true); while (clazz.getSuperclass() != null && clazz != reflectUpToClass) { clazz = clazz.getSuperclass(); - reflectionAppend(object, clazz, builder, testTransients, excludeFields); + reflectionAppend(object, clazz, builder, testTransients, excludeFields, true); } return builder.toHashCode(); } @@ -504,10 +559,16 @@ private static void unregister(final Object value) { * Uses two hard coded choices for the constants needed to build a {@code hashCode}. */ public HashCodeBuilder() { - constant = 37; - total = 17; + this(builder().setInitialOddNumber(17).setMultiplierOddNumber(37)); } + private HashCodeBuilder(Builder builder) { + super(builder); + Validate.isTrue(builder.initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value"); + Validate.isTrue(builder.multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier"); + constant = builder.multiplierOddNumber; + total = builder.initialOddNumber; } + /** * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class, * however this is not vital. @@ -524,10 +585,7 @@ public HashCodeBuilder() { * if the number is even */ public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) { - Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value"); - Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier"); - constant = multiplierOddNumber; - total = initialOddNumber; + this(builder().setInitialOddNumber(initialOddNumber).setMultiplierOddNumber(multiplierOddNumber)); } /** diff --git a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java index 418e96fd1fd..b38f3d7c42f 100644 --- a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java @@ -17,7 +17,6 @@ package org.apache.commons.lang3.builder; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; @@ -646,14 +645,14 @@ protected void appendFieldsIn(final Class clazz) { } // The elements in the returned array are not sorted and are not in any particular order. final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName)); - AccessibleObject.setAccessible(fields, true); + setAccessible(fields); for (final Field field : fields) { final String fieldName = field.getName(); if (accept(field)) { try { // Warning: Field.get(Object) creates wrappers objects // for primitive types. - final Object fieldValue = getValue(field); + final Object fieldValue = field.isAccessible() ? getValue(field) : null; if (!excludeNullValues || fieldValue != null) { this.append(fieldName, fieldValue, !field.isAnnotationPresent(ToStringSummary.class)); } diff --git a/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java b/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java index 379fef13438..cea81a55731 100644 --- a/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java @@ -87,13 +87,80 @@ * * @since 1.0 */ -public class ToStringBuilder implements Builder { +public class ToStringBuilder extends AbstractReflection implements Builder { + + /** + * Builds instances of CompareToBuilder. + * + * @since 3.21.0 + */ + public static class Builder extends AbstractBuilder { + + private Object object; + private ToStringStyle style; + private StringBuffer buffer; + + /** + * Constructs a new Builder instance. + */ + private Builder() { + // empty + } + + @Override + public ToStringBuilder get() { + return new ToStringBuilder(this); + } + + /** + * Sets the {@link StringBuffer} to populate, may be null. + * + * @param buffer the {@link StringBuffer} to populate, may be null + * @return {@code this} builder instance. + */ + public Builder setBuffer(final StringBuffer buffer) { + this.buffer = buffer; + return asThis(); + } + + /** + * Sets the Object to build a {@code toString} for, not recommended to be null. + * + * @param object the Object to build a {@code toString} for, not recommended to be null. + * @return {@code this} builder instance. + */ + public Builder setObject(final Object object) { + this.object = object; + return asThis(); + } + + /** + * Sets the style of the {@code toString} to create, null uses the default style. + * + * @param style the style of the {@code toString} to create, null uses the default style + * @return {@code this} builder instance. + */ + public Builder setStyle(final ToStringStyle style) { + this.style = style; + return asThis(); + } + } /** * The default style of output to use, not null. */ private static volatile ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE; + /** + * Constructs a new Builder. + * + * @return a new Builder. + * @since 3.21.0 + */ + public static Builder builder() { + return new Builder(); + } + /** * Gets the default {@link ToStringStyle} to use. * @@ -210,6 +277,14 @@ public static void setDefaultStyle(final ToStringStyle style) { */ private final ToStringStyle style; + private ToStringBuilder(final Builder builder) { + super(builder); + this.style = builder.style != null ? builder.style : getDefaultStyle(); + this.buffer = builder.buffer != null ? builder.buffer : new StringBuffer(512); + this.object = builder.object; + style.appendStart(buffer, object); + } + /** * Constructs a builder for the specified object using the default output style. * @@ -244,18 +319,8 @@ public ToStringBuilder(final Object object, final ToStringStyle style) { * @param style the style of the {@code toString} to create, null uses the default style * @param buffer the {@link StringBuffer} to populate, may be null */ - public ToStringBuilder(final Object object, ToStringStyle style, StringBuffer buffer) { - if (style == null) { - style = getDefaultStyle(); - } - if (buffer == null) { - buffer = new StringBuffer(512); - } - this.buffer = buffer; - this.style = style; - this.object = object; - - style.appendStart(buffer, object); + public ToStringBuilder(final Object object, final ToStringStyle style, final StringBuffer buffer) { + this(builder().setObject(object).setStyle(style).setBuffer(buffer)); } /** diff --git a/src/test/java/org/apache/commons/lang3/AbstractLangTest.java b/src/test/java/org/apache/commons/lang3/AbstractLangTest.java index 8be8f69dd02..84373105b9a 100644 --- a/src/test/java/org/apache/commons/lang3/AbstractLangTest.java +++ b/src/test/java/org/apache/commons/lang3/AbstractLangTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.lang3; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -34,5 +35,4 @@ public void after() { assertTrue(ToStringStyle.getRegistry().isEmpty(), "Expected null, actual: " + ToStringStyle.getRegistry()); // TODO Do more to make sure memory is not retained, maybe like Log4j checks for it. } - } diff --git a/src/test/java/org/apache/commons/lang3/builder/AbstractBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/AbstractBuilderTest.java new file mode 100644 index 00000000000..86ae9e0707d --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/AbstractBuilderTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Objects; +import java.util.function.Supplier; + +import org.apache.commons.lang3.AbstractLangTest; + +/** + * Helps test this package. + */ +class AbstractBuilderTest extends AbstractLangTest { + + /** + * Delegates to {@link AbstractReflection#getForceAccessible()}. + * + * @return {@link AbstractReflection#getForceAccessible()}. + */ + protected static boolean accessibleFlag() { + return AbstractReflection.getForceAccessible(); + } + + /** + * Helps test reflection classes. + * + * @param string An input string. + * @return The given string or "". + */ + protected static String accessibleString(final String string) { + return accessibleFlag() ? string : ""; + } + + protected static void assertEqualsIfAccessible(final Object expected, final Object actual) { + assertEquals(accessibleFlag(), Objects.equals(expected, actual)); + } + + protected static void assertTrueIfAccessible(final boolean test) { + assertEquals(accessibleFlag(), test); + } + + protected static void assertTrueIfAccessible(final boolean test, final Supplier messageSupplier) { + assertEquals(accessibleFlag(), test, messageSupplier); + } +} diff --git a/src/test/java/org/apache/commons/lang3/builder/AbstractReflectionTest.java b/src/test/java/org/apache/commons/lang3/builder/AbstractReflectionTest.java new file mode 100644 index 00000000000..e0428310d0d --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/AbstractReflectionTest.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +/** + * Helps test no forced access. + */ +public class AbstractReflectionTest { + + static final String FORCE_ACCESSIBLE = "AbstractReflection.forceAccessible"; +} diff --git a/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderNoForceTest.java new file mode 100644 index 00000000000..14fe8a8ea8a --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link CompareToBuilderTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class CompareToBuilderNoForceTest extends CompareToBuilderTest { + // empty +} diff --git a/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java index d00a98706b2..43540c4860e 100644 --- a/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java @@ -24,13 +24,12 @@ import java.math.BigInteger; import java.util.Objects; -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; /** * Tests {@link CompareToBuilder}. */ -class CompareToBuilderTest extends AbstractLangTest { +class CompareToBuilderTest extends AbstractBuilderTest { static class TestObject implements Comparable { private int a; @@ -114,9 +113,10 @@ static class TestTransientSubObject extends TestObject { * @param z an object to compare * @param testTransients Whether to include transients in the comparison * @param excludeFields fields to exclude + * @param expectAccessibleFactor Whether accessibility is expected. */ - private void assertReflectionCompareContract(final Object x, final Object y, final Object z, final boolean testTransients, final String[] excludeFields) { - + private void assertReflectionCompareContract(final Object x, final Object y, final Object z, final boolean testTransients, final String[] excludeFields, + final boolean expectAccessibleFactor) { // signum assertEquals(reflectionCompareSignum(x, y, testTransients, excludeFields), -reflectionCompareSignum(y, x, testTransients, excludeFields)); @@ -132,7 +132,14 @@ private void assertReflectionCompareContract(final Object x, final Object y, fin } // strongly recommended but not strictly required - assertTrue(CompareToBuilder.reflectionCompare(x, y, testTransients) == 0 == EqualsBuilder.reflectionEquals(x, y, testTransients)); + // assertTrue(CompareToBuilder.reflectionCompare(x, y, testTransients) == 0 == EqualsBuilder.reflectionEquals(x, y, testTransients)); + //assertTrueIfAccessible(CompareToBuilder.reflectionCompare(x, y, testTransients) == 0 == EqualsBuilder.reflectionEquals(x, y, testTransients)); + final boolean actual = CompareToBuilder.reflectionCompare(x, y, testTransients) == 0 == EqualsBuilder.reflectionEquals(x, y, testTransients); + if (accessibleFlag()) { + assertEqualsIfAccessible(expectAccessibleFactor, actual); + } else { + assertEqualsIfAccessible(accessibleFlag() || expectAccessibleFactor, actual); + } } private void assertXYZCompareOrder(final Object x, final Object y, final Object z, final boolean testTransients, final String[] excludeFields) { @@ -140,13 +147,13 @@ private void assertXYZCompareOrder(final Object x, final Object y, final Object assertEquals(0, CompareToBuilder.reflectionCompare(y, y, testTransients, null, excludeFields)); assertEquals(0, CompareToBuilder.reflectionCompare(z, z, testTransients, null, excludeFields)); - assertTrue(0 > CompareToBuilder.reflectionCompare(x, y, testTransients, null, excludeFields)); - assertTrue(0 > CompareToBuilder.reflectionCompare(x, z, testTransients, null, excludeFields)); - assertTrue(0 > CompareToBuilder.reflectionCompare(y, z, testTransients, null, excludeFields)); + assertTrueIfAccessible(0 > CompareToBuilder.reflectionCompare(x, y, testTransients, null, excludeFields)); + assertTrueIfAccessible(0 > CompareToBuilder.reflectionCompare(x, z, testTransients, null, excludeFields)); + assertTrueIfAccessible(0 > CompareToBuilder.reflectionCompare(y, z, testTransients, null, excludeFields)); - assertTrue(0 < CompareToBuilder.reflectionCompare(y, x, testTransients, null, excludeFields)); - assertTrue(0 < CompareToBuilder.reflectionCompare(z, x, testTransients, null, excludeFields)); - assertTrue(0 < CompareToBuilder.reflectionCompare(z, y, testTransients, null, excludeFields)); + assertTrueIfAccessible(0 < CompareToBuilder.reflectionCompare(y, x, testTransients, null, excludeFields)); + assertTrueIfAccessible(0 < CompareToBuilder.reflectionCompare(z, x, testTransients, null, excludeFields)); + assertTrueIfAccessible(0 < CompareToBuilder.reflectionCompare(z, y, testTransients, null, excludeFields)); } /** @@ -1022,8 +1029,8 @@ void testReflectionCompare() { assertEquals(0, CompareToBuilder.reflectionCompare(o1, o1)); assertEquals(0, CompareToBuilder.reflectionCompare(o1, o2)); o2.setA(5); - assertTrue(CompareToBuilder.reflectionCompare(o1, o2) < 0); - assertTrue(CompareToBuilder.reflectionCompare(o2, o1) > 0); + assertTrueIfAccessible(CompareToBuilder.reflectionCompare(o1, o2) < 0); + assertTrueIfAccessible(CompareToBuilder.reflectionCompare(o2, o1) > 0); } @Test @@ -1052,14 +1059,14 @@ private void testReflectionHierarchyCompare(final boolean testTransients, final final TestSubObject tso2 = new TestSubObject(2, 2); final TestSubObject tso3 = new TestSubObject(3, 3); - assertReflectionCompareContract(to1, to1, to1, false, excludeFields); - assertReflectionCompareContract(to1, to2, to3, false, excludeFields); - assertReflectionCompareContract(tso1, tso1, tso1, false, excludeFields); - assertReflectionCompareContract(tso1, tso2, tso3, false, excludeFields); - assertReflectionCompareContract("1", "2", "3", false, excludeFields); + assertReflectionCompareContract(to1, to1, to1, false, excludeFields, accessibleFlag()); + assertReflectionCompareContract(to1, to2, to3, false, excludeFields, true); + assertReflectionCompareContract(tso1, tso1, tso1, false, excludeFields, accessibleFlag()); + assertReflectionCompareContract(tso1, tso2, tso3, false, excludeFields, true); + assertReflectionCompareContract("1", "2", "3", false, excludeFields, true); - assertTrue(0 != CompareToBuilder.reflectionCompare(tso1, new TestSubObject(1, 0), testTransients)); - assertTrue(0 != CompareToBuilder.reflectionCompare(tso1, new TestSubObject(0, 1), testTransients)); + assertTrueIfAccessible(0 != CompareToBuilder.reflectionCompare(tso1, new TestSubObject(1, 0), testTransients)); + assertTrueIfAccessible(0 != CompareToBuilder.reflectionCompare(tso1, new TestSubObject(0, 1), testTransients)); // root class assertXYZCompareOrder(to1, to2, to3, true, null); diff --git a/src/test/java/org/apache/commons/lang3/builder/DiffBuilderNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/DiffBuilderNoForceTest.java new file mode 100644 index 00000000000..933b08881e9 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/DiffBuilderNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link DiffBuilderTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class DiffBuilderNoForceTest extends DiffBuilderTest { + // empty +} diff --git a/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java index 5a879713364..ba81a6b3af4 100644 --- a/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java @@ -26,14 +26,13 @@ import java.util.List; -import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; /** * Tests {@link DiffBuilder}. */ -class DiffBuilderTest extends AbstractLangTest { +class DiffBuilderTest extends AbstractBuilderTest { /** * Test fixture. @@ -549,7 +548,7 @@ void testSimilarObjectIgnoresAppends() { final TypeTestClass testClass1 = new TypeTestClass(); final TypeTestClass testClass2 = new TypeTestClass(); final DiffResult list = new DiffBuilder<>(testClass1, testClass2, SHORT_STYLE).append("ignored", false, true).build(); - assertEquals(0, list.getNumberOfDiffs()); + assertEquals(accessibleFlag() ? 0 : 1, list.getNumberOfDiffs()); } @Test diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderNoForceTest.java new file mode 100644 index 00000000000..61aa9ab64d9 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderNoForceTest.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.util.HashMap; + +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link EqualsBuilderTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class EqualsBuilderNoForceTest extends EqualsBuilderTest { + + @Test + void testReflectionOnCustomArrayList() { + assertFalse(EqualsBuilder.reflectionEquals(new TestArrayList(1, "2", "3", "4"), new TestArrayList(1, "2", "3", "4"))); + assertFalse(EqualsBuilder.reflectionEquals(new TestArrayList(1, "2", "3", "4"), new TestArrayList(2, "2", "3", "4"))); + } + + @Test + void testReflectionOnCustomHashMap() { + assertFalse(EqualsBuilder.reflectionEquals(new TestHashMap(1, new HashMap<>()), new TestHashMap(1, new HashMap<>()))); + assertFalse(EqualsBuilder.reflectionEquals(new TestHashMap(1, new HashMap<>()), new TestHashMap(2, new HashMap<>()))); + } +} diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationNoForceTest.java new file mode 100644 index 00000000000..a5cecf88244 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link EqualsBuilderReflectJreImplementationTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class EqualsBuilderReflectJreImplementationNoForceTest extends EqualsBuilderReflectJreImplementationTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationTest.java index 7877356289e..929ea2af465 100644 --- a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderReflectJreImplementationTest.java @@ -47,14 +47,13 @@ import java.util.List; import java.util.function.Supplier; -import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.stream.IntStreams; import org.junit.jupiter.api.Test; /** * Tests that {@link EqualsBuilder} works using reflection when types that implement JRE interfaces like TemporalAccessor, TemporalAmout, and CharSequence work. */ -class EqualsBuilderReflectJreImplementationTest extends AbstractLangTest { +class EqualsBuilderReflectJreImplementationTest extends AbstractBuilderTest { static class MyCharSequence implements CharSequence { @@ -268,16 +267,16 @@ void testRecursive() { final MyClass o2 = new MyClass(new MyCharSequence("5"), new MyTemporal("6"), new MyTemporalAccessor("7"), new MyTemporalAmount("8")); final MyClass o2Bis = new MyClass(new MyCharSequence("5"), new MyTemporal("6"), new MyTemporalAccessor("7"), new MyTemporalAmount("8")); // MyTemporal - assertTrue(new EqualsBuilder().setTestRecursive(true).append(new MyTemporal("1"), new MyTemporal("1")).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(new MyTemporal("1"), new MyTemporal("1")).isEquals()); // MyTemporalAccessor - assertTrue(new EqualsBuilder().setTestRecursive(true).append(new MyTemporalAccessor("1"), new MyTemporalAccessor("1")).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(new MyTemporalAccessor("1"), new MyTemporalAccessor("1")).isEquals()); // MyCharSequence - assertTrue(new EqualsBuilder().setTestRecursive(true).append(new MyCharSequence("1"), new MyCharSequence("1")).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(new MyCharSequence("1"), new MyCharSequence("1")).isEquals()); // MyClass assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1, o1).isEquals(), o1::toString); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1, o1Bis).isEquals(), o1::toString); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1, o1Bis).isEquals(), o1::toString); assertTrue(new EqualsBuilder().setTestRecursive(true).append(o2, o2).isEquals(), o2::toString); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o2, o2Bis).isEquals(), o2::toString); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o2, o2Bis).isEquals(), o2::toString); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1, o2).isEquals()); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o2, o1).isEquals()); } diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java index 4148811780e..e1ff81ed4b1 100644 --- a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java @@ -31,14 +31,13 @@ import java.util.List; import java.util.Map; -import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.reflect.MethodUtils; import org.junit.jupiter.api.Test; /** * Tests {@link EqualsBuilder}. */ -class EqualsBuilderTest extends AbstractLangTest { +class EqualsBuilderTest extends AbstractBuilderTest { public static class TestACanEqualB { private final int a; @@ -607,7 +606,7 @@ void testCyclicalObjectReferences() { x3.setObjectReference(refX3); refX3.setObjectReference(x3); - assertEquals(x1, x2); + assertTrueIfAccessible(x1.equals(x2)); assertNotEquals(x1, x3); assertNotEquals(x2, x3); } @@ -1097,7 +1096,7 @@ void testObjectRecursive() { final TestRecursiveObject oNull = new TestRecursiveObject(null, null, 2); assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1A).isEquals()); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1A, o2).isEquals()); @@ -1120,10 +1119,10 @@ void testObjectRecursiveCycle() { o2.setCycle(i2); assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1A).isEquals()); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1A, o2).isEquals()); - assertTrue(EqualsBuilder.reflectionEquals(o1A, o1B, false, null, true)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(o1A, o1B, false, null, true)); assertFalse(EqualsBuilder.reflectionEquals(o1A, o2, false, null, true)); } @@ -1134,7 +1133,7 @@ void testObjectRecursiveCycleSelfreference() { final TestRecursiveCycleObject o2 = new TestRecursiveCycleObject(2); assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1A).isEquals()); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1A, o2).isEquals()); } @@ -1144,8 +1143,8 @@ void testObjectRecursiveGenericInteger() { final TestRecursiveGenericObject o1B = new TestRecursiveGenericObject<>(1); final TestRecursiveGenericObject o2 = new TestRecursiveGenericObject<>(2); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1B, o1A).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1B, o1A).isEquals()); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1B, o2).isEquals()); } @@ -1161,8 +1160,8 @@ void testObjectRecursiveGenericString() { // To trigger bug reported in LANG-1356, call hashCode only on string in instance o1_a s1A.hashCode(); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); - assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1B, o1A).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1A, o1B).isEquals()); + assertTrueIfAccessible(new EqualsBuilder().setTestRecursive(true).append(o1B, o1A).isEquals()); assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1B, o2).isEquals()); } @@ -1204,7 +1203,7 @@ void testReflectionAppend() { assertFalse(new EqualsBuilder().reflectionAppend(o1, o2).reflectionAppend(o1, o1).build()); o2.setA(4); - assertTrue(new EqualsBuilder().reflectionAppend(o1, o2).build()); + assertTrueIfAccessible(new EqualsBuilder().reflectionAppend(o1, o2).build()); assertFalse(new EqualsBuilder().reflectionAppend(o1, this).build()); @@ -1242,7 +1241,7 @@ void testReflectionEquals() { assertTrue(EqualsBuilder.reflectionEquals(o1, o1)); assertFalse(EqualsBuilder.reflectionEquals(o1, o2)); o2.setA(4); - assertTrue(EqualsBuilder.reflectionEquals(o1, o2)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(o1, o2)); assertFalse(EqualsBuilder.reflectionEquals(o1, this)); @@ -1279,12 +1278,10 @@ private void testReflectionEqualsEquivalenceRelationship( // reflection test assertTrue(EqualsBuilder.reflectionEquals(to, to, testTransients)); assertTrue(EqualsBuilder.reflectionEquals(to2, to2, testTransients)); - // symmetry test - assertTrue(EqualsBuilder.reflectionEquals(to, toBis, testTransients) && EqualsBuilder.reflectionEquals(toBis, to, testTransients)); - + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(to, toBis, testTransients) && EqualsBuilder.reflectionEquals(toBis, to, testTransients)); // transitive test - assertTrue( + assertEquals(accessibleFlag(), EqualsBuilder.reflectionEquals(to, toBis, testTransients) && EqualsBuilder.reflectionEquals(toBis, toTer, testTransients) && EqualsBuilder.reflectionEquals(to, toTer, testTransients)); @@ -1294,8 +1291,8 @@ private void testReflectionEqualsEquivalenceRelationship( if (oToChange instanceof TestSubObject) { ((TestSubObject) oToChange).setB(((TestSubObject) to).getB()); } - assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients)); - assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(oToChange, to, testTransients)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(oToChange, to, testTransients)); oToChange.setA(to.getA() + 1); if (oToChange instanceof TestSubObject) { ((TestSubObject) oToChange).setB(((TestSubObject) to).getB() + 1); @@ -1329,7 +1326,7 @@ void testReflectionEqualsExcludeFields() { assertFalse(EqualsBuilder.reflectionEquals(x1, x2, "three")); // equal if both differing fields excluded - assertTrue(EqualsBuilder.reflectionEquals(x1, x2, "two", "three")); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(x1, x2, "two", "three")); // still equal as long as both differing fields are among excluded assertTrue(EqualsBuilder.reflectionEquals(x1, x2, "one", "two", "three")); @@ -1346,8 +1343,8 @@ void testReflectionHierarchyEquals() { testReflectionHierarchyEquals(false); testReflectionHierarchyEquals(true); // Transients - assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true)); - assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), false)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), false)); assertFalse(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 0, 0, 4), new TestTTLeafObject(1, 2, 3, 4), true)); assertFalse(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 0), true)); assertFalse(EqualsBuilder.reflectionEquals(new TestTTLeafObject(0, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true)); @@ -1374,7 +1371,7 @@ private void testReflectionHierarchyEquals(final boolean testTransients) { // same values assertTrue(EqualsBuilder.reflectionEquals(ttlo, ttlo, testTransients)); - assertTrue(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 10), testTransients)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 10), testTransients)); // same super values, diff sub values assertFalse(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 11), testTransients)); assertFalse(EqualsBuilder.reflectionEquals(new TestSubObject(1, 11), new TestSubObject(1, 10), testTransients)); @@ -1383,17 +1380,17 @@ private void testReflectionHierarchyEquals(final boolean testTransients) { assertFalse(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(0, 10), testTransients)); // mix super and sub types: equals - assertTrue(EqualsBuilder.reflectionEquals(to1, teso, testTransients)); - assertTrue(EqualsBuilder.reflectionEquals(teso, to1, testTransients)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(to1, teso, testTransients)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(teso, to1, testTransients)); - assertTrue(EqualsBuilder.reflectionEquals(to1, ttso, false)); // Force testTransients = false for this assert - assertTrue(EqualsBuilder.reflectionEquals(ttso, to1, false)); // Force testTransients = false for this assert + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(to1, ttso, false)); // Force testTransients = false for this assert + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(ttso, to1, false)); // Force testTransients = false for this assert - assertTrue(EqualsBuilder.reflectionEquals(to1, tttso, false)); // Force testTransients = false for this assert - assertTrue(EqualsBuilder.reflectionEquals(tttso, to1, false)); // Force testTransients = false for this assert + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(to1, tttso, false)); // Force testTransients = false for this assert + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(tttso, to1, false)); // Force testTransients = false for this assert - assertTrue(EqualsBuilder.reflectionEquals(ttso, tttso, false)); // Force testTransients = false for this assert - assertTrue(EqualsBuilder.reflectionEquals(tttso, ttso, false)); // Force testTransients = false for this assert + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(ttso, tttso, false)); // Force testTransients = false for this assert + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(tttso, ttso, false)); // Force testTransients = false for this assert // mix super and sub types: NOT equals assertFalse(EqualsBuilder.reflectionEquals(new TestObject(0), new TestEmptySubObject(1), testTransients)); @@ -1502,7 +1499,7 @@ void testToEqualsExclude() { one = new TestObjectEqualsExclude(1, 2); two = new TestObjectEqualsExclude(2, 2); - assertTrue(EqualsBuilder.reflectionEquals(one, two)); + assertTrueIfAccessible(EqualsBuilder.reflectionEquals(one, two)); } /** diff --git a/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleNoForceTest.java new file mode 100644 index 00000000000..b3d3033b0a0 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link JsonToStringStyleTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class JsonToStringStyleNoForceTest extends JsonToStringStyleTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleTest.java b/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleTest.java index 5b55e2b1d00..3925cdd631b 100644 --- a/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleTest.java @@ -28,7 +28,6 @@ import java.util.List; import java.util.Map; -import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.builder.ToStringStyleTest.Person; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -37,7 +36,7 @@ /** * Tests {@link JsonToStringStyleTest}. */ -class JsonToStringStyleTest extends AbstractLangTest { +class JsonToStringStyleTest extends AbstractBuilderTest { static class AcademyClass { Teacher teacher; @@ -214,9 +213,9 @@ void testArrayEnum() { teacher.setHobbies(hobbies); - assertEquals(teacher.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}"); + assertEqualsIfAccessible(teacher.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}"); teacher.setHobbies(new Hobby[0]); - assertEquals(teacher.toString(), "{\"hobbies\":[]}"); + assertEqualsIfAccessible(teacher.toString(), "{\"hobbies\":[]}"); teacher.setHobbies(null); assertEquals(teacher.toString(), "{\"hobbies\":null}"); } @@ -295,7 +294,8 @@ void testCombineListAndEnum() { academyClass.setStudents(students); academyClass.setTeacher(teacher); - assertEquals(academyClass.toString(), "{\"students\":[{\"hobbies\":[\"BOOK\",\"MUSIC\"]},{\"hobbies\":[]},{\"hobbies\":[\"BOOK\"]}],\"teacher\":{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}}"); + assertEqualsIfAccessible(academyClass.toString(), + "{\"students\":[{\"hobbies\":[\"BOOK\",\"MUSIC\"]},{\"hobbies\":[]},{\"hobbies\":[\"BOOK\"]}],\"teacher\":{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}}"); } @Test @@ -368,9 +368,9 @@ void testList() { student.setHobbies(objects); - assertEquals(student.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}"); + assertEqualsIfAccessible(student.toString(), "{\"hobbies\":[\"BOOK\",\"SPORT\",\"MUSIC\"]}"); student.setHobbies(new ArrayList<>()); - assertEquals(student.toString(), "{\"hobbies\":[]}"); + assertEqualsIfAccessible(student.toString(), "{\"hobbies\":[]}"); student.setHobbies(null); assertEquals(student.toString(), "{\"hobbies\":null}"); } diff --git a/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleNoForceTest.java new file mode 100644 index 00000000000..d03c2d57404 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link MultilineRecursiveToStringStyleTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class MultilineRecursiveToStringStyleNoForceTest extends MultilineRecursiveToStringStyleTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleTest.java b/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleTest.java index 4d4d7f57aaf..a0bb2ece2fa 100644 --- a/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleTest.java @@ -22,12 +22,11 @@ import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; /** */ -class MultilineRecursiveToStringStyleTest extends AbstractLangTest { +class MultilineRecursiveToStringStyleTest extends AbstractBuilderTest { static class Account { Customer owner; @@ -110,7 +109,7 @@ public void boolArray() { + " false," + LS + " true" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -123,7 +122,7 @@ public void byteArray() { + " 1," + LS + " 2" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -136,7 +135,7 @@ public void charArray() { + " a," + LS + " A" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -149,7 +148,7 @@ public void doubleArray() { + " 1.0," + LS + " 2.0" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -162,7 +161,7 @@ public void floatArray() { + " 1.0," + LS + " 2.0" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } private String getClassPrefix(final Object object) { @@ -193,7 +192,7 @@ public void intArray() { + " 1," + LS + " 2" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -206,7 +205,7 @@ public void longArray() { + " 1," + LS + " 2" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -229,7 +228,7 @@ public void nestedAndArray() { + " ]" + LS + " }" + LS + "]"; - assertEquals(expected, toString(acc)); + assertEqualsIfAccessible(expected, toString(acc)); } @Test @@ -244,7 +243,7 @@ public void nestedElements() { + " ]," + LS + " name=Douglas Adams" + LS + "]"; - assertEquals(exp, toString(customer)); + assertEqualsIfAccessible(exp, toString(customer)); } @Test @@ -264,7 +263,7 @@ public void shortArray() { + " 1," + LS + " 2" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test @@ -274,7 +273,7 @@ public void simpleObject() { + " amount=100.0," + LS + " date=2014.10.15" + LS + "]"; - assertEquals(expected, toString(tx)); + assertEqualsIfAccessible(expected, toString(tx)); } @Test @@ -287,7 +286,7 @@ public void stringArray() { + " a," + LS + " A" + LS + " }"); - assertEquals(exp, toString(wa)); + assertEqualsIfAccessible(exp, toString(wa)); } @Test diff --git a/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleNoForceTest.java new file mode 100644 index 00000000000..5900ef6a5a5 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link RecursiveToStringStyleTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class RecursiveToStringStyleNoForceTest extends RecursiveToStringStyleTest { + // Empty. +} diff --git a/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleTest.java b/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleTest.java index ca4bd33b00b..a1238623d15 100644 --- a/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleTest.java @@ -50,6 +50,7 @@ static class Job { */ String title; } + static class Person { /** @@ -211,9 +212,11 @@ void testPerson() { p.job = new Job(); p.job.title = "Manager"; final String baseStr = p.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(p)); - final String jobStr = p.job.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(p.job)); - assertEquals(baseStr + "[age=33,job=" + jobStr + "[title=Manager],name=John Doe,smoker=false]", - new ReflectionToStringBuilder(p, new RecursiveToStringStyle()).toString()); + final String jobStr = p.job.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(p.job)); + final ReflectionToStringBuilder builder = new ReflectionToStringBuilder(p, new RecursiveToStringStyle()); + final String expected = baseStr + (builder.isForceAccessible() ? "[age=33,job=" + jobStr + "[title=Manager],name=John Doe,smoker=false]" + : "[age=,job=,name=,smoker=]"); + assertEquals(expected, builder.toString()); } @Test diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationNoForceTest.java new file mode 100644 index 00000000000..f592ce482c6 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ReflectionToStringBuilderCustomImplementationTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ReflectionToStringBuilderCustomImplementationNoForceTest extends ReflectionToStringBuilderCustomImplementationTest { + // Empty +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationTest.java index e8a2d5302b2..f7df8535749 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderCustomImplementationTest.java @@ -14,20 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.commons.lang3.builder; import static org.junit.jupiter.api.Assertions.assertEquals; import java.lang.reflect.Field; -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; /** - * Tests {@link ReflectionToStringBuilder} always uses {@link ReflectionToStringBuilder#getValue(Field)} to get the - * value of every field in the class. + * Tests {@link ReflectionToStringBuilder} always uses {@link ReflectionToStringBuilder#getValue(Field)} to get the value of every field in the class. */ -class ReflectionToStringBuilderCustomImplementationTest extends AbstractLangTest { +class ReflectionToStringBuilderCustomImplementationTest extends AbstractBuilderTest { public static class CustomReflectionToStringBuilder extends ReflectionToStringBuilder { @@ -48,8 +47,7 @@ protected Object getValue(final Field field) throws IllegalAccessException { @Test void testBuild() { - assertEquals("[stringField=prefix:string]", + assertEquals("[stringField=" + accessibleString("prefix:string") + "]", new CustomReflectionToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE).build()); } - } diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNoForceTest.java new file mode 100644 index 00000000000..52aad0f4622 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ReflectionToStringBuilderExcludeTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ReflectionToStringBuilderExcludeNoForceTest extends ReflectionToStringBuilderExcludeTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesNoForceTest.java new file mode 100644 index 00000000000..20b92782225 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ReflectionToStringBuilderExcludeNullValuesTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ReflectionToStringBuilderExcludeNullValuesNoForceTest extends ReflectionToStringBuilderExcludeNullValuesTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java index f40049a8c7a..8e161f76af5 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java @@ -20,10 +20,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; -class ReflectionToStringBuilderExcludeNullValuesTest extends AbstractLangTest { +class ReflectionToStringBuilderExcludeNullValuesTest extends AbstractBuilderTest { static class TestFixture { @SuppressWarnings("unused") @@ -49,17 +48,17 @@ void test_ConstructorOption() { ReflectionToStringBuilder builder = new ReflectionToStringBuilder(BOTH_NON_NULL, null, null, null, false, false, true); assertTrue(builder.isExcludeNullValues()); String toString = builder.toString(); - assertTrue(toString.contains(INTEGER_FIELD_NAME)); - assertTrue(toString.contains(STRING_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(INTEGER_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(STRING_FIELD_NAME)); builder = new ReflectionToStringBuilder(FIRST_NULL, null, null, null, false, false, true); toString = builder.toString(); assertFalse(toString.contains(INTEGER_FIELD_NAME)); - assertTrue(toString.contains(STRING_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(STRING_FIELD_NAME)); builder = new ReflectionToStringBuilder(SECOND_NULL, null, null, null, false, false, true); toString = builder.toString(); - assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(INTEGER_FIELD_NAME)); assertFalse(toString.contains(STRING_FIELD_NAME)); builder = new ReflectionToStringBuilder(BOTH_NULL, null, null, null, false, false, true); @@ -120,17 +119,17 @@ void test_excludeNull() { //test normal case String toString = ReflectionToStringBuilder.toString(BOTH_NON_NULL, null, false, false, true, null); - assertTrue(toString.contains(INTEGER_FIELD_NAME)); - assertTrue(toString.contains(STRING_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(INTEGER_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(STRING_FIELD_NAME)); //make one null toString = ReflectionToStringBuilder.toString(FIRST_NULL, null, false, false, true, null); assertFalse(toString.contains(INTEGER_FIELD_NAME)); - assertTrue(toString.contains(STRING_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(STRING_FIELD_NAME)); //other one null toString = ReflectionToStringBuilder.toString(SECOND_NULL, null, false, false, true, null); - assertTrue(toString.contains(INTEGER_FIELD_NAME)); + assertTrueIfAccessible(toString.contains(INTEGER_FIELD_NAME)); assertFalse(toString.contains(STRING_FIELD_NAME)); //both null diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeTest.java index a4d684b3f8d..3e85c74ab62 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeTest.java @@ -24,13 +24,12 @@ import java.util.Collection; import java.util.List; -import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; /** */ -class ReflectionToStringBuilderExcludeTest extends AbstractLangTest { +class ReflectionToStringBuilderExcludeTest extends AbstractBuilderTest { final class TestFixture { @SuppressWarnings("unused") @@ -123,7 +122,7 @@ void test_toStringExcludeNullCollection() { private void validateNonSecretField(final String toString) { assertTrue(toString.contains(NOT_SECRET_FIELD)); - assertTrue(toString.contains(NOT_SECRET_VALUE)); + assertTrueIfAccessible(toString.contains(NOT_SECRET_VALUE)); } private void validateSecretFieldAbsent(final String toString) { @@ -132,7 +131,7 @@ private void validateSecretFieldAbsent(final String toString) { } private void validateSecretFieldPresent(final String toString) { - assertTrue(toString.indexOf(SECRET_VALUE) > 0); + assertTrueIfAccessible(toString.indexOf(SECRET_VALUE) > 0); validateNonSecretField(toString); } } diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationNoForceTest.java new file mode 100644 index 00000000000..8cf66e31dad --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ReflectionToStringBuilderExcludeWithAnnotationTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ReflectionToStringBuilderExcludeWithAnnotationNoForceTest extends ReflectionToStringBuilderExcludeWithAnnotationTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java index 55f9f48ceaf..acb811af0bf 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java @@ -20,13 +20,12 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; /** * Test class for ToStringExclude annotation */ -class ReflectionToStringBuilderExcludeWithAnnotationTest extends AbstractLangTest { +class ReflectionToStringBuilderExcludeWithAnnotationTest extends AbstractBuilderTest { final class TestFixture { @ToStringExclude @@ -50,7 +49,7 @@ void test_toStringExclude() { assertFalse(toString.contains(EXCLUDED_FIELD_NAME)); assertFalse(toString.contains(EXCLUDED_FIELD_VALUE)); assertTrue(toString.contains(INCLUDED_FIELD_NAME)); - assertTrue(toString.contains(INCLUDED_FIELD_VALUE)); + assertTrueIfAccessible(toString.contains(INCLUDED_FIELD_VALUE)); } } diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeNoForceTest.java new file mode 100644 index 00000000000..25a7ec0bd05 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ReflectionToStringBuilderIncludeTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ReflectionToStringBuilderIncludeNoForceTest extends ReflectionToStringBuilderIncludeTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeTest.java index 56de2526e5d..c42bbaa9bf8 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderIncludeTest.java @@ -25,11 +25,10 @@ import java.util.Collection; import java.util.List; -import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; -class ReflectionToStringBuilderIncludeTest extends AbstractLangTest { +class ReflectionToStringBuilderIncludeTest extends AbstractBuilderTest { final class TestFeature { @SuppressWarnings("unused") @@ -214,7 +213,7 @@ private void validateIncludeFieldsPresent(final String toString, final String[] } for (final String includeValue : valuesToShow) { - assertTrue(toString.indexOf(includeValue) > 0); + assertTrueIfAccessible(toString.indexOf(includeValue) > 0); } validateNonIncludeFieldsAbsent(toString, fieldsToShow, valuesToShow); diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryNoForceTest.java new file mode 100644 index 00000000000..e9605f92091 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ReflectionToStringBuilderSummaryTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ReflectionToStringBuilderSummaryNoForceTest extends ReflectionToStringBuilderSummaryTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryTest.java index be0f5227c34..78ced90f178 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderSummaryTest.java @@ -16,12 +16,9 @@ */ package org.apache.commons.lang3.builder; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; -class ReflectionToStringBuilderSummaryTest extends AbstractLangTest { +class ReflectionToStringBuilderSummaryTest extends AbstractBuilderTest { @SuppressWarnings("unused") private final String stringField = "string"; @@ -31,8 +28,7 @@ class ReflectionToStringBuilderSummaryTest extends AbstractLangTest { @Test void testSummary() { - assertEquals("[stringField=string,summaryString=]", - new ReflectionToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE).build()); + assertEqualsIfAccessible("[stringField=string,summaryString=]", new ReflectionToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE).build()); } } diff --git a/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderNoForceTest.java b/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderNoForceTest.java new file mode 100644 index 00000000000..2b65c47f399 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderNoForceTest.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.builder; + +import org.junitpioneer.jupiter.SetSystemProperty; + +/** + * Like {@link ToStringBuilderTest} with force accessible disabled. + */ +@SetSystemProperty(key = AbstractReflectionTest.FORCE_ACCESSIBLE, value = "false") +public class ToStringBuilderNoForceTest extends ToStringBuilderTest { + // TODO Override failing methods with new assertions +} diff --git a/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java index befd4ae8bf2..fc79105affe 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java @@ -26,13 +26,12 @@ import java.util.HashMap; import java.util.List; -import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; /** * Tests for {@link org.apache.commons.lang3.builder.ToStringBuilder}. */ -class ToStringBuilderTest extends AbstractLangTest { +class ToStringBuilderTest extends AbstractBuilderTest { /** * Test fixture for ReflectionToStringBuilder.toString() for statics. @@ -655,20 +654,20 @@ void testGetSetDefault() { @Test void testInheritedReflectionStatics() { final InheritedReflectionStaticFieldsFixture instance1 = new InheritedReflectionStaticFieldsFixture(); - assertEquals(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2]", ReflectionToStringBuilder.toString(instance1, null, false, true, InheritedReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2,staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2,staticInt=12345,staticString=staticString]", ReflectionToStringBuilder.toString(instance1, null, false, true, SimpleReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2,staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2,staticInt=12345,staticString=staticString]", this.toStringWithStatics(instance1, null, SimpleReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2,staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt2=67890,staticString2=staticString2,staticInt=12345,staticString=staticString]", this.toStringWithStatics(instance1, null, SimpleReflectionStaticFieldsFixture.class)); } @Test void testInnerClassReflection() { final Outer outer = new Outer(); - assertEquals(toBaseString(outer) + "[inner=" + toBaseString(outer.inner) + "[]]", outer.toString()); + assertEqualsIfAccessible(toBaseString(outer) + "[inner=" + toBaseString(outer.inner) + "[]]", outer.toString()); } @Test @@ -790,9 +789,9 @@ void testReflectionArrayAndObjectCycle() { final Object[] objects = new Object[1]; final SimpleReflectionTestFixture simple = new SimpleReflectionTestFixture(objects); objects[0] = simple; - assertEquals(toBaseString(objects) + "[{" + toBaseString(simple) + "[o=" + toBaseString(objects) + "]}]", + assertEqualsIfAccessible(toBaseString(objects) + "[{" + toBaseString(simple) + "[o=" + toBaseString(objects) + "]}]", ToStringBuilder.reflectionToString(objects)); - assertEquals(toBaseString(simple) + "[o={" + toBaseString(simple) + "}]", ToStringBuilder.reflectionToString(simple)); + assertEqualsIfAccessible(toBaseString(simple) + "[o={" + toBaseString(simple) + "}]", ToStringBuilder.reflectionToString(simple)); } @Test @@ -837,9 +836,9 @@ void testReflectionArrayCycleLevel2() { void testReflectionBoolean() { Boolean b; b = Boolean.TRUE; - assertEquals(toBaseString(b) + "[value=true]", ToStringBuilder.reflectionToString(b)); + assertEqualsIfAccessible(toBaseString(b) + "[value=true]", ToStringBuilder.reflectionToString(b)); b = Boolean.FALSE; - assertEquals(toBaseString(b) + "[value=false]", ToStringBuilder.reflectionToString(b)); + assertEqualsIfAccessible(toBaseString(b) + "[value=false]", ToStringBuilder.reflectionToString(b)); } @Test @@ -885,7 +884,7 @@ void testReflectionByteArrayArray() { @Test void testReflectionCharacter() { final Character c = 'A'; - assertEquals(toBaseString(c) + "[value=A]", ToStringBuilder.reflectionToString(c)); + assertEqualsIfAccessible(toBaseString(c) + "[value=A]", ToStringBuilder.reflectionToString(c)); } @Test @@ -946,25 +945,24 @@ void testReflectionFloatArrayArray() { void testReflectionHierarchy() { final ReflectionTestFixtureA baseA = new ReflectionTestFixtureA(); String baseString = toBaseString(baseA); - assertEquals(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA)); - assertEquals(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null)); - assertEquals(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false)); - assertEquals(baseString + "[a=a,transientA=t]", ToStringBuilder.reflectionToString(baseA, null, true)); - assertEquals(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, null)); - assertEquals(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, Object.class)); - assertEquals(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, ReflectionTestFixtureA.class)); - + assertEqualsIfAccessible(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA)); + assertEqualsIfAccessible(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null)); + assertEqualsIfAccessible(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false)); + assertEqualsIfAccessible(baseString + "[a=a,transientA=t]", ToStringBuilder.reflectionToString(baseA, null, true)); + assertEqualsIfAccessible(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, null)); + assertEqualsIfAccessible(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, Object.class)); + assertEqualsIfAccessible(baseString + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, ReflectionTestFixtureA.class)); final ReflectionTestFixtureB baseB = new ReflectionTestFixtureB(); baseString = toBaseString(baseB); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB)); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB)); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null)); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false)); - assertEquals(baseString + "[b=b,transientB=t,a=a,transientA=t]", ToStringBuilder.reflectionToString(baseB, null, true)); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, null)); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, Object.class)); - assertEquals(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, ReflectionTestFixtureA.class)); - assertEquals(baseString + "[b=b]", ToStringBuilder.reflectionToString(baseB, null, false, ReflectionTestFixtureB.class)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false)); + assertEqualsIfAccessible(baseString + "[b=b,transientB=t,a=a,transientA=t]", ToStringBuilder.reflectionToString(baseB, null, true)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, null)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, Object.class)); + assertEqualsIfAccessible(baseString + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, ReflectionTestFixtureA.class)); + assertEqualsIfAccessible(baseString + "[b=b]", ToStringBuilder.reflectionToString(baseB, null, false, ReflectionTestFixtureB.class)); } // Reflection hierarchy tests @@ -973,13 +971,14 @@ void testReflectionHierarchyArrayList() { // LANG-1337 without this, the generated string can differ depending on the JVM version/vendor final List list = new ArrayList<>(ARRAYLIST_INITIAL_CAPACITY); final String baseString = toBaseString(list); - final String expectedWithTransients = baseString - + "[elementData={,,,,,,,,,},size=0,modCount=0]"; + final String expectedWithTransients = baseString + "[elementData=" + + accessibleString("{,,,,,,,,,}") + ",size=" + accessibleString("0") + ",modCount=" + + accessibleString("0") + "]"; final String toStringWithTransients = ToStringBuilder.reflectionToString(list, null, true); if (!expectedWithTransients.equals(toStringWithTransients)) { assertEquals(expectedWithTransients, toStringWithTransients); } - final String expectedWithoutTransients = baseString + "[size=0]"; + final String expectedWithoutTransients = baseString + "[size=" + accessibleString("0") + "]"; final String toStringWithoutTransients = ToStringBuilder.reflectionToString(list, null, false); if (!expectedWithoutTransients.equals(toStringWithoutTransients)) { assertEquals(expectedWithoutTransients, toStringWithoutTransients); @@ -1009,7 +1008,7 @@ void testReflectionIntArrayArray() { */ @Test void testReflectionInteger() { - assertEquals(baseStr + "[value=5]", ToStringBuilder.reflectionToString(base)); + assertEqualsIfAccessible(baseStr + "[value=5]", ToStringBuilder.reflectionToString(base)); } @Test @@ -1053,7 +1052,7 @@ void testReflectionObjectCycle() { final ReflectionTestCycleB b = new ReflectionTestCycleB(); a.b = b; b.a = a; - assertEquals(toBaseString(a) + "[b=" + toBaseString(b) + "[a=" + toBaseString(a) + "]]", a.toString()); + assertEqualsIfAccessible(toBaseString(a) + "[b=" + toBaseString(b) + "[a=" + toBaseString(a) + "]]", a.toString()); } @Test @@ -1080,14 +1079,14 @@ void testReflectionShortArray() { @Test void testReflectionStatics() { final ReflectionStaticFieldsFixture instance1 = new ReflectionStaticFieldsFixture(); - assertEquals(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString]", ReflectionToStringBuilder.toString(instance1, null, false, true, ReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + assertEqualsIfAccessible(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString,staticTransientInt=54321,staticTransientString=staticTransientString,transientInt=98765,transientString=transientString]", ReflectionToStringBuilder.toString(instance1, null, true, true, ReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString]", this.toStringWithStatics(instance1, null, ReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[instanceInt=67890,instanceString=instanceString,staticInt=12345,staticString=staticString]", this.toStringWithStatics(instance1, null, ReflectionStaticFieldsFixture.class)); } @@ -1098,7 +1097,7 @@ void testReflectionStatics() { @Test void testSelfInstanceTwoVarsReflectionObjectCycle() { final SelfInstanceTwoVarsReflectionTestFixture test = new SelfInstanceTwoVarsReflectionTestFixture(); - assertEquals(toBaseString(test) + "[otherType=" + test.getOtherType().toString() + ",typeIsSelf=" + toBaseString(test) + "]", + assertEqualsIfAccessible(toBaseString(test) + "[otherType=" + test.getOtherType().toString() + ",typeIsSelf=" + toBaseString(test) + "]", test.toString()); } @@ -1108,7 +1107,7 @@ void testSelfInstanceTwoVarsReflectionObjectCycle() { @Test void testSelfInstanceVarReflectionObjectCycle() { final SelfInstanceVarReflectionTestFixture test = new SelfInstanceVarReflectionTestFixture(); - assertEquals(toBaseString(test) + "[typeIsSelf=" + toBaseString(test) + "]", test.toString()); + assertEqualsIfAccessible(toBaseString(test) + "[typeIsSelf=" + toBaseString(test) + "]", test.toString()); } @Test @@ -1150,19 +1149,19 @@ void testShortArrayArray() { void testSimpleReflectionObjectCycle() { final SimpleReflectionTestFixture simple = new SimpleReflectionTestFixture(); simple.o = simple; - assertEquals(toBaseString(simple) + "[o=" + toBaseString(simple) + "]", simple.toString()); + assertEqualsIfAccessible(toBaseString(simple) + "[o=" + toBaseString(simple) + "]", simple.toString()); } @Test void testSimpleReflectionStatics() { final SimpleReflectionStaticFieldsFixture instance1 = new SimpleReflectionStaticFieldsFixture(); - assertEquals(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", ReflectionToStringBuilder.toString(instance1, null, false, true, SimpleReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", ReflectionToStringBuilder.toString(instance1, null, true, true, SimpleReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", this.toStringWithStatics(instance1, null, SimpleReflectionStaticFieldsFixture.class)); - assertEquals(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", + assertEqualsIfAccessible(toBaseString(instance1) + "[staticInt=12345,staticString=staticString]", this.toStringWithStatics(instance1, null, SimpleReflectionStaticFieldsFixture.class)); }