test/java/util/Map/Defaults.java

Print this page
rev 7932 : 8021591: Additional explicit null checks
Reviewed-by: psandoz, martin, alanb


 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));


 453         public static final int SIZE = values().length;
 454     };
 455     private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
 456     /**
 457      * Realized keys ensure that there is always a hard ref to all test objects.
 458      */
 459     private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
 460     /**
 461      * Realized values ensure that there is always a hard ref to all test
 462      * objects.
 463      */
 464     private static final String[] VALUES = new String[TEST_SIZE];
 465 
 466     static {
 467         IntegerEnum[] keys = IntegerEnum.values();
 468         for (int each = 0; each < TEST_SIZE; each++) {
 469             KEYS[each] = keys[each];
 470             VALUES[each] = String.valueOf(each);
 471         }
 472     }



 473     private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
 474     private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
 475 
 476     @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=all values=all", parallel = true)
 477     public static Iterator<Object[]> allMapProvider() {
 478         return makeAllMaps().iterator();
 479     }
 480 
 481     @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull", parallel = true)
 482     public static Iterator<Object[]> allMapWithNullsProvider() {
 483         return makeAllMapsWithNulls().iterator();
 484     }
 485 
 486     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull", parallel = true)
 487     public static Iterator<Object[]> rwNonNullMapProvider() {
 488         return makeRWNoNullsMaps().iterator();
 489     }
 490 
 491     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=all", parallel = true)
 492     public static Iterator<Object[]> rwNonNullKeysMapProvider() {


 566     private static Collection<Object[]> makeRWMaps(boolean nullKeys, boolean nullValues) {
 567         return Arrays.asList(
 568             new Object[]{"HashMap", makeMap(HashMap::new, nullKeys, nullValues)},
 569             new Object[]{"IdentityHashMap", makeMap(IdentityHashMap::new, nullKeys, nullValues)},
 570             new Object[]{"LinkedHashMap", makeMap(LinkedHashMap::new, nullKeys, nullValues)},
 571             new Object[]{"WeakHashMap", makeMap(WeakHashMap::new, nullKeys, nullValues)},
 572             new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(makeMap(HashMap::new, nullKeys, nullValues), IntegerEnum.class, String.class)},
 573             new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(makeMap(HashMap::new, nullKeys, nullValues))},
 574             new Object[]{"ExtendsAbstractMap", makeMap(ExtendsAbstractMap::new, nullKeys, nullValues)});
 575     }
 576 
 577     /**
 578      *
 579      * @param nulls include null values
 580      * @return
 581      */
 582     private static Collection<Object[]> makeRWNoNullKeysMaps(boolean nulls) {
 583         return Arrays.asList(
 584                 // null key hostile
 585                 new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls)},


 586                 new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls))}
 587                 );
 588     }
 589 
 590     private static Collection<Object[]> makeRWNoNullsMaps() {
 591         return Arrays.asList(
 592             // null key and value hostile
 593             new Object[]{"Hashtable", makeMap(Hashtable::new, false, false)},
 594             new Object[]{"TreeMap", makeMap(TreeMap::new, false, false)},
 595             new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false, false)},
 596             new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false, false)},

 597             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false, false), IntegerEnum.class, String.class)},

 598             new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false, false)}
 599             );
 600     }
 601 
 602     /**
 603      *
 604      * @param nulls include nulls
 605      * @return
 606      */
 607     private static Collection<Object[]> makeROMaps(boolean nulls) {
 608         return Arrays.asList(new Object[][]{
 609             new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls, nulls))}
 610         });
 611     }
 612 
 613      /**
 614      *
 615      * @param supplier a supplier of mutable map instances.
 616      *
 617      * @param nullKeys   include null keys


 624         for (int each = 0; each < TEST_SIZE; each++) {
 625             IntegerEnum key = nullKeys ? (each == 0) ? null : KEYS[each] : KEYS[each];
 626             String value = nullValues ? (each == 0) ? null : VALUES[each] : VALUES[each];
 627 
 628             result.put(key, value);
 629         }
 630 
 631         return result;
 632     }
 633 
 634     public interface Thrower<T extends Throwable> {
 635 
 636         public void run() throws T;
 637     }
 638 
 639     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
 640         assertThrows(thrower, throwable, null);
 641     }
 642 
 643     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
 644         Throwable result;
 645         try {
 646             thrower.run();
 647             result = null;
 648         } catch (Throwable caught) {
 649             result = caught;
 650         }
 651 
 652         assertInstance(result, throwable,
 653             (null != message)
 654             ? message
 655             : "Failed to throw " + throwable.getCanonicalName());
 656     }
 657 
 658     public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
 659         for(Thrower<T> thrower : throwers) {
 660             assertThrows(thrower, throwable, message);
 661         }
 662     }
 663 
 664     public static <T> void assertInstance(T actual, Class<? extends T> expected) {
 665         assertInstance(expected.isInstance(actual), null);
 666     }
 667 
 668     public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) {
 669         assertTrue(expected.isInstance(actual), message);
 670     }
 671 
 672     /**
 673      * A simple mutable map implementation that provides only default
 674      * implementations of all methods. ie. none of the Map interface default
 675      * methods have overridden implementations.
 676      *
 677      * @param <K> Type of keys
 678      * @param <V> Type of values
 679      */
 680     public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
 681 
 682         protected final M map;
 683 
 684         public ExtendsAbstractMap() { this( (M) new HashMap<K,V>()); }
 685 
 686         protected ExtendsAbstractMap(M map) { this.map = map; }
 687 
 688         public Set<Map.Entry<K, V>> entrySet() {




 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 + " should not allow replacement with null value");
 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=nonNull values=nonNull")
 198     public void testReplaceKVNoNulls(String description, Map<IntegerEnum, String> map) {
 199         assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
 200         assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
 201         assertThrows( () -> {map.replace(FIRST_KEY, null);}, NullPointerException.class, description + ": should throw NPE");
 202         assertSame(map.replace(FIRST_KEY, EXTRA_VALUE), FIRST_VALUE, description + ": replaced wrong value");
 203         assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
 204     }
 205 
 206     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 207     public void testReplaceKV(String description, Map<IntegerEnum, String> map) {
 208         assertTrue(map.containsKey(KEYS[1]));
 209         Object expected = map.get(KEYS[1]);
 210         assertTrue(null == expected || expected == VALUES[1]);
 211         assertSame(map.replace(KEYS[1], EXTRA_VALUE), expected);
 212         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 213 
 214         assertFalse(map.containsKey(EXTRA_KEY));
 215         assertNull(map.replace(EXTRA_KEY, EXTRA_VALUE));
 216         assertFalse(map.containsKey(EXTRA_KEY));
 217         assertNull(map.get(EXTRA_KEY));
 218         assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
 219         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 220         assertSame(map.replace(EXTRA_KEY, (String)expected), EXTRA_VALUE);
 221         assertSame(map.get(EXTRA_KEY), expected);
 222     }
 223 
 224     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
 225     public void testReplaceKVVNulls(String description, Map<IntegerEnum, String> map) {
 226         assertTrue(map.containsKey(null), "null key absent");
 227         assertNull(map.get(null), "value not null");
 228         assertFalse(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
 229         assertNull(map.get(null));
 230         assertTrue(map.replace(null, null, EXTRA_VALUE));
 231         assertSame(map.get(null), EXTRA_VALUE);
 232         assertTrue(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
 233         assertSame(map.get(null), EXTRA_VALUE);
 234     }
 235 
 236     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
 237     public void testReplaceKVVNoNulls(String description, Map<IntegerEnum, String> map) {
 238         assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
 239         assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
 240         assertThrows( () -> {map.replace(FIRST_KEY, FIRST_VALUE, null);}, NullPointerException.class, description + ": should throw NPE");
 241         assertThrows( () -> {if (!map.replace(FIRST_KEY, null, EXTRA_VALUE)) throw new NullPointerException("default returns false rather than throwing");}, NullPointerException.class,  description + ": should throw NPE");
 242         assertTrue(map.replace(FIRST_KEY, FIRST_VALUE, EXTRA_VALUE), description + ": replaced wrong value");
 243         assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
 244     }
 245 
 246     @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
 247     public void testReplaceKVV(String description, Map<IntegerEnum, String> map) {
 248         assertTrue(map.containsKey(KEYS[1]));
 249         Object expected = map.get(KEYS[1]);
 250         assertTrue(null == expected || expected == VALUES[1]);
 251         assertFalse(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
 252         assertSame(map.get(KEYS[1]), expected);
 253         assertTrue(map.replace(KEYS[1], (String)expected, EXTRA_VALUE));
 254         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 255         assertTrue(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
 256         assertSame(map.get(KEYS[1]), EXTRA_VALUE);
 257 
 258         assertFalse(map.containsKey(EXTRA_KEY));
 259         assertFalse(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
 260         assertFalse(map.containsKey(EXTRA_KEY));
 261         assertNull(map.get(EXTRA_KEY));
 262         assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
 263         assertTrue(map.containsKey(EXTRA_KEY));
 264         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
 265         assertTrue(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));


 472         public static final int SIZE = values().length;
 473     };
 474     private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
 475     /**
 476      * Realized keys ensure that there is always a hard ref to all test objects.
 477      */
 478     private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
 479     /**
 480      * Realized values ensure that there is always a hard ref to all test
 481      * objects.
 482      */
 483     private static final String[] VALUES = new String[TEST_SIZE];
 484 
 485     static {
 486         IntegerEnum[] keys = IntegerEnum.values();
 487         for (int each = 0; each < TEST_SIZE; each++) {
 488             KEYS[each] = keys[each];
 489             VALUES[each] = String.valueOf(each);
 490         }
 491     }
 492 
 493     private static final IntegerEnum FIRST_KEY = KEYS[0];
 494     private static final String FIRST_VALUE = VALUES[0];
 495     private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
 496     private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
 497 
 498     @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=all values=all", parallel = true)
 499     public static Iterator<Object[]> allMapProvider() {
 500         return makeAllMaps().iterator();
 501     }
 502 
 503     @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull", parallel = true)
 504     public static Iterator<Object[]> allMapWithNullsProvider() {
 505         return makeAllMapsWithNulls().iterator();
 506     }
 507 
 508     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull", parallel = true)
 509     public static Iterator<Object[]> rwNonNullMapProvider() {
 510         return makeRWNoNullsMaps().iterator();
 511     }
 512 
 513     @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=all", parallel = true)
 514     public static Iterator<Object[]> rwNonNullKeysMapProvider() {


 588     private static Collection<Object[]> makeRWMaps(boolean nullKeys, boolean nullValues) {
 589         return Arrays.asList(
 590             new Object[]{"HashMap", makeMap(HashMap::new, nullKeys, nullValues)},
 591             new Object[]{"IdentityHashMap", makeMap(IdentityHashMap::new, nullKeys, nullValues)},
 592             new Object[]{"LinkedHashMap", makeMap(LinkedHashMap::new, nullKeys, nullValues)},
 593             new Object[]{"WeakHashMap", makeMap(WeakHashMap::new, nullKeys, nullValues)},
 594             new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(makeMap(HashMap::new, nullKeys, nullValues), IntegerEnum.class, String.class)},
 595             new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(makeMap(HashMap::new, nullKeys, nullValues))},
 596             new Object[]{"ExtendsAbstractMap", makeMap(ExtendsAbstractMap::new, nullKeys, nullValues)});
 597     }
 598 
 599     /**
 600      *
 601      * @param nulls include null values
 602      * @return
 603      */
 604     private static Collection<Object[]> makeRWNoNullKeysMaps(boolean nulls) {
 605         return Arrays.asList(
 606                 // null key hostile
 607                 new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls)},
 608                 new Object[]{"TreeMap", makeMap(TreeMap::new, false, nulls)},
 609                 new Object[]{"ExtendsAbstractMap(TreeMap)", makeMap(() -> {return new ExtendsAbstractMap(new TreeMap());}, false, nulls)},
 610                 new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls))}
 611                 );
 612     }
 613 
 614     private static Collection<Object[]> makeRWNoNullsMaps() {
 615         return Arrays.asList(
 616             // null key and value hostile
 617             new Object[]{"Hashtable", makeMap(Hashtable::new, false, false)},

 618             new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false, false)},
 619             new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false, false)},
 620             new Object[]{"Collections.synchronizedMap(ConcurrentHashMap)", Collections.synchronizedMap(makeMap(ConcurrentHashMap::new, false, false))},
 621             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false, false), IntegerEnum.class, String.class)},
 622             new Object[]{"ExtendsAbstractMap(ConcurrentHashMap)", makeMap(() -> {return new ExtendsAbstractMap(new ConcurrentHashMap());}, false, false)},
 623             new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false, false)}
 624             );
 625     }
 626 
 627     /**
 628      *
 629      * @param nulls include nulls
 630      * @return
 631      */
 632     private static Collection<Object[]> makeROMaps(boolean nulls) {
 633         return Arrays.asList(new Object[][]{
 634             new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls, nulls))}
 635         });
 636     }
 637 
 638      /**
 639      *
 640      * @param supplier a supplier of mutable map instances.
 641      *
 642      * @param nullKeys   include null keys


 649         for (int each = 0; each < TEST_SIZE; each++) {
 650             IntegerEnum key = nullKeys ? (each == 0) ? null : KEYS[each] : KEYS[each];
 651             String value = nullValues ? (each == 0) ? null : VALUES[each] : VALUES[each];
 652 
 653             result.put(key, value);
 654         }
 655 
 656         return result;
 657     }
 658 
 659     public interface Thrower<T extends Throwable> {
 660 
 661         public void run() throws T;
 662     }
 663 
 664     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
 665         assertThrows(thrower, throwable, null);
 666     }
 667 
 668     public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
 669         Throwable thrown;
 670         try {
 671             thrower.run();
 672             thrown = null;
 673         } catch (Throwable caught) {
 674             thrown = caught;
 675         }
 676 
 677         assertInstance(thrown, throwable,
 678             ((null != message) ? message : "") +
 679             " Failed to throw " + throwable.getCanonicalName());

 680     }
 681 
 682     public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
 683         for(Thrower<T> thrower : throwers) {
 684             assertThrows(thrower, throwable, message);
 685         }
 686     }
 687 
 688     public static void assertInstance(Object actual, Class<?> expected) {
 689         assertInstance(expected.isInstance(actual), null);
 690     }
 691 
 692     public static void assertInstance(Object actual, Class<?> expected, String message) {
 693         assertTrue(expected.isInstance(actual), message);
 694     }
 695 
 696     /**
 697      * A simple mutable map implementation that provides only default
 698      * implementations of all methods. ie. none of the Map interface default
 699      * methods have overridden implementations.
 700      *
 701      * @param <K> Type of keys
 702      * @param <V> Type of values
 703      */
 704     public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
 705 
 706         protected final M map;
 707 
 708         public ExtendsAbstractMap() { this( (M) new HashMap<K,V>()); }
 709 
 710         protected ExtendsAbstractMap(M map) { this.map = map; }
 711 
 712         public Set<Map.Entry<K, V>> entrySet() {