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