blob: 3cd677aa84ada0dfac76299d2e774cd60cd26349 [file] [log] [blame]
mduigouf004b402013-04-16 11:17:19 -07001/*
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 */
31import java.util.AbstractMap;
32import java.util.AbstractSet;
33import java.util.ArrayList;
34import java.util.Arrays;
35import java.util.Collection;
36import java.util.Collections;
37import java.util.EnumMap;
38import java.util.HashMap;
mduigou8a44cfa2013-06-18 16:03:10 -070039import java.util.HashSet;
mduigouf004b402013-04-16 11:17:19 -070040import java.util.Hashtable;
41import java.util.IdentityHashMap;
42import java.util.Iterator;
43import java.util.LinkedHashMap;
44import java.util.Map;
45import java.util.TreeMap;
46import java.util.Set;
47import java.util.WeakHashMap;
48import java.util.concurrent.ConcurrentMap;
49import java.util.concurrent.ConcurrentHashMap;
50import java.util.concurrent.ConcurrentSkipListMap;
mduigou8a44cfa2013-06-18 16:03:10 -070051import java.util.function.BiFunction;
mduigouf004b402013-04-16 11:17:19 -070052import java.util.function.Supplier;
53
54import org.testng.annotations.Test;
55import org.testng.annotations.DataProvider;
56import static org.testng.Assert.fail;
57import static org.testng.Assert.assertEquals;
58import static org.testng.Assert.assertTrue;
59import static org.testng.Assert.assertFalse;
60import static org.testng.Assert.assertNull;
61import static org.testng.Assert.assertSame;
62
63public class Defaults {
64
mduigou8a44cfa2013-06-18 16:03:10 -070065 @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -070066 public void testGetOrDefaultNulls(String description, Map<IntegerEnum, String> map) {
mduigou8a44cfa2013-06-18 16:03:10 -070067 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");
mduigouf004b402013-04-16 11:17:19 -070070 }
71
mduigou8a44cfa2013-06-18 16:03:10 -070072 @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -070073 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
mduigou8a44cfa2013-06-18 16:03:10 -070081 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -070082 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
mduigou8a44cfa2013-06-18 16:03:10 -0700101 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700102 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
mduigou8a44cfa2013-06-18 16:03:10 -0700114 @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700115 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
mduigou8a44cfa2013-06-18 16:03:10 -0700125 assertEquals(KEYS, EACH_KEY, description);
mduigouf004b402013-04-16 11:17:19 -0700126 }
127
mduigou8a44cfa2013-06-18 16:03:10 -0700128 @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")
mduigouf004b402013-04-16 11:17:19 -0700162 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
mduigou8a44cfa2013-06-18 16:03:10 -0700174 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700175 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
mduigou8a44cfa2013-06-18 16:03:10 -0700189 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -0700190 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
mduigou8a44cfa2013-06-18 16:03:10 -0700197 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700198 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
mduigou8a44cfa2013-06-18 16:03:10 -0700215 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -0700216 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
mduigou8a44cfa2013-06-18 16:03:10 -0700227 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700228 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
mduigou8a44cfa2013-06-18 16:03:10 -0700250 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -0700251 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
mduigou8a44cfa2013-06-18 16:03:10 -0700258 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700259 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
mduigou8a44cfa2013-06-18 16:03:10 -0700272 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -0700273 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
mduigou8a44cfa2013-06-18 16:03:10 -0700284 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700285 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
mduigou8a44cfa2013-06-18 16:03:10 -0700305 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -0700306 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
mduigou8a44cfa2013-06-18 16:03:10 -0700325 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700326 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
mduigou8a44cfa2013-06-18 16:03:10 -0700352 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
mduigouf004b402013-04-16 11:17:19 -0700353 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
mduigou8a44cfa2013-06-18 16:03:10 -0700365 @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
mduigouf004b402013-04-16 11:17:19 -0700366 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);
386 assertSame(vv, EXTRA_VALUE);
387 return EXTRA_VALUE;
388 }), EXTRA_VALUE);
389 assertTrue(map.containsKey(EXTRA_KEY));
390 assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
391 }
392
393 enum IntegerEnum {
394
395 e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
396 e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
397 e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
398 e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
399 e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
400 e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
401 e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
402 e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
403 e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
404 e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
405 EXTRA_KEY;
406 public static final int SIZE = values().length;
407 };
408 private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
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
mduigou8a44cfa2013-06-18 16:03:10 -0700429 @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=all values=all", parallel = true)
430 public static Iterator<Object[]> allMapProvider() {
mduigouf004b402013-04-16 11:17:19 -0700431 return makeAllMaps().iterator();
432 }
433
mduigou8a44cfa2013-06-18 16:03:10 -0700434 @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull", parallel = true)
435 public static Iterator<Object[]> allMapWithNullsProvider() {
436 return makeAllMapsWithNulls().iterator();
mduigouf004b402013-04-16 11:17:19 -0700437 }
438
mduigou8a44cfa2013-06-18 16:03:10 -0700439 @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() {
mduigouf004b402013-04-16 11:17:19 -0700446 return makeRWMapsNoNulls().iterator();
447 }
448
mduigou8a44cfa2013-06-18 16:03:10 -0700449 @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=all values=all", parallel = true)
450 public static Iterator<Object[]> rwMapProvider() {
451 return makeAllRWMaps().iterator();
mduigouf004b402013-04-16 11:17:19 -0700452 }
453
mduigou8a44cfa2013-06-18 16:03:10 -0700454 @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() {
mduigouf004b402013-04-16 11:17:19 -0700460 Collection<Object[]> all = new ArrayList<>();
461
mduigou8a44cfa2013-06-18 16:03:10 -0700462 all.addAll(makeRWMaps(true, true));
mduigouf004b402013-04-16 11:17:19 -0700463
464 return all;
465 }
466
mduigou8a44cfa2013-06-18 16:03:10 -0700467
mduigouf004b402013-04-16 11:17:19 -0700468 private static Collection<Object[]> makeRWMapsNoNulls() {
469 Collection<Object[]> all = new ArrayList<>();
470
mduigou8a44cfa2013-06-18 16:03:10 -0700471 all.addAll(makeRWNoNullKeysMaps(false));
mduigouf004b402013-04-16 11:17:19 -0700472 all.addAll(makeRWNoNullsMaps());
473
474 return all;
475 }
476
mduigou8a44cfa2013-06-18 16:03:10 -0700477 private static Collection<Object[]> makeAllROMaps() {
mduigouf004b402013-04-16 11:17:19 -0700478 Collection<Object[]> all = new ArrayList<>();
479
480 all.addAll(makeROMaps(false));
mduigouf004b402013-04-16 11:17:19 -0700481 all.addAll(makeROMaps(true));
482
483 return all;
484 }
485
486 private static Collection<Object[]> makeAllRWMaps() {
487 Collection<Object[]> all = new ArrayList<>();
488
mduigouf004b402013-04-16 11:17:19 -0700489 all.addAll(makeRWNoNullsMaps());
mduigou8a44cfa2013-06-18 16:03:10 -0700490 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());
mduigouf004b402013-04-16 11:17:19 -0700501
502 return all;
503 }
504
mduigou8a44cfa2013-06-18 16:03:10 -0700505 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) {
mduigouf004b402013-04-16 11:17:19 -0700520 return Arrays.asList(
mduigou8a44cfa2013-06-18 16:03:10 -0700521 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 );
mduigouf004b402013-04-16 11:17:19 -0700541 }
542
543 private static Collection<Object[]> makeRWNoNullsMaps() {
544 return Arrays.asList(
mduigou8a44cfa2013-06-18 16:03:10 -0700545 // 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 );
mduigouf004b402013-04-16 11:17:19 -0700553 }
554
mduigou8a44cfa2013-06-18 16:03:10 -0700555 /**
556 *
557 * @param nulls include nulls
558 * @return
559 */
mduigouf004b402013-04-16 11:17:19 -0700560 private static Collection<Object[]> makeROMaps(boolean nulls) {
561 return Arrays.asList(new Object[][]{
mduigou8a44cfa2013-06-18 16:03:10 -0700562 new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls, nulls))}
mduigouf004b402013-04-16 11:17:19 -0700563 });
564 }
565
mduigou8a44cfa2013-06-18 16:03:10 -0700566 /**
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) {
mduigouf004b402013-04-16 11:17:19 -0700575 Map<IntegerEnum, String> result = supplier.get();
576
577 for (int each = 0; each < TEST_SIZE; each++) {
mduigou8a44cfa2013-06-18 16:03:10 -0700578 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);
mduigouf004b402013-04-16 11:17:19 -0700582 }
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
mduigou8a44cfa2013-06-18 16:03:10 -0700611 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
mduigouf004b402013-04-16 11:17:19 -0700617 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
635 protected final M map;
636
637 public ExtendsAbstractMap() { this( (M) new HashMap<K,V>()); }
638
639 protected ExtendsAbstractMap(M map) { this.map = map; }
640
641 public Set<Map.Entry<K, V>> entrySet() {
642 return new AbstractSet<Map.Entry<K, V>>() {
643 public int size() {
644 return map.size();
645 }
646
647 public Iterator<Map.Entry<K,V>> iterator() {
648 final Iterator<Map.Entry<K,V>> source = map.entrySet().iterator();
649 return new Iterator<Map.Entry<K,V>>() {
650 public boolean hasNext() { return source.hasNext(); }
651 public Map.Entry<K,V> next() { return source.next(); }
652 public void remove() { source.remove(); }
653 };
654 }
655
656 public boolean add(Map.Entry<K,V> e) {
657 return map.entrySet().add(e);
658 }
659 };
660 }
661
662 public V put(K key, V value) {
663 return map.put(key, value);
664 }
665 }
666
667 /**
668 * A simple mutable concurrent map implementation that provides only default
669 * implementations of all methods. ie. none of the ConcurrentMap interface
670 * default methods have overridden implementations.
671 *
672 * @param <K> Type of keys
673 * @param <V> Type of values
674 */
675 public static class ImplementsConcurrentMap<K, V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
676 public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
677
678 // ConcurrentMap reabstracts these methods
679
680 public V replace(K k, V v) { return map.replace(k, v); };
681
682 public boolean replace(K k, V v, V vv) { return map.replace(k, v, vv); };
683
684 public boolean remove(Object k, Object v) { return map.remove(k, v); }
685
686 public V putIfAbsent(K k, V v) { return map.putIfAbsent(k, v); }
687 }
688}