ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ConcurrentHashMapTest.java
Revision: 1.32
Committed: Wed Jun 12 18:09:00 2013 UTC (10 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.31: +6 -3 lines
Log Message:
un-diamond for maximal portability

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9 import junit.framework.*;
10 import java.util.*;
11 import java.util.concurrent.ConcurrentHashMap;
12
13 public class ConcurrentHashMapTest extends JSR166TestCase {
14 public static void main(String[] args) {
15 junit.textui.TestRunner.run(suite());
16 }
17 public static Test suite() {
18 return new TestSuite(ConcurrentHashMapTest.class);
19 }
20
21 /**
22 * Returns a new map from Integers 1-5 to Strings "A"-"E".
23 */
24 private static ConcurrentHashMap map5() {
25 ConcurrentHashMap map = new ConcurrentHashMap(5);
26 assertTrue(map.isEmpty());
27 map.put(one, "A");
28 map.put(two, "B");
29 map.put(three, "C");
30 map.put(four, "D");
31 map.put(five, "E");
32 assertFalse(map.isEmpty());
33 assertEquals(5, map.size());
34 return map;
35 }
36
37 // classes for testing Comparable fallbacks
38 static class BI implements Comparable<BI> {
39 private final int value;
40 BI(int value) { this.value = value; }
41 public int compareTo(BI other) {
42 return Integer.compare(value, other.value);
43 }
44 public boolean equals(Object x) {
45 return (x instanceof BI) && ((BI)x).value == value;
46 }
47 public int hashCode() { return 42; }
48 }
49 static class CI extends BI { CI(int value) { super(value); } }
50 static class DI extends BI { DI(int value) { super(value); } }
51
52 static class BS implements Comparable<BS> {
53 private final String value;
54 BS(String value) { this.value = value; }
55 public int compareTo(BS other) {
56 return value.compareTo(other.value);
57 }
58 public boolean equals(Object x) {
59 return (x instanceof BS) && value.equals(((BS)x).value);
60 }
61 public int hashCode() { return 42; }
62 }
63
64 static class LexicographicList<E extends Comparable<E>> extends ArrayList<E>
65 implements Comparable<LexicographicList<E>> {
66 LexicographicList(Collection<E> c) { super(c); }
67 LexicographicList(E e) { super(Collections.singleton(e)); }
68 public int compareTo(LexicographicList<E> other) {
69 int common = Math.min(size(), other.size());
70 int r = 0;
71 for (int i = 0; i < common; i++) {
72 if ((r = get(i).compareTo(other.get(i))) != 0)
73 break;
74 }
75 if (r == 0)
76 r = Integer.compare(size(), other.size());
77 return r;
78 }
79 private static final long serialVersionUID = 0;
80 }
81
82 /**
83 * Inserted elements that are subclasses of the same Comparable
84 * class are found.
85 */
86 public void testComparableFamily() {
87 ConcurrentHashMap<BI, Boolean> m =
88 new ConcurrentHashMap<BI, Boolean>();
89 for (int i = 0; i < 1000; i++) {
90 assertTrue(m.put(new CI(i), true) == null);
91 }
92 for (int i = 0; i < 1000; i++) {
93 assertTrue(m.containsKey(new CI(i)));
94 assertTrue(m.containsKey(new DI(i)));
95 }
96 }
97
98 /**
99 * Elements of classes with erased generic type parameters based
100 * on Comparable can be inserted and found.
101 */
102 public void testGenericComparable() {
103 ConcurrentHashMap<Object, Boolean> m =
104 new ConcurrentHashMap<Object, Boolean>();
105 for (int i = 0; i < 1000; i++) {
106 BI bi = new BI(i);
107 BS bs = new BS(String.valueOf(i));
108 LexicographicList<BI> bis = new LexicographicList<BI>(bi);
109 LexicographicList<BS> bss = new LexicographicList<BS>(bs);
110 assertTrue(m.putIfAbsent(bis, true) == null);
111 assertTrue(m.containsKey(bis));
112 if (m.putIfAbsent(bss, true) == null)
113 assertTrue(m.containsKey(bss));
114 assertTrue(m.containsKey(bis));
115 }
116 for (int i = 0; i < 1000; i++) {
117 assertTrue(m.containsKey(new ArrayList(Collections.singleton(new BI(i)))));
118 }
119 }
120
121 /**
122 * Elements of non-comparable classes equal to those of classes
123 * with erased generic type parameters based on Comparable can be
124 * inserted and found.
125 */
126 public void testGenericComparable2() {
127 ConcurrentHashMap<Object, Boolean> m =
128 new ConcurrentHashMap<Object, Boolean>();
129 for (int i = 0; i < 1000; i++) {
130 m.put(new ArrayList(Collections.singleton(new BI(i))), true);
131 }
132
133 for (int i = 0; i < 1000; i++) {
134 LexicographicList<BI> bis = new LexicographicList<BI>(new BI(i));
135 assertTrue(m.containsKey(bis));
136 }
137 }
138
139 /**
140 * clear removes all pairs
141 */
142 public void testClear() {
143 ConcurrentHashMap map = map5();
144 map.clear();
145 assertEquals(0, map.size());
146 }
147
148 /**
149 * Maps with same contents are equal
150 */
151 public void testEquals() {
152 ConcurrentHashMap map1 = map5();
153 ConcurrentHashMap map2 = map5();
154 assertEquals(map1, map2);
155 assertEquals(map2, map1);
156 map1.clear();
157 assertFalse(map1.equals(map2));
158 assertFalse(map2.equals(map1));
159 }
160
161 /**
162 * contains returns true for contained value
163 */
164 public void testContains() {
165 ConcurrentHashMap map = map5();
166 assertTrue(map.contains("A"));
167 assertFalse(map.contains("Z"));
168 }
169
170 /**
171 * containsKey returns true for contained key
172 */
173 public void testContainsKey() {
174 ConcurrentHashMap map = map5();
175 assertTrue(map.containsKey(one));
176 assertFalse(map.containsKey(zero));
177 }
178
179 /**
180 * containsValue returns true for held values
181 */
182 public void testContainsValue() {
183 ConcurrentHashMap map = map5();
184 assertTrue(map.containsValue("A"));
185 assertFalse(map.containsValue("Z"));
186 }
187
188 /**
189 * enumeration returns an enumeration containing the correct
190 * elements
191 */
192 public void testEnumeration() {
193 ConcurrentHashMap map = map5();
194 Enumeration e = map.elements();
195 int count = 0;
196 while (e.hasMoreElements()) {
197 count++;
198 e.nextElement();
199 }
200 assertEquals(5, count);
201 }
202
203 /**
204 * get returns the correct element at the given key,
205 * or null if not present
206 */
207 public void testGet() {
208 ConcurrentHashMap map = map5();
209 assertEquals("A", (String)map.get(one));
210 ConcurrentHashMap empty = new ConcurrentHashMap();
211 assertNull(map.get("anything"));
212 }
213
214 /**
215 * isEmpty is true of empty map and false for non-empty
216 */
217 public void testIsEmpty() {
218 ConcurrentHashMap empty = new ConcurrentHashMap();
219 ConcurrentHashMap map = map5();
220 assertTrue(empty.isEmpty());
221 assertFalse(map.isEmpty());
222 }
223
224 /**
225 * keys returns an enumeration containing all the keys from the map
226 */
227 public void testKeys() {
228 ConcurrentHashMap map = map5();
229 Enumeration e = map.keys();
230 int count = 0;
231 while (e.hasMoreElements()) {
232 count++;
233 e.nextElement();
234 }
235 assertEquals(5, count);
236 }
237
238 /**
239 * keySet returns a Set containing all the keys
240 */
241 public void testKeySet() {
242 ConcurrentHashMap map = map5();
243 Set s = map.keySet();
244 assertEquals(5, s.size());
245 assertTrue(s.contains(one));
246 assertTrue(s.contains(two));
247 assertTrue(s.contains(three));
248 assertTrue(s.contains(four));
249 assertTrue(s.contains(five));
250 }
251
252 /**
253 * keySet.toArray returns contains all keys
254 */
255 public void testKeySetToArray() {
256 ConcurrentHashMap map = map5();
257 Set s = map.keySet();
258 Object[] ar = s.toArray();
259 assertTrue(s.containsAll(Arrays.asList(ar)));
260 assertEquals(5, ar.length);
261 ar[0] = m10;
262 assertFalse(s.containsAll(Arrays.asList(ar)));
263 }
264
265 /**
266 * Values.toArray contains all values
267 */
268 public void testValuesToArray() {
269 ConcurrentHashMap map = map5();
270 Collection v = map.values();
271 Object[] ar = v.toArray();
272 ArrayList s = new ArrayList(Arrays.asList(ar));
273 assertEquals(5, ar.length);
274 assertTrue(s.contains("A"));
275 assertTrue(s.contains("B"));
276 assertTrue(s.contains("C"));
277 assertTrue(s.contains("D"));
278 assertTrue(s.contains("E"));
279 }
280
281 /**
282 * entrySet.toArray contains all entries
283 */
284 public void testEntrySetToArray() {
285 ConcurrentHashMap map = map5();
286 Set s = map.entrySet();
287 Object[] ar = s.toArray();
288 assertEquals(5, ar.length);
289 for (int i = 0; i < 5; ++i) {
290 assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey()));
291 assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue()));
292 }
293 }
294
295 /**
296 * values collection contains all values
297 */
298 public void testValues() {
299 ConcurrentHashMap map = map5();
300 Collection s = map.values();
301 assertEquals(5, s.size());
302 assertTrue(s.contains("A"));
303 assertTrue(s.contains("B"));
304 assertTrue(s.contains("C"));
305 assertTrue(s.contains("D"));
306 assertTrue(s.contains("E"));
307 }
308
309 /**
310 * entrySet contains all pairs
311 */
312 public void testEntrySet() {
313 ConcurrentHashMap map = map5();
314 Set s = map.entrySet();
315 assertEquals(5, s.size());
316 Iterator it = s.iterator();
317 while (it.hasNext()) {
318 Map.Entry e = (Map.Entry) it.next();
319 assertTrue(
320 (e.getKey().equals(one) && e.getValue().equals("A")) ||
321 (e.getKey().equals(two) && e.getValue().equals("B")) ||
322 (e.getKey().equals(three) && e.getValue().equals("C")) ||
323 (e.getKey().equals(four) && e.getValue().equals("D")) ||
324 (e.getKey().equals(five) && e.getValue().equals("E")));
325 }
326 }
327
328 /**
329 * putAll adds all key-value pairs from the given map
330 */
331 public void testPutAll() {
332 ConcurrentHashMap empty = new ConcurrentHashMap();
333 ConcurrentHashMap map = map5();
334 empty.putAll(map);
335 assertEquals(5, empty.size());
336 assertTrue(empty.containsKey(one));
337 assertTrue(empty.containsKey(two));
338 assertTrue(empty.containsKey(three));
339 assertTrue(empty.containsKey(four));
340 assertTrue(empty.containsKey(five));
341 }
342
343 /**
344 * putIfAbsent works when the given key is not present
345 */
346 public void testPutIfAbsent() {
347 ConcurrentHashMap map = map5();
348 map.putIfAbsent(six, "Z");
349 assertTrue(map.containsKey(six));
350 }
351
352 /**
353 * putIfAbsent does not add the pair if the key is already present
354 */
355 public void testPutIfAbsent2() {
356 ConcurrentHashMap map = map5();
357 assertEquals("A", map.putIfAbsent(one, "Z"));
358 }
359
360 /**
361 * replace fails when the given key is not present
362 */
363 public void testReplace() {
364 ConcurrentHashMap map = map5();
365 assertNull(map.replace(six, "Z"));
366 assertFalse(map.containsKey(six));
367 }
368
369 /**
370 * replace succeeds if the key is already present
371 */
372 public void testReplace2() {
373 ConcurrentHashMap map = map5();
374 assertNotNull(map.replace(one, "Z"));
375 assertEquals("Z", map.get(one));
376 }
377
378 /**
379 * replace value fails when the given key not mapped to expected value
380 */
381 public void testReplaceValue() {
382 ConcurrentHashMap map = map5();
383 assertEquals("A", map.get(one));
384 assertFalse(map.replace(one, "Z", "Z"));
385 assertEquals("A", map.get(one));
386 }
387
388 /**
389 * replace value succeeds when the given key mapped to expected value
390 */
391 public void testReplaceValue2() {
392 ConcurrentHashMap map = map5();
393 assertEquals("A", map.get(one));
394 assertTrue(map.replace(one, "A", "Z"));
395 assertEquals("Z", map.get(one));
396 }
397
398 /**
399 * remove removes the correct key-value pair from the map
400 */
401 public void testRemove() {
402 ConcurrentHashMap map = map5();
403 map.remove(five);
404 assertEquals(4, map.size());
405 assertFalse(map.containsKey(five));
406 }
407
408 /**
409 * remove(key,value) removes only if pair present
410 */
411 public void testRemove2() {
412 ConcurrentHashMap map = map5();
413 map.remove(five, "E");
414 assertEquals(4, map.size());
415 assertFalse(map.containsKey(five));
416 map.remove(four, "A");
417 assertEquals(4, map.size());
418 assertTrue(map.containsKey(four));
419 }
420
421 /**
422 * size returns the correct values
423 */
424 public void testSize() {
425 ConcurrentHashMap map = map5();
426 ConcurrentHashMap empty = new ConcurrentHashMap();
427 assertEquals(0, empty.size());
428 assertEquals(5, map.size());
429 }
430
431 /**
432 * toString contains toString of elements
433 */
434 public void testToString() {
435 ConcurrentHashMap map = map5();
436 String s = map.toString();
437 for (int i = 1; i <= 5; ++i) {
438 assertTrue(s.contains(String.valueOf(i)));
439 }
440 }
441
442 // Exception tests
443
444 /**
445 * Cannot create with negative capacity
446 */
447 public void testConstructor1() {
448 try {
449 new ConcurrentHashMap(-1,0,1);
450 shouldThrow();
451 } catch (IllegalArgumentException success) {}
452 }
453
454 /**
455 * Cannot create with negative concurrency level
456 */
457 public void testConstructor2() {
458 try {
459 new ConcurrentHashMap(1,0,-1);
460 shouldThrow();
461 } catch (IllegalArgumentException success) {}
462 }
463
464 /**
465 * Cannot create with only negative capacity
466 */
467 public void testConstructor3() {
468 try {
469 new ConcurrentHashMap(-1);
470 shouldThrow();
471 } catch (IllegalArgumentException success) {}
472 }
473
474 /**
475 * get(null) throws NPE
476 */
477 public void testGet_NullPointerException() {
478 try {
479 ConcurrentHashMap c = new ConcurrentHashMap(5);
480 c.get(null);
481 shouldThrow();
482 } catch (NullPointerException success) {}
483 }
484
485 /**
486 * containsKey(null) throws NPE
487 */
488 public void testContainsKey_NullPointerException() {
489 try {
490 ConcurrentHashMap c = new ConcurrentHashMap(5);
491 c.containsKey(null);
492 shouldThrow();
493 } catch (NullPointerException success) {}
494 }
495
496 /**
497 * containsValue(null) throws NPE
498 */
499 public void testContainsValue_NullPointerException() {
500 try {
501 ConcurrentHashMap c = new ConcurrentHashMap(5);
502 c.containsValue(null);
503 shouldThrow();
504 } catch (NullPointerException success) {}
505 }
506
507 /**
508 * contains(null) throws NPE
509 */
510 public void testContains_NullPointerException() {
511 try {
512 ConcurrentHashMap c = new ConcurrentHashMap(5);
513 c.contains(null);
514 shouldThrow();
515 } catch (NullPointerException success) {}
516 }
517
518 /**
519 * put(null,x) throws NPE
520 */
521 public void testPut1_NullPointerException() {
522 try {
523 ConcurrentHashMap c = new ConcurrentHashMap(5);
524 c.put(null, "whatever");
525 shouldThrow();
526 } catch (NullPointerException success) {}
527 }
528
529 /**
530 * put(x, null) throws NPE
531 */
532 public void testPut2_NullPointerException() {
533 try {
534 ConcurrentHashMap c = new ConcurrentHashMap(5);
535 c.put("whatever", null);
536 shouldThrow();
537 } catch (NullPointerException success) {}
538 }
539
540 /**
541 * putIfAbsent(null, x) throws NPE
542 */
543 public void testPutIfAbsent1_NullPointerException() {
544 try {
545 ConcurrentHashMap c = new ConcurrentHashMap(5);
546 c.putIfAbsent(null, "whatever");
547 shouldThrow();
548 } catch (NullPointerException success) {}
549 }
550
551 /**
552 * replace(null, x) throws NPE
553 */
554 public void testReplace_NullPointerException() {
555 try {
556 ConcurrentHashMap c = new ConcurrentHashMap(5);
557 c.replace(null, "whatever");
558 shouldThrow();
559 } catch (NullPointerException success) {}
560 }
561
562 /**
563 * replace(null, x, y) throws NPE
564 */
565 public void testReplaceValue_NullPointerException() {
566 try {
567 ConcurrentHashMap c = new ConcurrentHashMap(5);
568 c.replace(null, one, "whatever");
569 shouldThrow();
570 } catch (NullPointerException success) {}
571 }
572
573 /**
574 * putIfAbsent(x, null) throws NPE
575 */
576 public void testPutIfAbsent2_NullPointerException() {
577 try {
578 ConcurrentHashMap c = new ConcurrentHashMap(5);
579 c.putIfAbsent("whatever", null);
580 shouldThrow();
581 } catch (NullPointerException success) {}
582 }
583
584 /**
585 * replace(x, null) throws NPE
586 */
587 public void testReplace2_NullPointerException() {
588 try {
589 ConcurrentHashMap c = new ConcurrentHashMap(5);
590 c.replace("whatever", null);
591 shouldThrow();
592 } catch (NullPointerException success) {}
593 }
594
595 /**
596 * replace(x, null, y) throws NPE
597 */
598 public void testReplaceValue2_NullPointerException() {
599 try {
600 ConcurrentHashMap c = new ConcurrentHashMap(5);
601 c.replace("whatever", null, "A");
602 shouldThrow();
603 } catch (NullPointerException success) {}
604 }
605
606 /**
607 * replace(x, y, null) throws NPE
608 */
609 public void testReplaceValue3_NullPointerException() {
610 try {
611 ConcurrentHashMap c = new ConcurrentHashMap(5);
612 c.replace("whatever", one, null);
613 shouldThrow();
614 } catch (NullPointerException success) {}
615 }
616
617 /**
618 * remove(null) throws NPE
619 */
620 public void testRemove1_NullPointerException() {
621 try {
622 ConcurrentHashMap c = new ConcurrentHashMap(5);
623 c.put("sadsdf", "asdads");
624 c.remove(null);
625 shouldThrow();
626 } catch (NullPointerException success) {}
627 }
628
629 /**
630 * remove(null, x) throws NPE
631 */
632 public void testRemove2_NullPointerException() {
633 try {
634 ConcurrentHashMap c = new ConcurrentHashMap(5);
635 c.put("sadsdf", "asdads");
636 c.remove(null, "whatever");
637 shouldThrow();
638 } catch (NullPointerException success) {}
639 }
640
641 /**
642 * remove(x, null) returns false
643 */
644 public void testRemove3() {
645 ConcurrentHashMap c = new ConcurrentHashMap(5);
646 c.put("sadsdf", "asdads");
647 assertFalse(c.remove("sadsdf", null));
648 }
649
650 /**
651 * A deserialized map equals original
652 */
653 public void testSerialization() throws Exception {
654 Map x = map5();
655 Map y = serialClone(x);
656
657 assertNotSame(x, y);
658 assertEquals(x.size(), y.size());
659 assertEquals(x, y);
660 assertEquals(y, x);
661 }
662
663 /**
664 * SetValue of an EntrySet entry sets value in the map.
665 */
666 public void testSetValueWriteThrough() {
667 // Adapted from a bug report by Eric Zoerner
668 ConcurrentHashMap map = new ConcurrentHashMap(2, 5.0f, 1);
669 assertTrue(map.isEmpty());
670 for (int i = 0; i < 20; i++)
671 map.put(new Integer(i), new Integer(i));
672 assertFalse(map.isEmpty());
673 Map.Entry entry1 = (Map.Entry)map.entrySet().iterator().next();
674 // Unless it happens to be first (in which case remainder of
675 // test is skipped), remove a possibly-colliding key from map
676 // which, under some implementations, may cause entry1 to be
677 // cloned in map
678 if (!entry1.getKey().equals(new Integer(16))) {
679 map.remove(new Integer(16));
680 entry1.setValue("XYZ");
681 assertTrue(map.containsValue("XYZ")); // fails if write-through broken
682 }
683 }
684
685 }