Home | History | Annotate | Download | only in testing
      1 /*
      2  * Copyright (C) 2008 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.collect.testing;
     18 
     19 import java.util.concurrent.ConcurrentMap;
     20 
     21 /**
     22  * Tests representing the contract of {@link ConcurrentMap}. Concrete
     23  * subclasses of this base class test conformance of concrete
     24  * {@link ConcurrentMap} subclasses to that contract.
     25  *
     26  * <p>This class is GWT compatible.
     27  *
     28  * <p>The tests in this class for null keys and values only check maps for
     29  * which null keys and values are not allowed. There are currently no
     30  * {@link ConcurrentMap} implementations that support nulls.
     31  *
     32  * @author Jared Levy
     33  */
     34 public abstract class ConcurrentMapInterfaceTest<K, V>
     35     extends MapInterfaceTest<K, V> {
     36 
     37   protected ConcurrentMapInterfaceTest(boolean allowsNullKeys,
     38       boolean allowsNullValues, boolean supportsPut, boolean supportsRemove,
     39       boolean supportsClear) {
     40     super(allowsNullKeys, allowsNullValues, supportsPut, supportsRemove,
     41         supportsClear);
     42   }
     43 
     44   /**
     45    * Creates a new value that is not expected to be found in
     46    * {@link #makePopulatedMap()} and differs from the value returned by
     47    * {@link #getValueNotInPopulatedMap()}.
     48    *
     49    * @return a value
     50    * @throws UnsupportedOperationException if it's not possible to make a value
     51    * that will not be found in the map
     52    */
     53   protected abstract V getSecondValueNotInPopulatedMap()
     54       throws UnsupportedOperationException;
     55 
     56   @Override protected abstract ConcurrentMap<K, V> makeEmptyMap()
     57       throws UnsupportedOperationException;
     58 
     59   @Override protected abstract ConcurrentMap<K, V> makePopulatedMap()
     60       throws UnsupportedOperationException;
     61 
     62   @Override protected ConcurrentMap<K, V> makeEitherMap() {
     63     try {
     64       return makePopulatedMap();
     65     } catch (UnsupportedOperationException e) {
     66       return makeEmptyMap();
     67     }
     68   }
     69 
     70   public void testPutIfAbsentNewKey() {
     71     final ConcurrentMap<K, V> map;
     72     final K keyToPut;
     73     final V valueToPut;
     74     try {
     75       map = makeEitherMap();
     76       keyToPut = getKeyNotInPopulatedMap();
     77       valueToPut = getValueNotInPopulatedMap();
     78     } catch (UnsupportedOperationException e) {
     79       return;
     80     }
     81     if (supportsPut) {
     82       int initialSize = map.size();
     83       V oldValue = map.putIfAbsent(keyToPut, valueToPut);
     84       assertEquals(valueToPut, map.get(keyToPut));
     85       assertTrue(map.containsKey(keyToPut));
     86       assertTrue(map.containsValue(valueToPut));
     87       assertEquals(initialSize + 1, map.size());
     88       assertNull(oldValue);
     89     } else {
     90       try {
     91         map.putIfAbsent(keyToPut, valueToPut);
     92         fail("Expected UnsupportedOperationException.");
     93       } catch (UnsupportedOperationException e) {
     94         // Expected.
     95       }
     96     }
     97     assertInvariants(map);
     98   }
     99 
    100   public void testPutIfAbsentExistingKey() {
    101     final ConcurrentMap<K, V> map;
    102     final K keyToPut;
    103     final V valueToPut;
    104     try {
    105       map = makePopulatedMap();
    106       valueToPut = getValueNotInPopulatedMap();
    107     } catch (UnsupportedOperationException e) {
    108       return;
    109     }
    110     keyToPut = map.keySet().iterator().next();
    111     if (supportsPut) {
    112       V oldValue = map.get(keyToPut);
    113       int initialSize = map.size();
    114       assertEquals(oldValue, map.putIfAbsent(keyToPut, valueToPut));
    115       assertEquals(oldValue, map.get(keyToPut));
    116       assertTrue(map.containsKey(keyToPut));
    117       assertTrue(map.containsValue(oldValue));
    118       assertFalse(map.containsValue(valueToPut));
    119       assertEquals(initialSize, map.size());
    120     } else {
    121       try {
    122         map.putIfAbsent(keyToPut, valueToPut);
    123         fail("Expected UnsupportedOperationException.");
    124       } catch (UnsupportedOperationException e) {
    125         // Expected.
    126       }
    127     }
    128     assertInvariants(map);
    129   }
    130 
    131   public void testPutIfAbsentNullKey() {
    132     if (allowsNullKeys) {
    133       return;   // Not yet implemented
    134     }
    135     final ConcurrentMap<K, V> map;
    136     final V valueToPut;
    137     try {
    138       map = makeEitherMap();
    139       valueToPut = getValueNotInPopulatedMap();
    140     } catch (UnsupportedOperationException e) {
    141       return;
    142     }
    143     int initialSize = map.size();
    144     if (supportsPut) {
    145       try {
    146         map.putIfAbsent(null, valueToPut);
    147         fail("Expected NullPointerException");
    148       } catch (NullPointerException e) {
    149         // Expected.
    150       }
    151     } else {
    152       try {
    153         map.putIfAbsent(null, valueToPut);
    154         fail("Expected UnsupportedOperationException or NullPointerException");
    155       } catch (UnsupportedOperationException e) {
    156         // Expected.
    157       } catch (NullPointerException e) {
    158         // Expected.
    159       }
    160     }
    161     assertEquals(initialSize, map.size());
    162     assertInvariants(map);
    163   }
    164 
    165   public void testPutIfAbsentNewKeyNullValue() {
    166     if (allowsNullValues) {
    167       return;   // Not yet implemented
    168     }
    169     final ConcurrentMap<K, V> map;
    170     final K keyToPut;
    171     try {
    172       map = makeEitherMap();
    173       keyToPut = getKeyNotInPopulatedMap();
    174     } catch (UnsupportedOperationException e) {
    175       return;
    176     }
    177     int initialSize = map.size();
    178     if (supportsPut) {
    179       try {
    180         map.putIfAbsent(keyToPut, null);
    181         fail("Expected NullPointerException");
    182       } catch (NullPointerException e) {
    183         // Expected.
    184       }
    185     } else {
    186       try {
    187         map.putIfAbsent(keyToPut, null);
    188         fail("Expected UnsupportedOperationException or NullPointerException");
    189       } catch (UnsupportedOperationException e) {
    190         // Expected.
    191       } catch (NullPointerException e) {
    192         // Expected.
    193       }
    194     }
    195     assertEquals(initialSize, map.size());
    196     assertInvariants(map);
    197   }
    198 
    199   public void testPutIfAbsentExistingKeyNullValue() {
    200     if (allowsNullValues) {
    201       return;   // Not yet implemented
    202     }
    203     final ConcurrentMap<K, V> map;
    204     final K keyToPut;
    205     try {
    206       map = makePopulatedMap();
    207     } catch (UnsupportedOperationException e) {
    208       return;
    209     }
    210     keyToPut = map.keySet().iterator().next();
    211     int initialSize = map.size();
    212     if (supportsPut) {
    213       try {
    214         assertNull(map.putIfAbsent(keyToPut, null));
    215       } catch (NullPointerException e) {
    216         // Optional.
    217       }
    218     } else {
    219       try {
    220         map.putIfAbsent(keyToPut, null);
    221         fail("Expected UnsupportedOperationException or NullPointerException");
    222       } catch (UnsupportedOperationException e) {
    223         // Expected.
    224       } catch (NullPointerException e) {
    225         // Expected.
    226       }
    227     }
    228     assertEquals(initialSize, map.size());
    229     assertInvariants(map);
    230   }
    231 
    232   public void testRemoveKeyValueExisting() {
    233     final ConcurrentMap<K, V> map;
    234     final K keyToRemove;
    235     try {
    236       map = makePopulatedMap();
    237     } catch (UnsupportedOperationException e) {
    238       return;
    239     }
    240     keyToRemove = map.keySet().iterator().next();
    241     V oldValue = map.get(keyToRemove);
    242     if (supportsRemove) {
    243       int initialSize = map.size();
    244       assertTrue(map.remove(keyToRemove, oldValue));
    245       assertFalse(map.containsKey(keyToRemove));
    246       assertEquals(initialSize - 1, map.size());
    247     } else {
    248       try {
    249         map.remove(keyToRemove, oldValue);
    250         fail("Expected UnsupportedOperationException.");
    251       } catch (UnsupportedOperationException e) {
    252         // Expected.
    253       }
    254     }
    255     assertInvariants(map);
    256   }
    257 
    258   public void testRemoveKeyValueMissingKey() {
    259     final ConcurrentMap<K, V> map;
    260     final K keyToRemove;
    261     final V valueToRemove;
    262     try {
    263       map = makePopulatedMap();
    264       keyToRemove = getKeyNotInPopulatedMap();
    265       valueToRemove = getValueNotInPopulatedMap();
    266     } catch (UnsupportedOperationException e) {
    267       return;
    268     }
    269     if (supportsRemove) {
    270       int initialSize = map.size();
    271       assertFalse(map.remove(keyToRemove, valueToRemove));
    272       assertEquals(initialSize, map.size());
    273     } else {
    274       try {
    275         map.remove(keyToRemove, valueToRemove);
    276         fail("Expected UnsupportedOperationException.");
    277       } catch (UnsupportedOperationException e) {
    278         // Expected.
    279       }
    280     }
    281     assertInvariants(map);
    282   }
    283 
    284   public void testRemoveKeyValueDifferentValue() {
    285     final ConcurrentMap<K, V> map;
    286     final K keyToRemove;
    287     final V valueToRemove;
    288     try {
    289       map = makePopulatedMap();
    290       valueToRemove = getValueNotInPopulatedMap();
    291     } catch (UnsupportedOperationException e) {
    292       return;
    293     }
    294     keyToRemove = map.keySet().iterator().next();
    295     if (supportsRemove) {
    296       int initialSize = map.size();
    297       V oldValue = map.get(keyToRemove);
    298       assertFalse(map.remove(keyToRemove, valueToRemove));
    299       assertEquals(oldValue, map.get(keyToRemove));
    300       assertTrue(map.containsKey(keyToRemove));
    301       assertEquals(initialSize, map.size());
    302     } else {
    303       try {
    304         map.remove(keyToRemove, valueToRemove);
    305         fail("Expected UnsupportedOperationException.");
    306       } catch (UnsupportedOperationException e) {
    307         // Expected.
    308       }
    309     }
    310     assertInvariants(map);
    311   }
    312 
    313   public void testRemoveKeyValueNullKey() {
    314     if (allowsNullKeys) {
    315       return;   // Not yet implemented
    316     }
    317     final ConcurrentMap<K, V> map;
    318     final V valueToRemove;
    319     try {
    320       map = makeEitherMap();
    321       valueToRemove = getValueNotInPopulatedMap();
    322     } catch (UnsupportedOperationException e) {
    323       return;
    324     }
    325     int initialSize = map.size();
    326     if (supportsRemove) {
    327       try {
    328         assertFalse(map.remove(null, valueToRemove));
    329       } catch (NullPointerException e) {
    330         // Optional.
    331       }
    332     } else {
    333       try {
    334         assertFalse(map.remove(null, valueToRemove));
    335       } catch (UnsupportedOperationException e) {
    336         // Optional.
    337       } catch (NullPointerException e) {
    338         // Optional.
    339       }
    340     }
    341     assertEquals(initialSize, map.size());
    342     assertInvariants(map);
    343   }
    344 
    345   public void testRemoveKeyValueExistingKeyNullValue() {
    346     if (allowsNullValues) {
    347       return;   // Not yet implemented
    348     }
    349     final ConcurrentMap<K, V> map;
    350     final K keyToRemove;
    351     try {
    352       map = makePopulatedMap();
    353     } catch (UnsupportedOperationException e) {
    354       return;
    355     }
    356     keyToRemove = map.keySet().iterator().next();
    357     int initialSize = map.size();
    358     if (supportsRemove) {
    359       try {
    360         assertFalse(map.remove(keyToRemove, null));
    361       } catch (NullPointerException e) {
    362         // Optional.
    363       }
    364     } else {
    365       try {
    366         assertFalse(map.remove(keyToRemove, null));
    367       } catch (UnsupportedOperationException e) {
    368         // Optional.
    369       } catch (NullPointerException e) {
    370         // Optional.
    371       }
    372     }
    373     assertEquals(initialSize, map.size());
    374     assertInvariants(map);
    375   }
    376 
    377   public void testRemoveKeyValueMissingKeyNullValue() {
    378     if (allowsNullValues) {
    379       return;   // Not yet implemented
    380     }
    381     final ConcurrentMap<K, V> map;
    382     final K keyToRemove;
    383     try {
    384       map = makeEitherMap();
    385       keyToRemove = getKeyNotInPopulatedMap();
    386     } catch (UnsupportedOperationException e) {
    387       return;
    388     }
    389     int initialSize = map.size();
    390     if (supportsRemove) {
    391       try {
    392         assertFalse(map.remove(keyToRemove, null));
    393       } catch (NullPointerException e) {
    394         // Optional.
    395       }
    396     } else {
    397       try {
    398         assertFalse(map.remove(keyToRemove, null));
    399       } catch (UnsupportedOperationException e) {
    400         // Optional.
    401       } catch (NullPointerException e) {
    402         // Optional.
    403       }
    404     }
    405     assertEquals(initialSize, map.size());
    406     assertInvariants(map);
    407   }
    408 
    409   /* Replace2 tests call 2-parameter replace(key, value) */
    410 
    411   public void testReplace2ExistingKey() {
    412     final ConcurrentMap<K, V> map;
    413     final K keyToReplace;
    414     final V newValue;
    415     try {
    416       map = makePopulatedMap();
    417       newValue = getValueNotInPopulatedMap();
    418     } catch (UnsupportedOperationException e) {
    419       return;
    420     }
    421     keyToReplace = map.keySet().iterator().next();
    422     if (supportsPut) {
    423       V oldValue = map.get(keyToReplace);
    424       int initialSize = map.size();
    425       assertEquals(oldValue, map.replace(keyToReplace, newValue));
    426       assertEquals(newValue, map.get(keyToReplace));
    427       assertTrue(map.containsKey(keyToReplace));
    428       assertTrue(map.containsValue(newValue));
    429       assertEquals(initialSize, map.size());
    430     } else {
    431       try {
    432         map.replace(keyToReplace, newValue);
    433         fail("Expected UnsupportedOperationException.");
    434       } catch (UnsupportedOperationException e) {
    435         // Expected.
    436       }
    437     }
    438     assertInvariants(map);
    439   }
    440 
    441   public void testReplace2MissingKey() {
    442     final ConcurrentMap<K, V> map;
    443     final K keyToReplace;
    444     final V newValue;
    445     try {
    446       map = makeEitherMap();
    447       keyToReplace = getKeyNotInPopulatedMap();
    448       newValue = getValueNotInPopulatedMap();
    449     } catch (UnsupportedOperationException e) {
    450       return;
    451     }
    452     if (supportsPut) {
    453       int initialSize = map.size();
    454       assertNull(map.replace(keyToReplace, newValue));
    455       assertNull(map.get(keyToReplace));
    456       assertFalse(map.containsKey(keyToReplace));
    457       assertFalse(map.containsValue(newValue));
    458       assertEquals(initialSize, map.size());
    459     } else {
    460       try {
    461         map.replace(keyToReplace, newValue);
    462         fail("Expected UnsupportedOperationException.");
    463       } catch (UnsupportedOperationException e) {
    464         // Expected.
    465       }
    466     }
    467     assertInvariants(map);
    468   }
    469 
    470   public void testReplace2NullKey() {
    471     if (allowsNullKeys) {
    472       return;   // Not yet implemented
    473     }
    474     final ConcurrentMap<K, V> map;
    475     final V valueToReplace;
    476     try {
    477       map = makeEitherMap();
    478       valueToReplace = getValueNotInPopulatedMap();
    479     } catch (UnsupportedOperationException e) {
    480       return;
    481     }
    482     int initialSize = map.size();
    483     if (supportsPut) {
    484       try {
    485         assertNull(map.replace(null, valueToReplace));
    486       } catch (NullPointerException e) {
    487         // Optional.
    488       }
    489     } else {
    490       try {
    491         assertNull(map.replace(null, valueToReplace));
    492       } catch (UnsupportedOperationException e) {
    493         // Optional.
    494       } catch (NullPointerException e) {
    495         // Optional.
    496       }
    497     }
    498     assertEquals(initialSize, map.size());
    499     assertInvariants(map);
    500   }
    501 
    502   public void testReplace2ExistingKeyNullValue() {
    503     if (allowsNullValues) {
    504       return;   // Not yet implemented
    505     }
    506     final ConcurrentMap<K, V> map;
    507     final K keyToReplace;
    508     try {
    509       map = makePopulatedMap();
    510     } catch (UnsupportedOperationException e) {
    511       return;
    512     }
    513     keyToReplace = map.keySet().iterator().next();
    514     int initialSize = map.size();
    515     if (supportsPut) {
    516       try {
    517         map.replace(keyToReplace, null);
    518         fail("Expected NullPointerException");
    519       } catch (NullPointerException e) {
    520         // Expected.
    521       }
    522     } else {
    523       try {
    524         map.replace(keyToReplace, null);
    525         fail("Expected UnsupportedOperationException or NullPointerException");
    526       } catch (UnsupportedOperationException e) {
    527         // Expected.
    528       } catch (NullPointerException e) {
    529         // Expected.
    530       }
    531     }
    532     assertEquals(initialSize, map.size());
    533     assertInvariants(map);
    534   }
    535 
    536   public void testReplace2MissingKeyNullValue() {
    537     if (allowsNullValues) {
    538       return;   // Not yet implemented
    539     }
    540     final ConcurrentMap<K, V> map;
    541     final K keyToReplace;
    542     try {
    543       map = makeEitherMap();
    544       keyToReplace = getKeyNotInPopulatedMap();
    545     } catch (UnsupportedOperationException e) {
    546       return;
    547     }
    548     int initialSize = map.size();
    549     if (supportsPut) {
    550       try {
    551         assertNull(map.replace(keyToReplace, null));
    552       } catch (NullPointerException e) {
    553         // Optional.
    554       }
    555     } else {
    556       try {
    557         assertNull(map.replace(keyToReplace, null));
    558       } catch (UnsupportedOperationException e) {
    559         // Optional.
    560       } catch (NullPointerException e) {
    561         // Optional.
    562       }
    563     }
    564     assertEquals(initialSize, map.size());
    565     assertInvariants(map);
    566   }
    567 
    568   /*
    569    * Replace3 tests call 3-parameter replace(key, oldValue, newValue)
    570    */
    571 
    572   public void testReplace3ExistingKeyValue() {
    573     final ConcurrentMap<K, V> map;
    574     final K keyToReplace;
    575     final V oldValue;
    576     final V newValue;
    577     try {
    578       map = makePopulatedMap();
    579       newValue = getValueNotInPopulatedMap();
    580     } catch (UnsupportedOperationException e) {
    581       return;
    582     }
    583     keyToReplace = map.keySet().iterator().next();
    584     oldValue = map.get(keyToReplace);
    585     if (supportsPut) {
    586       int initialSize = map.size();
    587       assertTrue(map.replace(keyToReplace, oldValue, newValue));
    588       assertEquals(newValue, map.get(keyToReplace));
    589       assertTrue(map.containsKey(keyToReplace));
    590       assertTrue(map.containsValue(newValue));
    591       assertFalse(map.containsValue(oldValue));
    592       assertEquals(initialSize, map.size());
    593     } else {
    594       try {
    595         map.replace(keyToReplace, oldValue, newValue);
    596         fail("Expected UnsupportedOperationException.");
    597       } catch (UnsupportedOperationException e) {
    598         // Expected.
    599       }
    600     }
    601     assertInvariants(map);
    602   }
    603 
    604   public void testReplace3ExistingKeyDifferentValue() {
    605     final ConcurrentMap<K, V> map;
    606     final K keyToReplace;
    607     final V oldValue;
    608     final V newValue;
    609     try {
    610       map = makePopulatedMap();
    611       oldValue = getValueNotInPopulatedMap();
    612       newValue = getSecondValueNotInPopulatedMap();
    613     } catch (UnsupportedOperationException e) {
    614       return;
    615     }
    616     keyToReplace = map.keySet().iterator().next();
    617     final V originalValue = map.get(keyToReplace);
    618     int initialSize = map.size();
    619     if (supportsPut) {
    620       assertFalse(map.replace(keyToReplace, oldValue, newValue));
    621     } else {
    622       try {
    623         map.replace(keyToReplace, oldValue, newValue);
    624         fail("Expected UnsupportedOperationException.");
    625       } catch (UnsupportedOperationException e) {
    626         // Expected.
    627       }
    628     }
    629     assertTrue(map.containsKey(keyToReplace));
    630     assertFalse(map.containsValue(newValue));
    631     assertFalse(map.containsValue(oldValue));
    632     assertEquals(originalValue, map.get(keyToReplace));
    633     assertEquals(initialSize, map.size());
    634     assertInvariants(map);
    635   }
    636 
    637   public void testReplace3MissingKey() {
    638     final ConcurrentMap<K, V> map;
    639     final K keyToReplace;
    640     final V oldValue;
    641     final V newValue;
    642     try {
    643       map = makeEitherMap();
    644       keyToReplace = getKeyNotInPopulatedMap();
    645       oldValue = getValueNotInPopulatedMap();
    646       newValue = getSecondValueNotInPopulatedMap();
    647     } catch (UnsupportedOperationException e) {
    648       return;
    649     }
    650     int initialSize = map.size();
    651     if (supportsPut) {
    652       assertFalse(map.replace(keyToReplace, oldValue, newValue));
    653     } else {
    654       try {
    655         map.replace(keyToReplace, oldValue, newValue);
    656         fail("Expected UnsupportedOperationException.");
    657       } catch (UnsupportedOperationException e) {
    658         // Expected.
    659       }
    660     }
    661     assertFalse(map.containsKey(keyToReplace));
    662     assertFalse(map.containsValue(newValue));
    663     assertFalse(map.containsValue(oldValue));
    664     assertEquals(initialSize, map.size());
    665     assertInvariants(map);
    666   }
    667 
    668   public void testReplace3NullKey() {
    669     if (allowsNullKeys) {
    670       return;   // Not yet implemented
    671     }
    672     final ConcurrentMap<K, V> map;
    673     final V oldValue;
    674     final V newValue;
    675     try {
    676       map = makeEitherMap();
    677       oldValue = getValueNotInPopulatedMap();
    678       newValue = getSecondValueNotInPopulatedMap();
    679     } catch (UnsupportedOperationException e) {
    680       return;
    681     }
    682     int initialSize = map.size();
    683     if (supportsPut) {
    684       try {
    685         assertFalse(map.replace(null, oldValue, newValue));
    686       } catch (NullPointerException e) {
    687         // Optional.
    688       }
    689     } else {
    690       try {
    691         assertFalse(map.replace(null, oldValue, newValue));
    692       } catch (UnsupportedOperationException e) {
    693         // Optional.
    694       } catch (NullPointerException e) {
    695         // Optional.
    696       }
    697     }
    698     assertEquals(initialSize, map.size());
    699     assertInvariants(map);
    700   }
    701 
    702   public void testReplace3ExistingKeyNullOldValue() {
    703     if (allowsNullValues) {
    704       return;   // Not yet implemented
    705     }
    706     final ConcurrentMap<K, V> map;
    707     final K keyToReplace;
    708     final V newValue;
    709     try {
    710       map = makePopulatedMap();
    711       newValue = getValueNotInPopulatedMap();
    712     } catch (UnsupportedOperationException e) {
    713       return;
    714     }
    715     keyToReplace = map.keySet().iterator().next();
    716     final V originalValue = map.get(keyToReplace);
    717     int initialSize = map.size();
    718     if (supportsPut) {
    719       try {
    720         assertFalse(map.replace(keyToReplace, null, newValue));
    721       } catch (NullPointerException e) {
    722         // Optional.
    723       }
    724     } else {
    725       try {
    726         assertFalse(map.replace(keyToReplace, null, newValue));
    727       } catch (UnsupportedOperationException e) {
    728         // Optional.
    729       } catch (NullPointerException e) {
    730         // Optional.
    731       }
    732     }
    733     assertEquals(initialSize, map.size());
    734     assertEquals(originalValue, map.get(keyToReplace));
    735     assertInvariants(map);
    736   }
    737 
    738   public void testReplace3MissingKeyNullOldValue() {
    739     if (allowsNullValues) {
    740       return;   // Not yet implemented
    741     }
    742     final ConcurrentMap<K, V> map;
    743     final K keyToReplace;
    744     final V newValue;
    745     try {
    746       map = makeEitherMap();
    747       keyToReplace = getKeyNotInPopulatedMap();
    748       newValue = getValueNotInPopulatedMap();
    749     } catch (UnsupportedOperationException e) {
    750       return;
    751     }
    752     int initialSize = map.size();
    753     if (supportsPut) {
    754       try {
    755         assertFalse(map.replace(keyToReplace, null, newValue));
    756       } catch (NullPointerException e) {
    757         // Optional.
    758       }
    759     } else {
    760       try {
    761         assertFalse(map.replace(keyToReplace, null, newValue));
    762       } catch (UnsupportedOperationException e) {
    763         // Optional.
    764       } catch (NullPointerException e) {
    765         // Optional.
    766       }
    767     }
    768     assertEquals(initialSize, map.size());
    769     assertInvariants(map);
    770   }
    771 
    772   public void testReplace3MissingKeyNullNewValue() {
    773     if (allowsNullValues) {
    774       return;   // Not yet implemented
    775     }
    776     final ConcurrentMap<K, V> map;
    777     final K keyToReplace;
    778     final V oldValue;
    779     try {
    780       map = makeEitherMap();
    781       keyToReplace = getKeyNotInPopulatedMap();
    782       oldValue = getValueNotInPopulatedMap();
    783     } catch (UnsupportedOperationException e) {
    784       return;
    785     }
    786     int initialSize = map.size();
    787     if (supportsPut) {
    788       try {
    789         map.replace(keyToReplace, oldValue, null);
    790       } catch (NullPointerException e) {
    791         // Optional.
    792       }
    793     } else {
    794       try {
    795         map.replace(keyToReplace, oldValue, null);
    796       } catch (UnsupportedOperationException e) {
    797         // Optional.
    798       } catch (NullPointerException e) {
    799         // Optional.
    800       }
    801     }
    802     assertEquals(initialSize, map.size());
    803     assertInvariants(map);
    804   }
    805 
    806   public void testReplace3ExistingKeyValueNullNewValue() {
    807     if (allowsNullValues) {
    808       return;   // Not yet implemented
    809     }
    810     final ConcurrentMap<K, V> map;
    811     final K keyToReplace;
    812     final V oldValue;
    813     try {
    814       map = makePopulatedMap();
    815     } catch (UnsupportedOperationException e) {
    816       return;
    817     }
    818     keyToReplace = map.keySet().iterator().next();
    819     oldValue = map.get(keyToReplace);
    820     int initialSize = map.size();
    821     if (supportsPut) {
    822       try {
    823         map.replace(keyToReplace, oldValue, null);
    824         fail("Expected NullPointerException");
    825       } catch (NullPointerException e) {
    826         // Expected.
    827       }
    828     } else {
    829       try {
    830         map.replace(keyToReplace, oldValue, null);
    831         fail("Expected UnsupportedOperationException or NullPointerException");
    832       } catch (UnsupportedOperationException e) {
    833         // Expected.
    834       } catch (NullPointerException e) {
    835         // Expected.
    836       }
    837     }
    838     assertEquals(initialSize, map.size());
    839     assertEquals(oldValue, map.get(keyToReplace));
    840     assertInvariants(map);
    841   }
    842 }
    843