jdk/test/java/util/Map/Defaults.java
changeset 16867 76499721c6c1
parent 16042 0bf6469a1cfb
child 18280 6c3c0ff49eb5
equal deleted inserted replaced
16866:e659009ee08d 16867:76499721c6c1
       
     1 /*
       
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    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);
       
   351             assertSame(vv, EXTRA_VALUE);
       
   352             return EXTRA_VALUE;
       
   353         }), EXTRA_VALUE);
       
   354         assertTrue(map.containsKey(EXTRA_KEY));
       
   355         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
       
   356     }
       
   357 
       
   358     enum IntegerEnum {
       
   359 
       
   360         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
       
   361         e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
       
   362         e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
       
   363         e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
       
   364         e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
       
   365         e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
       
   366         e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
       
   367         e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
       
   368         e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
       
   369         e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
       
   370         EXTRA_KEY;
       
   371         public static final int SIZE = values().length;
       
   372     };
       
   373     private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
       
   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 
       
   541         protected final M map;
       
   542 
       
   543         public ExtendsAbstractMap() { this( (M) new HashMap<K,V>()); }
       
   544 
       
   545         protected ExtendsAbstractMap(M map) { this.map = map; }
       
   546 
       
   547         public Set<Map.Entry<K, V>> entrySet() {
       
   548             return new AbstractSet<Map.Entry<K, V>>() {
       
   549                 public int size() {
       
   550                     return map.size();
       
   551                 }
       
   552 
       
   553                 public Iterator<Map.Entry<K,V>> iterator() {
       
   554                     final Iterator<Map.Entry<K,V>> source = map.entrySet().iterator();
       
   555                     return new Iterator<Map.Entry<K,V>>() {
       
   556                        public boolean hasNext() { return source.hasNext(); }
       
   557                        public Map.Entry<K,V> next() { return source.next(); }
       
   558                        public void remove() { source.remove(); }
       
   559                     };
       
   560                 }
       
   561 
       
   562                 public boolean add(Map.Entry<K,V> e) {
       
   563                     return map.entrySet().add(e);
       
   564                 }
       
   565             };
       
   566         }
       
   567 
       
   568         public V put(K key, V value) {
       
   569             return map.put(key, value);
       
   570         }
       
   571     }
       
   572 
       
   573     /**
       
   574      * A simple mutable concurrent map implementation that provides only default
       
   575      * implementations of all methods. ie. none of the ConcurrentMap interface
       
   576      * default methods have overridden implementations.
       
   577      *
       
   578      * @param <K> Type of keys
       
   579      * @param <V> Type of values
       
   580      */
       
   581     public static class ImplementsConcurrentMap<K, V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
       
   582         public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
       
   583 
       
   584         // ConcurrentMap reabstracts these methods
       
   585 
       
   586         public V replace(K k, V v) { return map.replace(k, v); };
       
   587 
       
   588         public boolean replace(K k, V v, V vv) { return map.replace(k, v, vv); };
       
   589 
       
   590         public boolean remove(Object k, Object v) { return map.remove(k, v); }
       
   591 
       
   592         public V putIfAbsent(K k, V v) { return map.putIfAbsent(k, v); }
       
   593     }
       
   594 }