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.lang.builder;
18  
19  import junit.framework.Test;
20  import junit.framework.TestCase;
21  import junit.framework.TestSuite;
22  import junit.textui.TestRunner;
23  
24  /**
25   * Tests {@link org.apache.commons.lang.builder.HashCodeBuilder} and
26   * {@link org.apache.commons.lang.builder.EqualsBuilderTest} to insure that equal
27   * objects must have equal hash codes.
28   * 
29   * @author Gary Gregory
30   * @version $Id: HashCodeBuilderAndEqualsBuilderTest.java 437554 2006-08-28 06:21:41Z bayard $
31   */
32  public class HashCodeBuilderAndEqualsBuilderTest extends TestCase {
33  
34      /**
35       * Constructor for HashCodeBuilderAndEqualsBuilderTest.
36       * @param name
37       */
38      public HashCodeBuilderAndEqualsBuilderTest(String name) {
39          super(name);
40      }
41  
42      public static void main(String[] args) {
43          TestRunner.run(suite());
44      }
45  
46      public static Test suite() {
47          TestSuite suite = new TestSuite(HashCodeBuilderAndEqualsBuilderTest.class);
48          suite.setName("HashCodeBuilderAndEqualsBuilder Tests");
49          return suite;
50      }
51  
52      protected void setUp() throws Exception {
53          super.setUp();
54      }
55  
56      protected void tearDown() throws Exception {
57          super.tearDown();
58      }
59  
60      //-----------------------------------------------------------------------
61  
62      public void testInteger(boolean testTransients) {
63          Integer i1 = new Integer(12345);
64          Integer i2 = new Integer(12345);
65          assertEqualsAndHashCodeContract(i1, i2, testTransients);
66      }
67  
68      public void testInteger() {
69          testInteger(false);
70      }
71  
72      public void testIntegerWithTransients() {
73          testInteger(true);
74      }
75  
76      public void testFixture() {
77          testFixture(false);
78      }
79  
80      public void testFixtureWithTransients() {
81          testFixture(true);
82      }
83  
84      public void testFixture(boolean testTransients) {
85          assertEqualsAndHashCodeContract(new TestFixture(2, 'c', "Test", (short) 2), new TestFixture(2, 'c', "Test", (short) 2), testTransients);
86          assertEqualsAndHashCodeContract(
87              new AllTransientFixture(2, 'c', "Test", (short) 2),
88              new AllTransientFixture(2, 'c', "Test", (short) 2),
89              testTransients);
90          assertEqualsAndHashCodeContract(
91              new SubTestFixture(2, 'c', "Test", (short) 2, "Same"),
92              new SubTestFixture(2, 'c', "Test", (short) 2, "Same"),
93              testTransients);
94          assertEqualsAndHashCodeContract(
95              new SubAllTransientFixture(2, 'c', "Test", (short) 2, "Same"),
96              new SubAllTransientFixture(2, 'c', "Test", (short) 2, "Same"),
97              testTransients);
98      }
99  
100     /**
101      * Asserts that if <code>lhs</code> equals <code>rhs</code> 
102      * then their hash codes MUST be identical.
103      * 
104      * @param lhs The Left-Hand-Side of the equals test
105      * @param rhs The Right-Hand-Side of the equals test
106      * @param testTransients wether to test transient fields
107      */
108     public void assertEqualsAndHashCodeContract(Object lhs, Object rhs, boolean testTransients) {
109         if (EqualsBuilder.reflectionEquals(lhs, rhs, testTransients)) {
110             // test a couple of times for consistency.
111             assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
112             assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
113             assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
114         }
115     }
116 
117     static class TestFixture {
118         int i;
119         char c;
120         String string;
121         short s;
122 
123         TestFixture(int i, char c, String string, short s) {
124             this.i = i;
125             this.c = c;
126             this.string = string;
127             this.s = s;
128         }
129     }
130 
131     static class SubTestFixture extends TestFixture {
132         transient String tString;
133 
134         SubTestFixture(int i, char c, String string, short s, String tString) {
135             super(i, c, string, s);
136             this.tString = tString;
137         }
138     }
139 
140     static class AllTransientFixture {
141         transient int i;
142         transient char c;
143         transient String string;
144         transient short s;
145 
146         AllTransientFixture(int i, char c, String string, short s) {
147             this.i = i;
148             this.c = c;
149             this.string = string;
150             this.s = s;
151         }
152     }
153 
154     static class SubAllTransientFixture extends AllTransientFixture {
155         transient String tString;
156 
157         SubAllTransientFixture(int i, char c, String string, short s, String tString) {
158             super(i, c, string, s);
159             this.tString = tString;
160         }
161     }
162 
163 
164 }