ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/TreeMapTest.java
Revision: 1.37
Committed: Wed Jan 27 01:57:25 2021 UTC (3 years, 3 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.36: +7 -7 lines
Log Message:
use diamond <> pervasively

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