Home | History | Annotate | Download | only in jsr166
      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 {
     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());
     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      */
     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 {
     89             new TreeSet((Collection)null);
     90             shouldThrow();
     91         } catch (NullPointerException success) {}
     92     }
     93 
     94     /**
     95      * Initializing from Collection of null elements throws NPE
     96      */
     97     public void testConstructor4() {
     98         try {
     99             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      */
    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      */
    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));
    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      */
    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) {
    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      */
    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      */
    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() {
    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      */
    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      */
    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      */
    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      */
    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      */
    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);
    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      */
    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      */
    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));
    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      */
    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      */
    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);
    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      */
    495     public void testEmptyIterator() {
    496         assertIteratorExhausted(new TreeSet().iterator());
    497     }
    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);
    736             assertTrue(element >= min && element <= max);
    737             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);
    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 
    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);
    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 
    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) {
    983         return (i == null) ? j == -1 : i == j;
    984     }
    985 
    986 }
    987