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 
  36 import java.util.ArrayList;
  37 import java.util.Arrays;
  38 import java.util.Collection;
  39 import java.util.Collections;
  40 import java.util.Enumeration;
  41 import java.util.Iterator;
  42 import java.util.Map;
  43 import java.util.Random;
  44 import java.util.Set;
  45 import java.util.concurrent.ConcurrentHashMap;
  46 import java.util.concurrent.ExecutorService;
  47 import java.util.concurrent.Executors;
  48 
  49 import junit.framework.Test;
  50 import junit.framework.TestSuite;
  51 
  52 public 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 }