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