• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * @test
19  * @bug 7126277
20  * @run testng/othervm -Dtest.map.collisions.shortrun=true Collisions
21  * @summary Ensure Maps behave well with lots of hashCode() collisions.
22  */
23 package test.java.util.Map;
24 
25 import java.util.BitSet;
26 import java.util.IdentityHashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.function.Supplier;
30 
31 import org.testng.annotations.Test;
32 import static org.testng.Assert.assertTrue;
33 import static org.testng.Assert.assertFalse;
34 import static org.testng.Assert.assertEquals;
35 import static org.testng.Assert.assertNotNull;
36 
37 public class Collisions extends MapWithCollisionsProviders {
38 
39     @Test(dataProvider = "mapsWithObjects")
testIntegerIteration(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val)40     public void testIntegerIteration(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
41         Map<IntKey, IntKey> map = ms.get();
42         int mapSize = map.size();
43 
44         BitSet all = new BitSet(mapSize);
45         for (Map.Entry<IntKey, IntKey> each : map.entrySet()) {
46             assertFalse(all.get(each.getKey().getValue()), "Iteration: key already seen");
47             all.set(each.getKey().getValue());
48         }
49 
50         all.flip(0, mapSize);
51         assertTrue(all.isEmpty(), "Iteration: some keys not visited");
52 
53         for (IntKey each : map.keySet()) {
54             assertFalse(all.get(each.getValue()), "Iteration: key already seen");
55             all.set(each.getValue());
56         }
57 
58         all.flip(0, mapSize);
59         assertTrue(all.isEmpty(), "Iteration: some keys not visited");
60 
61         int count = 0;
62         for (IntKey each : map.values()) {
63             count++;
64         }
65 
66         assertEquals(map.size(), count,
67                 String.format("Iteration: value count matches size m%d != c%d", map.size(), count));
68     }
69 
70     @Test(dataProvider = "mapsWithStrings")
testStringIteration(String desc, Supplier<Map<String, String>> ms, String val)71     public void testStringIteration(String desc, Supplier<Map<String, String>> ms, String val) {
72         Map<String, String> map = ms.get();
73         int mapSize = map.size();
74 
75         BitSet all = new BitSet(mapSize);
76         for (Map.Entry<String, String> each : map.entrySet()) {
77             String key = each.getKey();
78             boolean longKey = key.length() > 5;
79             int index = key.hashCode() + (longKey ? mapSize / 2 : 0);
80             assertFalse(all.get(index), "key already seen");
81             all.set(index);
82         }
83 
84         all.flip(0, mapSize);
85         assertTrue(all.isEmpty(), "some keys not visited");
86 
87         for (String each : map.keySet()) {
88             boolean longKey = each.length() > 5;
89             int index = each.hashCode() + (longKey ? mapSize / 2 : 0);
90             assertFalse(all.get(index), "key already seen");
91             all.set(index);
92         }
93 
94         all.flip(0, mapSize);
95         assertTrue(all.isEmpty(), "some keys not visited");
96 
97         int count = 0;
98         for (String each : map.values()) {
99             count++;
100         }
101 
102         assertEquals(map.size(), mapSize,
103                 String.format("value count matches size m%d != k%d", map.size(), mapSize));
104     }
105 
106     @Test(dataProvider = "mapsWithObjectsAndStrings")
testRemove(String desc, Supplier<Map<Object, Object>> ms, Object val)107     public void testRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
108         Map<Object, Object> map = ms.get();
109         Object[] keys = map.keySet().toArray();
110 
111         for (int i = 0; i < keys.length; i++) {
112             Object each = keys[i];
113             assertNotNull(map.remove(each),
114                     String.format("remove: %s[%d]%s", desc, i, each));
115         }
116 
117         assertTrue(map.size() == 0 && map.isEmpty(),
118                 String.format("remove: map empty. size=%d", map.size()));
119     }
120 
121     @Test(dataProvider = "mapsWithObjectsAndStrings")
testKeysIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val)122     public void testKeysIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
123         Map<Object, Object> map = ms.get();
124 
125         Iterator<Object> each = map.keySet().iterator();
126         while (each.hasNext()) {
127             Object t = each.next();
128             each.remove();
129             assertFalse(map.containsKey(t), String.format("not removed: %s", each));
130         }
131 
132         assertTrue(map.size() == 0 && map.isEmpty(),
133                 String.format("remove: map empty. size=%d", map.size()));
134     }
135 
136     @Test(dataProvider = "mapsWithObjectsAndStrings")
testValuesIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val)137     public void testValuesIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
138         Map<Object, Object> map = ms.get();
139 
140         Iterator<Object> each = map.values().iterator();
141         while (each.hasNext()) {
142             Object t = each.next();
143             each.remove();
144             assertFalse(map.containsValue(t), String.format("not removed: %s", each));
145         }
146 
147         assertTrue(map.size() == 0 && map.isEmpty(),
148                 String.format("remove: map empty. size=%d", map.size()));
149     }
150 
151     @Test(dataProvider = "mapsWithObjectsAndStrings")
testEntriesIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val)152     public void testEntriesIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
153         Map<Object, Object> map = ms.get();
154 
155         Iterator<Map.Entry<Object, Object>> each = map.entrySet().iterator();
156         while (each.hasNext()) {
157             Map.Entry<Object, Object> t = each.next();
158             Object key = t.getKey();
159             Object value = t.getValue();
160             each.remove();
161             assertTrue((map instanceof IdentityHashMap) || !map.entrySet().contains(t),
162                     String.format("not removed: %s", each));
163             assertFalse(map.containsKey(key),
164                     String.format("not removed: %s", each));
165             assertFalse(map.containsValue(value),
166                     String.format("not removed: %s", each));
167         }
168 
169         assertTrue(map.size() == 0 && map.isEmpty(),
170                 String.format("remove: map empty. size=%d", map.size()));
171     }
172 
173 }