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 package jsr166; 8 9 import java.util.Arrays; 10 import java.util.BitSet; 11 import java.util.Collection; 12 import java.util.Comparator; 13 import java.util.Iterator; 14 import java.util.NavigableSet; 15 import java.util.NoSuchElementException; 16 import java.util.Random; 17 import java.util.Set; 18 import java.util.SortedSet; 19 import java.util.TreeSet; 20 21 import junit.framework.Test; 22 import junit.framework.TestSuite; 23 24 public class TreeSetTest extends JSR166TestCase { 25 // 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 // } 34 35 static class MyReverseComparator implements Comparator { compare(Object x, Object y)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 */ populatedSet(int n)50 private TreeSet<Integer> populatedSet(int n) { 51 TreeSet<Integer> q = new TreeSet<Integer>(); 52 assertTrue(q.isEmpty()); 53 for (int i = n-1; i >= 0; i -= 2) 54 assertTrue(q.add(new Integer(i))); 55 for (int i = (n & 1); i < n; i += 2) 56 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 */ set5()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 */ testConstructor1()80 public void testConstructor1() { 81 assertEquals(0, new TreeSet().size()); 82 } 83 84 /** 85 * Initializing from null Collection throws NPE 86 */ testConstructor3()87 public void testConstructor3() { 88 try { 89 new TreeSet((Collection)null); 90 shouldThrow(); 91 } catch (NullPointerException success) {} 92 } 93 94 /** 95 * Initializing from Collection of null elements throws NPE 96 */ testConstructor4()97 public void testConstructor4() { 98 try { 99 Integer[] ints = new Integer[SIZE]; 100 new TreeSet(Arrays.asList(ints)); 101 shouldThrow(); 102 } catch (NullPointerException success) {} 103 } 104 105 /** 106 * Initializing from Collection with some null elements throws NPE 107 */ testConstructor5()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); 113 new TreeSet(Arrays.asList(ints)); 114 shouldThrow(); 115 } catch (NullPointerException success) {} 116 } 117 118 /** 119 * Set contains all elements of collection used to initialize 120 */ testConstructor6()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 */ testConstructor7()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 */ testEmpty()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 */ testSize()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 */ testAddNull()177 public void testAddNull() { 178 TreeSet q = populatedSet(SIZE); 179 try { 180 q.add(null); 181 shouldThrow(); 182 } catch (NullPointerException success) {} 183 } 184 185 /** 186 * Add of comparable element succeeds 187 */ testAdd()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 */ testAddDup()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 */ testAddNonComparable()206 public void testAddNonComparable() { 207 TreeSet q = new TreeSet(); 208 try { 209 q.add(new Object()); 210 q.add(new Object()); 211 shouldThrow(); 212 } catch (ClassCastException success) {} 213 } 214 215 /** 216 * addAll(null) throws NPE 217 */ testAddAll1()218 public void testAddAll1() { 219 TreeSet q = new TreeSet(); 220 try { 221 q.addAll(null); 222 shouldThrow(); 223 } catch (NullPointerException success) {} 224 } 225 226 /** 227 * addAll of a collection with null elements throws NPE 228 */ testAddAll2()229 public void testAddAll2() { 230 TreeSet q = new TreeSet(); 231 Integer[] ints = new Integer[SIZE]; 232 try { 233 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 */ testAddAll3()242 public void testAddAll3() { 243 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); 247 try { 248 q.addAll(Arrays.asList(ints)); 249 shouldThrow(); 250 } catch (NullPointerException success) {} 251 } 252 253 /** 254 * Set contains all elements of successful addAll 255 */ testAddAll5()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 */ testPollFirst()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 */ testPollLast()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 */ testRemoveElement()293 public void testRemoveElement() { 294 TreeSet q = populatedSet(SIZE); 295 for (int i = 1; i < SIZE; i += 2) { 296 assertTrue(q.contains(i)); 297 assertTrue(q.remove(i)); 298 assertFalse(q.contains(i)); 299 assertTrue(q.contains(i-1)); 300 } 301 for (int i = 0; i < SIZE; i += 2) { 302 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 */ testContains()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 */ testClear()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 */ testContainsAll()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 */ testRetainAll()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 */ testRemoveAll()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) { 380 Integer x = (Integer)(p.pollFirst()); 381 assertFalse(q.contains(x)); 382 } 383 } 384 } 385 386 /** 387 * lower returns preceding element 388 */ testLower()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 */ testHigher()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 */ testFloor()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 */ testCeiling()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 */ testToArray()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 */ testToArray2()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 */ testIterator()483 public void testIterator() { 484 TreeSet q = populatedSet(SIZE); 485 Iterator it = q.iterator(); 486 int i; 487 for (i = 0; it.hasNext(); i++) 488 assertTrue(q.contains(it.next())); 489 assertEquals(i, SIZE); 490 assertIteratorExhausted(it); 491 } 492 493 /** 494 * iterator of empty set has no elements 495 */ testEmptyIterator()496 public void testEmptyIterator() { 497 assertIteratorExhausted(new TreeSet().iterator()); 498 } 499 500 /** 501 * iterator.remove removes current element 502 */ testIteratorRemove()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 */ testToString()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 */ testSerialization()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 */ testSubSetContents()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 testSubSetContents2()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 */ testHeadSetContents()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 */ testTailSetContents()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 */ testRecursiveSubSets()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 */ testAddAll_idempotent()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 newSet(Class cl)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 populate(NavigableSet<Integer> set, int limit)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 mutateSet(NavigableSet<Integer> set, int min, int max)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); 737 assertTrue(element >= min && element <= max); 738 put(set, element); 739 } 740 } 741 mutateSubSet(NavigableSet<Integer> set, int min, int max)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); 762 if (element >= min && element <= max) { 763 put(set, element); 764 } else { 765 try { 766 set.add(element); 767 shouldThrow(); 768 } catch (IllegalArgumentException success) {} 769 } 770 } 771 } 772 put(NavigableSet<Integer> set, int element)773 void put(NavigableSet<Integer> set, int element) { 774 if (set.add(element)) 775 bs.set(element); 776 } 777 remove(NavigableSet<Integer> set, int element)778 void remove(NavigableSet<Integer> set, int element) { 779 if (set.remove(element)) 780 bs.clear(element); 781 } 782 bashSubSet(NavigableSet<Integer> set, int min, int max, boolean ascending)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 */ check(NavigableSet<Integer> set, final int min, final int max, final boolean ascending)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 assertEq(Integer i, int j)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 eq(Integer i, int j)983 static boolean eq(Integer i, int j) { 984 return i == null ? j == -1 : i == j; 985 } 986 987 } 988