ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ConcurrentHashMapTest.java
Revision: 1.33
Committed: Sun Jul 14 21:41:06 2013 UTC (10 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.32: +5 -2 lines
Log Message:
backport to java 6, to help jsr166e

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