Java程序  |  398行  |  14.64 KB

/*
 * 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.CLOSED;
import static com.google.common.collect.BoundType.OPEN;
import static com.google.common.collect.BstSide.LEFT;
import static com.google.common.collect.BstSide.RIGHT;
import static com.google.common.collect.BstTesting.assertInOrderTraversalIs;
import static com.google.common.collect.BstTesting.balancePolicy;
import static com.google.common.collect.BstTesting.countAggregate;
import static com.google.common.collect.BstTesting.defaultNullPointerTester;
import static com.google.common.collect.BstTesting.nodeFactory;
import static com.google.common.collect.BstTesting.pathFactory;
import static com.google.common.collect.BstTesting.pathToList;
import static org.junit.contrib.truth.Truth.ASSERT;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.BstTesting.SimpleNode;

import junit.framework.TestCase;

import java.util.SortedSet;

/**
 * Tests for {@code BSTRangeOps}.
 *
 * @author Louis Wasserman
 */
@GwtCompatible(emulated = true)
public class BstRangeOpsTest extends TestCase {
  private static final SortedSet<Character> MODEL =
      ImmutableSortedSet.of('a', 'b', 'c', 'd', 'e', 'f', 'g');
  private static final SimpleNode ROOT;

  static {
    SimpleNode a = new SimpleNode('a', null, null);
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', a, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);
    ROOT = d;
  }

  public void testCountInRangeLowerBound() {
    for (char c : "abcdefg".toCharArray()) {
      for (BoundType type : BoundType.values()) {
        long count = BstRangeOps.totalInRange(
            countAggregate, GeneralRange.downTo(Ordering.natural(), c, type), ROOT);
        char d = c;
        if (type == BoundType.OPEN) {
          d++;
        }
        assertEquals(MODEL.tailSet(d).size(), count);
      }
    }
  }

  public void testCountInRangeUpperBound() {
    for (char c : "abcdefg".toCharArray()) {
      for (BoundType type : BoundType.values()) {
        long count = BstRangeOps.totalInRange(
            countAggregate, GeneralRange.upTo(Ordering.natural(), c, type), ROOT);
        char d = c;
        if (type == BoundType.CLOSED) {
          d++;
        }
        assertEquals(MODEL.headSet(d).size(), count);
      }
    }
  }

  public void testCountInRangeBothBounds() {
    String chars = "abcdefg";
    for (int i = 0; i < chars.length(); i++) {
      for (BoundType lb : BoundType.values()) {
        for (int j = i; j < chars.length(); j++) {
          for (BoundType ub : BoundType.values()) {
            if (i == j && lb == BoundType.OPEN && ub == BoundType.OPEN) {
              continue;
            }
            long count = BstRangeOps.totalInRange(countAggregate, GeneralRange.range(
                Ordering.natural(), chars.charAt(i), lb, chars.charAt(j), ub), ROOT);
            char lo = chars.charAt(i);
            if (lb == BoundType.OPEN) {
              lo++;
            }
            char hi = chars.charAt(j);
            if (ub == BoundType.CLOSED) {
              hi++;
            }
            if (lo > hi) {
              lo = hi;
            }
            assertEquals(MODEL.subSet(lo, hi).size(), count);
          }
        }
      }
    }
  }

  public void testCountInRangeAll() {
    assertEquals(MODEL.size(), BstRangeOps.totalInRange(
        countAggregate, GeneralRange.<Character>all(Ordering.natural()), ROOT));
  }

  public void testCountInRangeEmpty() {
    SimpleNode empty = null;
    GeneralRange<Character> range = GeneralRange.all(Ordering.natural());
    assertEquals(0, BstRangeOps.totalInRange(countAggregate, range, empty));
  }

  public void testClearRangeLowerBound() {
    //     d
    //    / \
    //   b   f
    //  /   / \
    //  a   e g
    SimpleNode a = new SimpleNode('a', null, null);
    SimpleNode b = new SimpleNode('b', a, null);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    assertInOrderTraversalIs(d, "abdefg");
    GeneralRange<Character> range1 = GeneralRange.downTo(Ordering.natural(), 'f', CLOSED);
    testTraversalAfterClearingRangeIs(d, range1, "abde");

    GeneralRange<Character> range2 = GeneralRange.downTo(Ordering.natural(), 'f', OPEN);
    testTraversalAfterClearingRangeIs(d, range2, "abdef");

    GeneralRange<Character> range3 = GeneralRange.downTo(Ordering.natural(), 'a', CLOSED);
    testTraversalAfterClearingRangeIs(d, range3, "");

    GeneralRange<Character> range4 = GeneralRange.downTo(Ordering.natural(), 'a', OPEN);
    testTraversalAfterClearingRangeIs(d, range4, "a");

    GeneralRange<Character> range5 = GeneralRange.downTo(Ordering.natural(), 'c', OPEN);
    testTraversalAfterClearingRangeIs(d, range5, "ab");

    GeneralRange<Character> range6 = GeneralRange.downTo(Ordering.natural(), 'c', CLOSED);
    testTraversalAfterClearingRangeIs(d, range6, "ab");
  }

  public void testClearRangeUpperBound() {
    //     d
    //    / \
    //   b   f
    //  /   / \
    //  a   e g
    SimpleNode a = new SimpleNode('a', null, null);
    SimpleNode b = new SimpleNode('b', a, null);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    assertInOrderTraversalIs(d, "abdefg");
    GeneralRange<Character> range1 = GeneralRange.upTo(Ordering.natural(), 'f', CLOSED);
    testTraversalAfterClearingRangeIs(d, range1, "g");

    GeneralRange<Character> range2 = GeneralRange.upTo(Ordering.natural(), 'f', OPEN);
    testTraversalAfterClearingRangeIs(d, range2, "fg");

    GeneralRange<Character> range3 = GeneralRange.upTo(Ordering.natural(), 'a', CLOSED);
    testTraversalAfterClearingRangeIs(d, range3, "bdefg");

    GeneralRange<Character> range4 = GeneralRange.upTo(Ordering.natural(), 'a', OPEN);
    testTraversalAfterClearingRangeIs(d, range4, "abdefg");

    GeneralRange<Character> range5 = GeneralRange.upTo(Ordering.natural(), 'c', OPEN);
    testTraversalAfterClearingRangeIs(d, range5, "defg");

    GeneralRange<Character> range6 = GeneralRange.upTo(Ordering.natural(), 'c', CLOSED);
    testTraversalAfterClearingRangeIs(d, range6, "defg");
  }

  public void testClearRangeDoublyBounded() {
    //     d
    //    / \
    //   b   f
    //  / \ / \
    //  a c e g
    SimpleNode a = new SimpleNode('a', null, null);
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', a, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 =
        GeneralRange.range(Ordering.natural(), 'c', OPEN, 'f', CLOSED);
    testTraversalAfterClearingRangeIs(d, range1, "abcg");

    GeneralRange<Character> range2 =
        GeneralRange.range(Ordering.natural(), 'a', CLOSED, 'h', OPEN);
    testTraversalAfterClearingRangeIs(d, range2, "");

  }

  public void testClearRangeAll() {
    //     d
    //    / \
    //   b   f
    //  / \ / \
    //  a c e g
    SimpleNode a = new SimpleNode('a', null, null);
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', a, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    testTraversalAfterClearingRangeIs(d, GeneralRange.<Character>all(Ordering.natural()), "");
  }

  private void testTraversalAfterClearingRangeIs(
      SimpleNode d, GeneralRange<Character> range, String expected) {
    assertInOrderTraversalIs(
        BstRangeOps.minusRange(range, balancePolicy, nodeFactory, d), expected);
  }

  public void testLeftmostPathAll() {
    //     d
    //    / \
    //   b   f
    //    \ / \
    //    c e g
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', null, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 = GeneralRange.all(Ordering.natural());
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range1, LEFT, pathFactory, d)))
        .hasContentsInOrder(b, d);

    assertNull(BstRangeOps.furthestPath(range1, LEFT, pathFactory, null));
  }

  public void testLeftmostPathDownTo() {
    //     d
    //    / \
    //   b   f
    //    \ / \
    //    c e g
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', null, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 = GeneralRange.downTo(Ordering.natural(), 'd', OPEN);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range1, LEFT, pathFactory, d)))
        .hasContentsInOrder(e, f, d);

    GeneralRange<Character> range2 = GeneralRange.downTo(Ordering.natural(), 'd', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range2, LEFT, pathFactory, d)))
        .hasContentsInOrder(d);

    GeneralRange<Character> range3 = GeneralRange.downTo(Ordering.natural(), 'a', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range3, LEFT, pathFactory, d)))
        .hasContentsInOrder(b, d);

    GeneralRange<Character> range4 = GeneralRange.downTo(Ordering.natural(), 'h', CLOSED);
    assertNull(BstRangeOps.furthestPath(range4, LEFT, pathFactory, d));
  }

  public void testLeftmostPathUpTo() {
    //     d
    //    / \
    //   b   f
    //    \ / \
    //    c e g
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', null, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 = GeneralRange.upTo(Ordering.natural(), 'd', OPEN);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range1, LEFT, pathFactory, d)))
        .hasContentsInOrder(b, d);

    GeneralRange<Character> range2 = GeneralRange.upTo(Ordering.natural(), 'd', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range2, LEFT, pathFactory, d)))
        .hasContentsInOrder(b, d);

    GeneralRange<Character> range3 = GeneralRange.upTo(Ordering.natural(), 'a', CLOSED);
    assertNull(BstRangeOps.furthestPath(range3, LEFT, pathFactory, d));
  }

  public void testRightmostPathAll() {
    //     d
    //    / \
    //   b   f
    //    \ / \
    //    c e g
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', null, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 = GeneralRange.all(Ordering.natural());
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range1, RIGHT, pathFactory, d)))
        .hasContentsInOrder(g, f, d);

    assertNull(BstRangeOps.furthestPath(range1, RIGHT, pathFactory, null));
  }

  public void testRightmostPathDownTo() {
    //     d
    //    / \
    //   b   f
    //    \ / \
    //    c e g
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', null, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 = GeneralRange.downTo(Ordering.natural(), 'd', OPEN);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range1, RIGHT, pathFactory, d)))
        .hasContentsInOrder(g, f, d);

    GeneralRange<Character> range2 = GeneralRange.downTo(Ordering.natural(), 'd', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range2, RIGHT, pathFactory, d)))
        .hasContentsInOrder(g, f, d);

    GeneralRange<Character> range3 = GeneralRange.downTo(Ordering.natural(), 'a', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range3, RIGHT, pathFactory, d)))
        .hasContentsInOrder(g, f, d);

    GeneralRange<Character> range4 = GeneralRange.downTo(Ordering.natural(), 'h', CLOSED);
    assertNull(BstRangeOps.furthestPath(range4, RIGHT, pathFactory, d));
  }

  public void testRightmostPathUpTo() {
    //     d
    //    / \
    //   b   f
    //    \ / \
    //    c e g
    SimpleNode c = new SimpleNode('c', null, null);
    SimpleNode b = new SimpleNode('b', null, c);
    SimpleNode e = new SimpleNode('e', null, null);
    SimpleNode g = new SimpleNode('g', null, null);
    SimpleNode f = new SimpleNode('f', e, g);
    SimpleNode d = new SimpleNode('d', b, f);

    GeneralRange<Character> range1 = GeneralRange.upTo(Ordering.natural(), 'd', OPEN);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range1, RIGHT, pathFactory, d)))
        .hasContentsInOrder(c, b, d);

    GeneralRange<Character> range2 = GeneralRange.upTo(Ordering.natural(), 'd', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range2, RIGHT, pathFactory, d)))
        .hasContentsInOrder(d);

    GeneralRange<Character> range3 = GeneralRange.upTo(Ordering.natural(), 'a', CLOSED);
    assertNull(BstRangeOps.furthestPath(range3, RIGHT, pathFactory, d));

    GeneralRange<Character> range4 = GeneralRange.upTo(Ordering.natural(), 'h', CLOSED);
    ASSERT.that(pathToList(BstRangeOps.furthestPath(range4, RIGHT, pathFactory, d)))
        .hasContentsInOrder(g, f, d);
  }

  @GwtIncompatible("NullPointerTester")
  public void testNullPointers() throws Exception {
    defaultNullPointerTester().testAllPublicStaticMethods(BstRangeOps.class);
  }
}