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