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(...);
     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             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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    496     public void testEmptyIterator() {
    497         assertIteratorExhausted(new TreeSet().iterator());
    498     }
    499 
    500     /**
    501      * iterator.remove removes current element
    502      */
    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      */
    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      */
    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      */
    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 
    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      */
    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      */
    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      */
    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      */
    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 
    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 
    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 
    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 
    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 
    773     void put(NavigableSet<Integer> set, int element) {
    774         if (set.add(element))
    775             bs.set(element);
    776     }
    777 
    778     void remove(NavigableSet<Integer> set, int element) {
    779         if (set.remove(element))
    780             bs.clear(element);
    781     }
    782 
    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      */
    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 
    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 
    983     static boolean eq(Integer i, int j) {
    984         return i == null ? j == -1 : i == j;
    985     }
    986 
    987 }
    988