diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8fbffc33a..9c9f63a95 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + Add option to disable the "objectsTriviallyEqual" test in DiffBuilder Add (T) casts to get unit tests to pass in old JDK Add JsonToStringStyle implementation to ToStringStyle Add NoClassNameToStringStyle implementation of ToStringStyle diff --git a/src/main/java/org/apache/commons/lang3/builder/DiffBuilder.java b/src/main/java/org/apache/commons/lang3/builder/DiffBuilder.java index 8c71b3590..125a68d22 100644 --- a/src/main/java/org/apache/commons/lang3/builder/DiffBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/DiffBuilder.java @@ -90,11 +90,18 @@ public class DiffBuilder implements Builder { * @param style * the style will use when outputting the objects, {@code null} * uses the default + * @param testTriviallyEqual + * If true, this will test if lhs and rhs are the same or equal. + * All of the append(fieldName, lhs, rhs) methods will abort + * without creating a field {@link Diff} if the trivially equal + * test is enabled and returns true. The result of this test + * is never changed throughout the life of this {@link DiffBuilder}. * @throws IllegalArgumentException * if {@code lhs} or {@code rhs} is {@code null} */ public DiffBuilder(final Object lhs, final Object rhs, - final ToStringStyle style) { + final ToStringStyle style, final boolean testTriviallyEqual) { + if (lhs == null) { throw new IllegalArgumentException("lhs cannot be null"); } @@ -108,7 +115,39 @@ public class DiffBuilder implements Builder { this.style = style; // Don't compare any fields if objects equal - this.objectsTriviallyEqual = (lhs == rhs || lhs.equals(rhs)); + this.objectsTriviallyEqual = testTriviallyEqual && (lhs == rhs || lhs.equals(rhs)); + } + + /** + *

+ * Constructs a builder for the specified objects with the specified style. + *

+ * + *

+ * If {@code lhs == rhs} or {@code lhs.equals(rhs)} then the builder will + * not evaluate any calls to {@code append(...)} and will return an empty + * {@link DiffResult} when {@link #build()} is executed. + *

+ * + *

+ * This delegates to {@link #DiffBuilder(Object, Object, ToStringStyle, boolean)} + * with the testTriviallyEqual flag enabled. + *

+ * + * @param lhs + * {@code this} object + * @param rhs + * the object to diff against + * @param style + * the style will use when outputting the objects, {@code null} + * uses the default + * @throws IllegalArgumentException + * if {@code lhs} or {@code rhs} is {@code null} + */ + public DiffBuilder(final Object lhs, final Object rhs, + final ToStringStyle style) { + + this(lhs, rhs, style, true); } /** 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 db0950494..ae835fef8 100644 --- a/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java @@ -16,10 +16,13 @@ */ package org.apache.commons.lang3.builder; +import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import org.apache.commons.lang3.ArrayUtils; +import org.hamcrest.Matcher; import org.junit.Test; @@ -412,4 +415,44 @@ public class DiffBuilderTest { list = class1.diff(class1); assertEquals(ToStringStyle.MULTI_LINE_STYLE, list.getToStringStyle()); } + + @Test + public void testTriviallyEqualTestDisabled() { + final Matcher equalToOne = equalTo(1); + + // Constructor's arguments are not trivially equal, but not testing for that. + DiffBuilder explicitTestAndNotEqual1 = new DiffBuilder(1, 2, null, false); + explicitTestAndNotEqual1.append("letter", "X", "Y"); + assertThat(explicitTestAndNotEqual1.build().getNumberOfDiffs(), equalToOne); + + // Constructor's arguments are trivially equal, but not testing for that. + DiffBuilder explicitTestAndNotEqual2 = new DiffBuilder(1, 1, null, false); + // This append(f, l, r) will not abort early. + explicitTestAndNotEqual2.append("letter", "X", "Y"); + assertThat(explicitTestAndNotEqual2.build().getNumberOfDiffs(), equalToOne); + } + + @Test + public void testTriviallyEqualTestEnabled() { + final Matcher equalToZero = equalTo(0); + final Matcher equalToOne = equalTo(1); + + // The option to test if trivially equal is enabled by default. + DiffBuilder implicitTestAndEqual = new DiffBuilder(1, 1, null); + // This append(f, l, r) will abort without creating a Diff for letter. + implicitTestAndEqual.append("letter", "X", "Y"); + assertThat(implicitTestAndEqual.build().getNumberOfDiffs(), equalToZero); + + DiffBuilder implicitTestAndNotEqual = new DiffBuilder(1, 2, null); + // This append(f, l, r) will not abort early + // because the constructor's arguments were not trivially equal. + implicitTestAndNotEqual.append("letter", "X", "Y"); + assertThat(implicitTestAndNotEqual.build().getNumberOfDiffs(), equalToOne); + + // This is explicitly enabling the trivially equal test. + DiffBuilder explicitTestAndEqual = new DiffBuilder(1, 1, null, true); + explicitTestAndEqual.append("letter", "X", "Y"); + assertThat(explicitTestAndEqual.build().getNumberOfDiffs(), equalToZero); + } + }