View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.lang3.builder;
19  
20  import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
21  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertNotEquals;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import org.apache.commons.lang3.AbstractLangTest;
27  import org.junit.jupiter.api.Test;
28  
29  /**
30   * Tests {@link org.apache.commons.lang3.builder.HashCodeBuilder}.
31   */
32  class HashCodeBuilderTest extends AbstractLangTest {
33  
34      /**
35       * A reflection test fixture.
36       */
37      static class ReflectionTestCycleA {
38          ReflectionTestCycleB b;
39  
40          @Override
41          public boolean equals(final Object o) {
42              // Pairs with hashCode()
43              return super.equals(o);
44          }
45  
46          @Override
47          public int hashCode() {
48              return HashCodeBuilder.reflectionHashCode(this);
49          }
50      }
51  
52      /**
53       * A reflection test fixture.
54       */
55      static class ReflectionTestCycleB {
56          ReflectionTestCycleA a;
57  
58          @Override
59          public boolean equals(final Object o) {
60              // Pairs with hashCode()
61              return super.equals(o);
62          }
63  
64          @Override
65          public int hashCode() {
66              return HashCodeBuilder.reflectionHashCode(this);
67          }
68      }
69  
70      static class TestObject {
71          private int a;
72  
73          TestObject(final int a) {
74              this.a = a;
75          }
76  
77          @Override
78          public boolean equals(final Object o) {
79              if (o == this) {
80                  return true;
81              }
82              if (!(o instanceof TestObject)) {
83                  return false;
84              }
85              final TestObject rhs = (TestObject) o;
86              return a == rhs.a;
87          }
88  
89          public int getA() {
90              return a;
91          }
92  
93          @Override
94          public int hashCode() {
95              return a;
96          }
97  
98          public void setA(final int a) {
99              this.a = a;
100         }
101     }
102 
103     static class TestObjectHashCodeExclude {
104         @HashCodeExclude
105         private final int a;
106         private final int b;
107 
108         TestObjectHashCodeExclude(final int a, final int b) {
109             this.a = a;
110             this.b = b;
111         }
112 
113         public int getA() {
114             return a;
115         }
116 
117         public int getB() {
118             return b;
119         }
120     }
121 
122     static class TestObjectHashCodeExclude2 {
123         @HashCodeExclude
124         private final int a;
125         @HashCodeExclude
126         private final int b;
127 
128         TestObjectHashCodeExclude2(final int a, final int b) {
129             this.a = a;
130             this.b = b;
131         }
132 
133         public int getA() {
134             return a;
135         }
136 
137         public int getB() {
138             return b;
139         }
140     }
141 
142     static class TestObjectWithMultipleFields {
143         @SuppressWarnings("unused")
144         private final int one;
145 
146         @SuppressWarnings("unused")
147         private final int two;
148 
149         @SuppressWarnings("unused")
150         private final int three;
151 
152         TestObjectWithMultipleFields(final int one, final int two, final int three) {
153             this.one = one;
154             this.two = two;
155             this.three = three;
156         }
157     }
158 
159     static class TestSubObject extends TestObject {
160         private int b;
161 
162         @SuppressWarnings("unused")
163         private transient int t;
164 
165         TestSubObject() {
166             super(0);
167         }
168 
169         TestSubObject(final int a, final int b, final int t) {
170             super(a);
171             this.b = b;
172             this.t = t;
173         }
174 
175         @Override
176         public boolean equals(final Object o) {
177             if (o == this) {
178                 return true;
179             }
180             if (!(o instanceof TestSubObject)) {
181                 return false;
182             }
183             final TestSubObject rhs = (TestSubObject) o;
184             return super.equals(o) && b == rhs.b;
185         }
186 
187         @Override
188         public int hashCode() {
189             return b * 17 + super.hashCode();
190         }
191 
192     }
193 
194     @Test
195     void testBoolean() {
196         assertEquals(17 * 37 + 0, new HashCodeBuilder(17, 37).append(true).toHashCode());
197         assertEquals(17 * 37 + 1, new HashCodeBuilder(17, 37).append(false).toHashCode());
198     }
199 
200     @Test
201     void testBooleanArray() {
202         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((boolean[]) null).toHashCode());
203         final boolean[] obj = new boolean[2];
204         assertEquals((17 * 37 + 1) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
205         obj[0] = true;
206         assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
207         obj[1] = false;
208         assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
209     }
210 
211     @Test
212     void testBooleanArrayAsObject() {
213         final boolean[] obj = new boolean[2];
214         assertEquals((17 * 37 + 1) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
215         obj[0] = true;
216         assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
217         obj[1] = false;
218         assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
219     }
220 
221     @Test
222     void testBooleanMultiArray() {
223         final boolean[][] obj = new boolean[2][];
224         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
225         obj[0] = new boolean[0];
226         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
227         obj[0] = new boolean[1];
228         assertEquals((17 * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
229         obj[0] = new boolean[2];
230         assertEquals(((17 * 37 + 1) * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
231         obj[0][0] = true;
232         assertEquals(((17 * 37 + 0) * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
233         obj[1] = new boolean[1];
234         assertEquals(((17 * 37 + 0) * 37 + 1) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
235     }
236 
237     @Test
238     void testByte() {
239         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((byte) 0).toHashCode());
240         assertEquals(17 * 37 + 123, new HashCodeBuilder(17, 37).append((byte) 123).toHashCode());
241     }
242 
243     @Test
244     void testByteArray() {
245         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((byte[]) null).toHashCode());
246         final byte[] obj = new byte[2];
247         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
248         obj[0] = (byte) 5;
249         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
250         obj[1] = (byte) 6;
251         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
252     }
253 
254     @Test
255     void testByteArrayAsObject() {
256         final byte[] obj = new byte[2];
257         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
258         obj[0] = (byte) 5;
259         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
260         obj[1] = (byte) 6;
261         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
262     }
263 
264     @Test
265     void testChar() {
266         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((char) 0).toHashCode());
267         assertEquals(17 * 37 + 1234, new HashCodeBuilder(17, 37).append((char) 1234).toHashCode());
268     }
269 
270     @Test
271     void testCharArray() {
272         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((char[]) null).toHashCode());
273         final char[] obj = new char[2];
274         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
275         obj[0] = (char) 5;
276         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
277         obj[1] = (char) 6;
278         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
279     }
280 
281     @Test
282     void testCharArrayAsObject() {
283         final char[] obj = new char[2];
284         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
285         obj[0] = (char) 5;
286         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
287         obj[1] = (char) 6;
288         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
289     }
290 
291     @Test
292     void testConstructorExEvenFirst() {
293         assertIllegalArgumentException(() -> new HashCodeBuilder(2, 3));
294     }
295 
296     @Test
297     void testConstructorExEvenNegative() {
298         assertIllegalArgumentException(() -> new HashCodeBuilder(-2, -2));
299     }
300 
301     @Test
302     void testConstructorExEvenSecond() {
303         assertIllegalArgumentException(() -> new HashCodeBuilder(3, 2));
304     }
305 
306     @Test
307     void testConstructorExZero() {
308         assertIllegalArgumentException(() -> new HashCodeBuilder(0, 0));
309     }
310 
311     @Test
312     void testDouble() {
313         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(0d).toHashCode());
314         final double d = 1234567.89;
315         final long l = Double.doubleToLongBits(d);
316         assertEquals(17 * 37 + (int) (l ^ l >> 32), new HashCodeBuilder(17, 37).append(d).toHashCode());
317     }
318 
319     @Test
320     void testDoubleArray() {
321         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((double[]) null).toHashCode());
322         final double[] obj = new double[2];
323         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
324         obj[0] = 5.4d;
325         final long l1 = Double.doubleToLongBits(5.4d);
326         final int h1 = (int) (l1 ^ l1 >> 32);
327         assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
328         obj[1] = 6.3d;
329         final long l2 = Double.doubleToLongBits(6.3d);
330         final int h2 = (int) (l2 ^ l2 >> 32);
331         assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
332     }
333 
334     @Test
335     void testDoubleArrayAsObject() {
336         final double[] obj = new double[2];
337         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
338         obj[0] = 5.4d;
339         final long l1 = Double.doubleToLongBits(5.4d);
340         final int h1 = (int) (l1 ^ l1 >> 32);
341         assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
342         obj[1] = 6.3d;
343         final long l2 = Double.doubleToLongBits(6.3d);
344         final int h2 = (int) (l2 ^ l2 >> 32);
345         assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
346     }
347 
348     @Test
349     void testEquals() {
350         final HashCodeBuilder hcb1 = new HashCodeBuilder(17, 37).append(1).append('a');
351         final HashCodeBuilder hcb2 = new HashCodeBuilder(17, 37).append(1).append('a');
352         final HashCodeBuilder hcb3 = new HashCodeBuilder(17, 37).append(2).append('c');
353         assertEquals(hcb1, hcb1);
354         assertEquals(hcb1, hcb2);
355         assertEquals(hcb2, hcb1);
356         assertNotEquals(hcb1, hcb3);
357         assertNotEquals(hcb2, hcb3);
358     }
359 
360     @Test
361     void testFloat() {
362         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(0f).toHashCode());
363         final float f = 1234.89f;
364         final int i = Float.floatToIntBits(f);
365         assertEquals(17 * 37 + i, new HashCodeBuilder(17, 37).append(f).toHashCode());
366     }
367 
368     @Test
369     void testFloatArray() {
370         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((float[]) null).toHashCode());
371         final float[] obj = new float[2];
372         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
373         obj[0] = 5.4f;
374         final int h1 = Float.floatToIntBits(5.4f);
375         assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
376         obj[1] = 6.3f;
377         final int h2 = Float.floatToIntBits(6.3f);
378         assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
379     }
380 
381     @Test
382     void testFloatArrayAsObject() {
383         final float[] obj = new float[2];
384         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
385         obj[0] = 5.4f;
386         final int h1 = Float.floatToIntBits(5.4f);
387         assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
388         obj[1] = 6.3f;
389         final int h2 = Float.floatToIntBits(6.3f);
390         assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
391     }
392 
393     @Test
394     void testInt() {
395         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(0).toHashCode());
396         assertEquals(17 * 37 + 123456, new HashCodeBuilder(17, 37).append(123456).toHashCode());
397     }
398 
399     @Test
400     void testIntArray() {
401         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((int[]) null).toHashCode());
402         final int[] obj = new int[2];
403         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
404         obj[0] = 5;
405         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
406         obj[1] = 6;
407         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
408     }
409 
410     @Test
411     void testIntArrayAsObject() {
412         final int[] obj = new int[2];
413         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
414         obj[0] = 5;
415         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
416         obj[1] = 6;
417         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
418     }
419 
420     @Test
421     void testLong() {
422         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(0L).toHashCode());
423         assertEquals(17 * 37 + (int) (123456789L ^ 123456789L >> 32), new HashCodeBuilder(17, 37).append(
424                 123456789L).toHashCode());
425     }
426 
427     @Test
428     void testLongArray() {
429         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((long[]) null).toHashCode());
430         final long[] obj = new long[2];
431         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
432         obj[0] = 5L;
433         final int h1 = (int) (5L ^ 5L >> 32);
434         assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
435         obj[1] = 6L;
436         final int h2 = (int) (6L ^ 6L >> 32);
437         assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
438     }
439 
440     @Test
441     void testLongArrayAsObject() {
442         final long[] obj = new long[2];
443         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
444         obj[0] = 5L;
445         final int h1 = (int) (5L ^ 5L >> 32);
446         assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
447         obj[1] = 6L;
448         final int h2 = (int) (6L ^ 6L >> 32);
449         assertEquals((17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
450     }
451 
452     @Test
453     void testObject() {
454         Object obj = null;
455         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
456         obj = new Object();
457         assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).toHashCode());
458     }
459 
460     @Test
461     void testObjectArray() {
462         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((Object[]) null).toHashCode());
463         final Object[] obj = new Object[2];
464         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
465         obj[0] = new Object();
466         assertEquals((17 * 37 + obj[0].hashCode()) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
467         obj[1] = new Object();
468         assertEquals((17 * 37 + obj[0].hashCode()) * 37 + obj[1].hashCode(), new HashCodeBuilder(17, 37).append(obj)
469                 .toHashCode());
470     }
471 
472     @Test
473     void testObjectArrayAsObject() {
474         final Object[] obj = new Object[2];
475         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
476         obj[0] = new Object();
477         assertEquals((17 * 37 + obj[0].hashCode()) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
478         obj[1] = new Object();
479         assertEquals((17 * 37 + obj[0].hashCode()) * 37 + obj[1].hashCode(), new HashCodeBuilder(17, 37).append(
480                 (Object) obj).toHashCode());
481     }
482 
483     @Test
484     void testObjectBuild() {
485         Object obj = null;
486         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).build().intValue());
487         obj = new Object();
488         assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).build().intValue());
489     }
490 
491     @Test
492     void testReflectionHashCode() {
493         assertEquals(17 * 37, HashCodeBuilder.reflectionHashCode(new TestObject(0)));
494         assertEquals(17 * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestObject(123456)));
495     }
496 
497     @Test
498     void testReflectionHashCodeEx1() {
499         assertIllegalArgumentException(() -> HashCodeBuilder.reflectionHashCode(0, 0, new TestObject(0), true));
500     }
501 
502     @Test
503     void testReflectionHashCodeEx2() {
504         assertIllegalArgumentException(() -> HashCodeBuilder.reflectionHashCode(2, 2, new TestObject(0), true));
505     }
506 
507     @Test
508     void testReflectionHashCodeEx3() {
509         assertNullPointerException(() -> HashCodeBuilder.reflectionHashCode(13, 19, null, true));
510     }
511 
512     @Test
513     void testReflectionHashCodeExcludeFields() {
514         final TestObjectWithMultipleFields x = new TestObjectWithMultipleFields(1, 2, 3);
515 
516         assertEquals(((17 * 37 + 1) * 37 + 3) * 37 + 2, HashCodeBuilder.reflectionHashCode(x));
517 
518         assertEquals(((17 * 37 + 1) * 37 + 3) * 37 + 2, HashCodeBuilder.reflectionHashCode(x, (String[]) null));
519         assertEquals(((17 * 37 + 1) * 37 + 3) * 37 + 2, HashCodeBuilder.reflectionHashCode(x));
520         assertEquals(((17 * 37 + 1) * 37 + 3) * 37 + 2, HashCodeBuilder.reflectionHashCode(x, "xxx"));
521 
522         assertEquals((17 * 37 + 1) * 37 + 3, HashCodeBuilder.reflectionHashCode(x, "two"));
523         assertEquals((17 * 37 + 1) * 37 + 2, HashCodeBuilder.reflectionHashCode(x, "three"));
524 
525         assertEquals(17 * 37 + 1, HashCodeBuilder.reflectionHashCode(x, "two", "three"));
526 
527         assertEquals(17, HashCodeBuilder.reflectionHashCode(x, "one", "two", "three"));
528         assertEquals(17, HashCodeBuilder.reflectionHashCode(x, "one", "two", "three", "xxx"));
529     }
530 
531     @Test
532     void testReflectionHierarchyHashCode() {
533         assertEquals(17 * 37 * 37, HashCodeBuilder.reflectionHashCode(new TestSubObject(0, 0, 0)));
534         assertEquals(17 * 37 * 37 * 37, HashCodeBuilder.reflectionHashCode(new TestSubObject(0, 0, 0), true));
535         assertEquals((17 * 37 + 7890) * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestSubObject(123456, 7890,
536                 0)));
537         assertEquals(((17 * 37 + 7890) * 37 + 0) * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestSubObject(
538                 123456, 7890, 0), true));
539     }
540 
541     @Test
542     void testReflectionHierarchyHashCodeEx1() {
543         assertIllegalArgumentException(() -> HashCodeBuilder.reflectionHashCode(0, 0, new TestSubObject(0, 0, 0), true));
544     }
545 
546     @Test
547     void testReflectionHierarchyHashCodeEx2() {
548         assertIllegalArgumentException(() -> HashCodeBuilder.reflectionHashCode(2, 2, new TestSubObject(0, 0, 0), true));
549     }
550 
551     /**
552      * Test Objects pointing to each other.
553      */
554     @Test
555     void testReflectionObjectCycle() {
556         final ReflectionTestCycleA a = new ReflectionTestCycleA();
557         final ReflectionTestCycleB b = new ReflectionTestCycleB();
558         a.b = b;
559         b.a = a;
560 
561         // Used to caused:
562         // java.lang.StackOverflowError
563         // at java.lang.ClassLoader.getCallerClassLoader(Native Method)
564         // at java.lang.Class.getDeclaredFields(Class.java:992)
565         // at org.apache.commons.lang.builder.HashCodeBuilder.reflectionAppend(HashCodeBuilder.java:373)
566         // at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:349)
567         // at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:155)
568         // at
569         // org.apache.commons.lang.builder.HashCodeBuilderTest$ReflectionTestCycleB.hashCode(HashCodeBuilderTest.java:53)
570         // at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:422)
571         // at org.apache.commons.lang.builder.HashCodeBuilder.reflectionAppend(HashCodeBuilder.java:383)
572         // at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:349)
573         // at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:155)
574         // at
575         // org.apache.commons.lang.builder.HashCodeBuilderTest$ReflectionTestCycleA.hashCode(HashCodeBuilderTest.java:42)
576         // at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:422)
577 
578         a.hashCode();
579         assertTrue(HashCodeBuilder.getRegistry().isEmpty());
580         b.hashCode();
581         assertTrue(HashCodeBuilder.getRegistry().isEmpty());
582     }
583 
584     @Test
585     void testShort() {
586         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((short) 0).toHashCode());
587         assertEquals(17 * 37 + 12345, new HashCodeBuilder(17, 37).append((short) 12345).toHashCode());
588     }
589 
590     @Test
591     void testShortArray() {
592         assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((short[]) null).toHashCode());
593         final short[] obj = new short[2];
594         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
595         obj[0] = (short) 5;
596         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
597         obj[1] = (short) 6;
598         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
599     }
600 
601     @Test
602     void testShortArrayAsObject() {
603         final short[] obj = new short[2];
604         assertEquals(17 * 37 * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
605         obj[0] = (short) 5;
606         assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
607         obj[1] = (short) 6;
608         assertEquals((17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
609     }
610 
611     @Test
612     void testSuper() {
613         final Object obj = new Object();
614         assertEquals(17 * 37 + 19 * 41 + obj.hashCode(), new HashCodeBuilder(17, 37).appendSuper(
615                 new HashCodeBuilder(19, 41).append(obj).toHashCode()).toHashCode());
616     }
617 
618     /**
619      * Ensures LANG-520 remains true
620      */
621     @Test
622     void testToHashCodeEqualsHashCode() {
623         final HashCodeBuilder hcb = new HashCodeBuilder(17, 37).append(new Object()).append('a');
624         assertEquals(hcb.toHashCode(), hcb.hashCode(),
625             "hashCode() is no longer returning the same value as toHashCode() - see LANG-520");
626     }
627 
628     @Test
629     void testToHashCodeExclude() {
630         final TestObjectHashCodeExclude one = new TestObjectHashCodeExclude(1, 2);
631         final TestObjectHashCodeExclude2 two = new TestObjectHashCodeExclude2(1, 2);
632         assertEquals(17 * 37 + 2, HashCodeBuilder.reflectionHashCode(one));
633         assertEquals(17, HashCodeBuilder.reflectionHashCode(two));
634     }
635 
636 }