ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/MapTest.java
Revision: 1.8
Committed: Mon Jul 8 21:18:36 2019 UTC (4 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.7: +1 -1 lines
Log Message:
use more tactful language

File Contents

# Content
1 /*
2 * Written by Doug Lea and Martin Buchholz with assistance from
3 * members of JCP JSR-166 Expert Group and released to the public
4 * domain, as explained at
5 * http://creativecommons.org/publicdomain/zero/1.0/
6 */
7
8 import junit.framework.Test;
9
10 import java.util.ArrayList;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.ThreadLocalRandom;
15
16 /**
17 * Contains tests applicable to all Map implementations.
18 */
19 public class MapTest extends JSR166TestCase {
20 final MapImplementation impl;
21
22 /** Tests are parameterized by a Map implementation. */
23 MapTest(MapImplementation impl, String methodName) {
24 super(methodName);
25 this.impl = impl;
26 }
27
28 public static Test testSuite(MapImplementation impl) {
29 return newTestSuite(
30 parameterizedTestSuite(MapTest.class,
31 MapImplementation.class,
32 impl));
33 }
34
35 public void testImplSanity() {
36 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
37 {
38 Map m = impl.emptyMap();
39 assertTrue(m.isEmpty());
40 assertEquals(0, m.size());
41 Object k = impl.makeKey(rnd.nextInt());
42 Object v = impl.makeValue(rnd.nextInt());
43 m.put(k, v);
44 assertFalse(m.isEmpty());
45 assertEquals(1, m.size());
46 assertTrue(m.containsKey(k));
47 assertTrue(m.containsValue(v));
48 }
49 {
50 Map m = impl.emptyMap();
51 Object v = impl.makeValue(rnd.nextInt());
52 if (impl.permitsNullKeys()) {
53 m.put(null, v);
54 assertTrue(m.containsKey(null));
55 assertTrue(m.containsValue(v));
56 } else {
57 assertThrows(NullPointerException.class, () -> m.put(null, v));
58 }
59 }
60 {
61 Map m = impl.emptyMap();
62 Object k = impl.makeKey(rnd.nextInt());
63 if (impl.permitsNullValues()) {
64 m.put(k, null);
65 assertTrue(m.containsKey(k));
66 assertTrue(m.containsValue(null));
67 } else {
68 assertThrows(NullPointerException.class, () -> m.put(k, null));
69 }
70 }
71 {
72 Map m = impl.emptyMap();
73 Object k = impl.makeKey(rnd.nextInt());
74 Object v1 = impl.makeValue(rnd.nextInt());
75 Object v2 = impl.makeValue(rnd.nextInt());
76 m.put(k, v1);
77 if (impl.supportsSetValue()) {
78 ((Map.Entry)(m.entrySet().iterator().next())).setValue(v2);
79 assertSame(v2, m.get(k));
80 assertTrue(m.containsKey(k));
81 assertTrue(m.containsValue(v2));
82 assertFalse(m.containsValue(v1));
83 } else {
84 assertThrows(UnsupportedOperationException.class,
85 () -> ((Map.Entry)(m.entrySet().iterator().next())).setValue(v2));
86 }
87 }
88 }
89
90 /**
91 * Tests and extends the scenario reported in
92 * https://bugs.openjdk.java.net/browse/JDK-8186171
93 * HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries
94 * ant -Djsr166.tckTestClass=HashMapTest -Djsr166.methodFilter=testBug8186171 -Djsr166.runsPerTest=1000 tck
95 */
96 public void testBug8186171() {
97 if (!impl.supportsSetValue()) return;
98 if (!atLeastJava10()) return; // jdk9 is no longer maintained
99 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
100 final boolean permitsNullValues = impl.permitsNullValues();
101 final Object v1 = (permitsNullValues && rnd.nextBoolean())
102 ? null : impl.makeValue(1);
103 final Object v2 = (permitsNullValues && rnd.nextBoolean() && v1 != null)
104 ? null : impl.makeValue(2);
105
106 // If true, always lands in first bucket in hash tables.
107 final boolean poorHash = rnd.nextBoolean();
108 class Key implements Comparable<Key> {
109 final int i;
110 Key(int i) { this.i = i; }
111 public int hashCode() { return poorHash ? 0 : super.hashCode(); }
112 public int compareTo(Key x) {
113 return Integer.compare(this.i, x.i);
114 }
115 }
116
117 // Both HashMap and ConcurrentHashMap have:
118 // TREEIFY_THRESHOLD = 8; UNTREEIFY_THRESHOLD = 6;
119 final int size = rnd.nextInt(1, 25);
120
121 List<Key> keys = new ArrayList<>();
122 for (int i = size; i-->0; ) keys.add(new Key(i));
123 Key keyToFrob = keys.get(rnd.nextInt(keys.size()));
124
125 Map<Key, Object> m = impl.emptyMap();
126 for (Key key : keys) m.put(key, v1);
127
128 for (Iterator<Map.Entry<Key, Object>> it = m.entrySet().iterator();
129 it.hasNext(); ) {
130 Map.Entry<Key, Object> entry = it.next();
131 if (entry.getKey() == keyToFrob)
132 entry.setValue(v2); // does this have the expected effect?
133 else
134 it.remove();
135 }
136
137 assertFalse(m.containsValue(v1));
138 assertTrue(m.containsValue(v2));
139 assertTrue(m.containsKey(keyToFrob));
140 assertEquals(1, m.size());
141 }
142
143 /**
144 * "Missing" test found while investigating JDK-8210280.
145 * ant -Djsr166.tckTestClass=HashMapTest -Djsr166.methodFilter=testBug8210280 -Djsr166.runsPerTest=1000000 tck
146 */
147 public void testBug8210280() {
148 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
149 final int size1 = rnd.nextInt(32);
150 final int size2 = rnd.nextInt(128);
151
152 final Map m1 = impl.emptyMap();
153 for (int i = 0; i < size1; i++) {
154 int elt = rnd.nextInt(1024 * i, 1024 * (i + 1));
155 assertNull(m1.put(impl.makeKey(elt), impl.makeValue(elt)));
156 }
157
158 final Map m2 = impl.emptyMap();
159 for (int i = 0; i < size2; i++) {
160 int elt = rnd.nextInt(Integer.MIN_VALUE + 1024 * i,
161 Integer.MIN_VALUE + 1024 * (i + 1));
162 assertNull(m2.put(impl.makeKey(elt), impl.makeValue(-elt)));
163 }
164
165 final Map m1Copy = impl.emptyMap();
166 m1Copy.putAll(m1);
167
168 m1.putAll(m2);
169
170 for (Object elt : m2.keySet())
171 assertEquals(m2.get(elt), m1.get(elt));
172 for (Object elt : m1Copy.keySet())
173 assertSame(m1Copy.get(elt), m1.get(elt));
174 assertEquals(size1 + size2, m1.size());
175 }
176
177 /**
178 * 8222930: ConcurrentSkipListMap.clone() shares size variable between original and clone
179 */
180 public void testClone() {
181 final ThreadLocalRandom rnd = ThreadLocalRandom.current();
182 final int size = rnd.nextInt(4);
183 final Map map = impl.emptyMap();
184 for (int i = 0; i < size; i++)
185 map.put(impl.makeKey(i), impl.makeValue(i));
186 final Map clone = cloneableClone(map);
187 if (clone == null) return; // not cloneable?
188
189 assertEquals(size, map.size());
190 assertEquals(size, clone.size());
191 assertEquals(map.isEmpty(), clone.isEmpty());
192
193 clone.put(impl.makeKey(-1), impl.makeValue(-1));
194 assertEquals(size, map.size());
195 assertEquals(size + 1, clone.size());
196
197 clone.clear();
198 assertEquals(size, map.size());
199 assertEquals(0, clone.size());
200 assertTrue(clone.isEmpty());
201 }
202
203 // public void testFailsIntentionallyForDebugging() {
204 // fail(impl.klazz().getSimpleName());
205 // }
206 }