blob: 4359287ff6966a5833a2d236f57dee0fde594b84 [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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 */
6
7package jsr166;
8
9import junit.framework.*;
10import java.util.*;
11import java.util.concurrent.ConcurrentSkipListMap;
12
13public class ConcurrentSkipListMapTest extends JSR166TestCase {
14
15 /**
16 * Returns a new map from Integers 1-5 to Strings "A"-"E".
17 */
18 private static ConcurrentSkipListMap map5() {
19 ConcurrentSkipListMap map = new ConcurrentSkipListMap();
20 assertTrue(map.isEmpty());
21 map.put(one, "A");
22 map.put(five, "E");
23 map.put(three, "C");
24 map.put(two, "B");
25 map.put(four, "D");
26 assertFalse(map.isEmpty());
27 assertEquals(5, map.size());
28 return map;
29 }
30
31 /**
32 * clear removes all pairs
33 */
34 public void testClear() {
35 ConcurrentSkipListMap map = map5();
36 map.clear();
37 assertEquals(0, map.size());
38 }
39
40 /**
41 * copy constructor creates map equal to source map
42 */
43 public void testConstructFromSorted() {
44 ConcurrentSkipListMap map = map5();
45 ConcurrentSkipListMap map2 = new ConcurrentSkipListMap(map);
46 assertEquals(map, map2);
47 }
48
49 /**
50 * Maps with same contents are equal
51 */
52 public void testEquals() {
53 ConcurrentSkipListMap map1 = map5();
54 ConcurrentSkipListMap map2 = map5();
55 assertEquals(map1, map2);
56 assertEquals(map2, map1);
57 map1.clear();
58 assertFalse(map1.equals(map2));
59 assertFalse(map2.equals(map1));
60 }
61
62 /**
63 * containsKey returns true for contained key
64 */
65 public void testContainsKey() {
66 ConcurrentSkipListMap map = map5();
67 assertTrue(map.containsKey(one));
68 assertFalse(map.containsKey(zero));
69 }
70
71 /**
72 * containsValue returns true for held values
73 */
74 public void testContainsValue() {
75 ConcurrentSkipListMap map = map5();
76 assertTrue(map.containsValue("A"));
77 assertFalse(map.containsValue("Z"));
78 }
79
80 /**
81 * get returns the correct element at the given key,
82 * or null if not present
83 */
84 public void testGet() {
85 ConcurrentSkipListMap map = map5();
86 assertEquals("A", (String)map.get(one));
87 ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
88 assertNull(empty.get(one));
89 }
90
91 /**
92 * isEmpty is true of empty map and false for non-empty
93 */
94 public void testIsEmpty() {
95 ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
96 ConcurrentSkipListMap map = map5();
97 assertTrue(empty.isEmpty());
98 assertFalse(map.isEmpty());
99 }
100
101 /**
102 * firstKey returns first key
103 */
104 public void testFirstKey() {
105 ConcurrentSkipListMap map = map5();
106 assertEquals(one, map.firstKey());
107 }
108
109 /**
110 * lastKey returns last key
111 */
112 public void testLastKey() {
113 ConcurrentSkipListMap map = map5();
114 assertEquals(five, map.lastKey());
115 }
116
117 /**
118 * keySet.toArray returns contains all keys
119 */
120 public void testKeySetToArray() {
121 ConcurrentSkipListMap map = map5();
122 Set s = map.keySet();
123 Object[] ar = s.toArray();
124 assertTrue(s.containsAll(Arrays.asList(ar)));
125 assertEquals(5, ar.length);
126 ar[0] = m10;
127 assertFalse(s.containsAll(Arrays.asList(ar)));
128 }
129
130 /**
131 * descendingkeySet.toArray returns contains all keys
132 */
133 public void testDescendingKeySetToArray() {
134 ConcurrentSkipListMap map = map5();
135 Set s = map.descendingKeySet();
136 Object[] ar = s.toArray();
137 assertEquals(5, ar.length);
138 assertTrue(s.containsAll(Arrays.asList(ar)));
139 ar[0] = m10;
140 assertFalse(s.containsAll(Arrays.asList(ar)));
141 }
142
143 /**
144 * keySet returns a Set containing all the keys
145 */
146 public void testKeySet() {
147 ConcurrentSkipListMap map = map5();
148 Set s = map.keySet();
149 assertEquals(5, s.size());
150 assertTrue(s.contains(one));
151 assertTrue(s.contains(two));
152 assertTrue(s.contains(three));
153 assertTrue(s.contains(four));
154 assertTrue(s.contains(five));
155 }
156
157 /**
158 * keySet is ordered
159 */
160 public void testKeySetOrder() {
161 ConcurrentSkipListMap map = map5();
162 Set s = map.keySet();
163 Iterator i = s.iterator();
164 Integer last = (Integer)i.next();
165 assertEquals(last, one);
166 int count = 1;
167 while (i.hasNext()) {
168 Integer k = (Integer)i.next();
169 assertTrue(last.compareTo(k) < 0);
170 last = k;
171 ++count;
172 }
173 assertEquals(5, count);
174 }
175
176 /**
177 * descending iterator of key set is inverse ordered
178 */
179 public void testKeySetDescendingIteratorOrder() {
180 ConcurrentSkipListMap map = map5();
181 NavigableSet s = map.navigableKeySet();
182 Iterator i = s.descendingIterator();
183 Integer last = (Integer)i.next();
184 assertEquals(last, five);
185 int count = 1;
186 while (i.hasNext()) {
187 Integer k = (Integer)i.next();
188 assertTrue(last.compareTo(k) > 0);
189 last = k;
190 ++count;
191 }
192 assertEquals(5, count);
193 }
194
195 /**
196 * descendingKeySet is ordered
197 */
198 public void testDescendingKeySetOrder() {
199 ConcurrentSkipListMap map = map5();
200 Set s = map.descendingKeySet();
201 Iterator i = s.iterator();
202 Integer last = (Integer)i.next();
203 assertEquals(last, five);
204 int count = 1;
205 while (i.hasNext()) {
206 Integer k = (Integer)i.next();
207 assertTrue(last.compareTo(k) > 0);
208 last = k;
209 ++count;
210 }
211 assertEquals(5, count);
212 }
213
214 /**
215 * descending iterator of descendingKeySet is ordered
216 */
217 public void testDescendingKeySetDescendingIteratorOrder() {
218 ConcurrentSkipListMap map = map5();
219 NavigableSet s = map.descendingKeySet();
220 Iterator i = s.descendingIterator();
221 Integer last = (Integer)i.next();
222 assertEquals(last, one);
223 int count = 1;
224 while (i.hasNext()) {
225 Integer k = (Integer)i.next();
226 assertTrue(last.compareTo(k) < 0);
227 last = k;
228 ++count;
229 }
230 assertEquals(5, count);
231 }
232
233 /**
234 * Values.toArray contains all values
235 */
236 public void testValuesToArray() {
237 ConcurrentSkipListMap map = map5();
238 Collection v = map.values();
239 Object[] ar = v.toArray();
240 ArrayList s = new ArrayList(Arrays.asList(ar));
241 assertEquals(5, ar.length);
242 assertTrue(s.contains("A"));
243 assertTrue(s.contains("B"));
244 assertTrue(s.contains("C"));
245 assertTrue(s.contains("D"));
246 assertTrue(s.contains("E"));
247 }
248
249 /**
250 * values collection contains all values
251 */
252 public void testValues() {
253 ConcurrentSkipListMap map = map5();
254 Collection s = map.values();
255 assertEquals(5, s.size());
256 assertTrue(s.contains("A"));
257 assertTrue(s.contains("B"));
258 assertTrue(s.contains("C"));
259 assertTrue(s.contains("D"));
260 assertTrue(s.contains("E"));
261 }
262
263 /**
264 * entrySet contains all pairs
265 */
266 public void testEntrySet() {
267 ConcurrentSkipListMap map = map5();
268 Set s = map.entrySet();
269 assertEquals(5, s.size());
270 Iterator it = s.iterator();
271 while (it.hasNext()) {
272 Map.Entry e = (Map.Entry) it.next();
273 assertTrue(
274 (e.getKey().equals(one) && e.getValue().equals("A")) ||
275 (e.getKey().equals(two) && e.getValue().equals("B")) ||
276 (e.getKey().equals(three) && e.getValue().equals("C")) ||
277 (e.getKey().equals(four) && e.getValue().equals("D")) ||
278 (e.getKey().equals(five) && e.getValue().equals("E")));
279 }
280 }
281
282 /**
283 * descendingEntrySet contains all pairs
284 */
285 public void testDescendingEntrySet() {
286 ConcurrentSkipListMap map = map5();
287 Set s = map.descendingMap().entrySet();
288 assertEquals(5, s.size());
289 Iterator it = s.iterator();
290 while (it.hasNext()) {
291 Map.Entry e = (Map.Entry) it.next();
292 assertTrue(
293 (e.getKey().equals(one) && e.getValue().equals("A")) ||
294 (e.getKey().equals(two) && e.getValue().equals("B")) ||
295 (e.getKey().equals(three) && e.getValue().equals("C")) ||
296 (e.getKey().equals(four) && e.getValue().equals("D")) ||
297 (e.getKey().equals(five) && e.getValue().equals("E")));
298 }
299 }
300
301 /**
302 * entrySet.toArray contains all entries
303 */
304 public void testEntrySetToArray() {
305 ConcurrentSkipListMap map = map5();
306 Set s = map.entrySet();
307 Object[] ar = s.toArray();
308 assertEquals(5, ar.length);
309 for (int i = 0; i < 5; ++i) {
310 assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey()));
311 assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue()));
312 }
313 }
314
315 /**
316 * descendingEntrySet.toArray contains all entries
317 */
318 public void testDescendingEntrySetToArray() {
319 ConcurrentSkipListMap map = map5();
320 Set s = map.descendingMap().entrySet();
321 Object[] ar = s.toArray();
322 assertEquals(5, ar.length);
323 for (int i = 0; i < 5; ++i) {
324 assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey()));
325 assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue()));
326 }
327 }
328
329 /**
330 * putAll adds all key-value pairs from the given map
331 */
332 public void testPutAll() {
333 ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
334 ConcurrentSkipListMap map = map5();
335 empty.putAll(map);
336 assertEquals(5, empty.size());
337 assertTrue(empty.containsKey(one));
338 assertTrue(empty.containsKey(two));
339 assertTrue(empty.containsKey(three));
340 assertTrue(empty.containsKey(four));
341 assertTrue(empty.containsKey(five));
342 }
343
344 /**
345 * putIfAbsent works when the given key is not present
346 */
347 public void testPutIfAbsent() {
348 ConcurrentSkipListMap map = map5();
349 map.putIfAbsent(six, "Z");
350 assertTrue(map.containsKey(six));
351 }
352
353 /**
354 * putIfAbsent does not add the pair if the key is already present
355 */
356 public void testPutIfAbsent2() {
357 ConcurrentSkipListMap map = map5();
358 assertEquals("A", map.putIfAbsent(one, "Z"));
359 }
360
361 /**
362 * replace fails when the given key is not present
363 */
364 public void testReplace() {
365 ConcurrentSkipListMap map = map5();
366 assertNull(map.replace(six, "Z"));
367 assertFalse(map.containsKey(six));
368 }
369
370 /**
371 * replace succeeds if the key is already present
372 */
373 public void testReplace2() {
374 ConcurrentSkipListMap map = map5();
375 assertNotNull(map.replace(one, "Z"));
376 assertEquals("Z", map.get(one));
377 }
378
379 /**
380 * replace value fails when the given key not mapped to expected value
381 */
382 public void testReplaceValue() {
383 ConcurrentSkipListMap map = map5();
384 assertEquals("A", map.get(one));
385 assertFalse(map.replace(one, "Z", "Z"));
386 assertEquals("A", map.get(one));
387 }
388
389 /**
390 * replace value succeeds when the given key mapped to expected value
391 */
392 public void testReplaceValue2() {
393 ConcurrentSkipListMap map = map5();
394 assertEquals("A", map.get(one));
395 assertTrue(map.replace(one, "A", "Z"));
396 assertEquals("Z", map.get(one));
397 }
398
399 /**
400 * remove removes the correct key-value pair from the map
401 */
402 public void testRemove() {
403 ConcurrentSkipListMap map = map5();
404 map.remove(five);
405 assertEquals(4, map.size());
406 assertFalse(map.containsKey(five));
407 }
408
409 /**
410 * remove(key,value) removes only if pair present
411 */
412 public void testRemove2() {
413 ConcurrentSkipListMap map = map5();
414 assertTrue(map.containsKey(five));
415 assertEquals("E", map.get(five));
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 * lowerEntry returns preceding entry.
426 */
427 public void testLowerEntry() {
428 ConcurrentSkipListMap map = map5();
429 Map.Entry e1 = map.lowerEntry(three);
430 assertEquals(two, e1.getKey());
431
432 Map.Entry e2 = map.lowerEntry(six);
433 assertEquals(five, e2.getKey());
434
435 Map.Entry e3 = map.lowerEntry(one);
436 assertNull(e3);
437
438 Map.Entry e4 = map.lowerEntry(zero);
439 assertNull(e4);
440 }
441
442 /**
443 * higherEntry returns next entry.
444 */
445 public void testHigherEntry() {
446 ConcurrentSkipListMap map = map5();
447 Map.Entry e1 = map.higherEntry(three);
448 assertEquals(four, e1.getKey());
449
450 Map.Entry e2 = map.higherEntry(zero);
451 assertEquals(one, e2.getKey());
452
453 Map.Entry e3 = map.higherEntry(five);
454 assertNull(e3);
455
456 Map.Entry e4 = map.higherEntry(six);
457 assertNull(e4);
458 }
459
460 /**
461 * floorEntry returns preceding entry.
462 */
463 public void testFloorEntry() {
464 ConcurrentSkipListMap map = map5();
465 Map.Entry e1 = map.floorEntry(three);
466 assertEquals(three, e1.getKey());
467
468 Map.Entry e2 = map.floorEntry(six);
469 assertEquals(five, e2.getKey());
470
471 Map.Entry e3 = map.floorEntry(one);
472 assertEquals(one, e3.getKey());
473
474 Map.Entry e4 = map.floorEntry(zero);
475 assertNull(e4);
476 }
477
478 /**
479 * ceilingEntry returns next entry.
480 */
481 public void testCeilingEntry() {
482 ConcurrentSkipListMap map = map5();
483 Map.Entry e1 = map.ceilingEntry(three);
484 assertEquals(three, e1.getKey());
485
486 Map.Entry e2 = map.ceilingEntry(zero);
487 assertEquals(one, e2.getKey());
488
489 Map.Entry e3 = map.ceilingEntry(five);
490 assertEquals(five, e3.getKey());
491
492 Map.Entry e4 = map.ceilingEntry(six);
493 assertNull(e4);
494 }
495
496 /**
497 * lowerEntry, higherEntry, ceilingEntry, and floorEntry return
498 * immutable entries
499 */
500 public void testEntryImmutability() {
501 ConcurrentSkipListMap map = map5();
502 Map.Entry e = map.lowerEntry(three);
503 assertEquals(two, e.getKey());
504 try {
505 e.setValue("X");
506 shouldThrow();
507 } catch (UnsupportedOperationException success) {}
508 e = map.higherEntry(zero);
509 assertEquals(one, e.getKey());
510 try {
511 e.setValue("X");
512 shouldThrow();
513 } catch (UnsupportedOperationException success) {}
514 e = map.floorEntry(one);
515 assertEquals(one, e.getKey());
516 try {
517 e.setValue("X");
518 shouldThrow();
519 } catch (UnsupportedOperationException success) {}
520 e = map.ceilingEntry(five);
521 assertEquals(five, e.getKey());
522 try {
523 e.setValue("X");
524 shouldThrow();
525 } catch (UnsupportedOperationException success) {}
526 }
527
528 /**
529 * lowerKey returns preceding element
530 */
531 public void testLowerKey() {
532 ConcurrentSkipListMap q = map5();
533 Object e1 = q.lowerKey(three);
534 assertEquals(two, e1);
535
536 Object e2 = q.lowerKey(six);
537 assertEquals(five, e2);
538
539 Object e3 = q.lowerKey(one);
540 assertNull(e3);
541
542 Object e4 = q.lowerKey(zero);
543 assertNull(e4);
544 }
545
546 /**
547 * higherKey returns next element
548 */
549 public void testHigherKey() {
550 ConcurrentSkipListMap q = map5();
551 Object e1 = q.higherKey(three);
552 assertEquals(four, e1);
553
554 Object e2 = q.higherKey(zero);
555 assertEquals(one, e2);
556
557 Object e3 = q.higherKey(five);
558 assertNull(e3);
559
560 Object e4 = q.higherKey(six);
561 assertNull(e4);
562 }
563
564 /**
565 * floorKey returns preceding element
566 */
567 public void testFloorKey() {
568 ConcurrentSkipListMap q = map5();
569 Object e1 = q.floorKey(three);
570 assertEquals(three, e1);
571
572 Object e2 = q.floorKey(six);
573 assertEquals(five, e2);
574
575 Object e3 = q.floorKey(one);
576 assertEquals(one, e3);
577
578 Object e4 = q.floorKey(zero);
579 assertNull(e4);
580 }
581
582 /**
583 * ceilingKey returns next element
584 */
585 public void testCeilingKey() {
586 ConcurrentSkipListMap q = map5();
587 Object e1 = q.ceilingKey(three);
588 assertEquals(three, e1);
589
590 Object e2 = q.ceilingKey(zero);
591 assertEquals(one, e2);
592
593 Object e3 = q.ceilingKey(five);
594 assertEquals(five, e3);
595
596 Object e4 = q.ceilingKey(six);
597 assertNull(e4);
598 }
599
600 /**
601 * pollFirstEntry returns entries in order
602 */
603 public void testPollFirstEntry() {
604 ConcurrentSkipListMap map = map5();
605 Map.Entry e = map.pollFirstEntry();
606 assertEquals(one, e.getKey());
607 assertEquals("A", e.getValue());
608 e = map.pollFirstEntry();
609 assertEquals(two, e.getKey());
610 map.put(one, "A");
611 e = map.pollFirstEntry();
612 assertEquals(one, e.getKey());
613 assertEquals("A", e.getValue());
614 e = map.pollFirstEntry();
615 assertEquals(three, e.getKey());
616 map.remove(four);
617 e = map.pollFirstEntry();
618 assertEquals(five, e.getKey());
619 try {
620 e.setValue("A");
621 shouldThrow();
622 } catch (UnsupportedOperationException success) {}
623 e = map.pollFirstEntry();
624 assertNull(e);
625 }
626
627 /**
628 * pollLastEntry returns entries in order
629 */
630 public void testPollLastEntry() {
631 ConcurrentSkipListMap map = map5();
632 Map.Entry e = map.pollLastEntry();
633 assertEquals(five, e.getKey());
634 assertEquals("E", e.getValue());
635 e = map.pollLastEntry();
636 assertEquals(four, e.getKey());
637 map.put(five, "E");
638 e = map.pollLastEntry();
639 assertEquals(five, e.getKey());
640 assertEquals("E", e.getValue());
641 e = map.pollLastEntry();
642 assertEquals(three, e.getKey());
643 map.remove(two);
644 e = map.pollLastEntry();
645 assertEquals(one, e.getKey());
646 try {
647 e.setValue("E");
648 shouldThrow();
649 } catch (UnsupportedOperationException success) {}
650 e = map.pollLastEntry();
651 assertNull(e);
652 }
653
654 /**
655 * size returns the correct values
656 */
657 public void testSize() {
658 ConcurrentSkipListMap map = map5();
659 ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
660 assertEquals(0, empty.size());
661 assertEquals(5, map.size());
662 }
663
664 /**
665 * toString contains toString of elements
666 */
667 public void testToString() {
668 ConcurrentSkipListMap map = map5();
669 String s = map.toString();
670 for (int i = 1; i <= 5; ++i) {
671 assertTrue(s.contains(String.valueOf(i)));
672 }
673 }
674
675 // Exception tests
676
677 /**
678 * get(null) of nonempty map throws NPE
679 */
680 public void testGet_NullPointerException() {
681 try {
682 ConcurrentSkipListMap c = map5();
683 c.get(null);
684 shouldThrow();
685 } catch (NullPointerException success) {}
686 }
687
688 /**
689 * containsKey(null) of nonempty map throws NPE
690 */
691 public void testContainsKey_NullPointerException() {
692 try {
693 ConcurrentSkipListMap c = map5();
694 c.containsKey(null);
695 shouldThrow();
696 } catch (NullPointerException success) {}
697 }
698
699 /**
700 * containsValue(null) throws NPE
701 */
702 public void testContainsValue_NullPointerException() {
703 try {
704 ConcurrentSkipListMap c = new ConcurrentSkipListMap();
705 c.containsValue(null);
706 shouldThrow();
707 } catch (NullPointerException success) {}
708 }
709
710 /**
711 * put(null,x) throws NPE
712 */
713 public void testPut1_NullPointerException() {
714 try {
715 ConcurrentSkipListMap c = map5();
716 c.put(null, "whatever");
717 shouldThrow();
718 } catch (NullPointerException success) {}
719 }
720
721 /**
722 * putIfAbsent(null, x) throws NPE
723 */
724 public void testPutIfAbsent1_NullPointerException() {
725 try {
726 ConcurrentSkipListMap c = map5();
727 c.putIfAbsent(null, "whatever");
728 shouldThrow();
729 } catch (NullPointerException success) {}
730 }
731
732 /**
733 * replace(null, x) throws NPE
734 */
735 public void testReplace_NullPointerException() {
736 try {
737 ConcurrentSkipListMap c = map5();
738 c.replace(null, "whatever");
739 shouldThrow();
740 } catch (NullPointerException success) {}
741 }
742
743 /**
744 * replace(null, x, y) throws NPE
745 */
746 public void testReplaceValue_NullPointerException() {
747 try {
748 ConcurrentSkipListMap c = map5();
749 c.replace(null, one, "whatever");
750 shouldThrow();
751 } catch (NullPointerException success) {}
752 }
753
754 /**
755 * remove(null) throws NPE
756 */
757 public void testRemove1_NullPointerException() {
758 try {
759 ConcurrentSkipListMap c = new ConcurrentSkipListMap();
760 c.put("sadsdf", "asdads");
761 c.remove(null);
762 shouldThrow();
763 } catch (NullPointerException success) {}
764 }
765
766 /**
767 * remove(null, x) throws NPE
768 */
769 public void testRemove2_NullPointerException() {
770 try {
771 ConcurrentSkipListMap c = new ConcurrentSkipListMap();
772 c.put("sadsdf", "asdads");
773 c.remove(null, "whatever");
774 shouldThrow();
775 } catch (NullPointerException success) {}
776 }
777
778 /**
779 * remove(x, null) returns false
780 */
781 public void testRemove3() {
782 ConcurrentSkipListMap c = new ConcurrentSkipListMap();
783 c.put("sadsdf", "asdads");
784 assertFalse(c.remove("sadsdf", null));
785 }
786
787 /**
788 * A deserialized map equals original
789 */
790 public void testSerialization() throws Exception {
791 NavigableMap x = map5();
792 NavigableMap y = serialClone(x);
793
794 assertNotSame(x, y);
795 assertEquals(x.size(), y.size());
796 assertEquals(x.toString(), y.toString());
797 assertEquals(x, y);
798 assertEquals(y, x);
799 }
800
801 /**
802 * subMap returns map with keys in requested range
803 */
804 public void testSubMapContents() {
805 ConcurrentSkipListMap map = map5();
806 NavigableMap sm = map.subMap(two, true, four, false);
807 assertEquals(two, sm.firstKey());
808 assertEquals(three, sm.lastKey());
809 assertEquals(2, sm.size());
810 assertFalse(sm.containsKey(one));
811 assertTrue(sm.containsKey(two));
812 assertTrue(sm.containsKey(three));
813 assertFalse(sm.containsKey(four));
814 assertFalse(sm.containsKey(five));
815 Iterator i = sm.keySet().iterator();
816 Object k;
817 k = (Integer)(i.next());
818 assertEquals(two, k);
819 k = (Integer)(i.next());
820 assertEquals(three, k);
821 assertFalse(i.hasNext());
822 Iterator r = sm.descendingKeySet().iterator();
823 k = (Integer)(r.next());
824 assertEquals(three, k);
825 k = (Integer)(r.next());
826 assertEquals(two, k);
827 assertFalse(r.hasNext());
828
829 Iterator j = sm.keySet().iterator();
830 j.next();
831 j.remove();
832 assertFalse(map.containsKey(two));
833 assertEquals(4, map.size());
834 assertEquals(1, sm.size());
835 assertEquals(three, sm.firstKey());
836 assertEquals(three, sm.lastKey());
837 assertEquals("C", sm.remove(three));
838 assertTrue(sm.isEmpty());
839 assertEquals(3, map.size());
840 }
841
842 public void testSubMapContents2() {
843 ConcurrentSkipListMap map = map5();
844 NavigableMap sm = map.subMap(two, true, three, false);
845 assertEquals(1, sm.size());
846 assertEquals(two, sm.firstKey());
847 assertEquals(two, sm.lastKey());
848 assertFalse(sm.containsKey(one));
849 assertTrue(sm.containsKey(two));
850 assertFalse(sm.containsKey(three));
851 assertFalse(sm.containsKey(four));
852 assertFalse(sm.containsKey(five));
853 Iterator i = sm.keySet().iterator();
854 Object k;
855 k = (Integer)(i.next());
856 assertEquals(two, k);
857 assertFalse(i.hasNext());
858 Iterator r = sm.descendingKeySet().iterator();
859 k = (Integer)(r.next());
860 assertEquals(two, k);
861 assertFalse(r.hasNext());
862
863 Iterator j = sm.keySet().iterator();
864 j.next();
865 j.remove();
866 assertFalse(map.containsKey(two));
867 assertEquals(4, map.size());
868 assertEquals(0, sm.size());
869 assertTrue(sm.isEmpty());
870 assertSame(sm.remove(three), null);
871 assertEquals(4, map.size());
872 }
873
874 /**
875 * headMap returns map with keys in requested range
876 */
877 public void testHeadMapContents() {
878 ConcurrentSkipListMap map = map5();
879 NavigableMap sm = map.headMap(four, false);
880 assertTrue(sm.containsKey(one));
881 assertTrue(sm.containsKey(two));
882 assertTrue(sm.containsKey(three));
883 assertFalse(sm.containsKey(four));
884 assertFalse(sm.containsKey(five));
885 Iterator i = sm.keySet().iterator();
886 Object k;
887 k = (Integer)(i.next());
888 assertEquals(one, k);
889 k = (Integer)(i.next());
890 assertEquals(two, k);
891 k = (Integer)(i.next());
892 assertEquals(three, k);
893 assertFalse(i.hasNext());
894 sm.clear();
895 assertTrue(sm.isEmpty());
896 assertEquals(2, map.size());
897 assertEquals(four, map.firstKey());
898 }
899
900 /**
901 * tailMap returns map with keys in requested range
902 */
903 public void testTailMapContents() {
904 ConcurrentSkipListMap map = map5();
905 NavigableMap sm = map.tailMap(two, true);
906 assertFalse(sm.containsKey(one));
907 assertTrue(sm.containsKey(two));
908 assertTrue(sm.containsKey(three));
909 assertTrue(sm.containsKey(four));
910 assertTrue(sm.containsKey(five));
911 Iterator i = sm.keySet().iterator();
912 Object k;
913 k = (Integer)(i.next());
914 assertEquals(two, k);
915 k = (Integer)(i.next());
916 assertEquals(three, k);
917 k = (Integer)(i.next());
918 assertEquals(four, k);
919 k = (Integer)(i.next());
920 assertEquals(five, k);
921 assertFalse(i.hasNext());
922 Iterator r = sm.descendingKeySet().iterator();
923 k = (Integer)(r.next());
924 assertEquals(five, k);
925 k = (Integer)(r.next());
926 assertEquals(four, k);
927 k = (Integer)(r.next());
928 assertEquals(three, k);
929 k = (Integer)(r.next());
930 assertEquals(two, k);
931 assertFalse(r.hasNext());
932
933 Iterator ei = sm.entrySet().iterator();
934 Map.Entry e;
935 e = (Map.Entry)(ei.next());
936 assertEquals(two, e.getKey());
937 assertEquals("B", e.getValue());
938 e = (Map.Entry)(ei.next());
939 assertEquals(three, e.getKey());
940 assertEquals("C", e.getValue());
941 e = (Map.Entry)(ei.next());
942 assertEquals(four, e.getKey());
943 assertEquals("D", e.getValue());
944 e = (Map.Entry)(ei.next());
945 assertEquals(five, e.getKey());
946 assertEquals("E", e.getValue());
947 assertFalse(i.hasNext());
948
949 NavigableMap ssm = sm.tailMap(four, true);
950 assertEquals(four, ssm.firstKey());
951 assertEquals(five, ssm.lastKey());
952 assertEquals("D", ssm.remove(four));
953 assertEquals(1, ssm.size());
954 assertEquals(3, sm.size());
955 assertEquals(4, map.size());
956 }
957
958 Random rnd = new Random(666);
959 BitSet bs;
960
961 /**
962 * Submaps of submaps subdivide correctly
963 */
964 public void testRecursiveSubMaps() throws Exception {
965 int mapSize = expensiveTests ? 1000 : 100;
966 Class cl = ConcurrentSkipListMap.class;
967 NavigableMap<Integer, Integer> map = newMap(cl);
968 bs = new BitSet(mapSize);
969
970 populate(map, mapSize);
971 check(map, 0, mapSize - 1, true);
972 check(map.descendingMap(), 0, mapSize - 1, false);
973
974 mutateMap(map, 0, mapSize - 1);
975 check(map, 0, mapSize - 1, true);
976 check(map.descendingMap(), 0, mapSize - 1, false);
977
978 bashSubMap(map.subMap(0, true, mapSize, false),
979 0, mapSize - 1, true);
980 }
981
982 static NavigableMap<Integer, Integer> newMap(Class cl) throws Exception {
983 NavigableMap<Integer, Integer> result =
984 (NavigableMap<Integer, Integer>) cl.newInstance();
985 assertEquals(0, result.size());
986 assertFalse(result.keySet().iterator().hasNext());
987 return result;
988 }
989
990 void populate(NavigableMap<Integer, Integer> map, int limit) {
991 for (int i = 0, n = 2 * limit / 3; i < n; i++) {
992 int key = rnd.nextInt(limit);
993 put(map, key);
994 }
995 }
996
997 void mutateMap(NavigableMap<Integer, Integer> map, int min, int max) {
998 int size = map.size();
999 int rangeSize = max - min + 1;
1000
1001 // Remove a bunch of entries directly
1002 for (int i = 0, n = rangeSize / 2; i < n; i++) {
1003 remove(map, min - 5 + rnd.nextInt(rangeSize + 10));
1004 }
1005
1006 // Remove a bunch of entries with iterator
1007 for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext(); ) {
1008 if (rnd.nextBoolean()) {
1009 bs.clear(it.next());
1010 it.remove();
1011 }
1012 }
1013
1014 // Add entries till we're back to original size
1015 while (map.size() < size) {
1016 int key = min + rnd.nextInt(rangeSize);
1017 assertTrue(key >= min && key<= max);
1018 put(map, key);
1019 }
1020 }
1021
1022 void mutateSubMap(NavigableMap<Integer, Integer> map, int min, int max) {
1023 int size = map.size();
1024 int rangeSize = max - min + 1;
1025
1026 // Remove a bunch of entries directly
1027 for (int i = 0, n = rangeSize / 2; i < n; i++) {
1028 remove(map, min - 5 + rnd.nextInt(rangeSize + 10));
1029 }
1030
1031 // Remove a bunch of entries with iterator
1032 for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext(); ) {
1033 if (rnd.nextBoolean()) {
1034 bs.clear(it.next());
1035 it.remove();
1036 }
1037 }
1038
1039 // Add entries till we're back to original size
1040 while (map.size() < size) {
1041 int key = min - 5 + rnd.nextInt(rangeSize + 10);
1042 if (key >= min && key<= max) {
1043 put(map, key);
1044 } else {
1045 try {
1046 map.put(key, 2 * key);
1047 shouldThrow();
1048 } catch (IllegalArgumentException success) {}
1049 }
1050 }
1051 }
1052
1053 void put(NavigableMap<Integer, Integer> map, int key) {
1054 if (map.put(key, 2 * key) == null)
1055 bs.set(key);
1056 }
1057
1058 void remove(NavigableMap<Integer, Integer> map, int key) {
1059 if (map.remove(key) != null)
1060 bs.clear(key);
1061 }
1062
1063 void bashSubMap(NavigableMap<Integer, Integer> map,
1064 int min, int max, boolean ascending) {
1065 check(map, min, max, ascending);
1066 check(map.descendingMap(), min, max, !ascending);
1067
1068 mutateSubMap(map, min, max);
1069 check(map, min, max, ascending);
1070 check(map.descendingMap(), min, max, !ascending);
1071
1072 // Recurse
1073 if (max - min < 2)
1074 return;
1075 int midPoint = (min + max) / 2;
1076
1077 // headMap - pick direction and endpoint inclusion randomly
1078 boolean incl = rnd.nextBoolean();
1079 NavigableMap<Integer,Integer> hm = map.headMap(midPoint, incl);
1080 if (ascending) {
1081 if (rnd.nextBoolean())
1082 bashSubMap(hm, min, midPoint - (incl ? 0 : 1), true);
1083 else
1084 bashSubMap(hm.descendingMap(), min, midPoint - (incl ? 0 : 1),
1085 false);
1086 } else {
1087 if (rnd.nextBoolean())
1088 bashSubMap(hm, midPoint + (incl ? 0 : 1), max, false);
1089 else
1090 bashSubMap(hm.descendingMap(), midPoint + (incl ? 0 : 1), max,
1091 true);
1092 }
1093
1094 // tailMap - pick direction and endpoint inclusion randomly
1095 incl = rnd.nextBoolean();
1096 NavigableMap<Integer,Integer> tm = map.tailMap(midPoint,incl);
1097 if (ascending) {
1098 if (rnd.nextBoolean())
1099 bashSubMap(tm, midPoint + (incl ? 0 : 1), max, true);
1100 else
1101 bashSubMap(tm.descendingMap(), midPoint + (incl ? 0 : 1), max,
1102 false);
1103 } else {
1104 if (rnd.nextBoolean()) {
1105 bashSubMap(tm, min, midPoint - (incl ? 0 : 1), false);
1106 } else {
1107 bashSubMap(tm.descendingMap(), min, midPoint - (incl ? 0 : 1),
1108 true);
1109 }
1110 }
1111
1112 // subMap - pick direction and endpoint inclusion randomly
1113 int rangeSize = max - min + 1;
1114 int[] endpoints = new int[2];
1115 endpoints[0] = min + rnd.nextInt(rangeSize);
1116 endpoints[1] = min + rnd.nextInt(rangeSize);
1117 Arrays.sort(endpoints);
1118 boolean lowIncl = rnd.nextBoolean();
1119 boolean highIncl = rnd.nextBoolean();
1120 if (ascending) {
1121 NavigableMap<Integer,Integer> sm = map.subMap(
1122 endpoints[0], lowIncl, endpoints[1], highIncl);
1123 if (rnd.nextBoolean())
1124 bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1),
1125 endpoints[1] - (highIncl ? 0 : 1), true);
1126 else
1127 bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1),
1128 endpoints[1] - (highIncl ? 0 : 1), false);
1129 } else {
1130 NavigableMap<Integer,Integer> sm = map.subMap(
1131 endpoints[1], highIncl, endpoints[0], lowIncl);
1132 if (rnd.nextBoolean())
1133 bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1),
1134 endpoints[1] - (highIncl ? 0 : 1), false);
1135 else
1136 bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1),
1137 endpoints[1] - (highIncl ? 0 : 1), true);
1138 }
1139 }
1140
1141 /**
1142 * min and max are both inclusive. If max < min, interval is empty.
1143 */
1144 void check(NavigableMap<Integer, Integer> map,
1145 final int min, final int max, final boolean ascending) {
1146 class ReferenceSet {
1147 int lower(int key) {
1148 return ascending ? lowerAscending(key) : higherAscending(key);
1149 }
1150 int floor(int key) {
1151 return ascending ? floorAscending(key) : ceilingAscending(key);
1152 }
1153 int ceiling(int key) {
1154 return ascending ? ceilingAscending(key) : floorAscending(key);
1155 }
1156 int higher(int key) {
1157 return ascending ? higherAscending(key) : lowerAscending(key);
1158 }
1159 int first() {
1160 return ascending ? firstAscending() : lastAscending();
1161 }
1162 int last() {
1163 return ascending ? lastAscending() : firstAscending();
1164 }
1165 int lowerAscending(int key) {
1166 return floorAscending(key - 1);
1167 }
1168 int floorAscending(int key) {
1169 if (key < min)
1170 return -1;
1171 else if (key > max)
1172 key = max;
1173
1174 // BitSet should support this! Test would run much faster
1175 while (key >= min) {
1176 if (bs.get(key))
1177 return key;
1178 key--;
1179 }
1180 return -1;
1181 }
1182 int ceilingAscending(int key) {
1183 if (key < min)
1184 key = min;
1185 else if (key > max)
1186 return -1;
1187 int result = bs.nextSetBit(key);
1188 return result > max ? -1 : result;
1189 }
1190 int higherAscending(int key) {
1191 return ceilingAscending(key + 1);
1192 }
1193 private int firstAscending() {
1194 int result = ceilingAscending(min);
1195 return result > max ? -1 : result;
1196 }
1197 private int lastAscending() {
1198 int result = floorAscending(max);
1199 return result < min ? -1 : result;
1200 }
1201 }
1202 ReferenceSet rs = new ReferenceSet();
1203
1204 // Test contents using containsKey
1205 int size = 0;
1206 for (int i = min; i <= max; i++) {
1207 boolean bsContainsI = bs.get(i);
1208 assertEquals(bsContainsI, map.containsKey(i));
1209 if (bsContainsI)
1210 size++;
1211 }
1212 assertEquals(size, map.size());
1213
1214 // Test contents using contains keySet iterator
1215 int size2 = 0;
1216 int previousKey = -1;
1217 for (int key : map.keySet()) {
1218 assertTrue(bs.get(key));
1219 size2++;
1220 assertTrue(previousKey < 0 ||
1221 (ascending ? key - previousKey > 0 : key - previousKey < 0));
1222 previousKey = key;
1223 }
1224 assertEquals(size2, size);
1225
1226 // Test navigation ops
1227 for (int key = min - 1; key <= max + 1; key++) {
1228 assertEq(map.lowerKey(key), rs.lower(key));
1229 assertEq(map.floorKey(key), rs.floor(key));
1230 assertEq(map.higherKey(key), rs.higher(key));
1231 assertEq(map.ceilingKey(key), rs.ceiling(key));
1232 }
1233
1234 // Test extrema
1235 if (map.size() != 0) {
1236 assertEq(map.firstKey(), rs.first());
1237 assertEq(map.lastKey(), rs.last());
1238 } else {
1239 assertEq(rs.first(), -1);
1240 assertEq(rs.last(), -1);
1241 try {
1242 map.firstKey();
1243 shouldThrow();
1244 } catch (NoSuchElementException success) {}
1245 try {
1246 map.lastKey();
1247 shouldThrow();
1248 } catch (NoSuchElementException success) {}
1249 }
1250 }
1251
1252 static void assertEq(Integer i, int j) {
1253 if (i == null)
1254 assertEquals(j, -1);
1255 else
1256 assertEquals((int) i, j);
1257 }
1258
1259 static boolean eq(Integer i, int j) {
1260 return i == null ? j == -1 : i == j;
1261 }
1262
1263}