test/java/util/Map/Defaults.java

Print this page
rev 7360 : 8016446: Improve forEach/replaceAll for Map, HashMap, Hashtable, IdentityHashMap, WeakHashMap, TreeMap
Reviewed-by: forax, duigou, psandoz
Contributed-by: Mike Duigou <mike.duigou@oracle.com>, Remi Forax <forax@univ-mlv.fr>


  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8010122 8004518
  27  * @summary Test Map default methods
  28  * @author Mike Duigou
  29  * @run testng Defaults
  30  */
  31 import java.util.AbstractMap;
  32 import java.util.AbstractSet;
  33 import java.util.ArrayList;
  34 import java.util.Arrays;
  35 import java.util.Collection;
  36 import java.util.Collections;
  37 import java.util.EnumMap;
  38 import java.util.HashMap;

  39 import java.util.Hashtable;
  40 import java.util.IdentityHashMap;
  41 import java.util.Iterator;
  42 import java.util.LinkedHashMap;
  43 import java.util.Map;
  44 import java.util.TreeMap;
  45 import java.util.Set;
  46 import java.util.WeakHashMap;
  47 import java.util.concurrent.ConcurrentMap;
  48 import java.util.concurrent.ConcurrentHashMap;
  49 import java.util.concurrent.ConcurrentSkipListMap;

  50 import java.util.function.Supplier;
  51 
  52 import org.testng.annotations.Test;
  53 import org.testng.annotations.DataProvider;
  54 import static org.testng.Assert.fail;
  55 import static org.testng.Assert.assertEquals;
  56 import static org.testng.Assert.assertTrue;
  57 import static org.testng.Assert.assertFalse;
  58 import static org.testng.Assert.assertNull;
  59 import static org.testng.Assert.assertSame;
  60 
  61 public class Defaults {
  62 
  63     @Test(dataProvider = "Nulls Map<IntegerEnum,String>")
  64     public void testGetOrDefaultNulls(String description, Map<IntegerEnum, String> map) {
  65         assertTrue(map.containsKey(null), "null key absent");
  66         assertNull(map.get(null), "value not null");
  67         assertSame(map.get(null), map.getOrDefault(null, EXTRA_VALUE), "values should match");
  68     }
  69 
  70     @Test(dataProvider = "Map<IntegerEnum,String>")
  71     public void testGetOrDefault(String description, Map<IntegerEnum, String> map) {
  72         assertTrue(map.containsKey(KEYS[1]), "expected key missing");
  73         assertSame(map.get(KEYS[1]), map.getOrDefault(KEYS[1], EXTRA_VALUE), "values should match");
  74         assertFalse(map.containsKey(EXTRA_KEY), "expected absent key");
  75         assertSame(map.getOrDefault(EXTRA_KEY, EXTRA_VALUE), EXTRA_VALUE, "value not returned as default");
  76         assertNull(map.getOrDefault(EXTRA_KEY, null), "null not returned as default");
  77     }
  78 
  79     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
  80     public void testPutIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
  81         assertTrue(map.containsKey(null), "null key absent");
  82         assertNull(map.get(null), "value not null");
  83         assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
  84         assertTrue(map.containsKey(null), "null key absent");
  85         assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
  86         assertSame(map.putIfAbsent(null, null), EXTRA_VALUE, "previous not expected value");
  87         assertTrue(map.containsKey(null), "null key absent");
  88         assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
  89         assertSame(map.remove(null), EXTRA_VALUE, "removed unexpected value");
  90 
  91         assertFalse(map.containsKey(null), description + ": key present after remove");
  92         assertNull(map.putIfAbsent(null, null), "previous not null");
  93         assertTrue(map.containsKey(null), "null key absent");
  94         assertNull(map.get(null), "value not null");
  95         assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
  96         assertSame(map.get(null), EXTRA_VALUE, "value not expected");
  97     }
  98 
  99     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 100     public void testPutIfAbsent(String description, Map<IntegerEnum, String> map) {
 101         assertTrue(map.containsKey(KEYS[1]));
 102         Object expected = map.get(KEYS[1]);
 103         assertTrue(null == expected || expected == VALUES[1]);
 104         assertSame(map.putIfAbsent(KEYS[1], EXTRA_VALUE), expected);
 105         assertSame(map.get(KEYS[1]), expected);
 106 
 107         assertFalse(map.containsKey(EXTRA_KEY));
 108         assertSame(map.putIfAbsent(EXTRA_KEY, EXTRA_VALUE), null);
 109         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 110     }
 111 
 112     @Test(dataProvider = "Nulls Map<IntegerEnum,String>")
 113     public void testForEach(String description, Map<IntegerEnum, String> map) {
 114         IntegerEnum[] EACH_KEY = new IntegerEnum[map.size()];
 115 
 116         map.forEach((k, v) -> {
 117             int idx = (null == k) ? 0 : k.ordinal(); // substitute for index.
 118             assertNull(EACH_KEY[idx]);
 119             EACH_KEY[idx] = (idx == 0) ? KEYS[0] : k; // substitute for comparison.
 120             assertSame(v, map.get(k));
 121         });
 122 
 123         assertEquals(KEYS, EACH_KEY);

































 124     }
 125 
 126     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 127     public static void testRemoveNulls(String description, Map<IntegerEnum, String> map) {
 128         assertTrue(map.containsKey(null), "null key absent");
 129         assertNull(map.get(null), "value not null");
 130         assertFalse(map.remove(null, EXTRA_VALUE), description);
 131         assertTrue(map.containsKey(null));
 132         assertNull(map.get(null));
 133         assertTrue(map.remove(null, null));
 134         assertFalse(map.containsKey(null));
 135         assertNull(map.get(null));
 136         assertFalse(map.remove(null, null));
 137     }
 138 
 139     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 140     public static void testRemove(String description, Map<IntegerEnum, String> map) {
 141         assertTrue(map.containsKey(KEYS[1]));
 142         Object expected = map.get(KEYS[1]);
 143         assertTrue(null == expected || expected == VALUES[1]);
 144         assertFalse(map.remove(KEYS[1], EXTRA_VALUE), description);
 145         assertSame(map.get(KEYS[1]), expected);
 146         assertTrue(map.remove(KEYS[1], expected));
 147         assertNull(map.get(KEYS[1]));
 148         assertFalse(map.remove(KEYS[1], expected));
 149 
 150         assertFalse(map.containsKey(EXTRA_KEY));
 151         assertFalse(map.remove(EXTRA_KEY, EXTRA_VALUE));
 152     }
 153 
 154     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 155     public void testReplaceKVNulls(String description, Map<IntegerEnum, String> map) {
 156         assertTrue(map.containsKey(null), "null key absent");
 157         assertNull(map.get(null), "value not null");
 158         assertSame(map.replace(null, EXTRA_VALUE), null);
 159         assertSame(map.get(null), EXTRA_VALUE);
 160     }
 161 
 162     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 163     public void testReplaceKV(String description, Map<IntegerEnum, String> map) {
 164         assertTrue(map.containsKey(KEYS[1]));
 165         Object expected = map.get(KEYS[1]);
 166         assertTrue(null == expected || expected == VALUES[1]);
 167         assertSame(map.replace(KEYS[1], EXTRA_VALUE), expected);
 168         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 169 
 170         assertFalse(map.containsKey(EXTRA_KEY));
 171         assertNull(map.replace(EXTRA_KEY, EXTRA_VALUE));
 172         assertFalse(map.containsKey(EXTRA_KEY));
 173         assertNull(map.get(EXTRA_KEY));
 174         assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
 175         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 176         assertSame(map.replace(EXTRA_KEY, (String)expected), EXTRA_VALUE);
 177         assertSame(map.get(EXTRA_KEY), expected);
 178     }
 179 
 180     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 181     public void testReplaceKVVNulls(String description, Map<IntegerEnum, String> map) {
 182         assertTrue(map.containsKey(null), "null key absent");
 183         assertNull(map.get(null), "value not null");
 184         assertFalse(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
 185         assertNull(map.get(null));
 186         assertTrue(map.replace(null, null, EXTRA_VALUE));
 187         assertSame(map.get(null), EXTRA_VALUE);
 188         assertTrue(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
 189         assertSame(map.get(null), EXTRA_VALUE);
 190     }
 191 
 192     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 193     public void testReplaceKVV(String description, Map<IntegerEnum, String> map) {
 194         assertTrue(map.containsKey(KEYS[1]));
 195         Object expected = map.get(KEYS[1]);
 196         assertTrue(null == expected || expected == VALUES[1]);
 197         assertFalse(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
 198         assertSame(map.get(KEYS[1]), expected);
 199         assertTrue(map.replace(KEYS[1], (String)expected, EXTRA_VALUE));
 200         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 201         assertTrue(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
 202         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 203 
 204         assertFalse(map.containsKey(EXTRA_KEY));
 205         assertFalse(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
 206         assertFalse(map.containsKey(EXTRA_KEY));
 207         assertNull(map.get(EXTRA_KEY));
 208         assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
 209         assertTrue(map.containsKey(EXTRA_KEY));
 210         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 211         assertTrue(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
 212         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 213     }
 214 
 215     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 216     public void testComputeIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
 217         assertTrue(map.containsKey(null), "null key absent");
 218         assertNull(map.get(null), "value not null");
 219         assertSame(map.computeIfAbsent(null, (k) -> EXTRA_VALUE), EXTRA_VALUE, description);
 220         assertSame(map.get(null), EXTRA_VALUE, description);
 221     }
 222 
 223     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 224     public void testComputeIfAbsent(String description, Map<IntegerEnum, String> map) {
 225         assertTrue(map.containsKey(KEYS[1]));
 226         Object expected = map.get(KEYS[1]);
 227         assertTrue(null == expected || expected == VALUES[1], description + String.valueOf(expected));
 228         expected = (null == expected) ? EXTRA_VALUE : expected;
 229         assertSame(map.computeIfAbsent(KEYS[1], (k) -> EXTRA_VALUE), expected, description);
 230         assertSame(map.get(KEYS[1]), expected, description);
 231 
 232         assertFalse(map.containsKey(EXTRA_KEY));
 233         assertSame(map.computeIfAbsent(EXTRA_KEY, (k) -> EXTRA_VALUE), EXTRA_VALUE);
 234         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 235     }
 236 
 237     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 238     public void testComputeIfPresentNulls(String description, Map<IntegerEnum, String> map) {
 239         assertTrue(map.containsKey(null));
 240         assertNull(map.get(null));
 241         assertSame(map.computeIfPresent(null, (k, v) -> {
 242             fail();
 243             return EXTRA_VALUE;
 244         }), null, description);
 245         assertTrue(map.containsKey(null));
 246         assertSame(map.get(null), null, description);
 247     }
 248 
 249     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 250     public void testComputeIfPresent(String description, Map<IntegerEnum, String> map) {
 251         assertTrue(map.containsKey(KEYS[1]));
 252         Object value = map.get(KEYS[1]);
 253         assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
 254         Object expected = (null == value) ? null : EXTRA_VALUE;
 255         assertSame(map.computeIfPresent(KEYS[1], (k, v) -> {
 256             assertSame(v, value);
 257             return EXTRA_VALUE;
 258         }), expected, description);
 259         assertSame(map.get(KEYS[1]), expected, description);
 260 
 261         assertFalse(map.containsKey(EXTRA_KEY));
 262         assertSame(map.computeIfPresent(EXTRA_KEY, (k, v) -> {
 263             fail();
 264             return EXTRA_VALUE;
 265         }), null);
 266         assertFalse(map.containsKey(EXTRA_KEY));
 267         assertSame(map.get(EXTRA_KEY), null);
 268     }
 269 
 270     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 271     public void testComputeNulls(String description, Map<IntegerEnum, String> map) {
 272         assertTrue(map.containsKey(null), "null key absent");
 273         assertNull(map.get(null), "value not null");
 274         assertSame(map.compute(null, (k, v) -> {
 275             assertSame(k, null);
 276             assertNull(v);
 277             return EXTRA_VALUE;
 278         }), EXTRA_VALUE, description);
 279         assertTrue(map.containsKey(null));
 280         assertSame(map.get(null), EXTRA_VALUE, description);
 281         assertSame(map.remove(null), EXTRA_VALUE, "removed value not expected");
 282         assertFalse(map.containsKey(null), "null key present");
 283         assertSame(map.compute(null, (k, v) -> {
 284             assertSame(k, null);
 285             assertNull(v);
 286             return null;
 287         }), null, description);
 288     }
 289 
 290     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 291     public void testCompute(String description, Map<IntegerEnum, String> map) {
 292         assertTrue(map.containsKey(KEYS[1]));
 293         Object value = map.get(KEYS[1]);
 294         assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
 295         assertSame(map.compute(KEYS[1], (k, v) -> {
 296             assertSame(k, KEYS[1]);
 297             assertSame(v, value);
 298             return EXTRA_VALUE;
 299         }), EXTRA_VALUE, description);
 300         assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
 301         assertNull(map.compute(KEYS[1], (k, v) -> {
 302             assertSame(v, EXTRA_VALUE);
 303             return null;
 304         }), description);
 305         assertFalse(map.containsKey(KEYS[1]));
 306 
 307         assertFalse(map.containsKey(EXTRA_KEY));
 308         assertSame(map.compute(EXTRA_KEY, (k, v) -> {
 309             assertNull(v);
 310             return EXTRA_VALUE;
 311         }), EXTRA_VALUE);
 312         assertTrue(map.containsKey(EXTRA_KEY));
 313         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 314     }
 315 
 316 
 317     @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
 318     public void testMergeNulls(String description, Map<IntegerEnum, String> map) {
 319         assertTrue(map.containsKey(null), "null key absent");
 320         assertNull(map.get(null), "value not null");
 321         assertSame(map.merge(null, EXTRA_VALUE, (v, vv) -> {
 322             assertNull(v);
 323             assertSame(vv, EXTRA_VALUE);
 324             return vv;
 325         }), EXTRA_VALUE, description);
 326         assertTrue(map.containsKey(null));
 327         assertSame(map.get(null), EXTRA_VALUE, description);
 328     }
 329 
 330     @Test(dataProvider = "R/W Map<IntegerEnum,String>")
 331     public void testMerge(String description, Map<IntegerEnum, String> map) {
 332         assertTrue(map.containsKey(KEYS[1]));
 333         Object value = map.get(KEYS[1]);
 334         assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
 335         assertSame(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
 336             assertSame(v, value);
 337             assertSame(vv, EXTRA_VALUE);
 338             return vv;
 339         }), EXTRA_VALUE, description);
 340         assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
 341         assertNull(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
 342             assertSame(v, EXTRA_VALUE);
 343             assertSame(vv, EXTRA_VALUE);
 344             return null;
 345         }), description);
 346         assertFalse(map.containsKey(KEYS[1]));
 347 
 348         assertFalse(map.containsKey(EXTRA_KEY));
 349         assertSame(map.merge(EXTRA_KEY, EXTRA_VALUE, (v, vv) -> {
 350             assertNull(v);


 374     /**
 375      * Realized keys ensure that there is always a hard ref to all test objects.
 376      */
 377     private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
 378     /**
 379      * Realized values ensure that there is always a hard ref to all test
 380      * objects.
 381      */
 382     private static final String[] VALUES = new String[TEST_SIZE];
 383 
 384     static {
 385         IntegerEnum[] keys = IntegerEnum.values();
 386         for (int each = 0; each < TEST_SIZE; each++) {
 387             KEYS[each] = keys[each];
 388             VALUES[each] = String.valueOf(each);
 389         }
 390     }
 391     private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
 392     private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
 393 
 394     @DataProvider(name = "Map<IntegerEnum,String>", parallel = true)
 395     public static Iterator<Object[]> allNullsMapProvider() {
 396         return makeAllMaps().iterator();
 397     }
 398 
 399     @DataProvider(name = "Nulls Map<IntegerEnum,String>", parallel = true)
 400     public static Iterator<Object[]> allMapProvider() {
 401         return makeRWMaps(true).iterator();
 402     }
 403 
 404     @DataProvider(name = "R/W Map<IntegerEnum,String>", parallel = true)
 405     public static Iterator<Object[]> rwMapProvider() {





 406         return makeRWMapsNoNulls().iterator();
 407     }
 408 
 409     @DataProvider(name = "R/W Nulls Map<IntegerEnum,String>", parallel = true)





 410     public static Iterator<Object[]> rwNullsMapProvider() {
 411         return makeRWMaps(true).iterator();
 412     }
 413 
 414     private static Collection<Object[]> makeAllMapsNoNulls() {
 415         Collection<Object[]> all = new ArrayList<>();
 416 
 417         all.addAll(makeRWMaps(false));
 418         all.addAll(makeRWNoNullsMaps());
 419         all.addAll(makeROMaps(false));
 420 
 421         return all;
 422     }
 423 

 424     private static Collection<Object[]> makeRWMapsNoNulls() {
 425         Collection<Object[]> all = new ArrayList<>();
 426 
 427         all.addAll(makeRWMaps(false));
 428         all.addAll(makeRWNoNullsMaps());
 429 
 430         return all;
 431     }
 432 
 433     private static Collection<Object[]> makeAllMaps() {
 434         Collection<Object[]> all = new ArrayList<>();
 435 
 436         all.addAll(makeROMaps(false));
 437         all.addAll(makeRWMaps(false));
 438         all.addAll(makeRWNoNullsMaps());
 439         all.addAll(makeRWMaps(true));
 440         all.addAll(makeROMaps(true));
 441 
 442         return all;
 443     }
 444 
 445     private static Collection<Object[]> makeAllRWMaps() {
 446         Collection<Object[]> all = new ArrayList<>();
 447 
 448         all.addAll(makeRWMaps(false));
 449         all.addAll(makeRWNoNullsMaps());
 450         all.addAll(makeRWMaps(true));










 451 
 452         return all;
 453     }
 454 
 455     private static Collection<Object[]> makeRWMaps(boolean nulls) {






























 456         return Arrays.asList(
 457             new Object[]{"HashMap", makeMap(HashMap::new, nulls)},
 458             new Object[]{"IdentityHashMap", makeMap(IdentityHashMap::new, nulls)},
 459             new Object[]{"LinkedHashMap", makeMap(LinkedHashMap::new, nulls)},
 460             new Object[]{"WeakHashMap", makeMap(WeakHashMap::new, nulls)},
 461             new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(makeMap(HashMap::new, nulls), IntegerEnum.class, String.class)},
 462             new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(makeMap(HashMap::new, nulls))},
 463             new Object[]{"ExtendsAbstractMap", makeMap(ExtendsAbstractMap::new, nulls)});
 464     }
 465 
 466     private static Collection<Object[]> makeRWNoNullsMaps() {
 467         return Arrays.asList(
 468             // null hostile
 469             new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false)},
 470             new Object[]{"Hashtable", makeMap(Hashtable::new, false)},
 471             new Object[]{"TreeMap", makeMap(TreeMap::new, false)},
 472             new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false)},
 473             new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false)},
 474             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false), IntegerEnum.class, String.class)},
 475             new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false))},
 476             new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false)});
 477     }
 478 





 479     private static Collection<Object[]> makeROMaps(boolean nulls) {
 480         return Arrays.asList(new Object[][]{
 481             new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls))}
 482         });
 483     }
 484 
 485     private static Map<IntegerEnum, String> makeMap(Supplier<Map<IntegerEnum, String>> supplier, boolean nulls) {








 486         Map<IntegerEnum, String> result = supplier.get();
 487 
 488         for (int each = 0; each < TEST_SIZE; each++) {
 489             if (nulls) {
 490                 result.put((each == 0) ? null : KEYS[each], null);
 491             } else {
 492                 result.put(KEYS[each], VALUES[each]);
 493             }
 494         }
 495 
 496         return result;
 497     }
 498 
 499     public interface Thrower<T extends Throwable> {
 500 
 501         public void run() throws T;
 502     }
 503 
 504     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
 505         assertThrows(thrower, throwable, null);
 506     }
 507 
 508     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
 509         Throwable result;
 510         try {
 511             thrower.run();
 512             result = null;
 513         } catch (Throwable caught) {
 514             result = caught;
 515         }
 516 
 517         assertInstance(result, throwable,
 518             (null != message)
 519             ? message
 520             : "Failed to throw " + throwable.getCanonicalName());






 521     }
 522 
 523     public static <T> void assertInstance(T actual, Class<? extends T> expected) {
 524         assertInstance(expected.isInstance(actual), null);
 525     }
 526 
 527     public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) {
 528         assertTrue(expected.isInstance(actual), message);
 529     }
 530 
 531     /**
 532      * A simple mutable map implementation that provides only default
 533      * implementations of all methods. ie. none of the Map interface default
 534      * methods have overridden implementations.
 535      *
 536      * @param <K> Type of keys
 537      * @param <V> Type of values
 538      */
 539     public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
 540 




  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8010122 8004518
  27  * @summary Test Map default methods
  28  * @author Mike Duigou
  29  * @run testng Defaults
  30  */
  31 import java.util.AbstractMap;
  32 import java.util.AbstractSet;
  33 import java.util.ArrayList;
  34 import java.util.Arrays;
  35 import java.util.Collection;
  36 import java.util.Collections;
  37 import java.util.EnumMap;
  38 import java.util.HashMap;
  39 import java.util.HashSet;
  40 import java.util.Hashtable;
  41 import java.util.IdentityHashMap;
  42 import java.util.Iterator;
  43 import java.util.LinkedHashMap;
  44 import java.util.Map;
  45 import java.util.TreeMap;
  46 import java.util.Set;
  47 import java.util.WeakHashMap;
  48 import java.util.concurrent.ConcurrentMap;
  49 import java.util.concurrent.ConcurrentHashMap;
  50 import java.util.concurrent.ConcurrentSkipListMap;
  51 import java.util.function.BiFunction;
  52 import java.util.function.Supplier;
  53 
  54 import org.testng.annotations.Test;
  55 import org.testng.annotations.DataProvider;
  56 import static org.testng.Assert.fail;
  57 import static org.testng.Assert.assertEquals;
  58 import static org.testng.Assert.assertTrue;
  59 import static org.testng.Assert.assertFalse;
  60 import static org.testng.Assert.assertNull;
  61 import static org.testng.Assert.assertSame;
  62 
  63 public class Defaults {
  64 
  65     @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull")
  66     public void testGetOrDefaultNulls(String description, Map<IntegerEnum, String> map) {
  67         assertTrue(map.containsKey(null), description + ": null key absent");
  68         assertNull(map.get(null), description + ": value not null");
  69         assertSame(map.get(null), map.getOrDefault(null, EXTRA_VALUE), description + ": values should match");
  70     }
  71 
  72     @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=all values=all")
  73     public void testGetOrDefault(String description, Map<IntegerEnum, String> map) {
  74         assertTrue(map.containsKey(KEYS[1]), "expected key missing");
  75         assertSame(map.get(KEYS[1]), map.getOrDefault(KEYS[1], EXTRA_VALUE), "values should match");
  76         assertFalse(map.containsKey(EXTRA_KEY), "expected absent key");
  77         assertSame(map.getOrDefault(EXTRA_KEY, EXTRA_VALUE), EXTRA_VALUE, "value not returned as default");
  78         assertNull(map.getOrDefault(EXTRA_KEY, null), "null not returned as default");
  79     }
  80 
  81     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
  82     public void testPutIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
  83         assertTrue(map.containsKey(null), "null key absent");
  84         assertNull(map.get(null), "value not null");
  85         assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
  86         assertTrue(map.containsKey(null), "null key absent");
  87         assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
  88         assertSame(map.putIfAbsent(null, null), EXTRA_VALUE, "previous not expected value");
  89         assertTrue(map.containsKey(null), "null key absent");
  90         assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
  91         assertSame(map.remove(null), EXTRA_VALUE, "removed unexpected value");
  92 
  93         assertFalse(map.containsKey(null), description + ": key present after remove");
  94         assertNull(map.putIfAbsent(null, null), "previous not null");
  95         assertTrue(map.containsKey(null), "null key absent");
  96         assertNull(map.get(null), "value not null");
  97         assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
  98         assertSame(map.get(null), EXTRA_VALUE, "value not expected");
  99     }
 100 
 101     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 102     public void testPutIfAbsent(String description, Map<IntegerEnum, String> map) {
 103         assertTrue(map.containsKey(KEYS[1]));
 104         Object expected = map.get(KEYS[1]);
 105         assertTrue(null == expected || expected == VALUES[1]);
 106         assertSame(map.putIfAbsent(KEYS[1], EXTRA_VALUE), expected);
 107         assertSame(map.get(KEYS[1]), expected);
 108 
 109         assertFalse(map.containsKey(EXTRA_KEY));
 110         assertSame(map.putIfAbsent(EXTRA_KEY, EXTRA_VALUE), null);
 111         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 112     }
 113 
 114     @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=all values=all")
 115     public void testForEach(String description, Map<IntegerEnum, String> map) {
 116         IntegerEnum[] EACH_KEY = new IntegerEnum[map.size()];
 117 
 118         map.forEach((k, v) -> {
 119             int idx = (null == k) ? 0 : k.ordinal(); // substitute for index.
 120             assertNull(EACH_KEY[idx]);
 121             EACH_KEY[idx] = (idx == 0) ? KEYS[0] : k; // substitute for comparison.
 122             assertSame(v, map.get(k));
 123         });
 124 
 125         assertEquals(KEYS, EACH_KEY, description);
 126     }
 127 
 128     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 129     public static void testReplaceAll(String description, Map<IntegerEnum, String> map) {
 130         IntegerEnum[] EACH_KEY = new IntegerEnum[map.size()];
 131         Set<String> EACH_REPLACE = new HashSet<>(map.size());
 132 
 133         map.replaceAll((k,v) -> {
 134             int idx = (null == k) ? 0 : k.ordinal(); // substitute for index.
 135             assertNull(EACH_KEY[idx]);
 136             EACH_KEY[idx] = (idx == 0) ? KEYS[0] : k; // substitute for comparison.
 137             assertSame(v, map.get(k));
 138             String replacement = v + " replaced";
 139             EACH_REPLACE.add(replacement);
 140             return replacement;
 141         });
 142 
 143         assertEquals(KEYS, EACH_KEY, description);
 144         assertEquals(map.values().size(), EACH_REPLACE.size(), description + EACH_REPLACE);
 145         assertTrue(EACH_REPLACE.containsAll(map.values()), description + " : " + EACH_REPLACE + " != " + map.values());
 146         assertTrue(map.values().containsAll(EACH_REPLACE), description + " : " + EACH_REPLACE + " != " + map.values());
 147     }
 148 
 149     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
 150     public static void testReplaceAllNoNullReplacement(String description, Map<IntegerEnum, String> map) {
 151         assertThrows(
 152             () -> { map.replaceAll(null); },
 153             NullPointerException.class,
 154             description);
 155         assertThrows(
 156             () -> { map.replaceAll((k,v) -> null); },
 157             NullPointerException.class,
 158             description);
 159     }
 160 
 161     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 162     public static void testRemoveNulls(String description, Map<IntegerEnum, String> map) {
 163         assertTrue(map.containsKey(null), "null key absent");
 164         assertNull(map.get(null), "value not null");
 165         assertFalse(map.remove(null, EXTRA_VALUE), description);
 166         assertTrue(map.containsKey(null));
 167         assertNull(map.get(null));
 168         assertTrue(map.remove(null, null));
 169         assertFalse(map.containsKey(null));
 170         assertNull(map.get(null));
 171         assertFalse(map.remove(null, null));
 172     }
 173 
 174     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 175     public static void testRemove(String description, Map<IntegerEnum, String> map) {
 176         assertTrue(map.containsKey(KEYS[1]));
 177         Object expected = map.get(KEYS[1]);
 178         assertTrue(null == expected || expected == VALUES[1]);
 179         assertFalse(map.remove(KEYS[1], EXTRA_VALUE), description);
 180         assertSame(map.get(KEYS[1]), expected);
 181         assertTrue(map.remove(KEYS[1], expected));
 182         assertNull(map.get(KEYS[1]));
 183         assertFalse(map.remove(KEYS[1], expected));
 184 
 185         assertFalse(map.containsKey(EXTRA_KEY));
 186         assertFalse(map.remove(EXTRA_KEY, EXTRA_VALUE));
 187     }
 188 
 189     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 190     public void testReplaceKVNulls(String description, Map<IntegerEnum, String> map) {
 191         assertTrue(map.containsKey(null), "null key absent");
 192         assertNull(map.get(null), "value not null");
 193         assertSame(map.replace(null, EXTRA_VALUE), null);
 194         assertSame(map.get(null), EXTRA_VALUE);
 195     }
 196 
 197     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 198     public void testReplaceKV(String description, Map<IntegerEnum, String> map) {
 199         assertTrue(map.containsKey(KEYS[1]));
 200         Object expected = map.get(KEYS[1]);
 201         assertTrue(null == expected || expected == VALUES[1]);
 202         assertSame(map.replace(KEYS[1], EXTRA_VALUE), expected);
 203         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 204 
 205         assertFalse(map.containsKey(EXTRA_KEY));
 206         assertNull(map.replace(EXTRA_KEY, EXTRA_VALUE));
 207         assertFalse(map.containsKey(EXTRA_KEY));
 208         assertNull(map.get(EXTRA_KEY));
 209         assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
 210         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 211         assertSame(map.replace(EXTRA_KEY, (String)expected), EXTRA_VALUE);
 212         assertSame(map.get(EXTRA_KEY), expected);
 213     }
 214 
 215     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 216     public void testReplaceKVVNulls(String description, Map<IntegerEnum, String> map) {
 217         assertTrue(map.containsKey(null), "null key absent");
 218         assertNull(map.get(null), "value not null");
 219         assertFalse(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
 220         assertNull(map.get(null));
 221         assertTrue(map.replace(null, null, EXTRA_VALUE));
 222         assertSame(map.get(null), EXTRA_VALUE);
 223         assertTrue(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
 224         assertSame(map.get(null), EXTRA_VALUE);
 225     }
 226 
 227     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 228     public void testReplaceKVV(String description, Map<IntegerEnum, String> map) {
 229         assertTrue(map.containsKey(KEYS[1]));
 230         Object expected = map.get(KEYS[1]);
 231         assertTrue(null == expected || expected == VALUES[1]);
 232         assertFalse(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
 233         assertSame(map.get(KEYS[1]), expected);
 234         assertTrue(map.replace(KEYS[1], (String)expected, EXTRA_VALUE));
 235         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 236         assertTrue(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
 237         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 238 
 239         assertFalse(map.containsKey(EXTRA_KEY));
 240         assertFalse(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
 241         assertFalse(map.containsKey(EXTRA_KEY));
 242         assertNull(map.get(EXTRA_KEY));
 243         assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
 244         assertTrue(map.containsKey(EXTRA_KEY));
 245         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 246         assertTrue(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
 247         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 248     }
 249 
 250     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 251     public void testComputeIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
 252         assertTrue(map.containsKey(null), "null key absent");
 253         assertNull(map.get(null), "value not null");
 254         assertSame(map.computeIfAbsent(null, (k) -> EXTRA_VALUE), EXTRA_VALUE, description);
 255         assertSame(map.get(null), EXTRA_VALUE, description);
 256     }
 257 
 258     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 259     public void testComputeIfAbsent(String description, Map<IntegerEnum, String> map) {
 260         assertTrue(map.containsKey(KEYS[1]));
 261         Object expected = map.get(KEYS[1]);
 262         assertTrue(null == expected || expected == VALUES[1], description + String.valueOf(expected));
 263         expected = (null == expected) ? EXTRA_VALUE : expected;
 264         assertSame(map.computeIfAbsent(KEYS[1], (k) -> EXTRA_VALUE), expected, description);
 265         assertSame(map.get(KEYS[1]), expected, description);
 266 
 267         assertFalse(map.containsKey(EXTRA_KEY));
 268         assertSame(map.computeIfAbsent(EXTRA_KEY, (k) -> EXTRA_VALUE), EXTRA_VALUE);
 269         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 270     }
 271 
 272     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 273     public void testComputeIfPresentNulls(String description, Map<IntegerEnum, String> map) {
 274         assertTrue(map.containsKey(null));
 275         assertNull(map.get(null));
 276         assertSame(map.computeIfPresent(null, (k, v) -> {
 277             fail();
 278             return EXTRA_VALUE;
 279         }), null, description);
 280         assertTrue(map.containsKey(null));
 281         assertSame(map.get(null), null, description);
 282     }
 283 
 284     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 285     public void testComputeIfPresent(String description, Map<IntegerEnum, String> map) {
 286         assertTrue(map.containsKey(KEYS[1]));
 287         Object value = map.get(KEYS[1]);
 288         assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
 289         Object expected = (null == value) ? null : EXTRA_VALUE;
 290         assertSame(map.computeIfPresent(KEYS[1], (k, v) -> {
 291             assertSame(v, value);
 292             return EXTRA_VALUE;
 293         }), expected, description);
 294         assertSame(map.get(KEYS[1]), expected, description);
 295 
 296         assertFalse(map.containsKey(EXTRA_KEY));
 297         assertSame(map.computeIfPresent(EXTRA_KEY, (k, v) -> {
 298             fail();
 299             return EXTRA_VALUE;
 300         }), null);
 301         assertFalse(map.containsKey(EXTRA_KEY));
 302         assertSame(map.get(EXTRA_KEY), null);
 303     }
 304 
 305     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 306     public void testComputeNulls(String description, Map<IntegerEnum, String> map) {
 307         assertTrue(map.containsKey(null), "null key absent");
 308         assertNull(map.get(null), "value not null");
 309         assertSame(map.compute(null, (k, v) -> {
 310             assertSame(k, null);
 311             assertNull(v);
 312             return EXTRA_VALUE;
 313         }), EXTRA_VALUE, description);
 314         assertTrue(map.containsKey(null));
 315         assertSame(map.get(null), EXTRA_VALUE, description);
 316         assertSame(map.remove(null), EXTRA_VALUE, "removed value not expected");
 317         assertFalse(map.containsKey(null), "null key present");
 318         assertSame(map.compute(null, (k, v) -> {
 319             assertSame(k, null);
 320             assertNull(v);
 321             return null;
 322         }), null, description);
 323     }
 324 
 325     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 326     public void testCompute(String description, Map<IntegerEnum, String> map) {
 327         assertTrue(map.containsKey(KEYS[1]));
 328         Object value = map.get(KEYS[1]);
 329         assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
 330         assertSame(map.compute(KEYS[1], (k, v) -> {
 331             assertSame(k, KEYS[1]);
 332             assertSame(v, value);
 333             return EXTRA_VALUE;
 334         }), EXTRA_VALUE, description);
 335         assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
 336         assertNull(map.compute(KEYS[1], (k, v) -> {
 337             assertSame(v, EXTRA_VALUE);
 338             return null;
 339         }), description);
 340         assertFalse(map.containsKey(KEYS[1]));
 341 
 342         assertFalse(map.containsKey(EXTRA_KEY));
 343         assertSame(map.compute(EXTRA_KEY, (k, v) -> {
 344             assertNull(v);
 345             return EXTRA_VALUE;
 346         }), EXTRA_VALUE);
 347         assertTrue(map.containsKey(EXTRA_KEY));
 348         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 349     }
 350 
 351 
 352     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 353     public void testMergeNulls(String description, Map<IntegerEnum, String> map) {
 354         assertTrue(map.containsKey(null), "null key absent");
 355         assertNull(map.get(null), "value not null");
 356         assertSame(map.merge(null, EXTRA_VALUE, (v, vv) -> {
 357             assertNull(v);
 358             assertSame(vv, EXTRA_VALUE);
 359             return vv;
 360         }), EXTRA_VALUE, description);
 361         assertTrue(map.containsKey(null));
 362         assertSame(map.get(null), EXTRA_VALUE, description);
 363     }
 364 
 365     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 366     public void testMerge(String description, Map<IntegerEnum, String> map) {
 367         assertTrue(map.containsKey(KEYS[1]));
 368         Object value = map.get(KEYS[1]);
 369         assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
 370         assertSame(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
 371             assertSame(v, value);
 372             assertSame(vv, EXTRA_VALUE);
 373             return vv;
 374         }), EXTRA_VALUE, description);
 375         assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
 376         assertNull(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
 377             assertSame(v, EXTRA_VALUE);
 378             assertSame(vv, EXTRA_VALUE);
 379             return null;
 380         }), description);
 381         assertFalse(map.containsKey(KEYS[1]));
 382 
 383         assertFalse(map.containsKey(EXTRA_KEY));
 384         assertSame(map.merge(EXTRA_KEY, EXTRA_VALUE, (v, vv) -> {
 385             assertNull(v);


 409     /**
 410      * Realized keys ensure that there is always a hard ref to all test objects.
 411      */
 412     private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
 413     /**
 414      * Realized values ensure that there is always a hard ref to all test
 415      * objects.
 416      */
 417     private static final String[] VALUES = new String[TEST_SIZE];
 418 
 419     static {
 420         IntegerEnum[] keys = IntegerEnum.values();
 421         for (int each = 0; each < TEST_SIZE; each++) {
 422             KEYS[each] = keys[each];
 423             VALUES[each] = String.valueOf(each);
 424         }
 425     }
 426     private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
 427     private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
 428 
 429     @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=all values=all", parallel = true)
 430     public static Iterator<Object[]> allMapProvider() {
 431         return makeAllMaps().iterator();
 432     }
 433 
 434     @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull", parallel = true)
 435     public static Iterator<Object[]> allMapWithNullsProvider() {
 436         return makeAllMapsWithNulls().iterator();
 437     }
 438 
 439     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull", parallel = true)
 440     public static Iterator<Object[]> rwNonNullMapProvider() {
 441         return makeRWNoNullsMaps().iterator();
 442     }
 443 
 444     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=all", parallel = true)
 445     public static Iterator<Object[]> rwNonNullKeysMapProvider() {
 446         return makeRWMapsNoNulls().iterator();
 447     }
 448 
 449     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=all values=all", parallel = true)
 450     public static Iterator<Object[]> rwMapProvider() {
 451         return makeAllRWMaps().iterator();
 452     }
 453 
 454     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull", parallel = true)
 455     public static Iterator<Object[]> rwNullsMapProvider() {
 456         return makeAllRWMapsWithNulls().iterator();
 457     }
 458 
 459     private static Collection<Object[]> makeAllRWMapsWithNulls() {
 460         Collection<Object[]> all = new ArrayList<>();
 461 
 462         all.addAll(makeRWMaps(true, true));


 463 
 464         return all;
 465     }
 466 
 467 
 468     private static Collection<Object[]> makeRWMapsNoNulls() {
 469         Collection<Object[]> all = new ArrayList<>();
 470 
 471         all.addAll(makeRWNoNullKeysMaps(false));
 472         all.addAll(makeRWNoNullsMaps());
 473 
 474         return all;
 475     }
 476 
 477     private static Collection<Object[]> makeAllROMaps() {
 478         Collection<Object[]> all = new ArrayList<>();
 479 
 480         all.addAll(makeROMaps(false));



 481         all.addAll(makeROMaps(true));
 482 
 483         return all;
 484     }
 485 
 486     private static Collection<Object[]> makeAllRWMaps() {
 487         Collection<Object[]> all = new ArrayList<>();
 488 

 489         all.addAll(makeRWNoNullsMaps());
 490         all.addAll(makeRWMaps(false,true));
 491         all.addAll(makeRWMaps(true,true));
 492         all.addAll(makeRWNoNullKeysMaps(true));
 493         return all;
 494     }
 495 
 496     private static Collection<Object[]> makeAllMaps() {
 497         Collection<Object[]> all = new ArrayList<>();
 498 
 499         all.addAll(makeAllROMaps());
 500         all.addAll(makeAllRWMaps());
 501 
 502         return all;
 503     }
 504 
 505     private static Collection<Object[]> makeAllMapsWithNulls() {
 506         Collection<Object[]> all = new ArrayList<>();
 507 
 508         all.addAll(makeROMaps(true));
 509         all.addAll(makeRWMaps(true,true));
 510 
 511         return all;
 512     }
 513     /**
 514      *
 515      * @param nullKeys include null keys
 516      * @param nullValues include null values
 517      * @return
 518      */
 519     private static Collection<Object[]> makeRWMaps(boolean nullKeys, boolean nullValues) {
 520         return Arrays.asList(
 521             new Object[]{"HashMap", makeMap(HashMap::new, nullKeys, nullValues)},
 522             new Object[]{"IdentityHashMap", makeMap(IdentityHashMap::new, nullKeys, nullValues)},
 523             new Object[]{"LinkedHashMap", makeMap(LinkedHashMap::new, nullKeys, nullValues)},
 524             new Object[]{"WeakHashMap", makeMap(WeakHashMap::new, nullKeys, nullValues)},
 525             new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(makeMap(HashMap::new, nullKeys, nullValues), IntegerEnum.class, String.class)},
 526             new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(makeMap(HashMap::new, nullKeys, nullValues))},
 527             new Object[]{"ExtendsAbstractMap", makeMap(ExtendsAbstractMap::new, nullKeys, nullValues)});
 528     }
 529 
 530     /**
 531      *
 532      * @param nulls include null values
 533      * @return
 534      */
 535     private static Collection<Object[]> makeRWNoNullKeysMaps(boolean nulls) {
 536         return Arrays.asList(
 537                 // null key hostile
 538                 new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls)},
 539                 new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls))}
 540                 );



 541     }
 542 
 543     private static Collection<Object[]> makeRWNoNullsMaps() {
 544         return Arrays.asList(
 545             // null key and value hostile
 546             new Object[]{"Hashtable", makeMap(Hashtable::new, false, false)},
 547             new Object[]{"TreeMap", makeMap(TreeMap::new, false, false)},
 548             new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false, false)},
 549             new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false, false)},
 550             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false, false), IntegerEnum.class, String.class)},
 551             new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false, false)}
 552             );

 553     }
 554 
 555     /**
 556      *
 557      * @param nulls include nulls
 558      * @return
 559      */
 560     private static Collection<Object[]> makeROMaps(boolean nulls) {
 561         return Arrays.asList(new Object[][]{
 562             new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls, nulls))}
 563         });
 564     }
 565 
 566      /**
 567      *
 568      * @param supplier a supplier of mutable map instances.
 569      *
 570      * @param nullKeys   include null keys
 571      * @param nullValues include null values
 572      * @return
 573      */
 574     private static Map<IntegerEnum, String> makeMap(Supplier<Map<IntegerEnum, String>> supplier, boolean nullKeys, boolean nullValues) {
 575         Map<IntegerEnum, String> result = supplier.get();
 576 
 577         for (int each = 0; each < TEST_SIZE; each++) {
 578             IntegerEnum key = nullKeys ? (each == 0) ? null : KEYS[each] : KEYS[each];
 579             String value = nullValues ? (each == 0) ? null : VALUES[each] : VALUES[each];
 580 
 581             result.put(key, value);

 582         }
 583 
 584         return result;
 585     }
 586 
 587     public interface Thrower<T extends Throwable> {
 588 
 589         public void run() throws T;
 590     }
 591 
 592     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
 593         assertThrows(thrower, throwable, null);
 594     }
 595 
 596     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
 597         Throwable result;
 598         try {
 599             thrower.run();
 600             result = null;
 601         } catch (Throwable caught) {
 602             result = caught;
 603         }
 604 
 605         assertInstance(result, throwable,
 606             (null != message)
 607             ? message
 608             : "Failed to throw " + throwable.getCanonicalName());
 609     }
 610 
 611     public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
 612         for(Thrower<T> thrower : throwers) {
 613             assertThrows(thrower, throwable, message);
 614         }
 615     }
 616 
 617     public static <T> void assertInstance(T actual, Class<? extends T> expected) {
 618         assertInstance(expected.isInstance(actual), null);
 619     }
 620 
 621     public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) {
 622         assertTrue(expected.isInstance(actual), message);
 623     }
 624 
 625     /**
 626      * A simple mutable map implementation that provides only default
 627      * implementations of all methods. ie. none of the Map interface default
 628      * methods have overridden implementations.
 629      *
 630      * @param <K> Type of keys
 631      * @param <V> Type of values
 632      */
 633     public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
 634