Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2012 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 
     15 package com.google.common.collect;
     16 
     17 import static com.google.common.truth.Truth.assertThat;
     18 
     19 import com.google.common.annotations.GwtIncompatible;
     20 import com.google.common.collect.testing.NavigableSetTestSuiteBuilder;
     21 import com.google.common.collect.testing.SampleElements;
     22 import com.google.common.collect.testing.TestSetGenerator;
     23 import com.google.common.collect.testing.features.CollectionFeature;
     24 import com.google.common.collect.testing.features.CollectionSize;
     25 import com.google.common.testing.SerializableTester;
     26 
     27 import junit.framework.Test;
     28 import junit.framework.TestSuite;
     29 
     30 import java.math.BigInteger;
     31 import java.util.List;
     32 import java.util.Set;
     33 
     34 /**
     35  * Tests for {@link ImmutableRangeSet}.
     36  *
     37  * @author Louis Wasserman
     38  */
     39 @GwtIncompatible("ImmutableRangeSet")
     40 public class ImmutableRangeSetTest extends AbstractRangeSetTest {
     41   @SuppressWarnings("unchecked") // varargs
     42   private static final ImmutableSet<Range<Integer>> RANGES = ImmutableSet.of(
     43       Range.<Integer>all(),
     44       Range.closedOpen(3, 5),
     45       Range.singleton(1),
     46       Range.lessThan(2),
     47       Range.greaterThan(10),
     48       Range.atMost(4),
     49       Range.atLeast(3),
     50       Range.closed(4, 6),
     51       Range.closedOpen(1, 3),
     52       Range.openClosed(5, 7),
     53       Range.open(3, 4));
     54 
     55   static final class ImmutableRangeSetIntegerAsSetGenerator implements TestSetGenerator<Integer> {
     56     @Override
     57     public SampleElements<Integer> samples() {
     58       return new SampleElements<Integer>(1, 4, 3, 2, 5);
     59     }
     60 
     61     @Override
     62     public Integer[] createArray(int length) {
     63       return new Integer[length];
     64     }
     65 
     66     @Override
     67     public Iterable<Integer> order(List<Integer> insertionOrder) {
     68       return Ordering.natural().sortedCopy(insertionOrder);
     69     }
     70 
     71     @Override
     72     public Set<Integer> create(Object... elements) {
     73       ImmutableRangeSet.Builder<Integer> builder = ImmutableRangeSet.builder();
     74       for (Object o : elements) {
     75         Integer i = (Integer) o;
     76         builder.add(Range.singleton(i));
     77       }
     78       return builder.build().asSet(DiscreteDomain.integers());
     79     }
     80   }
     81 
     82   static final class ImmutableRangeSetBigIntegerAsSetGenerator
     83       implements TestSetGenerator<BigInteger> {
     84     @Override
     85     public SampleElements<BigInteger> samples() {
     86       return new SampleElements<BigInteger>(
     87           BigInteger.valueOf(1),
     88           BigInteger.valueOf(4),
     89           BigInteger.valueOf(3),
     90           BigInteger.valueOf(2),
     91           BigInteger.valueOf(5));
     92     }
     93 
     94     @Override
     95     public BigInteger[] createArray(int length) {
     96       return new BigInteger[length];
     97     }
     98 
     99     @Override
    100     public Iterable<BigInteger> order(List<BigInteger> insertionOrder) {
    101       return Ordering.natural().sortedCopy(insertionOrder);
    102     }
    103 
    104     @Override
    105     public Set<BigInteger> create(Object... elements) {
    106       ImmutableRangeSet.Builder<BigInteger> builder = ImmutableRangeSet.builder();
    107       for (Object o : elements) {
    108         BigInteger i = (BigInteger) o;
    109         builder.add(Range.closedOpen(i, i.add(BigInteger.ONE)));
    110       }
    111       return builder.build().asSet(DiscreteDomain.bigIntegers());
    112     }
    113   }
    114 
    115   public static Test suite() {
    116     TestSuite suite = new TestSuite();
    117     suite.addTestSuite(ImmutableRangeSetTest.class);
    118     suite.addTest(NavigableSetTestSuiteBuilder.using(new ImmutableRangeSetIntegerAsSetGenerator())
    119         .named("ImmutableRangeSet.asSet[DiscreteDomain.integers[]]")
    120         .withFeatures(
    121             CollectionSize.ANY,
    122             CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
    123             CollectionFeature.ALLOWS_NULL_QUERIES,
    124             CollectionFeature.KNOWN_ORDER,
    125             CollectionFeature.NON_STANDARD_TOSTRING,
    126             CollectionFeature.SERIALIZABLE)
    127         .createTestSuite());
    128 
    129     suite.addTest(NavigableSetTestSuiteBuilder.using(
    130           new ImmutableRangeSetBigIntegerAsSetGenerator())
    131         .named("ImmutableRangeSet.asSet[DiscreteDomain.bigIntegers[]]")
    132         .withFeatures(
    133             CollectionSize.ANY,
    134             CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
    135             CollectionFeature.ALLOWS_NULL_QUERIES,
    136             CollectionFeature.KNOWN_ORDER,
    137             CollectionFeature.NON_STANDARD_TOSTRING,
    138             CollectionFeature.SERIALIZABLE)
    139         .createTestSuite());
    140     return suite;
    141   }
    142 
    143   public void testEmpty() {
    144     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of();
    145 
    146     assertThat(rangeSet.asRanges()).isEmpty();
    147     assertEquals(ImmutableRangeSet.<Integer>all(), rangeSet.complement());
    148     assertFalse(rangeSet.contains(0));
    149     assertFalse(rangeSet.encloses(Range.singleton(0)));
    150     assertTrue(rangeSet.enclosesAll(rangeSet));
    151     assertTrue(rangeSet.isEmpty());
    152   }
    153 
    154   public void testAll() {
    155     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.all();
    156 
    157     assertThat(rangeSet.asRanges()).has().item(Range.<Integer>all());
    158     assertTrue(rangeSet.contains(0));
    159     assertTrue(rangeSet.encloses(Range.<Integer>all()));
    160     assertTrue(rangeSet.enclosesAll(rangeSet));
    161     assertEquals(ImmutableRangeSet.<Integer>of(), rangeSet.complement());
    162   }
    163 
    164   public void testSingleBoundedRange() {
    165     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.closedOpen(1, 5));
    166 
    167     assertThat(rangeSet.asRanges()).has().item(Range.closedOpen(1, 5));
    168 
    169     assertTrue(rangeSet.encloses(Range.closed(3, 4)));
    170     assertTrue(rangeSet.encloses(Range.closedOpen(1, 4)));
    171     assertTrue(rangeSet.encloses(Range.closedOpen(1, 5)));
    172     assertFalse(rangeSet.encloses(Range.greaterThan(2)));
    173 
    174     assertTrue(rangeSet.contains(3));
    175     assertFalse(rangeSet.contains(5));
    176     assertFalse(rangeSet.contains(0));
    177 
    178     RangeSet<Integer> expectedComplement = TreeRangeSet.create();
    179     expectedComplement.add(Range.lessThan(1));
    180     expectedComplement.add(Range.atLeast(5));
    181 
    182     assertEquals(expectedComplement, rangeSet.complement());
    183   }
    184 
    185   public void testSingleBoundedBelowRange() {
    186     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.greaterThan(2));
    187 
    188     assertThat(rangeSet.asRanges()).has().item(Range.greaterThan(2));
    189 
    190     assertTrue(rangeSet.encloses(Range.closed(3, 4)));
    191     assertTrue(rangeSet.encloses(Range.greaterThan(3)));
    192     assertFalse(rangeSet.encloses(Range.closedOpen(1, 5)));
    193 
    194     assertTrue(rangeSet.contains(3));
    195     assertTrue(rangeSet.contains(5));
    196     assertFalse(rangeSet.contains(0));
    197     assertFalse(rangeSet.contains(2));
    198 
    199     assertEquals(ImmutableRangeSet.of(Range.atMost(2)), rangeSet.complement());
    200   }
    201 
    202   public void testSingleBoundedAboveRange() {
    203     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.of(Range.atMost(3));
    204 
    205     assertThat(rangeSet.asRanges()).has().item(Range.atMost(3));
    206 
    207     assertTrue(rangeSet.encloses(Range.closed(2, 3)));
    208     assertTrue(rangeSet.encloses(Range.lessThan(1)));
    209     assertFalse(rangeSet.encloses(Range.closedOpen(1, 5)));
    210 
    211     assertTrue(rangeSet.contains(3));
    212     assertTrue(rangeSet.contains(0));
    213     assertFalse(rangeSet.contains(4));
    214     assertFalse(rangeSet.contains(5));
    215 
    216     assertEquals(ImmutableRangeSet.of(Range.greaterThan(3)), rangeSet.complement());
    217   }
    218 
    219   public void testMultipleBoundedRanges() {
    220     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    221         .add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
    222 
    223     assertThat(rangeSet.asRanges())
    224         .has().exactly(Range.closedOpen(1, 3), Range.closed(5, 8)).inOrder();
    225 
    226     assertTrue(rangeSet.encloses(Range.closed(1, 2)));
    227     assertTrue(rangeSet.encloses(Range.open(5, 8)));
    228     assertFalse(rangeSet.encloses(Range.closed(1, 8)));
    229     assertFalse(rangeSet.encloses(Range.greaterThan(5)));
    230 
    231     RangeSet<Integer> expectedComplement = ImmutableRangeSet.<Integer>builder()
    232         .add(Range.lessThan(1))
    233         .add(Range.closedOpen(3, 5))
    234         .add(Range.greaterThan(8))
    235         .build();
    236 
    237     assertEquals(expectedComplement, rangeSet.complement());
    238   }
    239 
    240   public void testMultipleBoundedBelowRanges() {
    241     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    242         .add(Range.greaterThan(6)).add(Range.closedOpen(1, 3)).build();
    243 
    244     assertThat(rangeSet.asRanges())
    245         .has().exactly(Range.closedOpen(1, 3), Range.greaterThan(6)).inOrder();
    246 
    247     assertTrue(rangeSet.encloses(Range.closed(1, 2)));
    248     assertTrue(rangeSet.encloses(Range.open(6, 8)));
    249     assertFalse(rangeSet.encloses(Range.closed(1, 8)));
    250     assertFalse(rangeSet.encloses(Range.greaterThan(5)));
    251 
    252     RangeSet<Integer> expectedComplement = ImmutableRangeSet.<Integer>builder()
    253         .add(Range.lessThan(1))
    254         .add(Range.closed(3, 6))
    255         .build();
    256 
    257     assertEquals(expectedComplement, rangeSet.complement());
    258   }
    259 
    260   public void testMultipleBoundedAboveRanges() {
    261     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    262         .add(Range.atMost(0)).add(Range.closedOpen(2, 5)).build();
    263 
    264     assertThat(rangeSet.asRanges())
    265         .has().exactly(Range.atMost(0), Range.closedOpen(2, 5)).inOrder();
    266 
    267     assertTrue(rangeSet.encloses(Range.closed(2, 4)));
    268     assertTrue(rangeSet.encloses(Range.open(-5, -2)));
    269     assertFalse(rangeSet.encloses(Range.closed(1, 8)));
    270     assertFalse(rangeSet.encloses(Range.greaterThan(5)));
    271 
    272     RangeSet<Integer> expectedComplement = ImmutableRangeSet.<Integer>builder()
    273         .add(Range.open(0, 2))
    274         .add(Range.atLeast(5))
    275         .build();
    276 
    277     assertEquals(expectedComplement, rangeSet.complement());
    278   }
    279 
    280   public void testAddUnsupported() {
    281     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    282         .add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
    283 
    284     try {
    285       rangeSet.add(Range.open(3, 4));
    286       fail();
    287     } catch (UnsupportedOperationException expected) {
    288       // success
    289     }
    290   }
    291 
    292   public void testAddAllUnsupported() {
    293     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    294         .add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
    295 
    296     try {
    297       rangeSet.addAll(ImmutableRangeSet.<Integer>of());
    298       fail();
    299     } catch (UnsupportedOperationException expected) {
    300       // success
    301     }
    302   }
    303 
    304   public void testRemoveUnsupported() {
    305     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    306         .add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
    307 
    308     try {
    309       rangeSet.remove(Range.closed(6, 7));
    310       fail();
    311     } catch (UnsupportedOperationException expected) {
    312       // success
    313     }
    314   }
    315 
    316   public void testRemoveAllUnsupported() {
    317     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    318         .add(Range.closed(5, 8)).add(Range.closedOpen(1, 3)).build();
    319 
    320     try {
    321       rangeSet.removeAll(ImmutableRangeSet.<Integer>of());
    322       fail();
    323     } catch (UnsupportedOperationException expected) {
    324       // success
    325     }
    326 
    327     try {
    328       rangeSet.removeAll(ImmutableRangeSet.of(Range.closed(6, 8)));
    329       fail();
    330     } catch (UnsupportedOperationException expected) {
    331       // success
    332     }
    333   }
    334 
    335   public void testExhaustive() {
    336     @SuppressWarnings("unchecked")
    337     ImmutableSet<Range<Integer>> ranges = ImmutableSet.of(
    338         Range.<Integer>all(),
    339         Range.<Integer>closedOpen(3, 5),
    340         Range.singleton(1),
    341         Range.lessThan(2),
    342         Range.greaterThan(10),
    343         Range.atMost(4),
    344         Range.atLeast(3),
    345         Range.closed(4, 6),
    346         Range.closedOpen(1, 3),
    347         Range.openClosed(5, 7),
    348         Range.open(3, 4));
    349     for (Set<Range<Integer>> subset : Sets.powerSet(ranges)) {
    350       RangeSet<Integer> mutable = TreeRangeSet.create();
    351       ImmutableRangeSet.Builder<Integer> builder = ImmutableRangeSet.builder();
    352 
    353       int expectedRanges = 0;
    354       for (Range<Integer> range : subset) {
    355         boolean overlaps = false;
    356         for (Range<Integer> other : mutable.asRanges()) {
    357           if (other.isConnected(range) && !other.intersection(range).isEmpty()) {
    358             overlaps = true;
    359           }
    360         }
    361 
    362         try {
    363           builder.add(range);
    364           assertFalse(overlaps);
    365           mutable.add(range);
    366         } catch (IllegalArgumentException e) {
    367           assertTrue(overlaps);
    368         }
    369       }
    370 
    371       ImmutableRangeSet<Integer> built = builder.build();
    372       assertEquals(mutable, built);
    373       assertEquals(ImmutableRangeSet.copyOf(mutable), built);
    374       assertEquals(mutable.complement(), built.complement());
    375 
    376       for (int i = 0; i <= 11; i++) {
    377         assertEquals(mutable.contains(i), built.contains(i));
    378       }
    379 
    380       SerializableTester.reserializeAndAssert(built);
    381     }
    382   }
    383 
    384   public void testAsSet() {
    385     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    386         .add(Range.closed(2, 4))
    387         .add(Range.open(6, 7))
    388         .add(Range.closedOpen(8, 10))
    389         .add(Range.openClosed(15, 17))
    390         .build();
    391     ImmutableSortedSet<Integer> expectedSet = ImmutableSortedSet.of(2, 3, 4, 8, 9, 16, 17);
    392     ImmutableSortedSet<Integer> asSet = rangeSet.asSet(DiscreteDomain.integers());
    393     assertEquals(expectedSet, asSet);
    394     assertThat(asSet).has().exactlyAs(expectedSet).inOrder();
    395     assertTrue(asSet.containsAll(expectedSet));
    396     SerializableTester.reserializeAndAssert(asSet);
    397   }
    398 
    399   public void testAsSetHeadSet() {
    400     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    401         .add(Range.closed(2, 4))
    402         .add(Range.open(6, 7))
    403         .add(Range.closedOpen(8, 10))
    404         .add(Range.openClosed(15, 17))
    405         .build();
    406 
    407     ImmutableSortedSet<Integer> expectedSet = ImmutableSortedSet.of(2, 3, 4, 8, 9, 16, 17);
    408     ImmutableSortedSet<Integer> asSet = rangeSet.asSet(DiscreteDomain.integers());
    409 
    410     for (int i = 0; i <= 20; i++) {
    411       assertEquals(asSet.headSet(i, false), expectedSet.headSet(i, false));
    412       assertEquals(asSet.headSet(i, true), expectedSet.headSet(i, true));
    413     }
    414   }
    415 
    416   public void testAsSetTailSet() {
    417     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    418         .add(Range.closed(2, 4))
    419         .add(Range.open(6, 7))
    420         .add(Range.closedOpen(8, 10))
    421         .add(Range.openClosed(15, 17))
    422         .build();
    423 
    424     ImmutableSortedSet<Integer> expectedSet = ImmutableSortedSet.of(2, 3, 4, 8, 9, 16, 17);
    425     ImmutableSortedSet<Integer> asSet = rangeSet.asSet(DiscreteDomain.integers());
    426 
    427     for (int i = 0; i <= 20; i++) {
    428       assertEquals(asSet.tailSet(i, false), expectedSet.tailSet(i, false));
    429       assertEquals(asSet.tailSet(i, true), expectedSet.tailSet(i, true));
    430     }
    431   }
    432 
    433   public void testAsSetSubSet() {
    434     ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    435         .add(Range.closed(2, 4))
    436         .add(Range.open(6, 7))
    437         .add(Range.closedOpen(8, 10))
    438         .add(Range.openClosed(15, 17))
    439         .build();
    440 
    441     ImmutableSortedSet<Integer> expectedSet = ImmutableSortedSet.of(2, 3, 4, 8, 9, 16, 17);
    442     ImmutableSortedSet<Integer> asSet = rangeSet.asSet(DiscreteDomain.integers());
    443 
    444     for (int i = 0; i <= 20; i++) {
    445       for (int j = i + 1; j <= 20; j++) {
    446         assertEquals(expectedSet.subSet(i, false, j, false),
    447             asSet.subSet(i, false, j, false));
    448         assertEquals(expectedSet.subSet(i, true, j, false),
    449             asSet.subSet(i, true, j, false));
    450         assertEquals(expectedSet.subSet(i, false, j, true),
    451             asSet.subSet(i, false, j, true));
    452         assertEquals(expectedSet.subSet(i, true, j, true),
    453             asSet.subSet(i, true, j, true));
    454       }
    455     }
    456   }
    457 
    458   public void testSubRangeSet() {
    459     ImmutableList.Builder<Range<Integer>> rangesBuilder = ImmutableList.builder();
    460     rangesBuilder.add(Range.<Integer>all());
    461     for (int i = -2; i <= 2; i++) {
    462       for (BoundType boundType : BoundType.values()) {
    463         rangesBuilder.add(Range.upTo(i, boundType));
    464         rangesBuilder.add(Range.downTo(i, boundType));
    465       }
    466       for (int j = i + 1; j <= 2; j++) {
    467         for (BoundType lbType : BoundType.values()) {
    468           for (BoundType ubType : BoundType.values()) {
    469             rangesBuilder.add(Range.range(i, lbType, j, ubType));
    470           }
    471         }
    472       }
    473     }
    474     ImmutableList<Range<Integer>> ranges = rangesBuilder.build();
    475     for (int i = -2; i <= 2; i++) {
    476       rangesBuilder.add(Range.closedOpen(i, i));
    477       rangesBuilder.add(Range.openClosed(i, i));
    478     }
    479     ImmutableList<Range<Integer>> subRanges = rangesBuilder.build();
    480     for (Range<Integer> range1 : ranges) {
    481       for (Range<Integer> range2 : ranges) {
    482         if (!range1.isConnected(range2) || range1.intersection(range2).isEmpty()) {
    483           ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
    484               .add(range1)
    485               .add(range2)
    486               .build();
    487           for (Range<Integer> subRange : subRanges) {
    488             RangeSet<Integer> expected = TreeRangeSet.create();
    489             for (Range<Integer> range : rangeSet.asRanges()) {
    490               if (range.isConnected(subRange)) {
    491                 expected.add(range.intersection(subRange));
    492               }
    493             }
    494             ImmutableRangeSet<Integer> subRangeSet = rangeSet.subRangeSet(subRange);
    495             assertEquals(expected, subRangeSet);
    496             assertEquals(expected.asRanges(), subRangeSet.asRanges());
    497             if (!expected.isEmpty()) {
    498               assertEquals(expected.span(), subRangeSet.span());
    499             }
    500             for (int i = -3; i <= 3; i++) {
    501               assertEquals(expected.contains(i), subRangeSet.contains(i));
    502             }
    503           }
    504         }
    505       }
    506     }
    507   }
    508 }
    509