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(ConcurrentHashMapTest.class);
     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) {
     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;
     60         BI(int value) { this.value = value; }
     61         public int compareTo(BI other) {
     62             return compare(value, other.value);
     63         }
     64         public boolean equals(Object x) {
     65             return (x instanceof BI) && ((BI)x).value == value;
     66         }
     67         public int hashCode() { return 42; }
     68     }
     69     static class CI extends BI { CI(int value) { super(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;
     74         BS(String value) { this.value = value; }
     75         public int compareTo(BS other) {
     76             return value.compareTo(other.value);
     77         }
     78         public boolean equals(Object x) {
     79             return (x instanceof BS) && value.equals(((BS)x).value);
     80         }
     81         public int hashCode() { return 42; }
     82     }
     83 
     84     static class LexicographicList<E extends Comparable<E>> extends ArrayList<E>
     85         implements Comparable<LexicographicList<E>> {
     86         LexicographicList(Collection<E> c) { super(c); }
     87         LexicographicList(E e) { super(Collections.singleton(e)); }
     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;
    104         CollidingObject(final String value) { this.value = value; }
    105         public int hashCode() { return this.value.hashCode() & 1; }
    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> {
    112         ComparableCollidingObject(final String value) { super(value); }
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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