aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java')
-rw-r--r--src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java1422
1 files changed, 1422 insertions, 0 deletions
diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
new file mode 100644
index 000000000..eed05f414
--- /dev/null
+++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
@@ -0,0 +1,1422 @@
+/*
+ * 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.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.lang3.AbstractLangTest;
+import org.apache.commons.lang3.reflect.MethodUtils;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit tests {@link org.apache.commons.lang3.builder.EqualsBuilder}.
+ */
+public class EqualsBuilderTest extends AbstractLangTest {
+
+
+ static class TestObject {
+ private int a;
+
+ TestObject() {
+ }
+
+ TestObject(final int a) {
+ this.a = a;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (o == this) {
+ return true;
+ }
+ if (o.getClass() != getClass()) {
+ return false;
+ }
+
+ final TestObject rhs = (TestObject) o;
+ return a == rhs.a;
+ }
+
+ @Override
+ public int hashCode() {
+ return a;
+ }
+
+ public void setA(final int a) {
+ this.a = a;
+ }
+
+ public int getA() {
+ return a;
+ }
+ }
+
+ static class TestSubObject extends TestObject {
+ private int b;
+
+ TestSubObject() {
+ super(0);
+ }
+
+ TestSubObject(final int a, final int b) {
+ super(a);
+ this.b = b;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (o == this) {
+ return true;
+ }
+ if (o.getClass() != getClass()) {
+ return false;
+ }
+
+ final TestSubObject rhs = (TestSubObject) o;
+ return super.equals(o) && b == rhs.b;
+ }
+
+ @Override
+ public int hashCode() {
+ return b * 17 + super.hashCode();
+ }
+
+ public void setB(final int b) {
+ this.b = b;
+ }
+
+ public int getB() {
+ return b;
+ }
+ }
+
+ static class TestEmptySubObject extends TestObject {
+ TestEmptySubObject(final int a) {
+ super(a);
+ }
+ }
+
+ static class TestTSubObject extends TestObject {
+ @SuppressWarnings("unused")
+ private final transient int t;
+
+ TestTSubObject(final int a, final int t) {
+ super(a);
+ this.t = t;
+ }
+ }
+
+ static class TestTTSubObject extends TestTSubObject {
+ @SuppressWarnings("unused")
+ private final transient int tt;
+
+ TestTTSubObject(final int a, final int t, final int tt) {
+ super(a, t);
+ this.tt = tt;
+ }
+ }
+
+ static class TestTTLeafObject extends TestTTSubObject {
+ @SuppressWarnings("unused")
+ private final int leafValue;
+
+ TestTTLeafObject(final int a, final int t, final int tt, final int leafValue) {
+ super(a, t, tt);
+ this.leafValue = leafValue;
+ }
+ }
+
+ static class TestTSubObject2 extends TestObject {
+ private transient int t;
+
+ TestTSubObject2(final int a, final int t) {
+ super(a);
+ }
+
+ public int getT() {
+ return t;
+ }
+
+ public void setT(final int t) {
+ this.t = t;
+ }
+ }
+
+ static class TestRecursiveGenericObject<T> {
+
+ private final T a;
+
+ TestRecursiveGenericObject(final T a) {
+ this.a = a;
+ }
+
+ public T getA() {
+ return a;
+ }
+ }
+
+ static class TestRecursiveObject {
+ private final TestRecursiveInnerObject a;
+ private final TestRecursiveInnerObject b;
+ private int z;
+
+ TestRecursiveObject(final TestRecursiveInnerObject a,
+ final TestRecursiveInnerObject b, final int z) {
+ this.a = a;
+ this.b = b;
+ }
+
+ public TestRecursiveInnerObject getA() {
+ return a;
+ }
+
+ public TestRecursiveInnerObject getB() {
+ return b;
+ }
+
+ public int getZ() {
+ return z;
+ }
+
+ }
+
+ static class TestRecursiveInnerObject {
+ private final int n;
+
+ TestRecursiveInnerObject(final int n) {
+ this.n = n;
+ }
+
+ public int getN() {
+ return n;
+ }
+ }
+
+ static class TestRecursiveCycleObject {
+ private TestRecursiveCycleObject cycle;
+ private final int n;
+
+ TestRecursiveCycleObject(final int n) {
+ this.n = n;
+ this.cycle = this;
+ }
+
+ TestRecursiveCycleObject(final TestRecursiveCycleObject cycle, final int n) {
+ this.n = n;
+ this.cycle = cycle;
+ }
+
+ public int getN() {
+ return n;
+ }
+
+ public TestRecursiveCycleObject getCycle() {
+ return cycle;
+ }
+
+ public void setCycle(final TestRecursiveCycleObject cycle) {
+ this.cycle = cycle;
+ }
+ }
+
+ @Test
+ public void testReflectionEquals() {
+ final TestObject o1 = new TestObject(4);
+ final TestObject o2 = new TestObject(5);
+ assertTrue(EqualsBuilder.reflectionEquals(o1, o1));
+ assertFalse(EqualsBuilder.reflectionEquals(o1, o2));
+ o2.setA(4);
+ assertTrue(EqualsBuilder.reflectionEquals(o1, o2));
+
+ assertFalse(EqualsBuilder.reflectionEquals(o1, this));
+
+ assertFalse(EqualsBuilder.reflectionEquals(o1, null));
+ assertFalse(EqualsBuilder.reflectionEquals(null, o2));
+ assertTrue(EqualsBuilder.reflectionEquals(null, null));
+ }
+
+ @Test
+ public 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));
+ 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));
+ }
+
+ private void testReflectionHierarchyEquals(final boolean testTransients) {
+ final TestObject to1 = new TestObject(4);
+ final TestObject to1Bis = new TestObject(4);
+ final TestObject to1Ter = new TestObject(4);
+ final TestObject to2 = new TestObject(5);
+ final TestEmptySubObject teso = new TestEmptySubObject(4);
+ final TestTSubObject ttso = new TestTSubObject(4, 1);
+ final TestTTSubObject tttso = new TestTTSubObject(4, 1, 2);
+ final TestTTLeafObject ttlo = new TestTTLeafObject(4, 1, 2, 3);
+ final TestSubObject tso1 = new TestSubObject(1, 4);
+ final TestSubObject tso1bis = new TestSubObject(1, 4);
+ final TestSubObject tso1ter = new TestSubObject(1, 4);
+ final TestSubObject tso2 = new TestSubObject(2, 5);
+
+ testReflectionEqualsEquivalenceRelationship(to1, to1Bis, to1Ter, to2, new TestObject(), testTransients);
+ testReflectionEqualsEquivalenceRelationship(tso1, tso1bis, tso1ter, tso2, new TestSubObject(), testTransients);
+
+ // More sanity checks:
+
+ // same values
+ assertTrue(EqualsBuilder.reflectionEquals(ttlo, ttlo, testTransients));
+ assertTrue(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));
+ // diff super values, same sub values
+ assertFalse(EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestSubObject(1, 10), 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));
+
+ assertTrue(EqualsBuilder.reflectionEquals(to1, ttso, false)); // Force testTransients = false for this assert
+ assertTrue(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
+
+ assertTrue(EqualsBuilder.reflectionEquals(ttso, tttso, false)); // Force testTransients = false for this assert
+ assertTrue(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));
+ assertFalse(EqualsBuilder.reflectionEquals(new TestEmptySubObject(1), new TestObject(0), testTransients));
+
+ assertFalse(EqualsBuilder.reflectionEquals(new TestObject(0), new TestTSubObject(1, 1), testTransients));
+ assertFalse(EqualsBuilder.reflectionEquals(new TestTSubObject(1, 1), new TestObject(0), testTransients));
+
+ assertFalse(EqualsBuilder.reflectionEquals(new TestObject(1), new TestSubObject(0, 10), testTransients));
+ assertFalse(EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestObject(1), testTransients));
+
+ assertFalse(EqualsBuilder.reflectionEquals(to1, ttlo));
+ assertFalse(EqualsBuilder.reflectionEquals(tso1, this));
+ }
+
+ /**
+ * Equivalence relationship tests inspired by "Effective Java":
+ * <ul>
+ * <li>reflection</li>
+ * <li>symmetry</li>
+ * <li>transitive</li>
+ * <li>consistency</li>
+ * <li>non-null reference</li>
+ * </ul>
+ *
+ * @param to a TestObject
+ * @param toBis a TestObject, equal to to and toTer
+ * @param toTer left-hand side, equal to to and toBis
+ * @param to2 a different TestObject
+ * @param oToChange a TestObject that will be changed
+ * @param testTransients whether to test transient instance variables
+ */
+ private void testReflectionEqualsEquivalenceRelationship(
+ final TestObject to,
+ final TestObject toBis,
+ final TestObject toTer,
+ final TestObject to2,
+ final TestObject oToChange,
+ final boolean testTransients) {
+
+ // 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));
+
+ // transitive test
+ assertTrue(
+ EqualsBuilder.reflectionEquals(to, toBis, testTransients)
+ && EqualsBuilder.reflectionEquals(toBis, toTer, testTransients)
+ && EqualsBuilder.reflectionEquals(to, toTer, testTransients));
+
+ // consistency test
+ oToChange.setA(to.getA());
+ if (oToChange instanceof TestSubObject) {
+ ((TestSubObject) oToChange).setB(((TestSubObject) to).getB());
+ }
+ assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+ oToChange.setA(to.getA() + 1);
+ if (oToChange instanceof TestSubObject) {
+ ((TestSubObject) oToChange).setB(((TestSubObject) to).getB() + 1);
+ }
+ assertFalse(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+ assertFalse(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+
+ // non-null reference test
+ assertFalse(EqualsBuilder.reflectionEquals(to, null, testTransients));
+ assertFalse(EqualsBuilder.reflectionEquals(to2, null, testTransients));
+ assertFalse(EqualsBuilder.reflectionEquals(null, to, testTransients));
+ assertFalse(EqualsBuilder.reflectionEquals(null, to2, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals(null, null, testTransients));
+ }
+
+ @Test
+ public void testSuper() {
+ final TestObject o1 = new TestObject(4);
+ final TestObject o2 = new TestObject(5);
+ assertTrue(new EqualsBuilder().appendSuper(true).append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().appendSuper(false).append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().appendSuper(true).append(o1, o2).isEquals());
+ assertFalse(new EqualsBuilder().appendSuper(false).append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testObject() {
+ final TestObject o1 = new TestObject(4);
+ final TestObject o2 = new TestObject(5);
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ o2.setA(4);
+ assertTrue(new EqualsBuilder().append(o1, o2).isEquals());
+
+ assertFalse(new EqualsBuilder().append(o1, this).isEquals());
+
+ assertFalse(new EqualsBuilder().append(o1, null).isEquals());
+ assertFalse(new EqualsBuilder().append(null, o2).isEquals());
+ assertTrue(new EqualsBuilder().append((Object) null, null).isEquals());
+ }
+
+ @Test
+ public void testObjectBuild() {
+ final TestObject o1 = new TestObject(4);
+ final TestObject o2 = new TestObject(5);
+ assertEquals(Boolean.TRUE, new EqualsBuilder().append(o1, o1).build());
+ assertEquals(Boolean.FALSE, new EqualsBuilder().append(o1, o2).build());
+ o2.setA(4);
+ assertEquals(Boolean.TRUE, new EqualsBuilder().append(o1, o2).build());
+
+ assertEquals(Boolean.FALSE, new EqualsBuilder().append(o1, this).build());
+
+ assertEquals(Boolean.FALSE, new EqualsBuilder().append(o1, null).build());
+ assertEquals(Boolean.FALSE, new EqualsBuilder().append(null, o2).build());
+ assertEquals(Boolean.TRUE, new EqualsBuilder().append((Object) null, null).build());
+ }
+
+ @Test
+ public void testObjectRecursiveGenericInteger() {
+ final TestRecursiveGenericObject<Integer> o1_a = new TestRecursiveGenericObject<>(1);
+ final TestRecursiveGenericObject<Integer> o1_b = new TestRecursiveGenericObject<>(1);
+ final TestRecursiveGenericObject<Integer> o2 = new TestRecursiveGenericObject<>(2);
+
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_b).isEquals());
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_b, o1_a).isEquals());
+
+ assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1_b, o2).isEquals());
+ }
+
+ @Test
+ public void testObjectsBypassReflectionClasses() {
+ final List<Class<?>> bypassReflectionClasses = new ArrayList<>();
+ bypassReflectionClasses.add(List.class);
+ bypassReflectionClasses.add(Boolean.class);
+ assertTrue(new EqualsBuilder().setBypassReflectionClasses(bypassReflectionClasses).isEquals());
+ }
+
+ @Test
+ public void testObjectRecursiveGenericString() {
+ // Note: Do not use literals, because string literals are always mapped by same object (internal() of String))!
+ final String s1_a = String.valueOf(1);
+ final TestRecursiveGenericObject<String> o1_a = new TestRecursiveGenericObject<>(s1_a);
+ final TestRecursiveGenericObject<String> o1_b = new TestRecursiveGenericObject<>(String.valueOf(1));
+ final TestRecursiveGenericObject<String> o2 = new TestRecursiveGenericObject<>(String.valueOf(2));
+
+ // To trigger bug reported in LANG-1356, call hashCode only on string in instance o1_a
+ s1_a.hashCode();
+
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_b).isEquals());
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_b, o1_a).isEquals());
+
+ assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1_b, o2).isEquals());
+ }
+
+ @Test
+ public void testObjectRecursive() {
+ final TestRecursiveInnerObject i1_1 = new TestRecursiveInnerObject(1);
+ final TestRecursiveInnerObject i1_2 = new TestRecursiveInnerObject(1);
+ final TestRecursiveInnerObject i2_1 = new TestRecursiveInnerObject(2);
+ final TestRecursiveInnerObject i2_2 = new TestRecursiveInnerObject(2);
+ final TestRecursiveInnerObject i3 = new TestRecursiveInnerObject(3);
+ final TestRecursiveInnerObject i4 = new TestRecursiveInnerObject(4);
+
+ final TestRecursiveObject o1_a = new TestRecursiveObject(i1_1, i2_1, 1);
+ final TestRecursiveObject o1_b = new TestRecursiveObject(i1_2, i2_2, 1);
+ final TestRecursiveObject o2 = new TestRecursiveObject(i3, i4, 2);
+ final TestRecursiveObject oNull = new TestRecursiveObject(null, null, 2);
+
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_a).isEquals());
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_b).isEquals());
+
+ assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1_a, o2).isEquals());
+
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(oNull, oNull).isEquals());
+ assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1_a, oNull).isEquals());
+ }
+
+ @Test
+ public void testObjectRecursiveCycleSelfreference() {
+ final TestRecursiveCycleObject o1_a = new TestRecursiveCycleObject(1);
+ final TestRecursiveCycleObject o1_b = new TestRecursiveCycleObject(1);
+ final TestRecursiveCycleObject o2 = new TestRecursiveCycleObject(2);
+
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_a).isEquals());
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_b).isEquals());
+ assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1_a, o2).isEquals());
+ }
+
+ @Test
+ public void testObjectRecursiveCycle() {
+ final TestRecursiveCycleObject o1_a = new TestRecursiveCycleObject(1);
+ final TestRecursiveCycleObject i1_a = new TestRecursiveCycleObject(o1_a, 100);
+ o1_a.setCycle(i1_a);
+
+ final TestRecursiveCycleObject o1_b = new TestRecursiveCycleObject(1);
+ final TestRecursiveCycleObject i1_b = new TestRecursiveCycleObject(o1_b, 100);
+ o1_b.setCycle(i1_b);
+
+ final TestRecursiveCycleObject o2 = new TestRecursiveCycleObject(2);
+ final TestRecursiveCycleObject i2 = new TestRecursiveCycleObject(o1_b, 200);
+ o2.setCycle(i2);
+
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_a).isEquals());
+ assertTrue(new EqualsBuilder().setTestRecursive(true).append(o1_a, o1_b).isEquals());
+ assertFalse(new EqualsBuilder().setTestRecursive(true).append(o1_a, o2).isEquals());
+
+ assertTrue(EqualsBuilder.reflectionEquals(o1_a, o1_b, false, null, true));
+ assertFalse(EqualsBuilder.reflectionEquals(o1_a, o2, false, null, true));
+ }
+
+ @Test
+ public void testLong() {
+ final long o1 = 1L;
+ final long o2 = 2L;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testInt() {
+ final int o1 = 1;
+ final int o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testShort() {
+ final short o1 = 1;
+ final short o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testChar() {
+ final char o1 = 1;
+ final char o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testByte() {
+ final byte o1 = 1;
+ final byte o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testDouble() {
+ final double o1 = 1;
+ final double o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, Double.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Double.NaN, Double.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isEquals());
+ }
+
+ @Test
+ public void testFloat() {
+ final float o1 = 1;
+ final float o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, Float.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Float.NaN, Float.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY).isEquals());
+ }
+
+ @Test
+ public void testAccessors() {
+ final EqualsBuilder equalsBuilder = new EqualsBuilder();
+ assertTrue(equalsBuilder.isEquals());
+ equalsBuilder.setEquals(true);
+ assertTrue(equalsBuilder.isEquals());
+ equalsBuilder.setEquals(false);
+ assertFalse(equalsBuilder.isEquals());
+ }
+
+ @Test
+ public void testReset() {
+ final EqualsBuilder equalsBuilder = new EqualsBuilder();
+ assertTrue(equalsBuilder.isEquals());
+ equalsBuilder.setEquals(false);
+ assertFalse(equalsBuilder.isEquals());
+ equalsBuilder.reset();
+ assertTrue(equalsBuilder.isEquals());
+ }
+
+ @Test
+ public void testBoolean() {
+ final boolean o1 = true;
+ final boolean o2 = false;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertFalse(new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ @Test
+ public void testObjectArray() {
+ TestObject[] obj1 = new TestObject[3];
+ obj1[0] = new TestObject(4);
+ obj1[1] = new TestObject(5);
+ obj1[2] = null;
+ TestObject[] obj2 = new TestObject[3];
+ obj2[0] = new TestObject(4);
+ obj2[1] = new TestObject(5);
+ obj2[2] = null;
+
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj2, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1].setA(6);
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1].setA(5);
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[2] = obj1[1];
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[2] = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testLongArray() {
+ long[] obj1 = new long[2];
+ obj1[0] = 5L;
+ obj1[1] = 6L;
+ long[] obj2 = new long[2];
+ obj2[0] = 5L;
+ obj2[1] = 6L;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testIntArray() {
+ int[] obj1 = new int[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ int[] obj2 = new int[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testShortArray() {
+ short[] obj1 = new short[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ short[] obj2 = new short[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testCharArray() {
+ char[] obj1 = new char[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ char[] obj2 = new char[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testByteArray() {
+ byte[] obj1 = new byte[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ byte[] obj2 = new byte[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testDoubleArray() {
+ double[] obj1 = new double[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ double[] obj2 = new double[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testFloatArray() {
+ float[] obj1 = new float[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ float[] obj2 = new float[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testBooleanArray() {
+ boolean[] obj1 = new boolean[2];
+ obj1[0] = true;
+ obj1[1] = false;
+ boolean[] obj2 = new boolean[2];
+ obj2[0] = true;
+ obj2[1] = false;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = true;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testMultiLongArray() {
+ final long[][] array1 = new long[2][2];
+ final long[][] array2 = new long[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiIntArray() {
+ final int[][] array1 = new int[2][2];
+ final int[][] array2 = new int[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiShortArray() {
+ final short[][] array1 = new short[2][2];
+ final short[][] array2 = new short[2][2];
+ for (short i = 0; i < array1.length; ++i) {
+ for (short j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i;
+ array2[i][j] = i;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiCharArray() {
+ final char[][] array1 = new char[2][2];
+ final char[][] array2 = new char[2][2];
+ for (char i = 0; i < array1.length; ++i) {
+ for (char j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i;
+ array2[i][j] = i;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiByteArray() {
+ final byte[][] array1 = new byte[2][2];
+ final byte[][] array2 = new byte[2][2];
+ for (byte i = 0; i < array1.length; ++i) {
+ for (byte j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i;
+ array2[i][j] = i;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiFloatArray() {
+ final float[][] array1 = new float[2][2];
+ final float[][] array2 = new float[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiDoubleArray() {
+ final double[][] array1 = new double[2][2];
+ final double[][] array2 = new double[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMultiBooleanArray() {
+ final boolean[][] array1 = new boolean[2][2];
+ final boolean[][] array2 = new boolean[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i == 1 || j == 1;
+ array2[i][j] = i == 1 || j == 1;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = false;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+
+ // compare 1 dim to 2.
+ final boolean[] array3 = {true, true};
+ assertFalse(new EqualsBuilder().append(array1, array3).isEquals());
+ assertFalse(new EqualsBuilder().append(array3, array1).isEquals());
+ assertFalse(new EqualsBuilder().append(array2, array3).isEquals());
+ assertFalse(new EqualsBuilder().append(array3, array2).isEquals());
+ }
+
+ @Test
+ public void testRaggedArray() {
+ final long[][] array1 = new long[2][];
+ final long[][] array2 = new long[2][];
+ for (int i = 0; i < array1.length; ++i) {
+ array1[i] = new long[2];
+ array2[i] = new long[2];
+ for (int j = 0; j < array1[i].length; ++j) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testMixedArray() {
+ final Object[] array1 = new Object[2];
+ final Object[] array2 = new Object[2];
+ for (int i = 0; i < array1.length; ++i) {
+ array1[i] = new long[2];
+ array2[i] = new long[2];
+ for (int j = 0; j < 2; ++j) {
+ ((long[]) array1[i])[j] = (i + 1) * (j + 1);
+ ((long[]) array2[i])[j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ ((long[]) array1[1])[1] = 0;
+ assertFalse(new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ @Test
+ public void testObjectArrayHiddenByObject() {
+ final TestObject[] array1 = new TestObject[2];
+ array1[0] = new TestObject(4);
+ array1[1] = new TestObject(5);
+ final TestObject[] array2 = new TestObject[2];
+ array2[0] = new TestObject(4);
+ array2[1] = new TestObject(5);
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1].setA(6);
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testLongArrayHiddenByObject() {
+ final long[] array1 = new long[2];
+ array1[0] = 5L;
+ array1[1] = 6L;
+ final long[] array2 = new long[2];
+ array2[0] = 5L;
+ array2[1] = 6L;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testIntArrayHiddenByObject() {
+ final int[] array1 = new int[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ final int[] array2 = new int[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testShortArrayHiddenByObject() {
+ final short[] array1 = new short[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ final short[] array2 = new short[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testCharArrayHiddenByObject() {
+ final char[] array1 = new char[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ final char[] array2 = new char[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testByteArrayHiddenByObject() {
+ final byte[] array1 = new byte[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ final byte[] array2 = new byte[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testDoubleArrayHiddenByObject() {
+ final double[] array1 = new double[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ final double[] array2 = new double[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testFloatArrayHiddenByObject() {
+ final float[] array1 = new float[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ final float[] array2 = new float[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ @Test
+ public void testBooleanArrayHiddenByObject() {
+ final boolean[] array1 = new boolean[2];
+ array1[0] = true;
+ array1[1] = false;
+ final boolean[] array2 = new boolean[2];
+ array2[0] = true;
+ array2[1] = false;
+ final Object obj1 = array1;
+ final Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = true;
+ assertFalse(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public static class TestACanEqualB {
+ private final int a;
+
+ public TestACanEqualB(final int a) {
+ this.a = a;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof TestACanEqualB) {
+ return this.a == ((TestACanEqualB) o).getA();
+ }
+ if (o instanceof TestBCanEqualA) {
+ return this.a == ((TestBCanEqualA) o).getB();
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return a;
+ }
+
+ public int getA() {
+ return this.a;
+ }
+ }
+
+ public static class TestBCanEqualA {
+ private final int b;
+
+ public TestBCanEqualA(final int b) {
+ this.b = b;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof TestACanEqualB) {
+ return this.b == ((TestACanEqualB) o).getA();
+ }
+ if (o instanceof TestBCanEqualA) {
+ return this.b == ((TestBCanEqualA) o).getB();
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return b;
+ }
+
+ public int getB() {
+ return this.b;
+ }
+ }
+
+ /**
+ * Tests two instances of classes that can be equal and that are not "related". The two classes are not subclasses
+ * of each other and do not share a parent aside from Object.
+ * See https://issues.apache.org/jira/browse/LANG-6
+ */
+ @Test
+ public void testUnrelatedClasses() {
+ final Object[] x = {new TestACanEqualB(1)};
+ final Object[] y = {new TestBCanEqualA(1)};
+
+ // sanity checks:
+ assertArrayEquals(x, x);
+ assertArrayEquals(y, y);
+ assertArrayEquals(x, y);
+ assertArrayEquals(y, x);
+ // real tests:
+ assertEquals(x[0], x[0]);
+ assertEquals(y[0], y[0]);
+ assertEquals(x[0], y[0]);
+ assertEquals(y[0], x[0]);
+ assertTrue(new EqualsBuilder().append(x, x).isEquals());
+ assertTrue(new EqualsBuilder().append(y, y).isEquals());
+ assertTrue(new EqualsBuilder().append(x, y).isEquals());
+ assertTrue(new EqualsBuilder().append(y, x).isEquals());
+ }
+
+ /**
+ * Test from https://issues.apache.org/jira/browse/LANG-42
+ */
+ @Test
+ public void testNpeForNullElement() {
+ final Object[] x1 = {Integer.valueOf(1), null, Integer.valueOf(3)};
+ final Object[] x2 = {Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)};
+
+ // causes an NPE in 2.0 according to:
+ // https://issues.apache.org/jira/browse/LANG-42
+ new EqualsBuilder().append(x1, x2);
+ }
+
+ @Test
+ public void testReflectionEqualsExcludeFields() {
+ final TestObjectWithMultipleFields x1 = new TestObjectWithMultipleFields(1, 2, 3);
+ final TestObjectWithMultipleFields x2 = new TestObjectWithMultipleFields(1, 3, 4);
+
+ // not equal when including all fields
+ assertFalse(EqualsBuilder.reflectionEquals(x1, x2));
+
+ // doesn't barf on null, empty array, or non-existent field, but still tests as not equal
+ assertFalse(EqualsBuilder.reflectionEquals(x1, x2, (String[]) null));
+ assertFalse(EqualsBuilder.reflectionEquals(x1, x2));
+ assertFalse(EqualsBuilder.reflectionEquals(x1, x2, "xxx"));
+
+ // not equal if only one of the differing fields excluded
+ assertFalse(EqualsBuilder.reflectionEquals(x1, x2, "two"));
+ assertFalse(EqualsBuilder.reflectionEquals(x1, x2, "three"));
+
+ // equal if both differing fields excluded
+ assertTrue(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"));
+ assertTrue(EqualsBuilder.reflectionEquals(x1, x2, "one", "two", "three", "xxx"));
+
+ // still equal as long as both differing fields are among excluded
+ assertTrue(EqualsBuilder.reflectionEquals(x1, x2, Arrays.asList("one", "two", "three")));
+ assertTrue(EqualsBuilder.reflectionEquals(x1, x2, Arrays.asList("one", "two", "three", "xxx")));
+
+ }
+
+ static class TestObjectWithMultipleFields {
+ @SuppressWarnings("unused")
+ private final TestObject one;
+ @SuppressWarnings("unused")
+ private final TestObject two;
+ @SuppressWarnings("unused")
+ private final TestObject three;
+
+ TestObjectWithMultipleFields(final int one, final int two, final int three) {
+ this.one = new TestObject(one);
+ this.two = new TestObject(two);
+ this.three = new TestObject(three);
+ }
+ }
+
+ /**
+ * Test cyclical object references which cause a StackOverflowException if
+ * not handled properly. s. LANG-606
+ */
+ @Test
+ public void testCyclicalObjectReferences() {
+ final TestObjectReference refX1 = new TestObjectReference(1);
+ final TestObjectReference x1 = new TestObjectReference(1);
+ x1.setObjectReference(refX1);
+ refX1.setObjectReference(x1);
+
+ final TestObjectReference refX2 = new TestObjectReference(1);
+ final TestObjectReference x2 = new TestObjectReference(1);
+ x2.setObjectReference(refX2);
+ refX2.setObjectReference(x2);
+
+ final TestObjectReference refX3 = new TestObjectReference(2);
+ final TestObjectReference x3 = new TestObjectReference(2);
+ x3.setObjectReference(refX3);
+ refX3.setObjectReference(x3);
+
+ assertEquals(x1, x2);
+ assertNull(EqualsBuilder.getRegistry());
+ assertNotEquals(x1, x3);
+ assertNull(EqualsBuilder.getRegistry());
+ assertNotEquals(x2, x3);
+ assertNull(EqualsBuilder.getRegistry());
+ }
+
+ static class TestObjectReference {
+ @SuppressWarnings("unused")
+ private TestObjectReference reference;
+ @SuppressWarnings("unused")
+ private final TestObject one;
+
+ TestObjectReference(final int one) {
+ this.one = new TestObject(one);
+ }
+
+ public void setObjectReference(final TestObjectReference reference) {
+ this.reference = reference;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return EqualsBuilder.reflectionEquals(this, obj);
+ }
+ }
+
+ @Test
+ public void testReflectionArrays() {
+
+ final TestObject one = new TestObject(1);
+ final TestObject two = new TestObject(2);
+
+ final Object[] o1 = {one};
+ final Object[] o2 = {two};
+ final Object[] o3 = {one};
+
+ assertFalse(EqualsBuilder.reflectionEquals(o1, o2));
+ assertTrue(EqualsBuilder.reflectionEquals(o1, o1));
+ assertTrue(EqualsBuilder.reflectionEquals(o1, o3));
+
+ final double[] d1 = {0, 1};
+ final double[] d2 = {2, 3};
+ final double[] d3 = {0, 1};
+
+ assertFalse(EqualsBuilder.reflectionEquals(d1, d2));
+ assertTrue(EqualsBuilder.reflectionEquals(d1, d1));
+ assertTrue(EqualsBuilder.reflectionEquals(d1, d3));
+ }
+
+ static class TestObjectEqualsExclude {
+ @EqualsExclude
+ private final int a;
+ private final int b;
+
+ TestObjectEqualsExclude(final int a, final int b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ public int getA() {
+ return a;
+ }
+
+ public int getB() {
+ return b;
+ }
+ }
+
+ @Test
+ public void testToEqualsExclude() {
+ TestObjectEqualsExclude one = new TestObjectEqualsExclude(1, 2);
+ TestObjectEqualsExclude two = new TestObjectEqualsExclude(1, 3);
+
+ assertFalse(EqualsBuilder.reflectionEquals(one, two));
+
+ one = new TestObjectEqualsExclude(1, 2);
+ two = new TestObjectEqualsExclude(2, 2);
+
+ assertTrue(EqualsBuilder.reflectionEquals(one, two));
+ }
+
+ @Test
+ public void testReflectionAppend() {
+ assertTrue(EqualsBuilder.reflectionEquals(null, null));
+
+ final TestObject o1 = new TestObject(4);
+ final TestObject o2 = new TestObject(5);
+ assertTrue(new EqualsBuilder().reflectionAppend(o1, o1).build());
+ assertFalse(new EqualsBuilder().reflectionAppend(o1, o2).build());
+
+ o2.setA(4);
+ assertTrue(new EqualsBuilder().reflectionAppend(o1, o2).build());
+
+ assertFalse(new EqualsBuilder().reflectionAppend(o1, this).build());
+
+ assertFalse(new EqualsBuilder().reflectionAppend(o1, null).build());
+ assertFalse(new EqualsBuilder().reflectionAppend(null, o2).build());
+ }
+
+ @Test
+ public void testIsRegistered() throws Exception {
+ final Object firstObject = new Object();
+ final Object secondObject = new Object();
+
+ try {
+ final Method registerMethod = MethodUtils.getMatchingMethod(EqualsBuilder.class, "register", Object.class, Object.class);
+ registerMethod.setAccessible(true);
+ registerMethod.invoke(null, firstObject, secondObject);
+
+ assertTrue(EqualsBuilder.isRegistered(firstObject, secondObject));
+ assertTrue(EqualsBuilder.isRegistered(secondObject, firstObject)); // LANG-1349
+ } finally {
+ final Method unregisterMethod = MethodUtils.getMatchingMethod(EqualsBuilder.class, "unregister", Object.class, Object.class);
+ unregisterMethod.setAccessible(true);
+ unregisterMethod.invoke(null, firstObject, secondObject);
+ }
+ }
+}
+