1 /*
2 * Copyright (c) 2013, 2016, 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 8005698
27 * @run testng/othervm -Dtest.map.collisions.shortrun=true InPlaceOpsCollisions
28 * @summary Ensure overrides of in-place operations in Maps behave well with lots of collisions.
29 */
30 import java.util.Map;
31 import java.util.function.BiFunction;
32 import java.util.function.Function;
33 import java.util.function.Supplier;
34
35 import org.testng.annotations.Test;
36 import static org.testng.Assert.assertTrue;
37 import static org.testng.Assert.assertFalse;
38 import static org.testng.Assert.assertEquals;
39 import static org.testng.Assert.assertNull;
40
41 public class InPlaceOpsCollisions extends MapWithCollisionsProviders {
42
43 @Test(dataProvider = "mapsWithObjectsAndStrings")
44 void testPutIfAbsent(String desc, Supplier<Map<Object, Object>> ms, Object val) {
45 Map<Object, Object> map = ms.get();
46 Object[] keys = map.keySet().toArray();
47 Object retVal;
48 removeOddKeys(map, keys);
49 for (int i = 0; i < keys.length; i++) {
50 retVal = map.putIfAbsent(keys[i], val);
51 if (i % 2 == 0) { // even: not absent, not put
52
53 assertEquals(retVal, keys[i],
54 String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
55 assertEquals(keys[i], map.get(keys[i]),
56 String.format("putIfAbsent: get(%s[%d])", desc, i));
57 assertTrue(map.containsValue(keys[i]),
58 String.format("putIfAbsent: containsValue(%s[%d])", desc, i));
59 } else { // odd: absent, was put
60 assertNull(retVal,
61 String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
62 assertEquals(val, map.get(keys[i]),
63 String.format("putIfAbsent: get(%s[%d])", desc, i));
64 assertFalse(map.containsValue(keys[i]),
65 String.format("putIfAbsent: !containsValue(%s[%d])", desc, i));
66 }
67 assertTrue(map.containsKey(keys[i]),
68 String.format("insertion: containsKey(%s[%d])", desc, i));
69 }
70 assertEquals(map.size(), keys.length,
71 String.format("map expected size m%d != k%d", map.size(), keys.length));
72 }
73
74 @Test(dataProvider = "mapsWithObjectsAndStrings")
75 void testRemoveMapping(String desc, Supplier<Map<Object, Object>> ms, Object val) {
76 Map<Object, Object> map = ms.get();
77 Object[] keys = map.keySet().toArray();
78 boolean removed;
79 int removes = 0;
80 remapOddKeys(map, keys, val);
81 for (int i = 0; i < keys.length; i++) {
82 removed = map.remove(keys[i], keys[i]);
83 if (i % 2 == 0) { // even: original mapping, should be removed
84 assertTrue(removed,
85 String.format("removeMapping: retVal(%s[%d])", desc, i));
86 assertNull(map.get(keys[i]),
87 String.format("removeMapping: get(%s[%d])", desc, i));
88 assertFalse(map.containsKey(keys[i]),
89 String.format("removeMapping: !containsKey(%s[%d])", desc, i));
90 assertFalse(map.containsValue(keys[i]),
91 String.format("removeMapping: !containsValue(%s[%d])", desc, i));
92 removes++;
93 } else { // odd: new mapping, not removed
479 if (i % 3 == 2) {
480 map.remove(keys[i]);
481 removes++;
482 }
483 }
484 assertEquals(map.size(), keys.length - removes,
485 String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
486 }
487
488 /*
489 * Re-map the odd-numbered keys to map to the EXTRA value
490 */
491 private static <T> void remapOddKeys(Map<T, T> map, T[] keys, T val) {
492 for (int i = 0; i < keys.length; i++) {
493 if (i % 2 != 0) {
494 map.put(keys[i], val);
495 }
496 }
497 }
498
499 }
|
1 /*
2 * Copyright (c) 2013, 2019, 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 8005698
27 * @run testng/othervm -Dtest.map.collisions.shortrun=true InPlaceOpsCollisions
28 * @summary Ensure overrides of in-place operations in Maps behave well with lots of collisions.
29 */
30
31 import java.util.Arrays;
32 import java.util.Comparator;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.LinkedHashMap;
36 import java.util.Map;
37 import java.util.TreeMap;
38 import java.util.function.BiFunction;
39 import java.util.function.Function;
40 import java.util.function.Supplier;
41
42 import org.testng.annotations.DataProvider;
43 import org.testng.annotations.Test;
44 import static org.testng.Assert.assertTrue;
45 import static org.testng.Assert.assertFalse;
46 import static org.testng.Assert.assertEquals;
47 import static org.testng.Assert.assertNull;
48
49 public class InPlaceOpsCollisions extends MapWithCollisionsProviders {
50
51 @Test(dataProvider = "mapsWithObjectsAndStrings")
52 void testPutIfAbsent(String desc, Supplier<Map<Object, Object>> ms, Object val) {
53 Map<Object, Object> map = ms.get();
54 Object[] keys = map.keySet().toArray();
55 Object retVal;
56 removeOddKeys(map, keys);
57 for (int i = 0; i < keys.length; i++) {
58 retVal = map.putIfAbsent(keys[i], val);
59 if (i % 2 == 0) { // even: not absent, not put
60
61 assertEquals(retVal, keys[i],
62 String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
63 assertEquals(keys[i], map.get(keys[i]),
64 String.format("putIfAbsent: get(%s[%d])", desc, i));
65 assertTrue(map.containsValue(keys[i]),
66 String.format("putIfAbsent: containsValue(%s[%d])", desc, i));
67 } else { // odd: absent, was put
68 assertNull(retVal,
69 String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
70 assertEquals(val, map.get(keys[i]),
71 String.format("putIfAbsent: get(%s[%d])", desc, i));
72 assertFalse(map.containsValue(keys[i]),
73 String.format("putIfAbsent: !containsValue(%s[%d])", desc, i));
74 }
75 assertTrue(map.containsKey(keys[i]),
76 String.format("insertion: containsKey(%s[%d])", desc, i));
77 }
78 assertEquals(map.size(), keys.length,
79 String.format("map expected size m%d != k%d", map.size(), keys.length));
80 }
81
82 @Test(dataProvider = "nullValueFriendlyMaps")
83 void testPutIfAbsentOverwriteNull(String desc, Supplier<Map<Object, Object>> ms) {
84 Map<Object, Object> map = ms.get();
85 map.put("key", null);
86 assertEquals(map.size(), 1, desc + ": size != 1");
87 assertTrue(map.containsKey("key"), desc + ": does not have key");
88 assertNull(map.get("key"), desc + ": value is not null");
89 map.putIfAbsent("key", "value"); // must rewrite
90 assertEquals(map.size(), 1, desc + ": size != 1");
91 assertTrue(map.containsKey("key"), desc + ": does not have key");
92 assertEquals(map.get("key"), "value", desc + ": value is not 'value'");
93 }
94
95 @Test(dataProvider = "mapsWithObjectsAndStrings")
96 void testRemoveMapping(String desc, Supplier<Map<Object, Object>> ms, Object val) {
97 Map<Object, Object> map = ms.get();
98 Object[] keys = map.keySet().toArray();
99 boolean removed;
100 int removes = 0;
101 remapOddKeys(map, keys, val);
102 for (int i = 0; i < keys.length; i++) {
103 removed = map.remove(keys[i], keys[i]);
104 if (i % 2 == 0) { // even: original mapping, should be removed
105 assertTrue(removed,
106 String.format("removeMapping: retVal(%s[%d])", desc, i));
107 assertNull(map.get(keys[i]),
108 String.format("removeMapping: get(%s[%d])", desc, i));
109 assertFalse(map.containsKey(keys[i]),
110 String.format("removeMapping: !containsKey(%s[%d])", desc, i));
111 assertFalse(map.containsValue(keys[i]),
112 String.format("removeMapping: !containsValue(%s[%d])", desc, i));
113 removes++;
114 } else { // odd: new mapping, not removed
500 if (i % 3 == 2) {
501 map.remove(keys[i]);
502 removes++;
503 }
504 }
505 assertEquals(map.size(), keys.length - removes,
506 String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
507 }
508
509 /*
510 * Re-map the odd-numbered keys to map to the EXTRA value
511 */
512 private static <T> void remapOddKeys(Map<T, T> map, T[] keys, T val) {
513 for (int i = 0; i < keys.length; i++) {
514 if (i % 2 != 0) {
515 map.put(keys[i], val);
516 }
517 }
518 }
519
520 @DataProvider
521 public Iterator<Object[]> nullValueFriendlyMaps() {
522 return Arrays.asList(
523 new Object[]{"HashMap", (Supplier<Map<?, ?>>) HashMap::new},
524 new Object[]{"LinkedHashMap", (Supplier<Map<?, ?>>) LinkedHashMap::new},
525 new Object[]{"TreeMap", (Supplier<Map<?, ?>>) TreeMap::new},
526 new Object[]{"TreeMap(cmp)", (Supplier<Map<?, ?>>) () -> new TreeMap<>(Comparator.reverseOrder())}
527 ).iterator();
528 }
529 }
|