/*
 * Copyright (C) 2011 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.collect;

import static com.google.common.collect.BoundType.OPEN;
import static com.google.common.collect.Range.range;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.annotations.GwtIncompatible;
import com.google.common.testing.SerializableTester;
import java.util.Arrays;
import java.util.List;
import java.util.NavigableMap;

/**
 * Tests for {@link TreeRangeSet}.
 *
 * @author Louis Wasserman
 * @author Chris Povirk
 */
@GwtIncompatible // TreeRangeSet
public class TreeRangeSetTest extends AbstractRangeSetTest {
  // TODO(cpovirk): test all of these with the ranges added in the reverse order

  private static final ImmutableList<Range<Integer>> QUERY_RANGES;

  private static final int MIN_BOUND = -1;
  private static final int MAX_BOUND = 1;

  static {
    ImmutableList.Builder<Range<Integer>> queryBuilder = ImmutableList.builder();

    queryBuilder.add(Range.<Integer>all());

    for (int i = MIN_BOUND; i <= MAX_BOUND; i++) {
      for (BoundType boundType : BoundType.values()) {
        queryBuilder.add(Range.upTo(i, boundType));
        queryBuilder.add(Range.downTo(i, boundType));
      }
      queryBuilder.add(Range.singleton(i));
      queryBuilder.add(Range.openClosed(i, i));
      queryBuilder.add(Range.closedOpen(i, i));

      for (BoundType lowerBoundType : BoundType.values()) {
        for (int j = i + 1; j <= MAX_BOUND; j++) {
          for (BoundType upperBoundType : BoundType.values()) {
            queryBuilder.add(Range.range(i, lowerBoundType, j, upperBoundType));
          }
        }
      }
    }
    QUERY_RANGES = queryBuilder.build();
  }

  void testViewAgainstExpected(RangeSet<Integer> expected, RangeSet<Integer> view) {
    assertEquals(expected, view);
    assertEquals(expected.asRanges(), view.asRanges());
    assertEquals(expected.isEmpty(), view.isEmpty());

    if (!expected.isEmpty()) {
      assertEquals(expected.span(), view.span());
    }

    for (int i = MIN_BOUND - 1; i <= MAX_BOUND + 1; i++) {
      assertEquals(expected.contains(i), view.contains(i));
      assertEquals(expected.rangeContaining(i), view.rangeContaining(i));
    }
    testEnclosing(view);
    if (view instanceof TreeRangeSet) {
      testRangesByLowerBounds((TreeRangeSet<Integer>) view, expected.asRanges());
    }
  }

  private static final ImmutableList<Cut<Integer>> CUTS_TO_TEST;

  static {
    List<Cut<Integer>> cutsToTest = Lists.newArrayList();
    for (int i = MIN_BOUND - 1; i <= MAX_BOUND + 1; i++) {
      cutsToTest.add(Cut.belowValue(i));
      cutsToTest.add(Cut.aboveValue(i));
    }
    cutsToTest.add(Cut.<Integer>aboveAll());
    cutsToTest.add(Cut.<Integer>belowAll());
    CUTS_TO_TEST = ImmutableList.copyOf(cutsToTest);
  }

  private void testRangesByLowerBounds(
      TreeRangeSet<Integer> rangeSet, Iterable<Range<Integer>> expectedRanges) {
    NavigableMap<Cut<Integer>, Range<Integer>> expectedRangesByLowerBound = Maps.newTreeMap();
    for (Range<Integer> range : expectedRanges) {
      expectedRangesByLowerBound.put(range.lowerBound, range);
    }

    NavigableMap<Cut<Integer>, Range<Integer>> rangesByLowerBound = rangeSet.rangesByLowerBound;
    testNavigationAgainstExpected(expectedRangesByLowerBound, rangesByLowerBound, CUTS_TO_TEST);
  }

  <K, V> void testNavigationAgainstExpected(
      NavigableMap<K, V> expected, NavigableMap<K, V> navigableMap, Iterable<K> keysToTest) {
    for (K key : keysToTest) {
      assertEquals(expected.lowerEntry(key), navigableMap.lowerEntry(key));
      assertEquals(expected.floorEntry(key), navigableMap.floorEntry(key));
      assertEquals(expected.ceilingEntry(key), navigableMap.ceilingEntry(key));
      assertEquals(expected.higherEntry(key), navigableMap.higherEntry(key));
      for (boolean inclusive : new boolean[] {false, true}) {
        assertThat(navigableMap.headMap(key, inclusive).entrySet())
            .containsExactlyElementsIn(expected.headMap(key, inclusive).entrySet())
            .inOrder();
        assertThat(navigableMap.tailMap(key, inclusive).entrySet())
            .containsExactlyElementsIn(expected.tailMap(key, inclusive).entrySet())
            .inOrder();
        assertThat(navigableMap.headMap(key, inclusive).descendingMap().entrySet())
            .containsExactlyElementsIn(expected.headMap(key, inclusive).descendingMap().entrySet())
            .inOrder();
        assertThat(navigableMap.tailMap(key, inclusive).descendingMap().entrySet())
            .containsExactlyElementsIn(expected.tailMap(key, inclusive).descendingMap().entrySet())
            .inOrder();
      }
    }
  }

  public void testIntersects(RangeSet<Integer> rangeSet) {
    for (Range<Integer> query : QUERY_RANGES) {
      boolean expectIntersect = false;
      for (Range<Integer> expectedRange : rangeSet.asRanges()) {
        if (expectedRange.isConnected(query) && !expectedRange.intersection(query).isEmpty()) {
          expectIntersect = true;
          break;
        }
      }
      assertEquals(
          rangeSet + " was incorrect on intersects(" + query + ")",
          expectIntersect,
          rangeSet.intersects(query));
    }
  }

  public void testEnclosing(RangeSet<Integer> rangeSet) {
    assertTrue(rangeSet.enclosesAll(ImmutableList.<Range<Integer>>of()));
    for (Range<Integer> query : QUERY_RANGES) {
      boolean expectEnclose = false;
      for (Range<Integer> expectedRange : rangeSet.asRanges()) {
        if (expectedRange.encloses(query)) {
          expectEnclose = true;
          break;
        }
      }

      assertEquals(
          rangeSet + " was incorrect on encloses(" + query + ")",
          expectEnclose,
          rangeSet.encloses(query));
      assertEquals(
          rangeSet + " was incorrect on enclosesAll([" + query + "])",
          expectEnclose,
          rangeSet.enclosesAll(ImmutableList.of(query)));
    }
  }

  public void testAllSingleRangesComplementAgainstRemove() {
    for (Range<Integer> range : QUERY_RANGES) {
      TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
      rangeSet.add(range);

      TreeRangeSet<Integer> complement = TreeRangeSet.create();
      complement.add(Range.<Integer>all());
      complement.remove(range);

      assertEquals(complement, rangeSet.complement());
      assertThat(rangeSet.complement().asRanges())
          .containsExactlyElementsIn(complement.asRanges())
          .inOrder();
    }
  }

  public void testInvariantsEmpty() {
    testInvariants(TreeRangeSet.create());
  }

  public void testEmptyIntersecting() {
    testIntersects(TreeRangeSet.<Integer>create());
    testIntersects(TreeRangeSet.<Integer>create().complement());
  }

  public void testAllSingleRangesIntersecting() {
    for (Range<Integer> range : QUERY_RANGES) {
      TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
      rangeSet.add(range);
      testIntersects(rangeSet);
      testIntersects(rangeSet.complement());
    }
  }

  public void testAllTwoRangesIntersecting() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);
        testIntersects(rangeSet);
        testIntersects(rangeSet.complement());
      }
    }
  }

  public void testEmptyEnclosing() {
    testEnclosing(TreeRangeSet.<Integer>create());
    testEnclosing(TreeRangeSet.<Integer>create().complement());
  }

  public void testAllSingleRangesEnclosing() {
    for (Range<Integer> range : QUERY_RANGES) {
      TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
      rangeSet.add(range);
      testEnclosing(rangeSet);
      testEnclosing(rangeSet.complement());
    }
  }

  public void testAllTwoRangesEnclosing() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);
        testEnclosing(rangeSet);
        testEnclosing(rangeSet.complement());
      }
    }
  }

  public void testCreateCopy() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);

        assertEquals(rangeSet, TreeRangeSet.create(rangeSet));
      }
    }
  }

  private RangeSet<Integer> expectedSubRangeSet(
      RangeSet<Integer> rangeSet, Range<Integer> subRange) {
    RangeSet<Integer> expected = TreeRangeSet.create();
    for (Range<Integer> range : rangeSet.asRanges()) {
      if (range.isConnected(subRange)) {
        expected.add(range.intersection(subRange));
      }
    }
    return expected;
  }

  private RangeSet<Integer> expectedComplement(RangeSet<Integer> rangeSet) {
    RangeSet<Integer> expected = TreeRangeSet.create();
    expected.add(Range.<Integer>all());
    expected.removeAll(rangeSet);
    return expected;
  }

  public void testSubRangeSet() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);
        for (Range<Integer> subRange : QUERY_RANGES) {
          testViewAgainstExpected(
              expectedSubRangeSet(rangeSet, subRange), rangeSet.subRangeSet(subRange));
        }
      }
    }
  }

  public void testSubRangeSetAdd() {
    TreeRangeSet<Integer> set = TreeRangeSet.create();
    Range<Integer> range = Range.closedOpen(0, 5);
    set.subRangeSet(range).add(range);
  }

  public void testSubRangeSetReplaceAdd() {
    TreeRangeSet<Integer> set = TreeRangeSet.create();
    Range<Integer> range = Range.closedOpen(0, 5);
    set.add(range);
    set.subRangeSet(range).add(range);
  }

  public void testComplement() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);
        testViewAgainstExpected(expectedComplement(rangeSet), rangeSet.complement());
      }
    }
  }

  public void testSubRangeSetOfComplement() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);
        for (Range<Integer> subRange : QUERY_RANGES) {
          testViewAgainstExpected(
              expectedSubRangeSet(expectedComplement(rangeSet), subRange),
              rangeSet.complement().subRangeSet(subRange));
        }
      }
    }
  }

  public void testComplementOfSubRangeSet() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);
        for (Range<Integer> subRange : QUERY_RANGES) {
          testViewAgainstExpected(
              expectedComplement(expectedSubRangeSet(rangeSet, subRange)),
              rangeSet.subRangeSet(subRange).complement());
        }
      }
    }
  }

  public void testRangesByUpperBound() {
    for (Range<Integer> range1 : QUERY_RANGES) {
      for (Range<Integer> range2 : QUERY_RANGES) {
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(range1);
        rangeSet.add(range2);

        NavigableMap<Cut<Integer>, Range<Integer>> expectedRangesByUpperBound = Maps.newTreeMap();
        for (Range<Integer> range : rangeSet.asRanges()) {
          expectedRangesByUpperBound.put(range.upperBound, range);
        }
        testNavigationAgainstExpected(
            expectedRangesByUpperBound,
            new TreeRangeSet.RangesByUpperBound<Integer>(rangeSet.rangesByLowerBound),
            CUTS_TO_TEST);
      }
    }
  }

  public void testMergesConnectedWithOverlap() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 4));
    rangeSet.add(Range.open(2, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.atLeast(6))
        .inOrder();
  }

  public void testMergesConnectedDisjoint() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 4));
    rangeSet.add(Range.open(4, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.atLeast(6))
        .inOrder();
  }

  public void testIgnoresSmallerSharingNoBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 6));
    rangeSet.add(Range.open(2, 4));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testIgnoresSmallerSharingLowerBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 6));
    rangeSet.add(Range.closed(1, 4));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testIgnoresSmallerSharingUpperBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 6));
    rangeSet.add(Range.closed(3, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testIgnoresEqual() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 6));
    rangeSet.add(Range.closed(1, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testExtendSameLowerBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 4));
    rangeSet.add(Range.closed(1, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testExtendSameUpperBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.add(Range.closed(1, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testExtendBothDirections() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 4));
    rangeSet.add(Range.closed(1, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testAddEmpty() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closedOpen(3, 3));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).isEmpty();
    assertThat(rangeSet.complement().asRanges()).containsExactly(Range.<Integer>all());
  }

  public void testFillHoleExactly() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closedOpen(1, 3));
    rangeSet.add(Range.closedOpen(4, 6));
    rangeSet.add(Range.closedOpen(3, 4));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.atLeast(6))
        .inOrder();
  }

  public void testFillHoleWithOverlap() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closedOpen(1, 3));
    rangeSet.add(Range.closedOpen(4, 6));
    rangeSet.add(Range.closedOpen(2, 5));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closedOpen(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.atLeast(6))
        .inOrder();
  }

  public void testAddManyPairs() {
    for (int aLow = 0; aLow < 6; aLow++) {
      for (int aHigh = 0; aHigh < 6; aHigh++) {
        for (BoundType aLowType : BoundType.values()) {
          for (BoundType aHighType : BoundType.values()) {
            if ((aLow == aHigh && aLowType == OPEN && aHighType == OPEN) || aLow > aHigh) {
              continue;
            }
            for (int bLow = 0; bLow < 6; bLow++) {
              for (int bHigh = 0; bHigh < 6; bHigh++) {
                for (BoundType bLowType : BoundType.values()) {
                  for (BoundType bHighType : BoundType.values()) {
                    if ((bLow == bHigh && bLowType == OPEN && bHighType == OPEN) || bLow > bHigh) {
                      continue;
                    }
                    doPairTest(
                        range(aLow, aLowType, aHigh, aHighType),
                        range(bLow, bLowType, bHigh, bHighType));
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  private static void doPairTest(Range<Integer> a, Range<Integer> b) {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(a);
    rangeSet.add(b);
    if (a.isEmpty() && b.isEmpty()) {
      assertThat(rangeSet.asRanges()).isEmpty();
    } else if (a.isEmpty()) {
      assertThat(rangeSet.asRanges()).contains(b);
    } else if (b.isEmpty()) {
      assertThat(rangeSet.asRanges()).contains(a);
    } else if (a.isConnected(b)) {
      assertThat(rangeSet.asRanges()).containsExactly(a.span(b));
    } else {
      if (a.lowerEndpoint() < b.lowerEndpoint()) {
        assertThat(rangeSet.asRanges()).containsExactly(a, b).inOrder();
      } else {
        assertThat(rangeSet.asRanges()).containsExactly(b, a).inOrder();
      }
    }
  }

  public void testRemoveEmpty() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 6));
    rangeSet.remove(Range.closedOpen(3, 3));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.closed(1, 6));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(1), Range.greaterThan(6))
        .inOrder();
  }

  public void testRemovePartSharingLowerBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 5));
    rangeSet.remove(Range.closedOpen(3, 5));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.singleton(5));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(5), Range.greaterThan(5))
        .inOrder();
  }

  public void testRemovePartSharingUpperBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 5));
    rangeSet.remove(Range.openClosed(3, 5));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).contains(Range.singleton(3));
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.lessThan(3), Range.greaterThan(3))
        .inOrder();
  }

  public void testRemoveMiddle() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.atMost(6));
    rangeSet.remove(Range.closedOpen(3, 4));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges())
        .containsExactly(Range.lessThan(3), Range.closed(4, 6))
        .inOrder();
    assertThat(rangeSet.complement().asRanges())
        .containsExactly(Range.closedOpen(3, 4), Range.greaterThan(6))
        .inOrder();
  }

  public void testRemoveNoOverlap() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closedOpen(1, 3));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).containsExactly(Range.closed(3, 6));
  }

  public void testRemovePartFromBelowLowerBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closed(1, 3));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).containsExactly(Range.openClosed(3, 6));
  }

  public void testRemovePartFromAboveUpperBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closed(6, 9));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).containsExactly(Range.closedOpen(3, 6));
  }

  public void testRemoveExact() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closed(3, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).isEmpty();
  }

  public void testRemoveAllFromBelowLowerBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closed(2, 6));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).isEmpty();
  }

  public void testRemoveAllFromAboveUpperBound() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closed(3, 7));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).isEmpty();
  }

  public void testRemoveAllExtendingBothDirections() {
    TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 6));
    rangeSet.remove(Range.closed(2, 7));
    testInvariants(rangeSet);
    assertThat(rangeSet.asRanges()).isEmpty();
  }

  public void testRangeContaining1() {
    RangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 10));
    assertEquals(Range.closed(3, 10), rangeSet.rangeContaining(5));
    assertTrue(rangeSet.contains(5));
    assertNull(rangeSet.rangeContaining(1));
    assertFalse(rangeSet.contains(1));
  }

  public void testRangeContaining2() {
    RangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 10));
    rangeSet.remove(Range.open(5, 7));
    assertEquals(Range.closed(3, 5), rangeSet.rangeContaining(5));
    assertTrue(rangeSet.contains(5));
    assertEquals(Range.closed(7, 10), rangeSet.rangeContaining(8));
    assertTrue(rangeSet.contains(8));
    assertNull(rangeSet.rangeContaining(6));
    assertFalse(rangeSet.contains(6));
  }

  public void testAddAll() {
    RangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 10));
    rangeSet.addAll(Arrays.asList(Range.open(1, 3), Range.closed(5, 8), Range.closed(9, 11)));
    assertThat(rangeSet.asRanges()).containsExactly(Range.openClosed(1, 11)).inOrder();
  }

  public void testRemoveAll() {
    RangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 10));
    rangeSet.removeAll(Arrays.asList(Range.open(1, 3), Range.closed(5, 8), Range.closed(9, 11)));
    assertThat(rangeSet.asRanges())
        .containsExactly(Range.closedOpen(3, 5), Range.open(8, 9))
        .inOrder();
  }

  @GwtIncompatible // SerializableTester
  public void testSerialization() {
    RangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(3, 10));
    rangeSet.remove(Range.open(5, 7));
    SerializableTester.reserializeAndAssert(rangeSet);
  }
}
