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