EqualsBuilderTest.java revision 2637d96c202372854a7c71466ddcc6e90fc4fc53
1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5
6//Class comes from Apache Commons Lang, added some tiny changes
7package org.mockito.internal.matchers.apachecommons;
8
9import org.junit.Test;
10import org.mockitoutil.TestBase;
11
12import java.math.BigDecimal;
13import java.util.Arrays;
14
15import static junit.framework.TestCase.*;
16
17/**
18 * @author <a href="mailto:sdowney@panix.com">Steve Downey</a>
19 * @author <a href="mailto:scolebourne@joda.org">Stephen Colebourne</a>
20 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
21 * @author Maarten Coene
22 * @version $Id: EqualsBuilderTest.java 611543 2008-01-13 07:00:22Z bayard $
23 */
24public class EqualsBuilderTest extends TestBase {
25
26    @Test
27    public void testname() throws Exception {
28
29    }
30
31    static class TestObject {
32        private int a;
33        public TestObject() {
34        }
35        public TestObject(int a) {
36            this.a = a;
37        }
38        public boolean equals(Object o) {
39            if (o == null) { return false; }
40            if (o == this) { return true; }
41            if (o.getClass() != getClass()) {
42                return false;
43            }
44
45            TestObject rhs = (TestObject) o;
46            return (a == rhs.a);
47        }
48        public int hashCode() {
49            return super.hashCode();
50        }
51
52        public void setA(int a) {
53            this.a = a;
54        }
55
56        public int getA() {
57            return a;
58        }
59    }
60
61    static class TestSubObject extends TestObject {
62        private int b;
63        public TestSubObject() {
64            super(0);
65        }
66        public TestSubObject(int a, int b) {
67            super(a);
68            this.b = b;
69        }
70        public boolean equals(Object o) {
71            if (o == null) { return false; }
72            if (o == this) { return true; }
73            if (o.getClass() != getClass()) {
74                return false;
75            }
76
77            TestSubObject rhs = (TestSubObject) o;
78            return super.equals(o) && (b == rhs.b);
79        }
80        public int hashCode() {
81            return 1;
82        }
83
84        public void setB(int b) {
85            this.b = b;
86        }
87
88        public int getB() {
89            return b;
90        }
91    }
92
93    static class TestEmptySubObject extends TestObject {
94        public TestEmptySubObject(int a) {
95            super(a);
96        }
97    }
98
99    @SuppressWarnings("unused")
100    static class TestTSubObject extends TestObject {
101        private transient int t;
102        public TestTSubObject(int a, int t) {
103            super(a);
104            this.t = t;
105        }
106    }
107
108    @SuppressWarnings("unused")
109    static class TestTTSubObject extends TestTSubObject {
110        private transient int tt;
111        public TestTTSubObject(int a, int t, int tt) {
112            super(a, t);
113            this.tt = tt;
114        }
115    }
116
117    @SuppressWarnings("unused")
118    static class TestTTLeafObject extends TestTTSubObject {
119        private int leafValue;
120        public TestTTLeafObject(int a, int t, int tt, int leafValue) {
121            super(a, t, tt);
122            this.leafValue = leafValue;
123        }
124    }
125
126    static class TestTSubObject2 extends TestObject {
127        private transient int t;
128        public TestTSubObject2(int a, int t) {
129            super(a);
130        }
131        public int getT() {
132            return t;
133        }
134        public void setT(int t) {
135            this.t = t;
136        }
137    }
138
139    @Test public void testReflectionEquals() {
140        TestObject o1 = new TestObject(4);
141        TestObject o2 = new TestObject(5);
142        assertTrue(EqualsBuilder.reflectionEquals(o1, o1));
143        assertTrue(!EqualsBuilder.reflectionEquals(o1, o2));
144        o2.setA(4);
145        assertTrue(EqualsBuilder.reflectionEquals(o1, o2));
146
147        assertTrue(!EqualsBuilder.reflectionEquals(o1, this));
148
149        assertTrue(!EqualsBuilder.reflectionEquals(o1, null));
150        assertTrue(!EqualsBuilder.reflectionEquals(null, o2));
151        assertTrue(EqualsBuilder.reflectionEquals((Object) null, (Object) null));
152    }
153
154    @Test public void testReflectionHierarchyEquals() {
155        testReflectionHierarchyEquals(false);
156        testReflectionHierarchyEquals(true);
157        // Transients
158        assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true));
159        assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), false));
160        assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 0, 0, 4), new TestTTLeafObject(1, 2, 3, 4), true));
161        assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 0), true));
162        assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(0, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true));
163    }
164
165  private void testReflectionHierarchyEquals(boolean testTransients) {
166        TestObject to1 = new TestObject(4);
167        TestObject to1Bis = new TestObject(4);
168        TestObject to1Ter = new TestObject(4);
169        TestObject to2 = new TestObject(5);
170        TestEmptySubObject teso = new TestEmptySubObject(4);
171        TestTSubObject ttso = new TestTSubObject(4, 1);
172        TestTTSubObject tttso = new TestTTSubObject(4, 1, 2);
173        TestTTLeafObject ttlo = new TestTTLeafObject(4, 1, 2, 3);
174        TestSubObject tso1 = new TestSubObject(1, 4);
175        TestSubObject tso1bis = new TestSubObject(1, 4);
176        TestSubObject tso1ter = new TestSubObject(1, 4);
177        TestSubObject tso2 = new TestSubObject(2, 5);
178
179        testReflectionEqualsEquivalenceRelationship(to1, to1Bis, to1Ter, to2, new TestObject(), testTransients);
180        testReflectionEqualsEquivalenceRelationship(tso1, tso1bis, tso1ter, tso2, new TestSubObject(), testTransients);
181
182        // More sanity checks:
183
184        // same values
185        assertTrue(EqualsBuilder.reflectionEquals(ttlo, ttlo, testTransients));
186        assertTrue(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 10), testTransients));
187        // same super values, diff sub values
188        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 11), testTransients));
189        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 11), new TestSubObject(1, 10), testTransients));
190        // diff super values, same sub values
191        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestSubObject(1, 10), testTransients));
192        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(0, 10), testTransients));
193
194        // mix super and sub types: equals
195        assertTrue(EqualsBuilder.reflectionEquals(to1, teso, testTransients));
196        assertTrue(EqualsBuilder.reflectionEquals(teso, to1, testTransients));
197
198        assertTrue(EqualsBuilder.reflectionEquals(to1, ttso, false)); // Force testTransients = false for this assert
199        assertTrue(EqualsBuilder.reflectionEquals(ttso, to1, false)); // Force testTransients = false for this assert
200
201        assertTrue(EqualsBuilder.reflectionEquals(to1, tttso, false)); // Force testTransients = false for this assert
202        assertTrue(EqualsBuilder.reflectionEquals(tttso, to1, false)); // Force testTransients = false for this assert
203
204        assertTrue(EqualsBuilder.reflectionEquals(ttso, tttso, false)); // Force testTransients = false for this assert
205        assertTrue(EqualsBuilder.reflectionEquals(tttso, ttso, false)); // Force testTransients = false for this assert
206
207        // mix super and sub types: NOT equals
208        assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(0), new TestEmptySubObject(1), testTransients));
209        assertTrue(!EqualsBuilder.reflectionEquals(new TestEmptySubObject(1), new TestObject(0), testTransients));
210
211        assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(0), new TestTSubObject(1, 1), testTransients));
212        assertTrue(!EqualsBuilder.reflectionEquals(new TestTSubObject(1, 1), new TestObject(0), testTransients));
213
214        assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(1), new TestSubObject(0, 10), testTransients));
215        assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestObject(1), testTransients));
216
217        assertTrue(!EqualsBuilder.reflectionEquals(to1, ttlo));
218        assertTrue(!EqualsBuilder.reflectionEquals(tso1, this));
219    }
220
221    /**
222     * Equivalence relationship tests inspired by "Effective Java":
223     * <ul>
224     * <li>reflection</li>
225     * <li>symmetry</li>
226     * <li>transitive</li>
227     * <li>consistency</li>
228     * <li>non-null reference</li>
229     * </ul>
230     * @param to a TestObject
231     * @param toBis a TestObject, equal to to and toTer
232     * @param toTer Left hand side, equal to to and toBis
233     * @param to2 a different TestObject
234     * @param oToChange a TestObject that will be changed
235     */
236    private void testReflectionEqualsEquivalenceRelationship(
237        TestObject to,
238        TestObject toBis,
239        TestObject toTer,
240        TestObject to2,
241        TestObject oToChange,
242        boolean testTransients) {
243
244        // reflection test
245        assertTrue(EqualsBuilder.reflectionEquals(to, to, testTransients));
246        assertTrue(EqualsBuilder.reflectionEquals(to2, to2, testTransients));
247
248        // symmetry test
249        assertTrue(EqualsBuilder.reflectionEquals(to, toBis, testTransients) && EqualsBuilder.reflectionEquals(toBis, to, testTransients));
250
251        // transitive test
252        assertTrue(
253            EqualsBuilder.reflectionEquals(to, toBis, testTransients)
254                && EqualsBuilder.reflectionEquals(toBis, toTer, testTransients)
255                && EqualsBuilder.reflectionEquals(to, toTer, testTransients));
256
257        // consistency test
258        oToChange.setA(to.getA());
259        if (oToChange instanceof TestSubObject) {
260            ((TestSubObject) oToChange).setB(((TestSubObject) to).getB());
261        }
262        assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
263        assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
264        oToChange.setA(to.getA() + 1);
265        if (oToChange instanceof TestSubObject) {
266            ((TestSubObject) oToChange).setB(((TestSubObject) to).getB() + 1);
267        }
268        assertTrue(!EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
269        assertTrue(!EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
270
271        // non-null reference test
272        assertTrue(!EqualsBuilder.reflectionEquals(to, null, testTransients));
273        assertTrue(!EqualsBuilder.reflectionEquals(to2, null, testTransients));
274        assertTrue(!EqualsBuilder.reflectionEquals(null, to, testTransients));
275        assertTrue(!EqualsBuilder.reflectionEquals(null, to2, testTransients));
276        assertTrue(EqualsBuilder.reflectionEquals((Object) null, (Object) null, testTransients));
277    }
278
279    @Test public void testSuper() {
280        TestObject o1 = new TestObject(4);
281        TestObject o2 = new TestObject(5);
282        assertEquals(true, new EqualsBuilder().appendSuper(true).append(o1, o1).isEquals());
283        assertEquals(false, new EqualsBuilder().appendSuper(false).append(o1, o1).isEquals());
284        assertEquals(false, new EqualsBuilder().appendSuper(true).append(o1, o2).isEquals());
285        assertEquals(false, new EqualsBuilder().appendSuper(false).append(o1, o2).isEquals());
286    }
287
288    @Test public void testObject() {
289        TestObject o1 = new TestObject(4);
290        TestObject o2 = new TestObject(5);
291        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
292        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
293        o2.setA(4);
294        assertTrue(new EqualsBuilder().append(o1, o2).isEquals());
295
296        assertTrue(!new EqualsBuilder().append(o1, this).isEquals());
297
298        assertTrue(!new EqualsBuilder().append(o1, null).isEquals());
299        assertTrue(!new EqualsBuilder().append(null, o2).isEquals());
300        assertTrue(new EqualsBuilder().append((Object) null, (Object) null).isEquals());
301    }
302
303    @Test public void testLong() {
304        long o1 = 1L;
305        long o2 = 2L;
306        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
307        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
308    }
309
310    @Test public void testInt() {
311        int o1 = 1;
312        int o2 = 2;
313        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
314        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
315    }
316
317    @Test public void testShort() {
318        short o1 = 1;
319        short o2 = 2;
320        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
321        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
322    }
323
324    @Test public void testChar() {
325        char o1 = 1;
326        char o2 = 2;
327        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
328        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
329    }
330
331    @Test public void testByte() {
332        byte o1 = 1;
333        byte o2 = 2;
334        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
335        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
336    }
337
338    @Test public void testDouble() {
339        double o1 = 1;
340        double o2 = 2;
341        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
342        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
343        assertTrue(!new EqualsBuilder().append(o1, Double.NaN).isEquals());
344        assertTrue(new EqualsBuilder().append(Double.NaN, Double.NaN).isEquals());
345        assertTrue(new EqualsBuilder().append(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isEquals());
346    }
347
348    @Test public void testFloat() {
349        float o1 = 1;
350        float o2 = 2;
351        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
352        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
353        assertTrue(!new EqualsBuilder().append(o1, Float.NaN).isEquals());
354        assertTrue(new EqualsBuilder().append(Float.NaN, Float.NaN).isEquals());
355        assertTrue(new EqualsBuilder().append(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY).isEquals());
356    }
357
358    // https://issues.apache.org/jira/browse/LANG-393
359    @Test public void testBigDecimal() {
360        BigDecimal o1 = new BigDecimal("2.0");
361        BigDecimal o2 = new BigDecimal("2.00");
362        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
363        assertTrue(new EqualsBuilder().append(o1, o2).isEquals());
364    }
365
366    @Test public void testAccessors() {
367        EqualsBuilder equalsBuilder = new EqualsBuilder();
368        assertTrue(equalsBuilder.isEquals());
369        equalsBuilder.setEquals(true);
370        assertTrue(equalsBuilder.isEquals());
371        equalsBuilder.setEquals(false);
372        assertFalse(equalsBuilder.isEquals());
373    }
374
375    @Test public void testBoolean() {
376        boolean o1 = true;
377        boolean o2 = false;
378        assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
379        assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
380    }
381
382    @Test public void testObjectArray() {
383        TestObject[] obj1 = new TestObject[3];
384        obj1[0] = new TestObject(4);
385        obj1[1] = new TestObject(5);
386        obj1[2] = null;
387        TestObject[] obj2 = new TestObject[3];
388        obj2[0] = new TestObject(4);
389        obj2[1] = new TestObject(5);
390        obj2[2] = null;
391
392        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
393        assertTrue(new EqualsBuilder().append(obj2, obj2).isEquals());
394        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
395        obj1[1].setA(6);
396        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
397        obj1[1].setA(5);
398        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
399        obj1[2] = obj1[1];
400        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
401        obj1[2] = null;
402        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
403
404        obj2 = null;
405        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
406        obj1 = null;
407        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
408    }
409
410    @Test public void testLongArray() {
411        long[] obj1 = new long[2];
412        obj1[0] = 5L;
413        obj1[1] = 6L;
414        long[] obj2 = new long[2];
415        obj2[0] = 5L;
416        obj2[1] = 6L;
417        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
418        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
419        obj1[1] = 7;
420        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
421
422        obj2 = null;
423        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
424        obj1 = null;
425        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
426    }
427
428    @Test public void testIntArray() {
429        int[] obj1 = new int[2];
430        obj1[0] = 5;
431        obj1[1] = 6;
432        int[] obj2 = new int[2];
433        obj2[0] = 5;
434        obj2[1] = 6;
435        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
436        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
437        obj1[1] = 7;
438        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
439
440        obj2 = null;
441        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
442        obj1 = null;
443        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
444    }
445
446    @Test public void testShortArray() {
447        short[] obj1 = new short[2];
448        obj1[0] = 5;
449        obj1[1] = 6;
450        short[] obj2 = new short[2];
451        obj2[0] = 5;
452        obj2[1] = 6;
453        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
454        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
455        obj1[1] = 7;
456        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
457
458        obj2 = null;
459        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
460        obj1 = null;
461        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
462    }
463
464    @Test public void testCharArray() {
465        char[] obj1 = new char[2];
466        obj1[0] = 5;
467        obj1[1] = 6;
468        char[] obj2 = new char[2];
469        obj2[0] = 5;
470        obj2[1] = 6;
471        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
472        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
473        obj1[1] = 7;
474        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
475
476        obj2 = null;
477        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
478        obj1 = null;
479        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
480    }
481
482    @Test public void testByteArray() {
483        byte[] obj1 = new byte[2];
484        obj1[0] = 5;
485        obj1[1] = 6;
486        byte[] obj2 = new byte[2];
487        obj2[0] = 5;
488        obj2[1] = 6;
489        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
490        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
491        obj1[1] = 7;
492        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
493
494        obj2 = null;
495        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
496        obj1 = null;
497        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
498    }
499
500    @Test public void testDoubleArray() {
501        double[] obj1 = new double[2];
502        obj1[0] = 5;
503        obj1[1] = 6;
504        double[] obj2 = new double[2];
505        obj2[0] = 5;
506        obj2[1] = 6;
507        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
508        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
509        obj1[1] = 7;
510        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
511
512        obj2 = null;
513        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
514        obj1 = null;
515        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
516    }
517
518    @Test public void testFloatArray() {
519        float[] obj1 = new float[2];
520        obj1[0] = 5;
521        obj1[1] = 6;
522        float[] obj2 = new float[2];
523        obj2[0] = 5;
524        obj2[1] = 6;
525        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
526        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
527        obj1[1] = 7;
528        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
529
530        obj2 = null;
531        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
532        obj1 = null;
533        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
534    }
535
536    @Test public void testBooleanArray() {
537        boolean[] obj1 = new boolean[2];
538        obj1[0] = true;
539        obj1[1] = false;
540        boolean[] obj2 = new boolean[2];
541        obj2[0] = true;
542        obj2[1] = false;
543        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
544        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
545        obj1[1] = true;
546        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
547
548        obj2 = null;
549        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
550        obj1 = null;
551        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
552    }
553
554    @Test public void testMultiLongArray() {
555        long[][] array1 = new long[2][2];
556        long[][] array2 = new long[2][2];
557        for (int i = 0; i < array1.length; ++i) {
558            for (int j = 0; j < array1[0].length; j++) {
559                array1[i][j] = (i + 1) * (j + 1);
560                array2[i][j] = (i + 1) * (j + 1);
561            }
562        }
563        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
564        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
565        array1[1][1] = 0;
566        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
567    }
568
569    @Test public void testMultiIntArray() {
570        int[][] array1 = new int[2][2];
571        int[][] array2 = new int[2][2];
572        for (int i = 0; i < array1.length; ++i) {
573            for (int j = 0; j < array1[0].length; j++) {
574                array1[i][j] = (i + 1) * (j + 1);
575                array2[i][j] = (i + 1) * (j + 1);
576            }
577        }
578        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
579        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
580        array1[1][1] = 0;
581        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
582    }
583
584    @Test public void testMultiShortArray() {
585        short[][] array1 = new short[2][2];
586        short[][] array2 = new short[2][2];
587        for (short i = 0; i < array1.length; ++i) {
588            for (short j = 0; j < array1[0].length; j++) {
589                array1[i][j] = i;
590                array2[i][j] = i;
591            }
592        }
593        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
594        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
595        array1[1][1] = 0;
596        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
597    }
598
599    @Test public void testMultiCharArray() {
600        char[][] array1 = new char[2][2];
601        char[][] array2 = new char[2][2];
602        for (char i = 0; i < array1.length; ++i) {
603            for (char j = 0; j < array1[0].length; j++) {
604                array1[i][j] = i;
605                array2[i][j] = i;
606            }
607        }
608        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
609        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
610        array1[1][1] = 0;
611        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
612    }
613
614    @Test public void testMultiByteArray() {
615        byte[][] array1 = new byte[2][2];
616        byte[][] array2 = new byte[2][2];
617        for (byte i = 0; i < array1.length; ++i) {
618            for (byte j = 0; j < array1[0].length; j++) {
619                array1[i][j] = i;
620                array2[i][j] = i;
621            }
622        }
623        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
624        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
625        array1[1][1] = 0;
626        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
627    }
628    @Test public void testMultiFloatArray() {
629        float[][] array1 = new float[2][2];
630        float[][] array2 = new float[2][2];
631        for (int i = 0; i < array1.length; ++i) {
632            for (int j = 0; j < array1[0].length; j++) {
633                array1[i][j] = (i + 1) * (j + 1);
634                array2[i][j] = (i + 1) * (j + 1);
635            }
636        }
637        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
638        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
639        array1[1][1] = 0;
640        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
641    }
642
643    @Test public void testMultiDoubleArray() {
644        double[][] array1 = new double[2][2];
645        double[][] array2 = new double[2][2];
646        for (int i = 0; i < array1.length; ++i) {
647            for (int j = 0; j < array1[0].length; j++) {
648                array1[i][j] = (i + 1) * (j + 1);
649                array2[i][j] = (i + 1) * (j + 1);
650            }
651        }
652        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
653        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
654        array1[1][1] = 0;
655        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
656    }
657
658    @Test public void testMultiBooleanArray() {
659        boolean[][] array1 = new boolean[2][2];
660        boolean[][] array2 = new boolean[2][2];
661        for (int i = 0; i < array1.length; ++i) {
662            for (int j = 0; j < array1[0].length; j++) {
663                array1[i][j] = (i == 1) || (j == 1);
664                array2[i][j] = (i == 1) || (j == 1);
665            }
666        }
667        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
668        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
669        array1[1][1] = false;
670        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
671
672        // compare 1 dim to 2.
673        boolean[] array3 = new boolean[]{true, true};
674        assertFalse(new EqualsBuilder().append(array1, array3).isEquals());
675        assertFalse(new EqualsBuilder().append(array3, array1).isEquals());
676        assertFalse(new EqualsBuilder().append(array2, array3).isEquals());
677        assertFalse(new EqualsBuilder().append(array3, array2).isEquals());
678    }
679
680    @Test public void testRaggedArray() {
681        long[][] array1 = new long[2][];
682        long[][] array2 = new long[2][];
683        for (int i = 0; i < array1.length; ++i) {
684            array1[i] = new long[2];
685            array2[i] = new long[2];
686            for (int j = 0; j < array1[i].length; ++j) {
687                array1[i][j] = (i + 1) * (j + 1);
688                array2[i][j] = (i + 1) * (j + 1);
689            }
690        }
691        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
692        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
693        array1[1][1] = 0;
694        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
695    }
696
697    @Test public void testMixedArray() {
698        Object[] array1 = new Object[2];
699        Object[] array2 = new Object[2];
700        for (int i = 0; i < array1.length; ++i) {
701            array1[i] = new long[2];
702            array2[i] = new long[2];
703            for (int j = 0; j < 2; ++j) {
704                ((long[]) array1[i])[j] = (i + 1) * (j + 1);
705                ((long[]) array2[i])[j] = (i + 1) * (j + 1);
706            }
707        }
708        assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
709        assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
710        ((long[]) array1[1])[1] = 0;
711        assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
712    }
713
714    @Test public void testObjectArrayHiddenByObject() {
715        TestObject[] array1 = new TestObject[2];
716        array1[0] = new TestObject(4);
717        array1[1] = new TestObject(5);
718        TestObject[] array2 = new TestObject[2];
719        array2[0] = new TestObject(4);
720        array2[1] = new TestObject(5);
721        Object obj1 = array1;
722        Object obj2 = array2;
723        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
724        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
725        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
726        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
727        array1[1].setA(6);
728        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
729    }
730
731    @Test public void testLongArrayHiddenByObject() {
732        long[] array1 = new long[2];
733        array1[0] = 5L;
734        array1[1] = 6L;
735        long[] array2 = new long[2];
736        array2[0] = 5L;
737        array2[1] = 6L;
738        Object obj1 = array1;
739        Object obj2 = array2;
740        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
741        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
742        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
743        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
744        array1[1] = 7;
745        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
746    }
747
748    @Test public void testIntArrayHiddenByObject() {
749        int[] array1 = new int[2];
750        array1[0] = 5;
751        array1[1] = 6;
752        int[] array2 = new int[2];
753        array2[0] = 5;
754        array2[1] = 6;
755        Object obj1 = array1;
756        Object obj2 = array2;
757        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
758        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
759        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
760        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
761        array1[1] = 7;
762        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
763    }
764
765    @Test public void testShortArrayHiddenByObject() {
766        short[] array1 = new short[2];
767        array1[0] = 5;
768        array1[1] = 6;
769        short[] array2 = new short[2];
770        array2[0] = 5;
771        array2[1] = 6;
772        Object obj1 = array1;
773        Object obj2 = array2;
774        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
775        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
776        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
777        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
778        array1[1] = 7;
779        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
780    }
781
782    @Test public void testCharArrayHiddenByObject() {
783        char[] array1 = new char[2];
784        array1[0] = 5;
785        array1[1] = 6;
786        char[] array2 = new char[2];
787        array2[0] = 5;
788        array2[1] = 6;
789        Object obj1 = array1;
790        Object obj2 = array2;
791        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
792        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
793        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
794        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
795        array1[1] = 7;
796        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
797    }
798
799    @Test public void testByteArrayHiddenByObject() {
800        byte[] array1 = new byte[2];
801        array1[0] = 5;
802        array1[1] = 6;
803        byte[] array2 = new byte[2];
804        array2[0] = 5;
805        array2[1] = 6;
806        Object obj1 = array1;
807        Object obj2 = array2;
808        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
809        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
810        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
811        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
812        array1[1] = 7;
813        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
814    }
815
816    @Test public void testDoubleArrayHiddenByObject() {
817        double[] array1 = new double[2];
818        array1[0] = 5;
819        array1[1] = 6;
820        double[] array2 = new double[2];
821        array2[0] = 5;
822        array2[1] = 6;
823        Object obj1 = array1;
824        Object obj2 = array2;
825        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
826        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
827        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
828        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
829        array1[1] = 7;
830        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
831    }
832
833    @Test public void testFloatArrayHiddenByObject() {
834        float[] array1 = new float[2];
835        array1[0] = 5;
836        array1[1] = 6;
837        float[] array2 = new float[2];
838        array2[0] = 5;
839        array2[1] = 6;
840        Object obj1 = array1;
841        Object obj2 = array2;
842        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
843        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
844        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
845        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
846        array1[1] = 7;
847        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
848    }
849
850    @Test public void testBooleanArrayHiddenByObject() {
851        boolean[] array1 = new boolean[2];
852        array1[0] = true;
853        array1[1] = false;
854        boolean[] array2 = new boolean[2];
855        array2[0] = true;
856        array2[1] = false;
857        Object obj1 = array1;
858        Object obj2 = array2;
859        assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
860        assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
861        assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
862        assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
863        array1[1] = true;
864        assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
865    }
866
867    public static class TestACanEqualB {
868        private int a;
869
870        public TestACanEqualB(int a) {
871            this.a = a;
872        }
873
874        public boolean equals(Object o) {
875            if (o == this) {
876                return true;
877            }
878            if (o instanceof TestACanEqualB) {
879                return this.a == ((TestACanEqualB) o).getA();
880            }
881            if (o instanceof TestBCanEqualA) {
882                return this.a == ((TestBCanEqualA) o).getB();
883            }
884            return false;
885        }
886        public int hashCode() {
887            return 1;
888        }
889
890        public int getA() {
891            return this.a;
892        }
893    }
894
895    public static class TestBCanEqualA {
896        private int b;
897
898        public TestBCanEqualA(int b) {
899            this.b = b;
900        }
901
902        public boolean equals(Object o) {
903            if (o == this) {
904                return true;
905            }
906            if (o instanceof TestACanEqualB) {
907                return this.b == ((TestACanEqualB) o).getA();
908            }
909            if (o instanceof TestBCanEqualA) {
910                return this.b == ((TestBCanEqualA) o).getB();
911            }
912            return false;
913        }
914        public int hashCode() {
915            return 1;
916        }
917
918        public int getB() {
919            return this.b;
920        }
921    }
922
923    /**
924     * Tests two instances of classes that can be equal and that are not "related". The two classes are not subclasses
925     * of each other and do not share a parent aside from Object.
926     * See http://issues.apache.org/bugzilla/show_bug.cgi?id=33069
927     */
928    @Test public void testUnrelatedClasses() {
929        Object[] x = new Object[]{new TestACanEqualB(1)};
930        Object[] y = new Object[]{new TestBCanEqualA(1)};
931
932        // sanity checks:
933        assertTrue(Arrays.equals(x, x));
934        assertTrue(Arrays.equals(y, y));
935        assertTrue(Arrays.equals(x, y));
936        assertTrue(Arrays.equals(y, x));
937        // real tests:
938        assertTrue(x[0].equals(x[0]));
939        assertTrue(y[0].equals(y[0]));
940        assertTrue(x[0].equals(y[0]));
941        assertTrue(y[0].equals(x[0]));
942        assertTrue(new EqualsBuilder().append(x, x).isEquals());
943        assertTrue(new EqualsBuilder().append(y, y).isEquals());
944        assertTrue(new EqualsBuilder().append(x, y).isEquals());
945        assertTrue(new EqualsBuilder().append(y, x).isEquals());
946    }
947
948    /**
949     * Test from http://issues.apache.org/bugzilla/show_bug.cgi?id=33067
950     */
951    @Test public void testNpeForNullElement() {
952        Object[] x1 = new Object[] { new Integer(1), null, new Integer(3) };
953        Object[] x2 = new Object[] { new Integer(1), new Integer(2), new Integer(3) };
954
955        // causes an NPE in 2.0 according to:
956        // http://issues.apache.org/bugzilla/show_bug.cgi?id=33067
957        new EqualsBuilder().append(x1, x2);
958    }
959
960    @Test public void testReflectionEqualsExcludeFields() throws Exception {
961        TestObjectWithMultipleFields x1 = new TestObjectWithMultipleFields(1, 2, 3);
962        TestObjectWithMultipleFields x2 = new TestObjectWithMultipleFields(1, 3, 4);
963
964        // not equal when including all fields
965        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2));
966
967        // doesn't barf on null, empty array, or non-existent field, but still tests as not equal
968        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, (String[]) null));
969        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {}));
970        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {"xxx"}));
971
972        // not equal if only one of the differing fields excluded
973        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {"two"}));
974        assertTrue(!EqualsBuilder.reflectionEquals(x1, x2, new String[] {"three"}));
975
976        // equal if both differing fields excluded
977        assertTrue(EqualsBuilder.reflectionEquals(x1, x2, new String[] {"two", "three"}));
978
979        // still equal as long as both differing fields are among excluded
980        assertTrue(EqualsBuilder.reflectionEquals(x1, x2, new String[] {"one", "two", "three"}));
981        assertTrue(EqualsBuilder.reflectionEquals(x1, x2, new String[] {"one", "two", "three", "xxx"}));
982    }
983
984    @SuppressWarnings("unused")
985    static class TestObjectWithMultipleFields {
986        private TestObject one;
987        private TestObject two;
988        private TestObject three;
989
990        public TestObjectWithMultipleFields(int one, int two, int three) {
991            this.one = new TestObject(one);
992            this.two = new TestObject(two);
993            this.three = new TestObject(three);
994        }
995    }
996}
997