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(TreeSetTest.class); 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 new TreeSet(Arrays.asList(new Integer[SIZE])); 100 shouldThrow(); 101 } catch (NullPointerException success) {} 102 } 103 104 /** 105 * Initializing from Collection with some null elements throws NPE 106 */ testConstructor5()107 public void testConstructor5() { 108 Integer[] ints = new Integer[SIZE]; 109 for (int i = 0; i < SIZE - 1; ++i) 110 ints[i] = new Integer(i); 111 try { 112 new TreeSet(Arrays.asList(ints)); 113 shouldThrow(); 114 } catch (NullPointerException success) {} 115 } 116 117 /** 118 * Set contains all elements of collection used to initialize 119 */ testConstructor6()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 */ testConstructor7()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)); 140 for (int i = SIZE - 1; i >= 0; --i) 141 assertEquals(ints[i], q.pollFirst()); 142 } 143 144 /** 145 * isEmpty is true before add, false after 146 */ testEmpty()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 */ testSize()161 public void testSize() { 162 TreeSet q = populatedSet(SIZE); 163 for (int i = 0; i < SIZE; ++i) { 164 assertEquals(SIZE - i, q.size()); 165 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 */ testAddNull()176 public void testAddNull() { 177 TreeSet q = populatedSet(SIZE); 178 try { 179 q.add(null); 180 shouldThrow(); 181 } catch (NullPointerException success) {} 182 } 183 184 /** 185 * Add of comparable element succeeds 186 */ testAdd()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 */ testAddDup()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 */ testAddNonComparable()205 public void testAddNonComparable() { 206 TreeSet q = new TreeSet(); 207 try { 208 q.add(new Object()); 209 q.add(new Object()); 210 shouldThrow(); 211 } catch (ClassCastException success) {} 212 } 213 214 /** 215 * addAll(null) throws NPE 216 */ testAddAll1()217 public void testAddAll1() { 218 TreeSet q = new TreeSet(); 219 try { 220 q.addAll(null); 221 shouldThrow(); 222 } catch (NullPointerException success) {} 223 } 224 225 /** 226 * addAll of a collection with null elements throws NPE 227 */ testAddAll2()228 public void testAddAll2() { 229 TreeSet q = new TreeSet(); 230 Integer[] ints = new Integer[SIZE]; 231 try { 232 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 */ testAddAll3()241 public void testAddAll3() { 242 TreeSet q = new TreeSet(); 243 Integer[] ints = new Integer[SIZE]; 244 for (int i = 0; i < SIZE - 1; ++i) 245 ints[i] = new Integer(i); 246 try { 247 q.addAll(Arrays.asList(ints)); 248 shouldThrow(); 249 } catch (NullPointerException success) {} 250 } 251 252 /** 253 * Set contains all elements of successful addAll 254 */ testAddAll5()255 public void testAddAll5() { 256 Integer[] empty = new Integer[0]; 257 Integer[] ints = new Integer[SIZE]; 258 for (int i = 0; i < SIZE; ++i) 259 ints[i] = new Integer(SIZE - 1 - i); 260 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 */ testPollFirst()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 */ testPollLast()281 public void testPollLast() { 282 TreeSet q = populatedSet(SIZE); 283 for (int i = SIZE - 1; i >= 0; --i) { 284 assertEquals(i, q.pollLast()); 285 } 286 assertNull(q.pollFirst()); 287 } 288 289 /** 290 * remove(x) removes x and returns true if present 291 */ testRemoveElement()292 public void testRemoveElement() { 293 TreeSet q = populatedSet(SIZE); 294 for (int i = 1; i < SIZE; i += 2) { 295 assertTrue(q.contains(i)); 296 assertTrue(q.remove(i)); 297 assertFalse(q.contains(i)); 298 assertTrue(q.contains(i - 1)); 299 } 300 for (int i = 0; i < SIZE; i += 2) { 301 assertTrue(q.contains(i)); 302 assertTrue(q.remove(i)); 303 assertFalse(q.contains(i)); 304 assertFalse(q.remove(i + 1)); 305 assertFalse(q.contains(i + 1)); 306 } 307 assertTrue(q.isEmpty()); 308 } 309 310 /** 311 * contains(x) reports true when elements added but not yet removed 312 */ testContains()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 */ testClear()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 */ testContainsAll()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 */ testRetainAll()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)); 364 assertEquals(SIZE - i, q.size()); 365 p.pollFirst(); 366 } 367 } 368 369 /** 370 * removeAll(c) removes only those elements of c and reports true if changed 371 */ testRemoveAll()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)); 377 assertEquals(SIZE - i, q.size()); 378 for (int j = 0; j < i; ++j) { 379 Integer x = (Integer)(p.pollFirst()); 380 assertFalse(q.contains(x)); 381 } 382 } 383 } 384 385 /** 386 * lower returns preceding element 387 */ testLower()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 */ testHigher()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 */ testFloor()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 */ testCeiling()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 */ testToArray()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 */ testToArray2()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 */ testIterator()482 public void testIterator() { 483 TreeSet q = populatedSet(SIZE); 484 Iterator it = q.iterator(); 485 int i; 486 for (i = 0; it.hasNext(); i++) 487 assertTrue(q.contains(it.next())); 488 assertEquals(i, SIZE); 489 assertIteratorExhausted(it); 490 } 491 492 /** 493 * iterator of empty set has no elements 494 */ testEmptyIterator()495 public void testEmptyIterator() { 496 assertIteratorExhausted(new TreeSet().iterator()); 497 } 498 499 /** 500 * iterator.remove removes current element 501 */ testIteratorRemove()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 */ testToString()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 */ testSerialization()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 */ testSubSetContents()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 testSubSetContents2()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 */ testHeadSetContents()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 */ testTailSetContents()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 */ testRecursiveSubSets()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 */ testAddAll_idempotent()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 newSet(Class cl)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 populate(NavigableSet<Integer> set, int limit)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 mutateSet(NavigableSet<Integer> set, int min, int max)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); 736 assertTrue(element >= min && element <= max); 737 put(set, element); 738 } 739 } 740 mutateSubSet(NavigableSet<Integer> set, int min, int max)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); 761 if (element >= min && element <= max) { 762 put(set, element); 763 } else { 764 try { 765 set.add(element); 766 shouldThrow(); 767 } catch (IllegalArgumentException success) {} 768 } 769 } 770 } 771 put(NavigableSet<Integer> set, int element)772 void put(NavigableSet<Integer> set, int element) { 773 if (set.add(element)) 774 bs.set(element); 775 } 776 remove(NavigableSet<Integer> set, int element)777 void remove(NavigableSet<Integer> set, int element) { 778 if (set.remove(element)) 779 bs.clear(element); 780 } 781 bashSubSet(NavigableSet<Integer> set, int min, int max, boolean ascending)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 */ check(NavigableSet<Integer> set, final int min, final int max, final boolean ascending)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); 911 return (result > max) ? -1 : result; 912 } 913 int higherAscending(int element) { 914 return ceilingAscending(element + 1); 915 } 916 private int firstAscending() { 917 int result = ceilingAscending(min); 918 return (result > max) ? -1 : result; 919 } 920 private int lastAscending() { 921 int result = floorAscending(max); 922 return (result < min) ? -1 : result; 923 } 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 assertEq(Integer i, int j)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 eq(Integer i, int j)982 static boolean eq(Integer i, int j) { 983 return (i == null) ? j == -1 : i == j; 984 } 985 986 } 987