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