1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 * Other contributors include Andrew Wright, Jeffrey Hayes, 6 * Pat Fisher, Mike Judd. 7 */ 8 9 package jsr166; 10 11 import java.util.ArrayList; 12 import java.util.Arrays; 13 import java.util.Collection; 14 import java.util.Collections; 15 import java.util.Enumeration; 16 import java.util.Iterator; 17 import java.util.Map; 18 import java.util.Random; 19 import java.util.Set; 20 import java.util.concurrent.ConcurrentHashMap; 21 22 import junit.framework.Test; 23 import junit.framework.TestSuite; 24 25 public class ConcurrentHashMapTest extends JSR166TestCase { 26 // android-note: Removed because the CTS runner does a bad job of 27 // retrying tests that have suite() declarations. 28 // 29 // public static void main(String[] args) { 30 // main(suite(), args); 31 // } 32 // public static Test suite() { 33 // return new TestSuite(ConcurrentHashMapTest.class); 34 // } 35 36 /** 37 * Returns a new map from Integers 1-5 to Strings "A"-"E". 38 */ map5()39 private static ConcurrentHashMap<Integer, String> map5() { 40 ConcurrentHashMap map = new ConcurrentHashMap<Integer, String>(5); 41 assertTrue(map.isEmpty()); 42 map.put(one, "A"); 43 map.put(two, "B"); 44 map.put(three, "C"); 45 map.put(four, "D"); 46 map.put(five, "E"); 47 assertFalse(map.isEmpty()); 48 assertEquals(5, map.size()); 49 return map; 50 } 51 52 /** Re-implement Integer.compare for old java versions */ compare(int x, int y)53 static int compare(int x, int y) { 54 return (x < y) ? -1 : (x > y) ? 1 : 0; 55 } 56 57 // classes for testing Comparable fallbacks 58 static class BI implements Comparable<BI> { 59 private final int value; BI(int value)60 BI(int value) { this.value = value; } compareTo(BI other)61 public int compareTo(BI other) { 62 return compare(value, other.value); 63 } equals(Object x)64 public boolean equals(Object x) { 65 return (x instanceof BI) && ((BI)x).value == value; 66 } hashCode()67 public int hashCode() { return 42; } 68 } CI(int value)69 static class CI extends BI { CI(int value) { super(value); } } DI(int value)70 static class DI extends BI { DI(int value) { super(value); } } 71 72 static class BS implements Comparable<BS> { 73 private final String value; BS(String value)74 BS(String value) { this.value = value; } compareTo(BS other)75 public int compareTo(BS other) { 76 return value.compareTo(other.value); 77 } equals(Object x)78 public boolean equals(Object x) { 79 return (x instanceof BS) && value.equals(((BS)x).value); 80 } hashCode()81 public int hashCode() { return 42; } 82 } 83 84 static class LexicographicList<E extends Comparable<E>> extends ArrayList<E> 85 implements Comparable<LexicographicList<E>> { LexicographicList(Collection<E> c)86 LexicographicList(Collection<E> c) { super(c); } LexicographicList(E e)87 LexicographicList(E e) { super(Collections.singleton(e)); } compareTo(LexicographicList<E> other)88 public int compareTo(LexicographicList<E> other) { 89 int common = Math.min(size(), other.size()); 90 int r = 0; 91 for (int i = 0; i < common; i++) { 92 if ((r = get(i).compareTo(other.get(i))) != 0) 93 break; 94 } 95 if (r == 0) 96 r = compare(size(), other.size()); 97 return r; 98 } 99 private static final long serialVersionUID = 0; 100 } 101 102 static class CollidingObject { 103 final String value; CollidingObject(final String value)104 CollidingObject(final String value) { this.value = value; } hashCode()105 public int hashCode() { return this.value.hashCode() & 1; } equals(final Object obj)106 public boolean equals(final Object obj) { 107 return (obj instanceof CollidingObject) && ((CollidingObject)obj).value.equals(value); 108 } 109 } 110 111 static class ComparableCollidingObject extends CollidingObject implements Comparable<ComparableCollidingObject> { ComparableCollidingObject(final String value)112 ComparableCollidingObject(final String value) { super(value); } compareTo(final ComparableCollidingObject o)113 public int compareTo(final ComparableCollidingObject o) { 114 return value.compareTo(o.value); 115 } 116 } 117 118 /** 119 * Inserted elements that are subclasses of the same Comparable 120 * class are found. 121 */ testComparableFamily()122 public void testComparableFamily() { 123 int size = 500; // makes measured test run time -> 60ms 124 ConcurrentHashMap<BI, Boolean> m = 125 new ConcurrentHashMap<BI, Boolean>(); 126 for (int i = 0; i < size; i++) { 127 assertTrue(m.put(new CI(i), true) == null); 128 } 129 for (int i = 0; i < size; i++) { 130 assertTrue(m.containsKey(new CI(i))); 131 assertTrue(m.containsKey(new DI(i))); 132 } 133 } 134 135 /** 136 * Elements of classes with erased generic type parameters based 137 * on Comparable can be inserted and found. 138 */ testGenericComparable()139 public void testGenericComparable() { 140 int size = 120; // makes measured test run time -> 60ms 141 ConcurrentHashMap<Object, Boolean> m = 142 new ConcurrentHashMap<Object, Boolean>(); 143 for (int i = 0; i < size; i++) { 144 BI bi = new BI(i); 145 BS bs = new BS(String.valueOf(i)); 146 LexicographicList<BI> bis = new LexicographicList<BI>(bi); 147 LexicographicList<BS> bss = new LexicographicList<BS>(bs); 148 assertTrue(m.putIfAbsent(bis, true) == null); 149 assertTrue(m.containsKey(bis)); 150 if (m.putIfAbsent(bss, true) == null) 151 assertTrue(m.containsKey(bss)); 152 assertTrue(m.containsKey(bis)); 153 } 154 for (int i = 0; i < size; i++) { 155 assertTrue(m.containsKey(Collections.singletonList(new BI(i)))); 156 } 157 } 158 159 /** 160 * Elements of non-comparable classes equal to those of classes 161 * with erased generic type parameters based on Comparable can be 162 * inserted and found. 163 */ testGenericComparable2()164 public void testGenericComparable2() { 165 int size = 500; // makes measured test run time -> 60ms 166 ConcurrentHashMap<Object, Boolean> m = 167 new ConcurrentHashMap<Object, Boolean>(); 168 for (int i = 0; i < size; i++) { 169 m.put(Collections.singletonList(new BI(i)), true); 170 } 171 172 for (int i = 0; i < size; i++) { 173 LexicographicList<BI> bis = new LexicographicList<BI>(new BI(i)); 174 assertTrue(m.containsKey(bis)); 175 } 176 } 177 178 /** 179 * Mixtures of instances of comparable and non-comparable classes 180 * can be inserted and found. 181 */ testMixedComparable()182 public void testMixedComparable() { 183 int size = 1200; // makes measured test run time -> 35ms 184 ConcurrentHashMap<Object, Object> map = 185 new ConcurrentHashMap<Object, Object>(); 186 Random rng = new Random(); 187 for (int i = 0; i < size; i++) { 188 Object x; 189 switch (rng.nextInt(4)) { 190 case 0: 191 x = new Object(); 192 break; 193 case 1: 194 x = new CollidingObject(Integer.toString(i)); 195 break; 196 default: 197 x = new ComparableCollidingObject(Integer.toString(i)); 198 } 199 assertNull(map.put(x, x)); 200 } 201 int count = 0; 202 for (Object k : map.keySet()) { 203 assertEquals(map.get(k), k); 204 ++count; 205 } 206 assertEquals(count, size); 207 assertEquals(map.size(), size); 208 for (Object k : map.keySet()) { 209 assertEquals(map.put(k, k), k); 210 } 211 } 212 213 /** 214 * clear removes all pairs 215 */ testClear()216 public void testClear() { 217 ConcurrentHashMap map = map5(); 218 map.clear(); 219 assertEquals(0, map.size()); 220 } 221 222 /** 223 * Maps with same contents are equal 224 */ testEquals()225 public void testEquals() { 226 ConcurrentHashMap map1 = map5(); 227 ConcurrentHashMap map2 = map5(); 228 assertEquals(map1, map2); 229 assertEquals(map2, map1); 230 map1.clear(); 231 assertFalse(map1.equals(map2)); 232 assertFalse(map2.equals(map1)); 233 } 234 235 /** 236 * hashCode() equals sum of each key.hashCode ^ value.hashCode 237 */ testHashCode()238 public void testHashCode() { 239 ConcurrentHashMap<Integer,String> map = map5(); 240 int sum = 0; 241 for (Map.Entry<Integer,String> e : map.entrySet()) 242 sum += e.getKey().hashCode() ^ e.getValue().hashCode(); 243 assertEquals(sum, map.hashCode()); 244 } 245 246 /** 247 * contains returns true for contained value 248 */ testContains()249 public void testContains() { 250 ConcurrentHashMap map = map5(); 251 assertTrue(map.contains("A")); 252 assertFalse(map.contains("Z")); 253 } 254 255 /** 256 * containsKey returns true for contained key 257 */ testContainsKey()258 public void testContainsKey() { 259 ConcurrentHashMap map = map5(); 260 assertTrue(map.containsKey(one)); 261 assertFalse(map.containsKey(zero)); 262 } 263 264 /** 265 * containsValue returns true for held values 266 */ testContainsValue()267 public void testContainsValue() { 268 ConcurrentHashMap map = map5(); 269 assertTrue(map.containsValue("A")); 270 assertFalse(map.containsValue("Z")); 271 } 272 273 /** 274 * enumeration returns an enumeration containing the correct 275 * elements 276 */ testEnumeration()277 public void testEnumeration() { 278 ConcurrentHashMap map = map5(); 279 Enumeration e = map.elements(); 280 int count = 0; 281 while (e.hasMoreElements()) { 282 count++; 283 e.nextElement(); 284 } 285 assertEquals(5, count); 286 } 287 288 /** 289 * get returns the correct element at the given key, 290 * or null if not present 291 */ testGet()292 public void testGet() { 293 ConcurrentHashMap map = map5(); 294 assertEquals("A", (String)map.get(one)); 295 ConcurrentHashMap empty = new ConcurrentHashMap(); 296 assertNull(map.get("anything")); 297 assertNull(empty.get("anything")); 298 } 299 300 /** 301 * isEmpty is true of empty map and false for non-empty 302 */ testIsEmpty()303 public void testIsEmpty() { 304 ConcurrentHashMap empty = new ConcurrentHashMap(); 305 ConcurrentHashMap map = map5(); 306 assertTrue(empty.isEmpty()); 307 assertFalse(map.isEmpty()); 308 } 309 310 /** 311 * keys returns an enumeration containing all the keys from the map 312 */ testKeys()313 public void testKeys() { 314 ConcurrentHashMap map = map5(); 315 Enumeration e = map.keys(); 316 int count = 0; 317 while (e.hasMoreElements()) { 318 count++; 319 e.nextElement(); 320 } 321 assertEquals(5, count); 322 } 323 324 /** 325 * keySet returns a Set containing all the keys 326 */ testKeySet()327 public void testKeySet() { 328 ConcurrentHashMap map = map5(); 329 Set s = map.keySet(); 330 assertEquals(5, s.size()); 331 assertTrue(s.contains(one)); 332 assertTrue(s.contains(two)); 333 assertTrue(s.contains(three)); 334 assertTrue(s.contains(four)); 335 assertTrue(s.contains(five)); 336 } 337 338 /** 339 * keySet.toArray returns contains all keys 340 */ testKeySetToArray()341 public void testKeySetToArray() { 342 ConcurrentHashMap map = map5(); 343 Set s = map.keySet(); 344 Object[] ar = s.toArray(); 345 assertTrue(s.containsAll(Arrays.asList(ar))); 346 assertEquals(5, ar.length); 347 ar[0] = m10; 348 assertFalse(s.containsAll(Arrays.asList(ar))); 349 } 350 351 /** 352 * Values.toArray contains all values 353 */ testValuesToArray()354 public void testValuesToArray() { 355 ConcurrentHashMap map = map5(); 356 Collection v = map.values(); 357 Object[] ar = v.toArray(); 358 ArrayList s = new ArrayList(Arrays.asList(ar)); 359 assertEquals(5, ar.length); 360 assertTrue(s.contains("A")); 361 assertTrue(s.contains("B")); 362 assertTrue(s.contains("C")); 363 assertTrue(s.contains("D")); 364 assertTrue(s.contains("E")); 365 } 366 367 /** 368 * entrySet.toArray contains all entries 369 */ testEntrySetToArray()370 public void testEntrySetToArray() { 371 ConcurrentHashMap map = map5(); 372 Set s = map.entrySet(); 373 Object[] ar = s.toArray(); 374 assertEquals(5, ar.length); 375 for (int i = 0; i < 5; ++i) { 376 assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); 377 assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); 378 } 379 } 380 381 /** 382 * values collection contains all values 383 */ testValues()384 public void testValues() { 385 ConcurrentHashMap map = map5(); 386 Collection s = map.values(); 387 assertEquals(5, s.size()); 388 assertTrue(s.contains("A")); 389 assertTrue(s.contains("B")); 390 assertTrue(s.contains("C")); 391 assertTrue(s.contains("D")); 392 assertTrue(s.contains("E")); 393 } 394 395 /** 396 * entrySet contains all pairs 397 */ testEntrySet()398 public void testEntrySet() { 399 ConcurrentHashMap map = map5(); 400 Set s = map.entrySet(); 401 assertEquals(5, s.size()); 402 Iterator it = s.iterator(); 403 while (it.hasNext()) { 404 Map.Entry e = (Map.Entry) it.next(); 405 assertTrue( 406 (e.getKey().equals(one) && e.getValue().equals("A")) || 407 (e.getKey().equals(two) && e.getValue().equals("B")) || 408 (e.getKey().equals(three) && e.getValue().equals("C")) || 409 (e.getKey().equals(four) && e.getValue().equals("D")) || 410 (e.getKey().equals(five) && e.getValue().equals("E"))); 411 } 412 } 413 414 /** 415 * putAll adds all key-value pairs from the given map 416 */ testPutAll()417 public void testPutAll() { 418 ConcurrentHashMap empty = new ConcurrentHashMap(); 419 ConcurrentHashMap map = map5(); 420 empty.putAll(map); 421 assertEquals(5, empty.size()); 422 assertTrue(empty.containsKey(one)); 423 assertTrue(empty.containsKey(two)); 424 assertTrue(empty.containsKey(three)); 425 assertTrue(empty.containsKey(four)); 426 assertTrue(empty.containsKey(five)); 427 } 428 429 /** 430 * putIfAbsent works when the given key is not present 431 */ testPutIfAbsent()432 public void testPutIfAbsent() { 433 ConcurrentHashMap map = map5(); 434 map.putIfAbsent(six, "Z"); 435 assertTrue(map.containsKey(six)); 436 } 437 438 /** 439 * putIfAbsent does not add the pair if the key is already present 440 */ testPutIfAbsent2()441 public void testPutIfAbsent2() { 442 ConcurrentHashMap map = map5(); 443 assertEquals("A", map.putIfAbsent(one, "Z")); 444 } 445 446 /** 447 * replace fails when the given key is not present 448 */ testReplace()449 public void testReplace() { 450 ConcurrentHashMap map = map5(); 451 assertNull(map.replace(six, "Z")); 452 assertFalse(map.containsKey(six)); 453 } 454 455 /** 456 * replace succeeds if the key is already present 457 */ testReplace2()458 public void testReplace2() { 459 ConcurrentHashMap map = map5(); 460 assertNotNull(map.replace(one, "Z")); 461 assertEquals("Z", map.get(one)); 462 } 463 464 /** 465 * replace value fails when the given key not mapped to expected value 466 */ testReplaceValue()467 public void testReplaceValue() { 468 ConcurrentHashMap map = map5(); 469 assertEquals("A", map.get(one)); 470 assertFalse(map.replace(one, "Z", "Z")); 471 assertEquals("A", map.get(one)); 472 } 473 474 /** 475 * replace value succeeds when the given key mapped to expected value 476 */ testReplaceValue2()477 public void testReplaceValue2() { 478 ConcurrentHashMap map = map5(); 479 assertEquals("A", map.get(one)); 480 assertTrue(map.replace(one, "A", "Z")); 481 assertEquals("Z", map.get(one)); 482 } 483 484 /** 485 * remove removes the correct key-value pair from the map 486 */ testRemove()487 public void testRemove() { 488 ConcurrentHashMap map = map5(); 489 map.remove(five); 490 assertEquals(4, map.size()); 491 assertFalse(map.containsKey(five)); 492 } 493 494 /** 495 * remove(key,value) removes only if pair present 496 */ testRemove2()497 public void testRemove2() { 498 ConcurrentHashMap map = map5(); 499 map.remove(five, "E"); 500 assertEquals(4, map.size()); 501 assertFalse(map.containsKey(five)); 502 map.remove(four, "A"); 503 assertEquals(4, map.size()); 504 assertTrue(map.containsKey(four)); 505 } 506 507 /** 508 * size returns the correct values 509 */ testSize()510 public void testSize() { 511 ConcurrentHashMap map = map5(); 512 ConcurrentHashMap empty = new ConcurrentHashMap(); 513 assertEquals(0, empty.size()); 514 assertEquals(5, map.size()); 515 } 516 517 /** 518 * toString contains toString of elements 519 */ testToString()520 public void testToString() { 521 ConcurrentHashMap map = map5(); 522 String s = map.toString(); 523 for (int i = 1; i <= 5; ++i) { 524 assertTrue(s.contains(String.valueOf(i))); 525 } 526 } 527 528 // Exception tests 529 530 /** 531 * Cannot create with only negative capacity 532 */ testConstructor1()533 public void testConstructor1() { 534 try { 535 new ConcurrentHashMap(-1); 536 shouldThrow(); 537 } catch (IllegalArgumentException success) {} 538 } 539 540 /** 541 * Constructor (initialCapacity, loadFactor) throws 542 * IllegalArgumentException if either argument is negative 543 */ testConstructor2()544 public void testConstructor2() { 545 try { 546 new ConcurrentHashMap(-1, .75f); 547 shouldThrow(); 548 } catch (IllegalArgumentException success) {} 549 550 try { 551 new ConcurrentHashMap(16, -1); 552 shouldThrow(); 553 } catch (IllegalArgumentException success) {} 554 } 555 556 /** 557 * Constructor (initialCapacity, loadFactor, concurrencyLevel) 558 * throws IllegalArgumentException if any argument is negative 559 */ testConstructor3()560 public void testConstructor3() { 561 try { 562 new ConcurrentHashMap(-1, .75f, 1); 563 shouldThrow(); 564 } catch (IllegalArgumentException success) {} 565 566 try { 567 new ConcurrentHashMap(16, -1, 1); 568 shouldThrow(); 569 } catch (IllegalArgumentException success) {} 570 571 try { 572 new ConcurrentHashMap(16, .75f, -1); 573 shouldThrow(); 574 } catch (IllegalArgumentException success) {} 575 } 576 577 /** 578 * ConcurrentHashMap(map) throws NullPointerException if the given 579 * map is null 580 */ testConstructor4()581 public void testConstructor4() { 582 try { 583 new ConcurrentHashMap(null); 584 shouldThrow(); 585 } catch (NullPointerException success) {} 586 } 587 588 /** 589 * ConcurrentHashMap(map) creates a new map with the same mappings 590 * as the given map 591 */ testConstructor5()592 public void testConstructor5() { 593 ConcurrentHashMap map1 = map5(); 594 ConcurrentHashMap map2 = new ConcurrentHashMap(map5()); 595 assertTrue(map2.equals(map1)); 596 map2.put(one, "F"); 597 assertFalse(map2.equals(map1)); 598 } 599 600 /** 601 * get(null) throws NPE 602 */ testGet_NullPointerException()603 public void testGet_NullPointerException() { 604 ConcurrentHashMap c = new ConcurrentHashMap(5); 605 try { 606 c.get(null); 607 shouldThrow(); 608 } catch (NullPointerException success) {} 609 } 610 611 /** 612 * containsKey(null) throws NPE 613 */ testContainsKey_NullPointerException()614 public void testContainsKey_NullPointerException() { 615 ConcurrentHashMap c = new ConcurrentHashMap(5); 616 try { 617 c.containsKey(null); 618 shouldThrow(); 619 } catch (NullPointerException success) {} 620 } 621 622 /** 623 * containsValue(null) throws NPE 624 */ testContainsValue_NullPointerException()625 public void testContainsValue_NullPointerException() { 626 ConcurrentHashMap c = new ConcurrentHashMap(5); 627 try { 628 c.containsValue(null); 629 shouldThrow(); 630 } catch (NullPointerException success) {} 631 } 632 633 /** 634 * contains(null) throws NPE 635 */ testContains_NullPointerException()636 public void testContains_NullPointerException() { 637 ConcurrentHashMap c = new ConcurrentHashMap(5); 638 try { 639 c.contains(null); 640 shouldThrow(); 641 } catch (NullPointerException success) {} 642 } 643 644 /** 645 * put(null,x) throws NPE 646 */ testPut1_NullPointerException()647 public void testPut1_NullPointerException() { 648 ConcurrentHashMap c = new ConcurrentHashMap(5); 649 try { 650 c.put(null, "whatever"); 651 shouldThrow(); 652 } catch (NullPointerException success) {} 653 } 654 655 /** 656 * put(x, null) throws NPE 657 */ testPut2_NullPointerException()658 public void testPut2_NullPointerException() { 659 ConcurrentHashMap c = new ConcurrentHashMap(5); 660 try { 661 c.put("whatever", null); 662 shouldThrow(); 663 } catch (NullPointerException success) {} 664 } 665 666 /** 667 * putIfAbsent(null, x) throws NPE 668 */ testPutIfAbsent1_NullPointerException()669 public void testPutIfAbsent1_NullPointerException() { 670 ConcurrentHashMap c = new ConcurrentHashMap(5); 671 try { 672 c.putIfAbsent(null, "whatever"); 673 shouldThrow(); 674 } catch (NullPointerException success) {} 675 } 676 677 /** 678 * replace(null, x) throws NPE 679 */ testReplace_NullPointerException()680 public void testReplace_NullPointerException() { 681 ConcurrentHashMap c = new ConcurrentHashMap(5); 682 try { 683 c.replace(null, "whatever"); 684 shouldThrow(); 685 } catch (NullPointerException success) {} 686 } 687 688 /** 689 * replace(null, x, y) throws NPE 690 */ testReplaceValue_NullPointerException()691 public void testReplaceValue_NullPointerException() { 692 ConcurrentHashMap c = new ConcurrentHashMap(5); 693 try { 694 c.replace(null, one, "whatever"); 695 shouldThrow(); 696 } catch (NullPointerException success) {} 697 } 698 699 /** 700 * putIfAbsent(x, null) throws NPE 701 */ testPutIfAbsent2_NullPointerException()702 public void testPutIfAbsent2_NullPointerException() { 703 ConcurrentHashMap c = new ConcurrentHashMap(5); 704 try { 705 c.putIfAbsent("whatever", null); 706 shouldThrow(); 707 } catch (NullPointerException success) {} 708 } 709 710 /** 711 * replace(x, null) throws NPE 712 */ testReplace2_NullPointerException()713 public void testReplace2_NullPointerException() { 714 ConcurrentHashMap c = new ConcurrentHashMap(5); 715 try { 716 c.replace("whatever", null); 717 shouldThrow(); 718 } catch (NullPointerException success) {} 719 } 720 721 /** 722 * replace(x, null, y) throws NPE 723 */ testReplaceValue2_NullPointerException()724 public void testReplaceValue2_NullPointerException() { 725 ConcurrentHashMap c = new ConcurrentHashMap(5); 726 try { 727 c.replace("whatever", null, "A"); 728 shouldThrow(); 729 } catch (NullPointerException success) {} 730 } 731 732 /** 733 * replace(x, y, null) throws NPE 734 */ testReplaceValue3_NullPointerException()735 public void testReplaceValue3_NullPointerException() { 736 ConcurrentHashMap c = new ConcurrentHashMap(5); 737 try { 738 c.replace("whatever", one, null); 739 shouldThrow(); 740 } catch (NullPointerException success) {} 741 } 742 743 /** 744 * remove(null) throws NPE 745 */ testRemove1_NullPointerException()746 public void testRemove1_NullPointerException() { 747 ConcurrentHashMap c = new ConcurrentHashMap(5); 748 c.put("sadsdf", "asdads"); 749 try { 750 c.remove(null); 751 shouldThrow(); 752 } catch (NullPointerException success) {} 753 } 754 755 /** 756 * remove(null, x) throws NPE 757 */ testRemove2_NullPointerException()758 public void testRemove2_NullPointerException() { 759 ConcurrentHashMap c = new ConcurrentHashMap(5); 760 c.put("sadsdf", "asdads"); 761 try { 762 c.remove(null, "whatever"); 763 shouldThrow(); 764 } catch (NullPointerException success) {} 765 } 766 767 /** 768 * remove(x, null) returns false 769 */ testRemove3()770 public void testRemove3() { 771 ConcurrentHashMap c = new ConcurrentHashMap(5); 772 c.put("sadsdf", "asdads"); 773 assertFalse(c.remove("sadsdf", null)); 774 } 775 776 /** 777 * A deserialized map equals original 778 */ testSerialization()779 public void testSerialization() throws Exception { 780 Map x = map5(); 781 Map y = serialClone(x); 782 783 assertNotSame(x, y); 784 assertEquals(x.size(), y.size()); 785 assertEquals(x, y); 786 assertEquals(y, x); 787 } 788 789 /** 790 * SetValue of an EntrySet entry sets value in the map. 791 */ testSetValueWriteThrough()792 public void testSetValueWriteThrough() { 793 // Adapted from a bug report by Eric Zoerner 794 ConcurrentHashMap map = new ConcurrentHashMap(2, 5.0f, 1); 795 assertTrue(map.isEmpty()); 796 for (int i = 0; i < 20; i++) 797 map.put(new Integer(i), new Integer(i)); 798 assertFalse(map.isEmpty()); 799 Map.Entry entry1 = (Map.Entry)map.entrySet().iterator().next(); 800 // Unless it happens to be first (in which case remainder of 801 // test is skipped), remove a possibly-colliding key from map 802 // which, under some implementations, may cause entry1 to be 803 // cloned in map 804 if (!entry1.getKey().equals(new Integer(16))) { 805 map.remove(new Integer(16)); 806 entry1.setValue("XYZ"); 807 assertTrue(map.containsValue("XYZ")); // fails if write-through broken 808 } 809 } 810 811 } 812