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  package org.apache.commons.lang3.builder;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  
21  import org.apache.commons.lang3.AbstractLangTest;
22  import org.junit.jupiter.api.Test;
23  
24  /**
25   * Tests {@link org.apache.commons.lang3.builder.HashCodeBuilder} and
26   * {@link org.apache.commons.lang3.builder.EqualsBuilderTest} to ensure that equal
27   * objects must have equal hash codes.
28   */
29  public class HashCodeBuilderAndEqualsBuilderTest extends AbstractLangTest {
30  
31  
32      static class AllTransientFixture {
33          transient int i;
34          transient char c;
35          transient String string;
36          transient short s;
37  
38          AllTransientFixture(final int i, final char c, final String string, final short s) {
39              this.i = i;
40              this.c = c;
41              this.string = string;
42              this.s = s;
43          }
44      }
45  
46      static class SubAllTransientFixture extends AllTransientFixture {
47          transient String tString;
48  
49          SubAllTransientFixture(final int i, final char c, final String string, final short s, final String tString) {
50              super(i, c, string, s);
51              this.tString = tString;
52          }
53      }
54  
55      static class SubTestFixture extends TestFixture {
56          transient String tString;
57  
58          SubTestFixture(final int i, final char c, final String string, final short s, final String tString) {
59              super(i, c, string, s);
60              this.tString = tString;
61          }
62      }
63  
64      static class TestFixture {
65          int i;
66          char c;
67          String string;
68          short s;
69  
70          TestFixture(final int i, final char c, final String string, final short s) {
71              this.i = i;
72              this.c = c;
73              this.string = string;
74              this.s = s;
75          }
76      }
77  
78      /**
79       * Asserts that if {@code lhs} equals {@code rhs}
80       * then their hash codes MUST be identical.
81       *
82       * @param lhs The Left-Hand-Side of the equals test
83       * @param rhs The Right-Hand-Side of the equals test
84       * @param testTransients whether to test transient fields
85       */
86      private void assertEqualsAndHashCodeContract(final Object lhs, final Object rhs, final boolean testTransients) {
87          if (EqualsBuilder.reflectionEquals(lhs, rhs, testTransients)) {
88              // test a couple of times for consistency.
89              assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
90              assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
91              assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
92          }
93      }
94  
95      @Test
96      public void testFixture() {
97          testFixture(false);
98      }
99  
100     private void testFixture(final boolean testTransients) {
101         assertEqualsAndHashCodeContract(new TestFixture(2, 'c', "Test", (short) 2), new TestFixture(2, 'c', "Test", (short) 2), testTransients);
102         assertEqualsAndHashCodeContract(
103             new AllTransientFixture(2, 'c', "Test", (short) 2),
104             new AllTransientFixture(2, 'c', "Test", (short) 2),
105             testTransients);
106         assertEqualsAndHashCodeContract(
107             new SubTestFixture(2, 'c', "Test", (short) 2, "Same"),
108             new SubTestFixture(2, 'c', "Test", (short) 2, "Same"),
109             testTransients);
110         assertEqualsAndHashCodeContract(
111             new SubAllTransientFixture(2, 'c', "Test", (short) 2, "Same"),
112             new SubAllTransientFixture(2, 'c', "Test", (short) 2, "Same"),
113             testTransients);
114     }
115 
116     @Test
117     public void testFixtureWithTransients() {
118         testFixture(true);
119     }
120 
121     @Test
122     public void testInteger() {
123         testInteger(false);
124     }
125 
126     private void testInteger(final boolean testTransients) {
127         final Integer i1 = Integer.valueOf(12345);
128         final Integer i2 = Integer.valueOf(12345);
129         assertEqualsAndHashCodeContract(i1, i2, testTransients);
130     }
131 
132     @Test
133     public void testIntegerWithTransients() {
134         testInteger(true);
135     }
136 
137 
138 }