blob: a93563743263093c59fac3dbd97900e0a956cbf8 [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
Calin Juravle8f0d92b2013-08-01 17:26:00 +01009import java.util.Arrays;
10import java.util.BitSet;
11import java.util.Collection;
12import java.util.Comparator;
13import java.util.Iterator;
14import java.util.NavigableSet;
15import java.util.NoSuchElementException;
16import java.util.Random;
17import java.util.Set;
18import java.util.SortedSet;
19import java.util.TreeSet;
20
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010021import junit.framework.Test;
22import junit.framework.TestSuite;
23
Calin Juravle8f0d92b2013-08-01 17:26:00 +010024public class TreeSetTest extends JSR166TestCase {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010025 // android-note: Removed because the CTS runner does a bad job of
26 // retrying tests that have suite() declarations.
27 //
28 // public static void main(String[] args) {
29 // main(suite(), args);
30 // }
31 // public static Test suite() {
32 // return new TestSuite(...);
33 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010034
35 static class MyReverseComparator implements Comparator {
36 public int compare(Object x, Object y) {
37 return ((Comparable)y).compareTo(x);
38 }
39 }
40
41 /**
42 * The number of elements to place in collections, arrays, etc.
43 */
44 static final int SIZE = 20;
45
46 /**
47 * Returns a new set of given size containing consecutive
48 * Integers 0 ... n.
49 */
50 private TreeSet<Integer> populatedSet(int n) {
51 TreeSet<Integer> q = new TreeSet<Integer>();
52 assertTrue(q.isEmpty());
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010053 for (int i = n-1; i >= 0; i -= 2)
Calin Juravle8f0d92b2013-08-01 17:26:00 +010054 assertTrue(q.add(new Integer(i)));
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010055 for (int i = (n & 1); i < n; i += 2)
Calin Juravle8f0d92b2013-08-01 17:26:00 +010056 assertTrue(q.add(new Integer(i)));
57 assertFalse(q.isEmpty());
58 assertEquals(n, q.size());
59 return q;
60 }
61
62 /**
63 * Returns a new set of first 5 ints.
64 */
65 private TreeSet set5() {
66 TreeSet q = new TreeSet();
67 assertTrue(q.isEmpty());
68 q.add(one);
69 q.add(two);
70 q.add(three);
71 q.add(four);
72 q.add(five);
73 assertEquals(5, q.size());
74 return q;
75 }
76
77 /**
78 * A new set has unbounded capacity
79 */
80 public void testConstructor1() {
81 assertEquals(0, new TreeSet().size());
82 }
83
84 /**
85 * Initializing from null Collection throws NPE
86 */
87 public void testConstructor3() {
88 try {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010089 new TreeSet((Collection)null);
Calin Juravle8f0d92b2013-08-01 17:26:00 +010090 shouldThrow();
91 } catch (NullPointerException success) {}
92 }
93
94 /**
95 * Initializing from Collection of null elements throws NPE
96 */
97 public void testConstructor4() {
98 try {
99 Integer[] ints = new Integer[SIZE];
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100100 new TreeSet(Arrays.asList(ints));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100101 shouldThrow();
102 } catch (NullPointerException success) {}
103 }
104
105 /**
106 * Initializing from Collection with some null elements throws NPE
107 */
108 public void testConstructor5() {
109 try {
110 Integer[] ints = new Integer[SIZE];
111 for (int i = 0; i < SIZE-1; ++i)
112 ints[i] = new Integer(i);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100113 new TreeSet(Arrays.asList(ints));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100114 shouldThrow();
115 } catch (NullPointerException success) {}
116 }
117
118 /**
119 * Set contains all elements of collection used to initialize
120 */
121 public void testConstructor6() {
122 Integer[] ints = new Integer[SIZE];
123 for (int i = 0; i < SIZE; ++i)
124 ints[i] = new Integer(i);
125 TreeSet q = new TreeSet(Arrays.asList(ints));
126 for (int i = 0; i < SIZE; ++i)
127 assertEquals(ints[i], q.pollFirst());
128 }
129
130 /**
131 * The comparator used in constructor is used
132 */
133 public void testConstructor7() {
134 MyReverseComparator cmp = new MyReverseComparator();
135 TreeSet q = new TreeSet(cmp);
136 assertEquals(cmp, q.comparator());
137 Integer[] ints = new Integer[SIZE];
138 for (int i = 0; i < SIZE; ++i)
139 ints[i] = new Integer(i);
140 q.addAll(Arrays.asList(ints));
141 for (int i = SIZE-1; i >= 0; --i)
142 assertEquals(ints[i], q.pollFirst());
143 }
144
145 /**
146 * isEmpty is true before add, false after
147 */
148 public void testEmpty() {
149 TreeSet q = new TreeSet();
150 assertTrue(q.isEmpty());
151 q.add(new Integer(1));
152 assertFalse(q.isEmpty());
153 q.add(new Integer(2));
154 q.pollFirst();
155 q.pollFirst();
156 assertTrue(q.isEmpty());
157 }
158
159 /**
160 * size changes when elements added and removed
161 */
162 public void testSize() {
163 TreeSet q = populatedSet(SIZE);
164 for (int i = 0; i < SIZE; ++i) {
165 assertEquals(SIZE-i, q.size());
166 q.pollFirst();
167 }
168 for (int i = 0; i < SIZE; ++i) {
169 assertEquals(i, q.size());
170 q.add(new Integer(i));
171 }
172 }
173
174 /**
175 * add(null) throws NPE if nonempty
176 */
177 public void testAddNull() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100178 TreeSet q = populatedSet(SIZE);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100179 try {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100180 q.add(null);
181 shouldThrow();
182 } catch (NullPointerException success) {}
183 }
184
185 /**
186 * Add of comparable element succeeds
187 */
188 public void testAdd() {
189 TreeSet q = new TreeSet();
190 assertTrue(q.add(zero));
191 assertTrue(q.add(one));
192 }
193
194 /**
195 * Add of duplicate element fails
196 */
197 public void testAddDup() {
198 TreeSet q = new TreeSet();
199 assertTrue(q.add(zero));
200 assertFalse(q.add(zero));
201 }
202
203 /**
204 * Add of non-Comparable throws CCE
205 */
206 public void testAddNonComparable() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100207 TreeSet q = new TreeSet();
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100208 try {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100209 q.add(new Object());
210 q.add(new Object());
211 shouldThrow();
212 } catch (ClassCastException success) {}
213 }
214
215 /**
216 * addAll(null) throws NPE
217 */
218 public void testAddAll1() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100219 TreeSet q = new TreeSet();
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100220 try {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100221 q.addAll(null);
222 shouldThrow();
223 } catch (NullPointerException success) {}
224 }
225
226 /**
227 * addAll of a collection with null elements throws NPE
228 */
229 public void testAddAll2() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100230 TreeSet q = new TreeSet();
231 Integer[] ints = new Integer[SIZE];
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100232 try {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100233 q.addAll(Arrays.asList(ints));
234 shouldThrow();
235 } catch (NullPointerException success) {}
236 }
237
238 /**
239 * addAll of a collection with any null elements throws NPE after
240 * possibly adding some elements
241 */
242 public void testAddAll3() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100243 TreeSet q = new TreeSet();
244 Integer[] ints = new Integer[SIZE];
245 for (int i = 0; i < SIZE-1; ++i)
246 ints[i] = new Integer(i);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100247 try {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100248 q.addAll(Arrays.asList(ints));
249 shouldThrow();
250 } catch (NullPointerException success) {}
251 }
252
253 /**
254 * Set contains all elements of successful addAll
255 */
256 public void testAddAll5() {
257 Integer[] empty = new Integer[0];
258 Integer[] ints = new Integer[SIZE];
259 for (int i = 0; i < SIZE; ++i)
260 ints[i] = new Integer(SIZE-1-i);
261 TreeSet q = new TreeSet();
262 assertFalse(q.addAll(Arrays.asList(empty)));
263 assertTrue(q.addAll(Arrays.asList(ints)));
264 for (int i = 0; i < SIZE; ++i)
265 assertEquals(new Integer(i), q.pollFirst());
266 }
267
268 /**
269 * pollFirst succeeds unless empty
270 */
271 public void testPollFirst() {
272 TreeSet q = populatedSet(SIZE);
273 for (int i = 0; i < SIZE; ++i) {
274 assertEquals(i, q.pollFirst());
275 }
276 assertNull(q.pollFirst());
277 }
278
279 /**
280 * pollLast succeeds unless empty
281 */
282 public void testPollLast() {
283 TreeSet q = populatedSet(SIZE);
284 for (int i = SIZE-1; i >= 0; --i) {
285 assertEquals(i, q.pollLast());
286 }
287 assertNull(q.pollFirst());
288 }
289
290 /**
291 * remove(x) removes x and returns true if present
292 */
293 public void testRemoveElement() {
294 TreeSet q = populatedSet(SIZE);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100295 for (int i = 1; i < SIZE; i += 2) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100296 assertTrue(q.contains(i));
297 assertTrue(q.remove(i));
298 assertFalse(q.contains(i));
299 assertTrue(q.contains(i-1));
300 }
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100301 for (int i = 0; i < SIZE; i += 2) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100302 assertTrue(q.contains(i));
303 assertTrue(q.remove(i));
304 assertFalse(q.contains(i));
305 assertFalse(q.remove(i+1));
306 assertFalse(q.contains(i+1));
307 }
308 assertTrue(q.isEmpty());
309 }
310
311 /**
312 * contains(x) reports true when elements added but not yet removed
313 */
314 public void testContains() {
315 TreeSet q = populatedSet(SIZE);
316 for (int i = 0; i < SIZE; ++i) {
317 assertTrue(q.contains(new Integer(i)));
318 q.pollFirst();
319 assertFalse(q.contains(new Integer(i)));
320 }
321 }
322
323 /**
324 * clear removes all elements
325 */
326 public void testClear() {
327 TreeSet q = populatedSet(SIZE);
328 q.clear();
329 assertTrue(q.isEmpty());
330 assertEquals(0, q.size());
331 q.add(new Integer(1));
332 assertFalse(q.isEmpty());
333 q.clear();
334 assertTrue(q.isEmpty());
335 }
336
337 /**
338 * containsAll(c) is true when c contains a subset of elements
339 */
340 public void testContainsAll() {
341 TreeSet q = populatedSet(SIZE);
342 TreeSet p = new TreeSet();
343 for (int i = 0; i < SIZE; ++i) {
344 assertTrue(q.containsAll(p));
345 assertFalse(p.containsAll(q));
346 p.add(new Integer(i));
347 }
348 assertTrue(p.containsAll(q));
349 }
350
351 /**
352 * retainAll(c) retains only those elements of c and reports true if changed
353 */
354 public void testRetainAll() {
355 TreeSet q = populatedSet(SIZE);
356 TreeSet p = populatedSet(SIZE);
357 for (int i = 0; i < SIZE; ++i) {
358 boolean changed = q.retainAll(p);
359 if (i == 0)
360 assertFalse(changed);
361 else
362 assertTrue(changed);
363
364 assertTrue(q.containsAll(p));
365 assertEquals(SIZE-i, q.size());
366 p.pollFirst();
367 }
368 }
369
370 /**
371 * removeAll(c) removes only those elements of c and reports true if changed
372 */
373 public void testRemoveAll() {
374 for (int i = 1; i < SIZE; ++i) {
375 TreeSet q = populatedSet(SIZE);
376 TreeSet p = populatedSet(i);
377 assertTrue(q.removeAll(p));
378 assertEquals(SIZE-i, q.size());
379 for (int j = 0; j < i; ++j) {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100380 Integer x = (Integer)(p.pollFirst());
381 assertFalse(q.contains(x));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100382 }
383 }
384 }
385
386 /**
387 * lower returns preceding element
388 */
389 public void testLower() {
390 TreeSet q = set5();
391 Object e1 = q.lower(three);
392 assertEquals(two, e1);
393
394 Object e2 = q.lower(six);
395 assertEquals(five, e2);
396
397 Object e3 = q.lower(one);
398 assertNull(e3);
399
400 Object e4 = q.lower(zero);
401 assertNull(e4);
402 }
403
404 /**
405 * higher returns next element
406 */
407 public void testHigher() {
408 TreeSet q = set5();
409 Object e1 = q.higher(three);
410 assertEquals(four, e1);
411
412 Object e2 = q.higher(zero);
413 assertEquals(one, e2);
414
415 Object e3 = q.higher(five);
416 assertNull(e3);
417
418 Object e4 = q.higher(six);
419 assertNull(e4);
420 }
421
422 /**
423 * floor returns preceding element
424 */
425 public void testFloor() {
426 TreeSet q = set5();
427 Object e1 = q.floor(three);
428 assertEquals(three, e1);
429
430 Object e2 = q.floor(six);
431 assertEquals(five, e2);
432
433 Object e3 = q.floor(one);
434 assertEquals(one, e3);
435
436 Object e4 = q.floor(zero);
437 assertNull(e4);
438 }
439
440 /**
441 * ceiling returns next element
442 */
443 public void testCeiling() {
444 TreeSet q = set5();
445 Object e1 = q.ceiling(three);
446 assertEquals(three, e1);
447
448 Object e2 = q.ceiling(zero);
449 assertEquals(one, e2);
450
451 Object e3 = q.ceiling(five);
452 assertEquals(five, e3);
453
454 Object e4 = q.ceiling(six);
455 assertNull(e4);
456 }
457
458 /**
459 * toArray contains all elements in sorted order
460 */
461 public void testToArray() {
462 TreeSet q = populatedSet(SIZE);
463 Object[] o = q.toArray();
464 for (int i = 0; i < o.length; i++)
465 assertSame(o[i], q.pollFirst());
466 }
467
468 /**
469 * toArray(a) contains all elements in sorted order
470 */
471 public void testToArray2() {
472 TreeSet<Integer> q = populatedSet(SIZE);
473 Integer[] ints = new Integer[SIZE];
474 Integer[] array = q.toArray(ints);
475 assertSame(ints, array);
476 for (int i = 0; i < ints.length; i++)
477 assertSame(ints[i], q.pollFirst());
478 }
479
480 /**
481 * iterator iterates through all elements
482 */
483 public void testIterator() {
484 TreeSet q = populatedSet(SIZE);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100485 Iterator it = q.iterator();
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100486 int i;
487 for (i = 0; it.hasNext(); i++)
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100488 assertTrue(q.contains(it.next()));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100489 assertEquals(i, SIZE);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100490 assertIteratorExhausted(it);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100491 }
492
493 /**
494 * iterator of empty set has no elements
495 */
496 public void testEmptyIterator() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100497 assertIteratorExhausted(new TreeSet().iterator());
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100498 }
499
500 /**
501 * iterator.remove removes current element
502 */
503 public void testIteratorRemove() {
504 final TreeSet q = new TreeSet();
505 q.add(new Integer(2));
506 q.add(new Integer(1));
507 q.add(new Integer(3));
508
509 Iterator it = q.iterator();
510 it.next();
511 it.remove();
512
513 it = q.iterator();
514 assertEquals(it.next(), new Integer(2));
515 assertEquals(it.next(), new Integer(3));
516 assertFalse(it.hasNext());
517 }
518
519 /**
520 * toString contains toStrings of elements
521 */
522 public void testToString() {
523 TreeSet q = populatedSet(SIZE);
524 String s = q.toString();
525 for (int i = 0; i < SIZE; ++i) {
526 assertTrue(s.contains(String.valueOf(i)));
527 }
528 }
529
530 /**
531 * A deserialized serialized set has same elements
532 */
533 public void testSerialization() throws Exception {
534 NavigableSet x = populatedSet(SIZE);
535 NavigableSet y = serialClone(x);
536
537 assertNotSame(x, y);
538 assertEquals(x.size(), y.size());
539 assertEquals(x, y);
540 assertEquals(y, x);
541 while (!x.isEmpty()) {
542 assertFalse(y.isEmpty());
543 assertEquals(x.pollFirst(), y.pollFirst());
544 }
545 assertTrue(y.isEmpty());
546 }
547
548 /**
549 * subSet returns set with keys in requested range
550 */
551 public void testSubSetContents() {
552 TreeSet set = set5();
553 SortedSet sm = set.subSet(two, four);
554 assertEquals(two, sm.first());
555 assertEquals(three, sm.last());
556 assertEquals(2, sm.size());
557 assertFalse(sm.contains(one));
558 assertTrue(sm.contains(two));
559 assertTrue(sm.contains(three));
560 assertFalse(sm.contains(four));
561 assertFalse(sm.contains(five));
562 Iterator i = sm.iterator();
563 Object k;
564 k = (Integer)(i.next());
565 assertEquals(two, k);
566 k = (Integer)(i.next());
567 assertEquals(three, k);
568 assertFalse(i.hasNext());
569 Iterator j = sm.iterator();
570 j.next();
571 j.remove();
572 assertFalse(set.contains(two));
573 assertEquals(4, set.size());
574 assertEquals(1, sm.size());
575 assertEquals(three, sm.first());
576 assertEquals(three, sm.last());
577 assertTrue(sm.remove(three));
578 assertTrue(sm.isEmpty());
579 assertEquals(3, set.size());
580 }
581
582 public void testSubSetContents2() {
583 TreeSet set = set5();
584 SortedSet sm = set.subSet(two, three);
585 assertEquals(1, sm.size());
586 assertEquals(two, sm.first());
587 assertEquals(two, sm.last());
588 assertFalse(sm.contains(one));
589 assertTrue(sm.contains(two));
590 assertFalse(sm.contains(three));
591 assertFalse(sm.contains(four));
592 assertFalse(sm.contains(five));
593 Iterator i = sm.iterator();
594 Object k;
595 k = (Integer)(i.next());
596 assertEquals(two, k);
597 assertFalse(i.hasNext());
598 Iterator j = sm.iterator();
599 j.next();
600 j.remove();
601 assertFalse(set.contains(two));
602 assertEquals(4, set.size());
603 assertEquals(0, sm.size());
604 assertTrue(sm.isEmpty());
605 assertFalse(sm.remove(three));
606 assertEquals(4, set.size());
607 }
608
609 /**
610 * headSet returns set with keys in requested range
611 */
612 public void testHeadSetContents() {
613 TreeSet set = set5();
614 SortedSet sm = set.headSet(four);
615 assertTrue(sm.contains(one));
616 assertTrue(sm.contains(two));
617 assertTrue(sm.contains(three));
618 assertFalse(sm.contains(four));
619 assertFalse(sm.contains(five));
620 Iterator i = sm.iterator();
621 Object k;
622 k = (Integer)(i.next());
623 assertEquals(one, k);
624 k = (Integer)(i.next());
625 assertEquals(two, k);
626 k = (Integer)(i.next());
627 assertEquals(three, k);
628 assertFalse(i.hasNext());
629 sm.clear();
630 assertTrue(sm.isEmpty());
631 assertEquals(2, set.size());
632 assertEquals(four, set.first());
633 }
634
635 /**
636 * tailSet returns set with keys in requested range
637 */
638 public void testTailSetContents() {
639 TreeSet set = set5();
640 SortedSet sm = set.tailSet(two);
641 assertFalse(sm.contains(one));
642 assertTrue(sm.contains(two));
643 assertTrue(sm.contains(three));
644 assertTrue(sm.contains(four));
645 assertTrue(sm.contains(five));
646 Iterator i = sm.iterator();
647 Object k;
648 k = (Integer)(i.next());
649 assertEquals(two, k);
650 k = (Integer)(i.next());
651 assertEquals(three, k);
652 k = (Integer)(i.next());
653 assertEquals(four, k);
654 k = (Integer)(i.next());
655 assertEquals(five, k);
656 assertFalse(i.hasNext());
657
658 SortedSet ssm = sm.tailSet(four);
659 assertEquals(four, ssm.first());
660 assertEquals(five, ssm.last());
661 assertTrue(ssm.remove(four));
662 assertEquals(1, ssm.size());
663 assertEquals(3, sm.size());
664 assertEquals(4, set.size());
665 }
666
667 Random rnd = new Random(666);
668 BitSet bs;
669
670 /**
671 * Subsets of subsets subdivide correctly
672 */
673 public void testRecursiveSubSets() throws Exception {
674 int setSize = expensiveTests ? 1000 : 100;
675 Class cl = TreeSet.class;
676
677 NavigableSet<Integer> set = newSet(cl);
678 bs = new BitSet(setSize);
679
680 populate(set, setSize);
681 check(set, 0, setSize - 1, true);
682 check(set.descendingSet(), 0, setSize - 1, false);
683
684 mutateSet(set, 0, setSize - 1);
685 check(set, 0, setSize - 1, true);
686 check(set.descendingSet(), 0, setSize - 1, false);
687
688 bashSubSet(set.subSet(0, true, setSize, false),
689 0, setSize - 1, true);
690 }
691
692 /**
693 * addAll is idempotent
694 */
695 public void testAddAll_idempotent() throws Exception {
696 Set x = populatedSet(SIZE);
697 Set y = new TreeSet(x);
698 y.addAll(x);
699 assertEquals(x, y);
700 assertEquals(y, x);
701 }
702
703 static NavigableSet<Integer> newSet(Class cl) throws Exception {
704 NavigableSet<Integer> result = (NavigableSet<Integer>) cl.newInstance();
705 assertEquals(0, result.size());
706 assertFalse(result.iterator().hasNext());
707 return result;
708 }
709
710 void populate(NavigableSet<Integer> set, int limit) {
711 for (int i = 0, n = 2 * limit / 3; i < n; i++) {
712 int element = rnd.nextInt(limit);
713 put(set, element);
714 }
715 }
716
717 void mutateSet(NavigableSet<Integer> set, int min, int max) {
718 int size = set.size();
719 int rangeSize = max - min + 1;
720
721 // Remove a bunch of entries directly
722 for (int i = 0, n = rangeSize / 2; i < n; i++) {
723 remove(set, min - 5 + rnd.nextInt(rangeSize + 10));
724 }
725
726 // Remove a bunch of entries with iterator
727 for (Iterator<Integer> it = set.iterator(); it.hasNext(); ) {
728 if (rnd.nextBoolean()) {
729 bs.clear(it.next());
730 it.remove();
731 }
732 }
733
734 // Add entries till we're back to original size
735 while (set.size() < size) {
736 int element = min + rnd.nextInt(rangeSize);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100737 assertTrue(element >= min && element <= max);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100738 put(set, element);
739 }
740 }
741
742 void mutateSubSet(NavigableSet<Integer> set, int min, int max) {
743 int size = set.size();
744 int rangeSize = max - min + 1;
745
746 // Remove a bunch of entries directly
747 for (int i = 0, n = rangeSize / 2; i < n; i++) {
748 remove(set, min - 5 + rnd.nextInt(rangeSize + 10));
749 }
750
751 // Remove a bunch of entries with iterator
752 for (Iterator<Integer> it = set.iterator(); it.hasNext(); ) {
753 if (rnd.nextBoolean()) {
754 bs.clear(it.next());
755 it.remove();
756 }
757 }
758
759 // Add entries till we're back to original size
760 while (set.size() < size) {
761 int element = min - 5 + rnd.nextInt(rangeSize + 10);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100762 if (element >= min && element <= max) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100763 put(set, element);
764 } else {
765 try {
766 set.add(element);
767 shouldThrow();
768 } catch (IllegalArgumentException success) {}
769 }
770 }
771 }
772
773 void put(NavigableSet<Integer> set, int element) {
774 if (set.add(element))
775 bs.set(element);
776 }
777
778 void remove(NavigableSet<Integer> set, int element) {
779 if (set.remove(element))
780 bs.clear(element);
781 }
782
783 void bashSubSet(NavigableSet<Integer> set,
784 int min, int max, boolean ascending) {
785 check(set, min, max, ascending);
786 check(set.descendingSet(), min, max, !ascending);
787
788 mutateSubSet(set, min, max);
789 check(set, min, max, ascending);
790 check(set.descendingSet(), min, max, !ascending);
791
792 // Recurse
793 if (max - min < 2)
794 return;
795 int midPoint = (min + max) / 2;
796
797 // headSet - pick direction and endpoint inclusion randomly
798 boolean incl = rnd.nextBoolean();
799 NavigableSet<Integer> hm = set.headSet(midPoint, incl);
800 if (ascending) {
801 if (rnd.nextBoolean())
802 bashSubSet(hm, min, midPoint - (incl ? 0 : 1), true);
803 else
804 bashSubSet(hm.descendingSet(), min, midPoint - (incl ? 0 : 1),
805 false);
806 } else {
807 if (rnd.nextBoolean())
808 bashSubSet(hm, midPoint + (incl ? 0 : 1), max, false);
809 else
810 bashSubSet(hm.descendingSet(), midPoint + (incl ? 0 : 1), max,
811 true);
812 }
813
814 // tailSet - pick direction and endpoint inclusion randomly
815 incl = rnd.nextBoolean();
816 NavigableSet<Integer> tm = set.tailSet(midPoint,incl);
817 if (ascending) {
818 if (rnd.nextBoolean())
819 bashSubSet(tm, midPoint + (incl ? 0 : 1), max, true);
820 else
821 bashSubSet(tm.descendingSet(), midPoint + (incl ? 0 : 1), max,
822 false);
823 } else {
824 if (rnd.nextBoolean()) {
825 bashSubSet(tm, min, midPoint - (incl ? 0 : 1), false);
826 } else {
827 bashSubSet(tm.descendingSet(), min, midPoint - (incl ? 0 : 1),
828 true);
829 }
830 }
831
832 // subSet - pick direction and endpoint inclusion randomly
833 int rangeSize = max - min + 1;
834 int[] endpoints = new int[2];
835 endpoints[0] = min + rnd.nextInt(rangeSize);
836 endpoints[1] = min + rnd.nextInt(rangeSize);
837 Arrays.sort(endpoints);
838 boolean lowIncl = rnd.nextBoolean();
839 boolean highIncl = rnd.nextBoolean();
840 if (ascending) {
841 NavigableSet<Integer> sm = set.subSet(
842 endpoints[0], lowIncl, endpoints[1], highIncl);
843 if (rnd.nextBoolean())
844 bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1),
845 endpoints[1] - (highIncl ? 0 : 1), true);
846 else
847 bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1),
848 endpoints[1] - (highIncl ? 0 : 1), false);
849 } else {
850 NavigableSet<Integer> sm = set.subSet(
851 endpoints[1], highIncl, endpoints[0], lowIncl);
852 if (rnd.nextBoolean())
853 bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1),
854 endpoints[1] - (highIncl ? 0 : 1), false);
855 else
856 bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1),
857 endpoints[1] - (highIncl ? 0 : 1), true);
858 }
859 }
860
861 /**
862 * min and max are both inclusive. If max < min, interval is empty.
863 */
864 void check(NavigableSet<Integer> set,
865 final int min, final int max, final boolean ascending) {
866 class ReferenceSet {
867 int lower(int element) {
868 return ascending ?
869 lowerAscending(element) : higherAscending(element);
870 }
871 int floor(int element) {
872 return ascending ?
873 floorAscending(element) : ceilingAscending(element);
874 }
875 int ceiling(int element) {
876 return ascending ?
877 ceilingAscending(element) : floorAscending(element);
878 }
879 int higher(int element) {
880 return ascending ?
881 higherAscending(element) : lowerAscending(element);
882 }
883 int first() {
884 return ascending ? firstAscending() : lastAscending();
885 }
886 int last() {
887 return ascending ? lastAscending() : firstAscending();
888 }
889 int lowerAscending(int element) {
890 return floorAscending(element - 1);
891 }
892 int floorAscending(int element) {
893 if (element < min)
894 return -1;
895 else if (element > max)
896 element = max;
897
898 // BitSet should support this! Test would run much faster
899 while (element >= min) {
900 if (bs.get(element))
901 return element;
902 element--;
903 }
904 return -1;
905 }
906 int ceilingAscending(int element) {
907 if (element < min)
908 element = min;
909 else if (element > max)
910 return -1;
911 int result = bs.nextSetBit(element);
912 return result > max ? -1 : result;
913 }
914 int higherAscending(int element) {
915 return ceilingAscending(element + 1);
916 }
917 private int firstAscending() {
918 int result = ceilingAscending(min);
919 return result > max ? -1 : result;
920 }
921 private int lastAscending() {
922 int result = floorAscending(max);
923 return result < min ? -1 : result;
924 }
925 }
926 ReferenceSet rs = new ReferenceSet();
927
928 // Test contents using containsElement
929 int size = 0;
930 for (int i = min; i <= max; i++) {
931 boolean bsContainsI = bs.get(i);
932 assertEquals(bsContainsI, set.contains(i));
933 if (bsContainsI)
934 size++;
935 }
936 assertEquals(size, set.size());
937
938 // Test contents using contains elementSet iterator
939 int size2 = 0;
940 int previousElement = -1;
941 for (int element : set) {
942 assertTrue(bs.get(element));
943 size2++;
944 assertTrue(previousElement < 0 || (ascending ?
945 element - previousElement > 0 : element - previousElement < 0));
946 previousElement = element;
947 }
948 assertEquals(size2, size);
949
950 // Test navigation ops
951 for (int element = min - 1; element <= max + 1; element++) {
952 assertEq(set.lower(element), rs.lower(element));
953 assertEq(set.floor(element), rs.floor(element));
954 assertEq(set.higher(element), rs.higher(element));
955 assertEq(set.ceiling(element), rs.ceiling(element));
956 }
957
958 // Test extrema
959 if (set.size() != 0) {
960 assertEq(set.first(), rs.first());
961 assertEq(set.last(), rs.last());
962 } else {
963 assertEq(rs.first(), -1);
964 assertEq(rs.last(), -1);
965 try {
966 set.first();
967 shouldThrow();
968 } catch (NoSuchElementException success) {}
969 try {
970 set.last();
971 shouldThrow();
972 } catch (NoSuchElementException success) {}
973 }
974 }
975
976 static void assertEq(Integer i, int j) {
977 if (i == null)
978 assertEquals(j, -1);
979 else
980 assertEquals((int) i, j);
981 }
982
983 static boolean eq(Integer i, int j) {
984 return i == null ? j == -1 : i == j;
985 }
986
987}