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.enums; 18 19 import java.lang.reflect.InvocationTargetException; 20 import java.lang.reflect.Method; 21 import java.net.URL; 22 import java.net.URLClassLoader; 23 import java.util.ArrayList; 24 import java.util.HashMap; 25 import java.util.Iterator; 26 import java.util.List; 27 import java.util.Map; 28 29 import junit.framework.AssertionFailedError; 30 import junit.framework.TestCase; 31 32 import org.apache.commons.lang.SerializationUtils; 33 34 /** 35 * Test cases for the {@link Enum} class. 36 * 37 * @author Apache Software Foundation 38 * @author Gary D. Gregory 39 * @version $Id: EnumTest.java 905636 2010-02-02 14:03:32Z niallp $ 40 */ 41 42 public final class EnumTest extends TestCase { 43 44 private static final String ENUMS_CLASS_NAME = "org.apache.commons.lang.enums.ColorEnum"; 45 EnumTest(String name)46 public EnumTest(String name) { 47 super(name); 48 } 49 setUp()50 public void setUp() { 51 } 52 testName()53 public void testName() { 54 assertEquals("Red", ColorEnum.RED.getName()); 55 assertEquals("Green", ColorEnum.GREEN.getName()); 56 assertEquals("Blue", ColorEnum.BLUE.getName()); 57 } 58 testCompareTo()59 public void testCompareTo() { 60 assertTrue(ColorEnum.BLUE.compareTo(ColorEnum.BLUE) == 0); 61 assertTrue(ColorEnum.RED.compareTo(ColorEnum.BLUE) > 0); 62 assertTrue(ColorEnum.BLUE.compareTo(ColorEnum.RED) < 0); 63 try { 64 ColorEnum.RED.compareTo(null); 65 fail(); 66 } catch (NullPointerException ex) {} 67 try { 68 ColorEnum.RED.compareTo(new Object()); 69 fail(); 70 } catch (ClassCastException ex) {} 71 } 72 73 public void testEquals() { 74 assertSame(ColorEnum.RED, ColorEnum.RED); 75 assertSame(ColorEnum.getEnum("Red"), ColorEnum.RED); 76 assertEquals(false, ColorEnum.RED.equals(null)); 77 assertEquals(true, ColorEnum.RED.equals(ColorEnum.RED)); 78 assertEquals(true, ColorEnum.RED.equals(ColorEnum.getEnum("Red"))); 79 } 80 81 public void testHashCode() { 82 assertEquals(ColorEnum.RED.hashCode(), ColorEnum.RED.hashCode()); 83 assertEquals(7 + ColorEnum.class.hashCode() + 3 * "Red".hashCode(), ColorEnum.RED.hashCode()); 84 } 85 86 public void testToString() { 87 String toString = ColorEnum.RED.toString(); 88 assertEquals("ColorEnum[Red]", toString); 89 assertSame(toString, ColorEnum.RED.toString()); 90 } 91 92 public void testIterator() { 93 Iterator it = ColorEnum.iterator(); 94 assertSame(ColorEnum.RED, it.next()); 95 assertSame(ColorEnum.GREEN, it.next()); 96 assertSame(ColorEnum.BLUE, it.next()); 97 } 98 99 public void testList() { 100 List list = new ArrayList(ColorEnum.getEnumList()); 101 102 assertNotNull(list); 103 104 assertEquals( list.size(), 105 ColorEnum.getEnumMap().keySet().size()); 106 107 Iterator it = list.iterator(); 108 assertSame(ColorEnum.RED, it.next()); 109 assertSame(ColorEnum.GREEN, it.next()); 110 assertSame(ColorEnum.BLUE, it.next()); 111 } 112 113 public void testMap() { 114 Map map = new HashMap(ColorEnum.getEnumMap()); 115 116 assertNotNull(map); 117 assertTrue(map.containsValue(ColorEnum.RED)); 118 assertTrue(map.containsValue(ColorEnum.GREEN)); 119 assertTrue(map.containsValue(ColorEnum.BLUE)); 120 assertSame(ColorEnum.RED, map.get("Red")); 121 assertSame(ColorEnum.GREEN, map.get("Green")); 122 assertSame(ColorEnum.BLUE, map.get("Blue")); 123 assertEquals( map.keySet().size(), 124 ColorEnum.getEnumList().size()); 125 } 126 127 public void testGet() { 128 assertSame(ColorEnum.RED, ColorEnum.getEnum("Red")); 129 assertSame(ColorEnum.GREEN, ColorEnum.getEnum("Green")); 130 assertSame(ColorEnum.BLUE, ColorEnum.getEnum("Blue")); 131 assertSame(null, ColorEnum.getEnum("Pink")); 132 } 133 134 public void testSerialization() { 135 int hashCode = ColorEnum.RED.hashCode(); 136 assertSame(ColorEnum.RED, SerializationUtils.clone(ColorEnum.RED)); 137 assertEquals(hashCode, SerializationUtils.clone(ColorEnum.RED).hashCode()); 138 assertSame(ColorEnum.GREEN, SerializationUtils.clone(ColorEnum.GREEN)); 139 assertSame(ColorEnum.BLUE, SerializationUtils.clone(ColorEnum.BLUE)); 140 } 141 142 public void testBroken1() { 143 try { 144 Broken1Enum.RED.getName(); 145 fail(); 146 } catch (ExceptionInInitializerError ex) { 147 assertTrue(ex.getException() instanceof IllegalArgumentException); 148 } 149 } 150 151 public void testBroken2() { 152 try { 153 Broken2Enum.RED.getName(); 154 fail(); 155 } catch (ExceptionInInitializerError ex) { 156 assertTrue(ex.getException() instanceof IllegalArgumentException); 157 } 158 } 159 160 public void testBroken3() { 161 try { 162 Broken3Enum.RED.getName(); 163 fail(); 164 } catch (ExceptionInInitializerError ex) { 165 assertTrue(ex.getException() instanceof IllegalArgumentException); 166 } 167 } 168 169 public void testBroken1Operation() { 170 try { 171 Broken1OperationEnum.PLUS.getName(); 172 fail(); 173 } catch (ExceptionInInitializerError ex) { 174 assertTrue(ex.getException() instanceof IllegalArgumentException); 175 } 176 } 177 178 public void testBroken2Operation() { 179 try { 180 Broken2OperationEnum.PLUS.getName(); 181 fail(); 182 } catch (ExceptionInInitializerError ex) { 183 assertTrue(ex.getException() instanceof IllegalArgumentException); 184 } 185 } 186 187 public void testBroken3Operation() { 188 try { 189 Broken3OperationEnum.PLUS.getName(); 190 fail(); 191 } catch (ExceptionInInitializerError ex) { 192 assertTrue(ex.getException() instanceof IllegalArgumentException); 193 } 194 } 195 196 public void testBroken4Operation() { 197 try { 198 Broken4OperationEnum.PLUS.getName(); 199 fail(); 200 } catch (ExceptionInInitializerError ex) { 201 assertTrue(ex.getException() instanceof IllegalArgumentException); 202 } 203 } 204 205 public void testBroken5Operation() { 206 try { 207 Broken5OperationEnum.PLUS.getName(); 208 fail(); 209 } catch (ExceptionInInitializerError ex) { 210 assertTrue(ex.getException() instanceof IllegalArgumentException); 211 } 212 } 213 214 public void testOperationGet() { 215 assertSame(OperationEnum.PLUS, OperationEnum.getEnum("Plus")); 216 assertSame(OperationEnum.MINUS, OperationEnum.getEnum("Minus")); 217 assertSame(null, OperationEnum.getEnum("Pink")); 218 } 219 220 public void testOperationSerialization() { 221 assertSame(OperationEnum.PLUS, SerializationUtils.clone(OperationEnum.PLUS)); 222 assertSame(OperationEnum.MINUS, SerializationUtils.clone(OperationEnum.MINUS)); 223 } 224 225 public void testOperationToString() { 226 assertEquals("OperationEnum[Plus]", OperationEnum.PLUS.toString()); 227 } 228 229 public void testOperationList() { 230 List list = OperationEnum.getEnumList(); 231 assertNotNull(list); 232 assertEquals(2, list.size()); 233 assertEquals(list.size(), OperationEnum.getEnumMap().keySet().size()); 234 235 Iterator it = list.iterator(); 236 assertSame(OperationEnum.PLUS, it.next()); 237 assertSame(OperationEnum.MINUS, it.next()); 238 } 239 240 public void testOperationMap() { 241 Map map = OperationEnum.getEnumMap(); 242 assertNotNull(map); 243 assertEquals(map.keySet().size(), OperationEnum.getEnumList().size()); 244 245 assertTrue(map.containsValue(OperationEnum.PLUS)); 246 assertTrue(map.containsValue(OperationEnum.MINUS)); 247 assertSame(OperationEnum.PLUS, map.get("Plus")); 248 assertSame(OperationEnum.MINUS, map.get("Minus")); 249 } 250 251 public void testOperationCalculation() { 252 assertEquals(3, OperationEnum.PLUS.eval(1, 2)); 253 assertEquals(-1, OperationEnum.MINUS.eval(1, 2)); 254 } 255 256 //----------------------------------------------------------------------- 257 public void testExtended1Get() { 258 assertSame(Extended1Enum.ALPHA, Extended1Enum.getEnum("Alpha")); 259 assertSame(Extended1Enum.BETA, Extended1Enum.getEnum("Beta")); 260 assertSame(null, Extended1Enum.getEnum("Gamma")); 261 assertSame(null, Extended1Enum.getEnum("Delta")); 262 } 263 264 public void testExtended2Get() { 265 assertSame(Extended1Enum.ALPHA, Extended2Enum.ALPHA); 266 assertSame(Extended1Enum.BETA, Extended2Enum.BETA); 267 268 assertSame(Extended2Enum.ALPHA, Extended2Enum.getEnum("Alpha")); 269 assertSame(Extended2Enum.BETA, Extended2Enum.getEnum("Beta")); 270 assertSame(Extended2Enum.GAMMA, Extended2Enum.getEnum("Gamma")); 271 assertSame(null, Extended2Enum.getEnum("Delta")); 272 } 273 274 public void testExtended3Get() { 275 assertSame(Extended2Enum.ALPHA, Extended3Enum.ALPHA); 276 assertSame(Extended2Enum.BETA, Extended3Enum.BETA); 277 assertSame(Extended2Enum.GAMMA, Extended3Enum.GAMMA); 278 279 assertSame(Extended3Enum.ALPHA, Extended3Enum.getEnum("Alpha")); 280 assertSame(Extended3Enum.BETA, Extended3Enum.getEnum("Beta")); 281 assertSame(Extended3Enum.GAMMA, Extended3Enum.getEnum("Gamma")); 282 assertSame(Extended3Enum.DELTA, Extended3Enum.getEnum("Delta")); 283 } 284 285 public void testExtendedSerialization() { 286 assertSame(Extended1Enum.ALPHA, SerializationUtils.clone(Extended1Enum.ALPHA)); 287 assertSame(Extended1Enum.BETA, SerializationUtils.clone(Extended1Enum.BETA)); 288 assertSame(Extended2Enum.GAMMA, SerializationUtils.clone(Extended2Enum.GAMMA)); 289 assertSame(Extended3Enum.DELTA, SerializationUtils.clone(Extended3Enum.DELTA)); 290 } 291 292 public void testExtendedToString() { 293 assertEquals("Extended1Enum[Alpha]", Extended1Enum.ALPHA.toString()); 294 assertEquals("Extended1Enum[Beta]", Extended1Enum.BETA.toString()); 295 296 assertEquals("Extended1Enum[Alpha]", Extended2Enum.ALPHA.toString()); 297 assertEquals("Extended1Enum[Beta]", Extended2Enum.BETA.toString()); 298 assertEquals("Extended2Enum[Gamma]", Extended2Enum.GAMMA.toString()); 299 300 assertEquals("Extended1Enum[Alpha]", Extended3Enum.ALPHA.toString()); 301 assertEquals("Extended1Enum[Beta]", Extended3Enum.BETA.toString()); 302 assertEquals("Extended2Enum[Gamma]", Extended3Enum.GAMMA.toString()); 303 assertEquals("Extended3Enum[Delta]", Extended3Enum.DELTA.toString()); 304 } 305 306 public void testExtended1List() { 307 List list = Extended1Enum.getEnumList(); 308 assertNotNull(list); 309 assertEquals(2, list.size()); 310 assertEquals(list.size(), Extended1Enum.getEnumMap().keySet().size()); 311 312 Iterator it = list.iterator(); 313 assertSame(Extended1Enum.ALPHA, it.next()); 314 assertSame(Extended1Enum.BETA, it.next()); 315 } 316 317 public void testExtended2List() { 318 List list = Extended2Enum.getEnumList(); 319 assertNotNull(list); 320 assertEquals(3, list.size()); 321 assertEquals(list.size(), Extended2Enum.getEnumMap().keySet().size()); 322 323 Iterator it = list.iterator(); 324 assertSame(Extended2Enum.ALPHA, it.next()); 325 assertSame(Extended2Enum.BETA, it.next()); 326 assertSame(Extended2Enum.GAMMA, it.next()); 327 } 328 329 public void testExtended3List() { 330 List list = Extended3Enum.getEnumList(); 331 assertNotNull(list); 332 assertEquals(4, list.size()); 333 assertEquals(list.size(), Extended3Enum.getEnumMap().keySet().size()); 334 335 Iterator it = list.iterator(); 336 assertSame(Extended3Enum.ALPHA, it.next()); 337 assertSame(Extended3Enum.BETA, it.next()); 338 assertSame(Extended3Enum.GAMMA, it.next()); 339 assertSame(Extended3Enum.DELTA, it.next()); 340 } 341 342 public void testExtended1Map() { 343 Map map = Extended1Enum.getEnumMap(); 344 assertNotNull(map); 345 assertEquals(map.keySet().size(), Extended1Enum.getEnumList().size()); 346 347 assertTrue(map.containsValue(Extended1Enum.ALPHA)); 348 assertTrue(map.containsValue(Extended1Enum.BETA)); 349 assertSame(Extended1Enum.ALPHA, map.get("Alpha")); 350 assertSame(Extended1Enum.BETA, map.get("Beta")); 351 } 352 353 public void testExtended2Map() { 354 Map map = Extended2Enum.getEnumMap(); 355 assertNotNull(map); 356 assertEquals(map.keySet().size(), Extended2Enum.getEnumList().size()); 357 358 assertTrue(map.containsValue(Extended2Enum.ALPHA)); 359 assertTrue(map.containsValue(Extended2Enum.BETA)); 360 assertTrue(map.containsValue(Extended2Enum.GAMMA)); 361 assertSame(Extended2Enum.ALPHA, map.get("Alpha")); 362 assertSame(Extended2Enum.BETA, map.get("Beta")); 363 assertSame(Extended2Enum.GAMMA, map.get("Gamma")); 364 } 365 366 public void testExtended3Map() { 367 Map map = Extended3Enum.getEnumMap(); 368 assertNotNull(map); 369 assertEquals(map.keySet().size(), Extended3Enum.getEnumList().size()); 370 371 assertTrue(map.containsValue(Extended3Enum.ALPHA)); 372 assertTrue(map.containsValue(Extended3Enum.BETA)); 373 assertTrue(map.containsValue(Extended3Enum.GAMMA)); 374 assertTrue(map.containsValue(Extended3Enum.DELTA)); 375 assertSame(Extended3Enum.ALPHA, map.get("Alpha")); 376 assertSame(Extended3Enum.BETA, map.get("Beta")); 377 assertSame(Extended3Enum.GAMMA, map.get("Gamma")); 378 assertSame(Extended3Enum.DELTA, map.get("Delta")); 379 } 380 381 //----------------------------------------------------------------------- 382 public void testNested() { 383 List list = new ArrayList(Nest.ColorEnum.getEnumList()); 384 assertEquals(3, list.size()); // all is well 385 Iterator it = list.iterator(); 386 assertSame(Nest.ColorEnum.RED, it.next()); 387 assertSame(Nest.ColorEnum.GREEN, it.next()); 388 assertSame(Nest.ColorEnum.BLUE, it.next()); 389 // This nesting works because the enum constants are defined in the SAME 390 // class as the getEnumList(). It just acts as a normal enum. 391 } 392 393 public void testNestedBroken() { 394 List list = new ArrayList(NestBroken.ColorEnum.getEnumList()); 395 try { 396 assertEquals(0, list.size()); // no enums!!! 397 // this is BROKEN because the enum constants are defined in a DIFFERENT 398 // class from getEnumList(). Once NestBroken class is referenced, 399 // and thus class loaded with its enum constants, the getEnumList works: 400 } catch (AssertionFailedError ex) { 401 // this actually works and isn't broken on Linux SunJDK1.4.1, so... 402 assertEquals(3, list.size()); 403 } 404 new NestBroken(); 405 list = new ArrayList(NestBroken.ColorEnum.getEnumList()); 406 assertEquals(3, list.size()); // all is well!!! 407 Iterator it = list.iterator(); 408 assertSame(NestBroken.RED, it.next()); 409 assertSame(NestBroken.GREEN, it.next()); 410 assertSame(NestBroken.BLUE, it.next()); 411 } 412 413 public void testNestedLinked() { 414 List list = new ArrayList(NestLinked.ColorEnum.getEnumList()); 415 assertEquals(3, list.size()); // all is well 416 Iterator it = list.iterator(); 417 assertSame(NestLinked.RED, it.next()); 418 assertSame(NestLinked.GREEN, it.next()); 419 assertSame(NestLinked.BLUE, it.next()); 420 // This nesting works because a static block in the enum class forces a 421 // class load of the outer class which defines the enum constants. 422 } 423 424 public void testNestedReferenced() { 425 List list = new ArrayList(NestReferenced.ColorEnum.getEnumList()); 426 assertEquals(3, list.size()); // all is well 427 Iterator it = list.iterator(); 428 assertSame(NestReferenced.RED, it.next()); 429 assertSame(NestReferenced.GREEN, it.next()); 430 assertSame(NestReferenced.BLUE, it.next()); 431 // This nesting works because the enum constants are actually defined in 432 // the SAME class as the getEnumList(). The references in the outer class 433 // are just extra references. 434 } 435 436 public void testColorEnumEqualsWithDifferentClassLoaders() throws SecurityException, IllegalArgumentException, 437 ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { 438 this.testWithDifferentClassLoaders(ColorEnum.BLUE); 439 this.testWithDifferentClassLoaders(ColorEnum.GREEN); 440 this.testWithDifferentClassLoaders(ColorEnum.RED); 441 } 442 443 void testWithDifferentClassLoaders(ColorEnum colorEnum) throws ClassNotFoundException, SecurityException, 444 NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 445 // Sanity checks: 446 assertTrue(colorEnum.equals(colorEnum)); 447 assertNotNull(ColorEnum.class.getClassLoader()); 448 // set up: 449 ClassLoader myClassLoader = EnumTest.class.getClassLoader(); 450 if (!(myClassLoader instanceof URLClassLoader)) { 451 fail("EnumTest ClassLoader = " + (myClassLoader == null ? null : myClassLoader.getClass().getName())); 452 } 453 ClassLoader classLoader = URLClassLoader.newInstance( ((URLClassLoader)myClassLoader).getURLs(), null); 454 Object enumObjectFromOtherClassLoader = this.getColorEnum(classLoader, colorEnum.getName()); 455 456 // the real test, part 1. 457 try { 458 ColorEnum testCase = (ColorEnum) enumObjectFromOtherClassLoader; 459 fail("Should have thrown a ClassCastException for " + testCase); 460 } catch (ClassCastException e) { 461 // normal. 462 } 463 464 // the real test, part 2. 465 assertEquals("The two objects should match even though they are from different class loaders", colorEnum, 466 enumObjectFromOtherClassLoader); 467 468 // the real test, part 3 - testing equals(Object) 469 int falseCount = 0; 470 for (Iterator iter = ColorEnum.iterator(); iter.hasNext();) { 471 ColorEnum element = (ColorEnum) iter.next(); 472 if (!colorEnum.equals(element)) { 473 falseCount++; 474 assertFalse(enumObjectFromOtherClassLoader.equals(element)); 475 } 476 } 477 assertEquals(ColorEnum.getEnumList().size() - 1, falseCount); 478 479 // the real test, part 4 - testing compareTo(Object) == 0 480 falseCount = 0; 481 for (Iterator iter = ColorEnum.iterator(); iter.hasNext();) { 482 ColorEnum element = (ColorEnum) iter.next(); 483 if (!colorEnum.equals(element)) { 484 falseCount++; 485 assertFalse( ((Comparable)enumObjectFromOtherClassLoader).compareTo(element) == 0); 486 } 487 } 488 assertEquals(ColorEnum.getEnumList().size() - 1, falseCount); 489 } 490 491 Object getColorEnum(ClassLoader classLoader, String color) throws ClassNotFoundException, SecurityException, 492 NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 493 // Sanity check: 494 ColorEnum.RED.equals(ColorEnum.RED); 495 assertNotNull(ColorEnum.class.getClassLoader()); 496 // set up: 497 assertNotNull(classLoader); 498 assertFalse(classLoader.equals(ColorEnum.class.getClassLoader())); 499 Class otherColorEnumClass = null; 500 try { 501 otherColorEnumClass = classLoader.loadClass(ENUMS_CLASS_NAME); 502 } catch (ClassNotFoundException e) { 503 // Dump some information to help debug class loader issues under different JREs, Ant, Eclipse. 504 System.err.println("Could not load " + ENUMS_CLASS_NAME + " from the class loader " + classLoader); 505 URLClassLoader urlCl = (URLClassLoader) classLoader; 506 URL[] urls = urlCl.getURLs(); 507 System.err.println("Class loader has " + urls.length + " URLs:"); 508 for (int i = 0; i < urls.length; i++) { 509 System.err.println("URL[" + i + "] = " + urls[i]); 510 } 511 e.printStackTrace(); 512 throw e; 513 } 514 assertNotNull(otherColorEnumClass); 515 assertNotNull(otherColorEnumClass.getClassLoader()); 516 assertTrue(classLoader.equals(otherColorEnumClass.getClassLoader())); 517 assertFalse(otherColorEnumClass.getClassLoader().equals(ColorEnum.class.getClassLoader())); 518 Method method = otherColorEnumClass.getMethod("getEnum", new Class[]{String.class}); 519 Object enumObject = method.invoke(otherColorEnumClass, new Object[]{color}); 520 assertNotNull(enumObject); 521 assertFalse(ColorEnum.class.equals(enumObject.getClass())); 522 assertFalse(ColorEnum.class == enumObject.getClass()); 523 return enumObject; 524 } 525 526 public void testEqualsToWrongInstance() { 527 for (Iterator iter = ColorEnum.iterator(); iter.hasNext();) { 528 ColorEnum element = (ColorEnum) iter.next(); 529 this.testEqualsToWrongInstance(element); 530 } 531 } 532 533 void testEqualsToWrongInstance(ColorEnum colorEnum) { 534 assertEquals(false, colorEnum.equals("test")); 535 assertEquals(false, colorEnum.equals(new Integer(1))); 536 assertEquals(false, colorEnum.equals(new Boolean(true))); 537 assertEquals(false, colorEnum.equals(new StringBuffer("test"))); 538 assertEquals(false, colorEnum.equals(new Object())); 539 assertEquals(false, colorEnum.equals(null)); 540 assertEquals(false, colorEnum.equals("")); 541 assertEquals(false, colorEnum.equals(ColorEnum.getEnum(null))); 542 assertEquals(false, colorEnum.equals(ColorEnum.getEnum(""))); 543 assertEquals(false, colorEnum.equals(ColorEnum.getEnum("This ColorEnum does not exist."))); 544 } 545 } 546