HashtableTest.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
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 18package tests.api.java.util; 19 20import java.util.ArrayList; 21import java.util.Arrays; 22import java.util.Collection; 23import java.util.ConcurrentModificationException; 24import java.util.Enumeration; 25import java.util.HashSet; 26import java.util.Hashtable; 27import java.util.Iterator; 28import java.util.Map; 29import java.util.NoSuchElementException; 30import java.util.Set; 31import java.util.TreeMap; 32import java.util.Vector; 33 34import tests.api.java.util.HashMapTest.ReusableKey; 35import tests.support.Support_MapTest2; 36import tests.support.Support_UnmodifiableCollectionTest; 37 38public class HashtableTest extends junit.framework.TestCase { 39 40 private Hashtable ht10; 41 42 private Hashtable ht100; 43 44 private Hashtable htfull; 45 46 private Vector keyVector; 47 48 private Vector elmVector; 49 50 private String h10sVal; 51 52 /** 53 * @tests java.util.Hashtable#Hashtable() 54 */ 55 public void test_Constructor() { 56 // Test for method java.util.Hashtable() 57 new Support_MapTest2(new Hashtable()).runTest(); 58 59 Hashtable h = new Hashtable(); 60 61 assertEquals("Created incorrect hashtable", 0, h.size()); 62 } 63 64 /** 65 * @tests java.util.Hashtable#Hashtable(int) 66 */ 67 public void test_ConstructorI() { 68 // Test for method java.util.Hashtable(int) 69 Hashtable h = new Hashtable(9); 70 71 assertEquals("Created incorrect hashtable", 0, h.size()); 72 73 Hashtable empty = new Hashtable(0); 74 assertNull("Empty hashtable access", empty.get("nothing")); 75 empty.put("something", "here"); 76 assertTrue("cannot get element", empty.get("something") == "here"); 77 } 78 79 /** 80 * @tests java.util.Hashtable#Hashtable(int, float) 81 */ 82 public void test_ConstructorIF() { 83 // Test for method java.util.Hashtable(int, float) 84 Hashtable h = new java.util.Hashtable(10, 0.5f); 85 assertEquals("Created incorrect hashtable", 0, h.size()); 86 87 Hashtable empty = new Hashtable(0, 0.75f); 88 assertNull("Empty hashtable access", empty.get("nothing")); 89 empty.put("something", "here"); 90 assertTrue("cannot get element", empty.get("something") == "here"); 91 } 92 93 /** 94 * @tests java.util.Hashtable#Hashtable(java.util.Map) 95 */ 96 public void test_ConstructorLjava_util_Map() { 97 // Test for method java.util.Hashtable(java.util.Map) 98 Map map = new TreeMap(); 99 Object firstVal = "Gabba"; 100 Object secondVal = new Integer(5); 101 map.put("Gah", firstVal); 102 map.put("Ooga", secondVal); 103 Hashtable ht = new Hashtable(map); 104 assertTrue("a) Incorrect Hashtable constructed", 105 ht.get("Gah") == firstVal); 106 assertTrue("b) Incorrect Hashtable constructed", 107 ht.get("Ooga") == secondVal); 108 } 109 110 /** 111 * @tests java.util.Hashtable#clear() 112 */ 113 public void test_clear() { 114 // Test for method void java.util.Hashtable.clear() 115 Hashtable h = hashtableClone(htfull); 116 h.clear(); 117 assertEquals("Hashtable was not cleared", 0, h.size()); 118 Enumeration el = h.elements(); 119 Enumeration keys = h.keys(); 120 assertTrue("Hashtable improperly cleared", !el.hasMoreElements() 121 && !(keys.hasMoreElements())); 122 } 123 124 /** 125 * @tests java.util.Hashtable#clone() 126 */ 127 public void test_clone() { 128 // Test for method java.lang.Object java.util.Hashtable.clone() 129 130 Hashtable h = (Hashtable) htfull.clone(); 131 assertTrue("Clone different size than original", h.size() == htfull 132 .size()); 133 134 Enumeration org = htfull.keys(); 135 Enumeration cpy = h.keys(); 136 137 String okey, ckey; 138 while (org.hasMoreElements()) { 139 assertTrue("Key comparison failed", (okey = (String) org 140 .nextElement()).equals(ckey = (String) cpy.nextElement())); 141 assertTrue("Value comparison failed", ((String) htfull.get(okey)) 142 .equals((String) h.get(ckey))); 143 } 144 assertTrue("Copy has more keys than original", !cpy.hasMoreElements()); 145 } 146 147 /** 148 * @tests java.util.Hashtable#contains(java.lang.Object) 149 */ 150 public void test_containsLjava_lang_Object() { 151 // Test for method boolean 152 // java.util.Hashtable.contains(java.lang.Object) 153 assertTrue("Element not found", ht10.contains("Val 7")); 154 assertTrue("Invalid element found", !ht10.contains("ZZZZZZZZZZZZZZZZ")); 155 } 156 157 /** 158 * @tests java.util.Hashtable#containsKey(java.lang.Object) 159 */ 160 public void test_containsKeyLjava_lang_Object() { 161 // Test for method boolean 162 // java.util.Hashtable.containsKey(java.lang.Object) 163 164 assertTrue("Failed to find key", htfull.containsKey("FKey 4")); 165 assertTrue("Failed to find key", !htfull.containsKey("FKey 99")); 166 } 167 168 /** 169 * @tests java.util.Hashtable#containsValue(java.lang.Object) 170 */ 171 public void test_containsValueLjava_lang_Object() { 172 // Test for method boolean 173 // java.util.Hashtable.containsValue(java.lang.Object) 174 Enumeration e = elmVector.elements(); 175 while (e.hasMoreElements()) 176 assertTrue("Returned false for valid value", ht10.containsValue(e 177 .nextElement())); 178 assertTrue("Returned true for invalid value", !ht10 179 .containsValue(new Object())); 180 } 181 182 /** 183 * @tests java.util.Hashtable#elements() 184 */ 185 public void test_elements() { 186 // Test for method java.util.Enumeration java.util.Hashtable.elements() 187 Enumeration elms = ht10.elements(); 188 int i = 0; 189 while (elms.hasMoreElements()) { 190 String s = (String) elms.nextElement(); 191 assertTrue("Missing key from enumeration", elmVector.contains(s)); 192 ++i; 193 } 194 195 assertEquals("All keys not retrieved", 10, ht10.size()); 196 } 197 198 /** 199 * @tests java.util.Hashtable#elements() 200 */ 201 public void test_elements_subtest0() { 202 // this is the reference implementation behavior 203 final Hashtable ht = new Hashtable(7); 204 ht.put("1", "a"); 205 // these three elements hash to the same bucket in a 7 element Hashtable 206 ht.put("2", "b"); 207 ht.put("9", "c"); 208 ht.put("12", "d"); 209 // Hashtable looks like: 210 // 0: "1" 211 // 1: "12" -> "9" -> "2" 212 Enumeration en = ht.elements(); 213 // cache the first entry 214 en.hasMoreElements(); 215 ht.remove("12"); 216 ht.remove("9"); 217 boolean exception = false; 218 try { 219 // cached "12" 220 Object result = en.nextElement(); 221 assertNull("unexpected: " + result, result); 222 // next is removed "9" 223 result = en.nextElement(); 224 assertNull("unexpected: " + result, result); 225 result = en.nextElement(); 226 assertTrue("unexpected: " + result, "b".equals(result)); 227 } catch (NoSuchElementException e) { 228 exception = true; 229 } 230 assertTrue("unexpected NoSuchElementException", !exception); 231 } 232 233 /** 234 * @tests java.util.Hashtable#entrySet() 235 */ 236 public void test_entrySet() { 237 // Test for method java.util.Set java.util.Hashtable.entrySet() 238 Set s = ht10.entrySet(); 239 Set s2 = new HashSet(); 240 Iterator i = s.iterator(); 241 while (i.hasNext()) 242 s2.add(((Map.Entry) i.next()).getValue()); 243 Enumeration e = elmVector.elements(); 244 while (e.hasMoreElements()) 245 assertTrue("Returned incorrect entry set", s2.contains(e 246 .nextElement())); 247 248 assertEquals("Not synchronized", 249 "java.util.Collections$SynchronizedSet", s.getClass().getName()); 250 251 boolean exception = false; 252 try { 253 ((Map.Entry) ht10.entrySet().iterator().next()).setValue(null); 254 } catch (NullPointerException e1) { 255 exception = true; 256 } 257 assertTrue( 258 "Should not be able to assign null to a Hashtable entrySet() Map.Entry", 259 exception); 260 } 261 262 /** 263 * @tests java.util.Hashtable#equals(java.lang.Object) 264 */ 265 public void test_equalsLjava_lang_Object() { 266 // Test for method boolean java.util.Hashtable.equals(java.lang.Object) 267 Hashtable h = hashtableClone(ht10); 268 assertTrue("Returned false for equal tables", ht10.equals(h)); 269 assertTrue("Returned true for unequal tables", !ht10.equals(htfull)); 270 } 271 272 /** 273 * @tests java.util.Hashtable#get(java.lang.Object) 274 */ 275 public void test_getLjava_lang_Object() { 276 // Test for method java.lang.Object 277 // java.util.Hashtable.get(java.lang.Object) 278 Hashtable h = hashtableClone(htfull); 279 assertEquals("Could not retrieve element", "FVal 2", ((String) h.get("FKey 2")) 280 ); 281 282 283 // Regression for HARMONY-262 284 ReusableKey k = new ReusableKey(); 285 Hashtable h2 = new Hashtable(); 286 k.setKey(1); 287 h2.put(k, "value1"); 288 289 k.setKey(13); 290 assertNull(h2.get(k)); 291 292 k.setKey(12); 293 assertNull(h2.get(k)); 294 } 295 296 /** 297 * @tests java.util.Hashtable#hashCode() 298 */ 299 public void test_hashCode() { 300 // Test for method int java.util.Hashtable.hashCode() 301 Set entrySet = ht10.entrySet(); 302 Iterator iterator = entrySet.iterator(); 303 int expectedHash; 304 for (expectedHash = 0; iterator.hasNext(); expectedHash += iterator 305 .next().hashCode()) 306 ; 307 assertTrue("Incorrect hashCode returned. Wanted: " + expectedHash 308 + " got: " + ht10.hashCode(), expectedHash == ht10.hashCode()); 309 } 310 311 /** 312 * @tests java.util.Hashtable#isEmpty() 313 */ 314 public void test_isEmpty() { 315 // Test for method boolean java.util.Hashtable.isEmpty() 316 317 assertTrue("isEmpty returned incorrect value", !ht10.isEmpty()); 318 assertTrue("isEmpty returned incorrect value", 319 new java.util.Hashtable().isEmpty()); 320 321 final Hashtable ht = new Hashtable(); 322 ht.put("0", ""); 323 Thread t1 = new Thread() { 324 public void run() { 325 while (!ht.isEmpty()) 326 ; 327 ht.put("final", ""); 328 } 329 }; 330 t1.start(); 331 for (int i = 1; i < 10000; i++) { 332 synchronized (ht) { 333 ht.remove(String.valueOf(i - 1)); 334 ht.put(String.valueOf(i), ""); 335 } 336 int size; 337 if ((size = ht.size()) != 1) { 338 String result = "Size is not 1: " + size + " " + ht; 339 // terminate the thread 340 ht.clear(); 341 fail(result); 342 } 343 } 344 // terminate the thread 345 ht.clear(); 346 } 347 348 /** 349 * @tests java.util.Hashtable#keys() 350 */ 351 public void test_keys() { 352 // Test for method java.util.Enumeration java.util.Hashtable.keys() 353 354 Enumeration keys = ht10.keys(); 355 int i = 0; 356 while (keys.hasMoreElements()) { 357 String s = (String) keys.nextElement(); 358 assertTrue("Missing key from enumeration", keyVector.contains(s)); 359 ++i; 360 } 361 362 assertEquals("All keys not retrieved", 10, ht10.size()); 363 } 364 365 /** 366 * @tests java.util.Hashtable#keys() 367 */ 368 public void test_keys_subtest0() { 369 // this is the reference implementation behavior 370 final Hashtable ht = new Hashtable(3); 371 ht.put("initial", ""); 372 Enumeration en = ht.keys(); 373 en.hasMoreElements(); 374 ht.remove("initial"); 375 boolean exception = false; 376 try { 377 Object result = en.nextElement(); 378 assertTrue("unexpected: " + result, "initial".equals(result)); 379 } catch (NoSuchElementException e) { 380 exception = true; 381 } 382 assertTrue("unexpected NoSuchElementException", !exception); 383 } 384 385 /** 386 * @tests java.util.Hashtable#keySet() 387 */ 388 public void test_keySet() { 389 // Test for method java.util.Set java.util.Hashtable.keySet() 390 Set s = ht10.keySet(); 391 Enumeration e = keyVector.elements(); 392 while (e.hasMoreElements()) 393 assertTrue("Returned incorrect key set", s 394 .contains(e.nextElement())); 395 396 assertEquals("Not synchronized", 397 "java.util.Collections$SynchronizedSet", s.getClass().getName()); 398 399 Map map = new Hashtable(101); 400 map.put(new Integer(1), "1"); 401 map.put(new Integer(102), "102"); 402 map.put(new Integer(203), "203"); 403 Iterator it = map.keySet().iterator(); 404 Integer remove1 = (Integer) it.next(); 405 it.remove(); 406 Integer remove2 = (Integer) it.next(); 407 it.remove(); 408 ArrayList list = new ArrayList(Arrays.asList(new Integer[] { 409 new Integer(1), new Integer(102), new Integer(203) })); 410 list.remove(remove1); 411 list.remove(remove2); 412 assertTrue("Wrong result", it.next().equals(list.get(0))); 413 assertEquals("Wrong size", 1, map.size()); 414 assertTrue("Wrong contents", map.keySet().iterator().next().equals( 415 list.get(0))); 416 417 Map map2 = new Hashtable(101); 418 map2.put(new Integer(1), "1"); 419 map2.put(new Integer(4), "4"); 420 Iterator it2 = map2.keySet().iterator(); 421 Integer remove3 = (Integer) it2.next(); 422 Integer next; 423 if (remove3.intValue() == 1) 424 next = new Integer(4); 425 else 426 next = new Integer(1); 427 it2.hasNext(); 428 it2.remove(); 429 assertTrue("Wrong result 2", it2.next().equals(next)); 430 assertEquals("Wrong size 2", 1, map2.size()); 431 assertTrue("Wrong contents 2", map2.keySet().iterator().next().equals( 432 next)); 433 } 434 435 /** 436 * @tests java.util.Hashtable#keySet() 437 */ 438 public void test_keySet_subtest0() { 439 Set s1 = ht10.keySet(); 440 assertTrue("should contain key", s1.remove("Key 0")); 441 assertTrue("should not contain key", !s1.remove("Key 0")); 442 443 final int iterations = 10000; 444 final Hashtable ht = new Hashtable(); 445 Thread t1 = new Thread() { 446 public void run() { 447 for (int i = 0; i < iterations; i++) { 448 ht.put(String.valueOf(i), ""); 449 ht.remove(String.valueOf(i)); 450 } 451 } 452 }; 453 t1.start(); 454 Set set = ht.keySet(); 455 for (int i = 0; i < iterations; i++) { 456 Iterator it = set.iterator(); 457 try { 458 it.next(); 459 it.remove(); 460 int size; 461 // ensure removing with the iterator doesn't corrupt the 462 // Hashtable 463 if ((size = ht.size()) < 0) { 464 fail("invalid size: " + size); 465 } 466 } catch (NoSuchElementException e) { 467 } catch (ConcurrentModificationException e) { 468 } 469 } 470 } 471 472 /** 473 * @tests java.util.Hashtable#keySet() 474 */ 475 public void test_keySet_subtest1() { 476 // this is the reference implementation behavior 477 final Hashtable ht = new Hashtable(7); 478 ht.put("1", "a"); 479 // these three elements hash to the same bucket in a 7 element Hashtable 480 ht.put("2", "b"); 481 ht.put("9", "c"); 482 ht.put("12", "d"); 483 // Hashtable looks like: 484 // 0: "1" 485 // 1: "12" -> "9" -> "2" 486 Enumeration en = ht.elements(); 487 // cache the first entry 488 en.hasMoreElements(); 489 Iterator it = ht.keySet().iterator(); 490 // this is mostly a copy of the test in test_elements_subtest0() 491 // test removing with the iterator does not null the values 492 while (it.hasNext()) { 493 String key = (String) it.next(); 494 if ("12".equals(key) || "9".equals(key)) { 495 it.remove(); 496 } 497 } 498 it.remove(); 499 boolean exception = false; 500 try { 501 // cached "12" 502 Object result = en.nextElement(); 503 assertTrue("unexpected: " + result, "d".equals(result)); 504 // next is removed "9" 505 result = en.nextElement(); 506 assertTrue("unexpected: " + result, "c".equals(result)); 507 result = en.nextElement(); 508 assertTrue("unexpected: " + result, "b".equals(result)); 509 } catch (NoSuchElementException e) { 510 exception = true; 511 } 512 assertTrue("unexpected NoSuchElementException", !exception); 513 } 514 515 /** 516 * @tests java.util.Hashtable#put(java.lang.Object, java.lang.Object) 517 */ 518 public void test_putLjava_lang_ObjectLjava_lang_Object() { 519 // Test for method java.lang.Object 520 // java.util.Hashtable.put(java.lang.Object, java.lang.Object) 521 Hashtable h = hashtableClone(ht100); 522 Integer key = new Integer(100); 523 h.put("Value 100", key); 524 assertTrue("Key/Value not inserted", h.size() == 1 && (h.contains(key))); 525 526 // Put into "full" table 527 h = hashtableClone(htfull); 528 h.put("Value 100", key); 529 assertTrue("Key/Value not inserted into full table", h.size() == 8 530 && (h.contains(key))); 531 } 532 533 /** 534 * @tests java.util.Hashtable#putAll(java.util.Map) 535 */ 536 public void test_putAllLjava_util_Map() { 537 // Test for method void java.util.Hashtable.putAll(java.util.Map) 538 Hashtable h = new Hashtable(); 539 h.putAll(ht10); 540 Enumeration e = keyVector.elements(); 541 while (e.hasMoreElements()) { 542 Object x = e.nextElement(); 543 assertTrue("Failed to put all elements", h.get(x).equals( 544 ht10.get(x))); 545 } 546 } 547 548 /** 549 * @tests java.util.Hashtable#remove(java.lang.Object) 550 */ 551 public void test_removeLjava_lang_Object() { 552 // Test for method java.lang.Object 553 // java.util.Hashtable.remove(java.lang.Object) 554 Hashtable h = hashtableClone(htfull); 555 Object k = h.remove("FKey 0"); 556 assertTrue("Remove failed", !h.containsKey("FKey 0") || k == null); 557 } 558 559 /** 560 * @tests java.util.Hashtable#size() 561 */ 562 public void test_size() { 563 // Test for method int java.util.Hashtable.size() 564 assertTrue("Returned invalid size", ht10.size() == 10 565 && (ht100.size() == 0)); 566 567 final Hashtable ht = new Hashtable(); 568 ht.put("0", ""); 569 Thread t1 = new Thread() { 570 public void run() { 571 while (ht.size() > 0) 572 ; 573 ht.put("final", ""); 574 } 575 }; 576 t1.start(); 577 for (int i = 1; i < 10000; i++) { 578 synchronized (ht) { 579 ht.remove(String.valueOf(i - 1)); 580 ht.put(String.valueOf(i), ""); 581 } 582 int size; 583 if ((size = ht.size()) != 1) { 584 String result = "Size is not 1: " + size + " " + ht; 585 // terminate the thread 586 ht.clear(); 587 fail(result); 588 } 589 } 590 // terminate the thread 591 ht.clear(); 592 } 593 594 /** 595 * @tests java.util.Hashtable#toString() 596 */ 597 public void test_toString() { 598 // Test for method java.lang.String java.util.Hashtable.toString() 599 Hashtable h = new Hashtable(); 600 assertEquals("Incorrect toString for Empty table", 601 "{}", h.toString()); 602 603 h.put("one", "1"); 604 h.put("two", h); 605 h.put(h, "3"); 606 h.put(h, h); 607 String result = h.toString(); 608 assertTrue("should contain self ref", result.indexOf("(this") > -1); 609 } 610 611 /** 612 * @tests java.util.Hashtable#values() 613 */ 614 public void test_values() { 615 // Test for method java.util.Collection java.util.Hashtable.values() 616 Collection c = ht10.values(); 617 Enumeration e = elmVector.elements(); 618 while (e.hasMoreElements()) 619 assertTrue("Returned incorrect values", c.contains(e.nextElement())); 620 621 assertEquals("Not synchronized", 622 "java.util.Collections$SynchronizedCollection", c.getClass().getName()); 623 624 Hashtable myHashtable = new Hashtable(); 625 for (int i = 0; i < 100; i++) 626 myHashtable.put(new Integer(i), new Integer(i)); 627 Collection values = myHashtable.values(); 628 new Support_UnmodifiableCollectionTest( 629 "Test Returned Collection From Hashtable.values()", values) 630 .runTest(); 631 values.remove(new Integer(0)); 632 assertTrue( 633 "Removing from the values collection should remove from the original map", 634 !myHashtable.containsValue(new Integer(0))); 635 } 636 637 /** 638 * Regression Test for JIRA 2181 639 */ 640 public void test_entrySet_remove() 641 { 642 Hashtable<String,String> hashtable = new Hashtable<String,String>(); 643 hashtable.put("my.nonexistent.prop", "AAA"); 644 hashtable.put( "parse.error", "BBB" ); 645 Iterator<Map.Entry<String,String>> iterator = 646 hashtable.entrySet().iterator(); 647 while(iterator.hasNext()) 648 { 649 Map.Entry entry = iterator.next(); 650 final Object value = entry.getValue(); 651 if(value.equals("AAA")) 652 { 653 iterator.remove(); 654 } 655 } 656 assertFalse(hashtable.containsKey("my.nonexistent.prop")); 657 } 658 659 protected Hashtable hashtableClone(Hashtable s) { 660 return (Hashtable) s.clone(); 661 } 662 663 /** 664 * Sets up the fixture, for example, open a network connection. This method 665 * is called before a test is executed. 666 */ 667 protected void setUp() { 668 669 ht10 = new Hashtable(10); 670 ht100 = new Hashtable(100); 671 htfull = new Hashtable(10); 672 keyVector = new Vector(10); 673 elmVector = new Vector(10); 674 675 for (int i = 0; i < 10; i++) { 676 ht10.put("Key " + i, "Val " + i); 677 keyVector.addElement("Key " + i); 678 elmVector.addElement("Val " + i); 679 } 680 681 for (int i = 0; i < 7; i++) 682 htfull.put("FKey " + i, "FVal " + i); 683 } 684 685 /** 686 * Tears down the fixture, for example, close a network connection. This 687 * method is called after a test is executed. 688 */ 689 protected void tearDown() { 690 } 691} 692