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() {
|