1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.javafx.scene; 27 28 import static org.junit.Assert.fail; 29 import javafx.geometry.BoundingBox; 30 import javafx.geometry.Bounds; 31 import javafx.geometry.Point2D; 32 import javafx.geometry.Rectangle2D; 33 import javafx.scene.paint.Color; 34 35 import org.junit.Test; 36 37 38 39 /** 40 * Tests equals and hashCode for those classes that override equals. The 41 * purpose of these tests is to ensure that we honor the contract of 42 * hashCode and equals. Namely, that two objects for which .equals() returns 43 * true must have the same hashCode. 44 */ 45 public class HashCodeTest { 46 47 private static final boolean VERBOSE = false; 48 49 50 void checkEqualsAndHashCode(Object o1, Object o2, boolean isEqual, boolean isNaN) { 51 52 int o1Hash = o1.hashCode(); 53 int o2Hash = o2.hashCode(); 54 boolean o1EqualsO2 = o1.equals(o2); 55 StringBuffer errMsg = new StringBuffer(); 56 57 if (o1EqualsO2 == isEqual) { 58 if (o1EqualsO2 && (o1Hash != o2Hash)) { 59 errMsg.append("ERROR: Equal objects have different hashCode"); 60 errMsg.append("\n o1 = ").append(o1); 61 errMsg.append("\n o2 = ").append(o2); 62 63 errMsg.append("\n o1.hashCode() = ").append(Integer.toHexString(o1Hash)).append(", o2.hashCode() = ").append(Integer.toHexString(o2Hash)); 64 fail(errMsg.toString()); 65 } 66 else if ((!o1EqualsO2) && (o1Hash == o2Hash)) { 67 if (isNaN) { 68 if (VERBOSE) { 69 System.out.println("Non-equal objects with NaN have same hashCode (as expected)"); 70 System.out.println("o1 = " + o1); 71 System.out.println("o2 = " + o2); 72 System.out.println("o1.hashCode() = " + Integer.toHexString(o1Hash) + 73 ", o2.hashCode() = " + 74 Integer.toHexString(o2Hash)); 75 System.out.println(""); 76 } 77 } 78 else { 79 errMsg.append("Warning: Non-equal objects have same hashCode"); 80 errMsg.append("\n o1 = ").append(o1); 81 errMsg.append("\n o2 = ").append(o2); 82 83 errMsg.append("\n o1.hashCode() = ").append(Integer.toHexString(o1Hash)).append(", o2.hashCode() = ").append(Integer.toHexString(o2Hash)); 84 fail(errMsg.toString()); 85 } 86 } 87 else if (VERBOSE) { 88 System.out.println("SUCCESS:"); 89 System.out.println("o1 = " + o1); 90 System.out.println("o2 = " + o2); 91 System.out.println("o1.equals(o2) = " + o1EqualsO2 + ", expected: " + isEqual); 92 System.out.println("o1.hashCode() = " + Integer.toHexString(o1Hash) + 93 ", o2.hashCode() = " + Integer.toHexString(o2Hash)); 94 System.out.println(""); 95 } 96 } 97 else { 98 errMsg.append("ERROR: o1.equals(o2) incorrect"); 99 errMsg.append("\n o1 = ").append(o1); 100 errMsg.append("\n o2 = ").append(o2); 101 errMsg.append("\n o1.equals(o2) = ").append(o1EqualsO2).append(", expected: ").append(isEqual); 102 errMsg.append("\n o1.hashCode() = ").append(Integer.toHexString(o1Hash)).append(", o2.hashCode() = ").append(Integer.toHexString(o2Hash)); 103 fail(errMsg.toString()); 104 } 105 } 106 107 @Test 108 public void testRectangleHash() { 109 Rectangle2D r1 = new Rectangle2D(0,0,0,0); 110 Rectangle2D r2 = new Rectangle2D(0,0,0,0); 111 checkEqualsAndHashCode(r1, r2, true, false); 112 113 r1 = new Rectangle2D(1,2,3,4); 114 r2 = new Rectangle2D(1,2,3,4); 115 checkEqualsAndHashCode(r1, r2, true, false); 116 117 r1 = new Rectangle2D(0,1,0,0); 118 r2 = new Rectangle2D(1,0,0,0); 119 checkEqualsAndHashCode(r1, r2, false, false); 120 121 r1 = new Rectangle2D(0.0f,1,0,0); 122 r2 = new Rectangle2D(0.0f,1,0,0); 123 checkEqualsAndHashCode(r1, r2, true, false); 124 125 // Cannot test -0 versus +0 due to RT-xxxx 126 /* 127 r1 = Rectangle2D(0.0 minY:1 width:0 height:0 } 128 r2 = Rectangle2D(-0.0 minY:1 width:0 height:0 } 129 checkEqualsAndHashCode(r1, r2, true, false); 130 */ 131 132 r1 = new Rectangle2D(1.0f,Float.POSITIVE_INFINITY, 0.0f, 0.0f); 133 r2 = new Rectangle2D(Float.POSITIVE_INFINITY, 1.0f, 0.0f, 0.0f); 134 checkEqualsAndHashCode(r1, r2, false, false); 135 136 r1 = new Rectangle2D(Float.POSITIVE_INFINITY, 1.0f, 0.0f, 0.0f); 137 r2 = new Rectangle2D(Float.POSITIVE_INFINITY, 1.0f, 0.0f, 0.0f); 138 checkEqualsAndHashCode(r1, r2, true, false); 139 140 r1 = new Rectangle2D(1.0f, Float.POSITIVE_INFINITY, 0.0f, 0.0f); 141 r2 = new Rectangle2D(1.0f, Float.POSITIVE_INFINITY, 0.0f, 0.0f); 142 checkEqualsAndHashCode(r1, r2, true, false); 143 144 r1 = new Rectangle2D(Float.NaN, 1.0f, 0.0f, 0.0f); 145 r2 = new Rectangle2D(Float.NaN, 1.0f, 0.0f, 0.0f); 146 checkEqualsAndHashCode(r1, r2, false, true); 147 148 r1 = new Rectangle2D(1.0f, Float.NaN, 0.0f, 0.0f); 149 r2 = new Rectangle2D(1.0f, Float.NaN, 0.0f, 0.0f); 150 checkEqualsAndHashCode(r1, r2, false, true); 151 } 152 153 @Test 154 public void testPointHash() { 155 Point2D p1 = new Point2D(0,0); 156 Point2D p2 = new Point2D(0,0); 157 checkEqualsAndHashCode(p1, p2, true, false); 158 159 p1 = new Point2D(1, 2); 160 p2 = new Point2D(1, 2); 161 checkEqualsAndHashCode(p1, p2, true, false); 162 163 p1 = new Point2D(0, 1); 164 p2 = new Point2D(1, 0); 165 checkEqualsAndHashCode(p1, p2, false, false); 166 167 p1 = new Point2D(1, 0.0f); 168 p2 = new Point2D(1, 0.0f); 169 checkEqualsAndHashCode(p1, p2, true, false); 170 171 // Cannot test -0 versus +0 due to RT-xxxx 172 173 //p1 = Point2D { x:1 y:-0.0 } 174 //p2 = Point2D { x:1 y:0.0 } 175 //checkEqualsAndHashCode(p1, p2, true, false); 176 } 177 178 @Test 179 public void testBoundingBoxHash() { 180 Bounds b1 = new BoundingBox(0,0,0,0); 181 Bounds b2 = new BoundingBox(0,0,0,0); 182 checkEqualsAndHashCode(b1, b2, true, false); 183 184 b1 = new BoundingBox(1,2,3,4); 185 b2 = new BoundingBox(1,2,3,4); 186 checkEqualsAndHashCode(b1, b2, true, false); 187 188 b1 = new BoundingBox(0,1,0,0); 189 b2 = new BoundingBox(1,0,0,0); 190 checkEqualsAndHashCode(b1, b2, false, false); 191 192 b1 = new BoundingBox(0.0f,1,0,0); 193 b2 = new BoundingBox(0.0f,1,0,0); 194 checkEqualsAndHashCode(b1, b2, true, false); 195 196 // Cannot test -0 versus +0 due to RT-xxxx 197 198 //b1 = BoundingBox(0.0 minY:1 width:0 height:0 } 199 //b2 = BoundingBox(-0.0 minY:1 width:0 height:0 } 200 //checkEqualsAndHashCode(b1, b2, true, false); 201 202 203 b1 = new BoundingBox(1.0f, Float.POSITIVE_INFINITY,0.0f,0.0f); 204 b2 = new BoundingBox(Float.POSITIVE_INFINITY, 1.0f, 0.0f, 0.0f); 205 checkEqualsAndHashCode(b1, b2, false, false); 206 207 b1 = new BoundingBox(Float.POSITIVE_INFINITY, 1.0f, 0.0f, 0.0f); 208 b2 = new BoundingBox(Float.POSITIVE_INFINITY, 1.0f, 0.0f, 0.0f); 209 checkEqualsAndHashCode(b1, b2, true, false); 210 211 b1 = new BoundingBox(1.0f, Float.POSITIVE_INFINITY, 0.0f, 0.0f); 212 b2 = new BoundingBox(1.0f, Float.POSITIVE_INFINITY, 0.0f, 0.0f); 213 checkEqualsAndHashCode(b1, b2, true, false); 214 215 b1 = new BoundingBox(Float.NaN, 1.0f, 0.0f, 0.0f); 216 b2 = new BoundingBox(Float.NaN, 1.0f, 0.0f, 0.0f); 217 checkEqualsAndHashCode(b1, b2, false, true); 218 219 b1 = new BoundingBox(1.0f, Float.NaN, 0.0f, 0.0f); 220 b2 = new BoundingBox(1.0f, Float.NaN, 0.0f, 0.0f); 221 checkEqualsAndHashCode(b1, b2, false, true); 222 } 223 224 @Test 225 public void testColorHash() { 226 Color c1 = new Color(0,0,0,1); 227 Color c2 = new Color(0,0,0,1); 228 checkEqualsAndHashCode(c1, c2, true, false); 229 230 c1 = Color.RED; 231 c2 = new Color(1.0f,0.0f,0.0f,1.0f); 232 checkEqualsAndHashCode(c1, c2, true, false); 233 234 c1 = Color.LIME; // Why LIME? Because w3c decided that GREEN is only 50% green 235 c2 = new Color(0.0f,1.0f,0.0f,1.0f); 236 checkEqualsAndHashCode(c1, c2, true, false); 237 238 c1 = Color.BLUE; 239 c2 = new Color(0.0f,0.0f,1.0f,1.0f); 240 checkEqualsAndHashCode(c1, c2, true, false); 241 242 c1 = Color.WHITE; 243 c2 = new Color(1.0f,1.0f,1.0f,1.0f); 244 checkEqualsAndHashCode(c1, c2, true, false); 245 246 c1 = Color.RED; 247 c2 = Color.color(1.0f, 0.0f, 0.0f, 1.0f); 248 checkEqualsAndHashCode(c1, c2, true, false); 249 250 c1 = Color.LIME; // Why LIME? Because w3c decided that GREEN is only 50% green 251 c2 = Color.color(0.0f, 1.0f, 0.0f, 1.0f); 252 checkEqualsAndHashCode(c1, c2, true, false); 253 254 c1 = Color.BLUE; 255 c2 = Color.color(0.0f, 0.0f, 1.0f, 1.0f); 256 checkEqualsAndHashCode(c1, c2, true, false); 257 258 c1 = Color.WHITE; 259 c2 = Color.color(1.0f, 1.0f, 1.0f, 1.0f); 260 checkEqualsAndHashCode(c1, c2, true, false); 261 262 c1 = Color.color(0.5f, 0.0f, 0.0f, 0.0f); 263 c2 = Color.color(0.5f, 0.0f, 0.0f, 0.0f); 264 checkEqualsAndHashCode(c1, c2, true, false); 265 266 c1 = Color.color(0.5f, 0.0f, 0.0f, 0.0f); 267 c2 = Color.color(0.0f, 0.5f, 0.0f, 0.0f); 268 checkEqualsAndHashCode(c1, c2, false, false); 269 270 c1 = Color.color(0.5f, 0.0f, 0.0f, 0.0f); 271 c2 = Color.color(0.0f, 0.0f, 0.5f, 0.0f); 272 checkEqualsAndHashCode(c1, c2, false, false); 273 274 c1 = Color.color(0.5f, 0.0f, 0.0f, 0.0f); 275 c2 = Color.color(0.0f, 0.0f, 0.0f, 0.5f); 276 checkEqualsAndHashCode(c1, c2, false, false); 277 278 c1 = Color.color(0.0f, 0.5f, 0.0f, 0.0f); 279 c2 = Color.color(0.0f, 0.0f, 0.5f, 0.0f); 280 checkEqualsAndHashCode(c1, c2, false, false); 281 282 c1 = Color.color(0.0f, 0.5f, 0.0f, 0.0f); 283 c2 = Color.color(0.0f, 0.0f, 0.0f, 0.5f); 284 checkEqualsAndHashCode(c1, c2, false, false); 285 286 c1 = Color.color(0.0f, 0.0f, 0.5f, 0.0f); 287 c2 = Color.color(0.0f, 0.0f, 0.0f, 0.5f); 288 checkEqualsAndHashCode(c1, c2, false, false); 289 } 290 }