/* * Copyright (C) 2008 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.DiscreteDomains.integers; import static com.google.common.testing.SerializableTester.reserializeAndAssert; import static java.util.Arrays.asList; import com.google.common.annotations.GwtCompatible; import com.google.common.base.Predicate; import com.google.common.collect.testing.Helpers; import com.google.common.testing.EqualsTester; import junit.framework.TestCase; import java.util.Collections; /** * Unit test for {@link Range}. * * @author Kevin Bourrillion */ @GwtCompatible public class RangeTest extends TestCase { public void testOpen() { Range range = Ranges.open(4, 8); checkContains(range); assertTrue(range.hasLowerBound()); assertEquals(4, (int) range.lowerEndpoint()); assertEquals(OPEN, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(8, (int) range.upperEndpoint()); assertEquals(OPEN, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("(4\u20258)", range.toString()); reserializeAndAssert(range); } public void testOpen_invalid() { try { Ranges.open(4, 3); fail(); } catch (IllegalArgumentException expected) { } try { Ranges.open(3, 3); fail(); } catch (IllegalArgumentException expected) { } } public void testClosed() { Range range = Ranges.closed(5, 7); checkContains(range); assertTrue(range.hasLowerBound()); assertEquals(5, (int) range.lowerEndpoint()); assertEquals(CLOSED, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(7, (int) range.upperEndpoint()); assertEquals(CLOSED, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("[5\u20257]", range.toString()); reserializeAndAssert(range); } public void testClosed_invalid() { try { Ranges.closed(4, 3); fail(); } catch (IllegalArgumentException expected) { } } public void testOpenClosed() { Range range = Ranges.openClosed(4, 7); checkContains(range); assertTrue(range.hasLowerBound()); assertEquals(4, (int) range.lowerEndpoint()); assertEquals(OPEN, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(7, (int) range.upperEndpoint()); assertEquals(CLOSED, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("(4\u20257]", range.toString()); reserializeAndAssert(range); } public void testClosedOpen() { Range range = Ranges.closedOpen(5, 8); checkContains(range); assertTrue(range.hasLowerBound()); assertEquals(5, (int) range.lowerEndpoint()); assertEquals(CLOSED, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(8, (int) range.upperEndpoint()); assertEquals(OPEN, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("[5\u20258)", range.toString()); reserializeAndAssert(range); } public void testIsConnected() { assertTrue(Ranges.closed(3, 5).isConnected(Ranges.open(5, 6))); assertTrue(Ranges.closed(3, 5).isConnected(Ranges.openClosed(5, 5))); assertTrue(Ranges.open(3, 5).isConnected(Ranges.closed(5, 6))); assertTrue(Ranges.closed(3, 7).isConnected(Ranges.open(6, 8))); assertTrue(Ranges.open(3, 7).isConnected(Ranges.closed(5, 6))); assertFalse(Ranges.closed(3, 5).isConnected(Ranges.closed(7, 8))); assertFalse(Ranges.closed(3, 5).isConnected(Ranges.closedOpen(7, 7))); } private static void checkContains(Range range) { assertFalse(range.contains(4)); assertTrue(range.contains(5)); assertTrue(range.contains(7)); assertFalse(range.contains(8)); } public void testSingleton() { Range range = Ranges.closed(4, 4); assertFalse(range.contains(3)); assertTrue(range.contains(4)); assertFalse(range.contains(5)); assertTrue(range.hasLowerBound()); assertEquals(4, (int) range.lowerEndpoint()); assertEquals(CLOSED, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(4, (int) range.upperEndpoint()); assertEquals(CLOSED, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("[4\u20254]", range.toString()); reserializeAndAssert(range); } public void testEmpty1() { Range range = Ranges.closedOpen(4, 4); assertFalse(range.contains(3)); assertFalse(range.contains(4)); assertFalse(range.contains(5)); assertTrue(range.hasLowerBound()); assertEquals(4, (int) range.lowerEndpoint()); assertEquals(CLOSED, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(4, (int) range.upperEndpoint()); assertEquals(OPEN, range.upperBoundType()); assertTrue(range.isEmpty()); assertEquals("[4\u20254)", range.toString()); reserializeAndAssert(range); } public void testEmpty2() { Range range = Ranges.openClosed(4, 4); assertFalse(range.contains(3)); assertFalse(range.contains(4)); assertFalse(range.contains(5)); assertTrue(range.hasLowerBound()); assertEquals(4, (int) range.lowerEndpoint()); assertEquals(OPEN, range.lowerBoundType()); assertTrue(range.hasUpperBound()); assertEquals(4, (int) range.upperEndpoint()); assertEquals(CLOSED, range.upperBoundType()); assertTrue(range.isEmpty()); assertEquals("(4\u20254]", range.toString()); reserializeAndAssert(range); } public void testLessThan() { Range range = Ranges.lessThan(5); assertTrue(range.contains(Integer.MIN_VALUE)); assertTrue(range.contains(4)); assertFalse(range.contains(5)); assertUnboundedBelow(range); assertTrue(range.hasUpperBound()); assertEquals(5, (int) range.upperEndpoint()); assertEquals(OPEN, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("(-\u221e\u20255)", range.toString()); reserializeAndAssert(range); } public void testGreaterThan() { Range range = Ranges.greaterThan(5); assertFalse(range.contains(5)); assertTrue(range.contains(6)); assertTrue(range.contains(Integer.MAX_VALUE)); assertTrue(range.hasLowerBound()); assertEquals(5, (int) range.lowerEndpoint()); assertEquals(OPEN, range.lowerBoundType()); assertUnboundedAbove(range); assertFalse(range.isEmpty()); assertEquals("(5\u2025+\u221e)", range.toString()); reserializeAndAssert(range); } public void testAtLeast() { Range range = Ranges.atLeast(6); assertFalse(range.contains(5)); assertTrue(range.contains(6)); assertTrue(range.contains(Integer.MAX_VALUE)); assertTrue(range.hasLowerBound()); assertEquals(6, (int) range.lowerEndpoint()); assertEquals(CLOSED, range.lowerBoundType()); assertUnboundedAbove(range); assertFalse(range.isEmpty()); assertEquals("[6\u2025+\u221e)", range.toString()); reserializeAndAssert(range); } public void testAtMost() { Range range = Ranges.atMost(4); assertTrue(range.contains(Integer.MIN_VALUE)); assertTrue(range.contains(4)); assertFalse(range.contains(5)); assertUnboundedBelow(range); assertTrue(range.hasUpperBound()); assertEquals(4, (int) range.upperEndpoint()); assertEquals(CLOSED, range.upperBoundType()); assertFalse(range.isEmpty()); assertEquals("(-\u221e\u20254]", range.toString()); reserializeAndAssert(range); } public void testAll() { Range range = Ranges.all(); assertTrue(range.contains(Integer.MIN_VALUE)); assertTrue(range.contains(Integer.MAX_VALUE)); assertUnboundedBelow(range); assertUnboundedAbove(range); assertFalse(range.isEmpty()); assertEquals("(-\u221e\u2025+\u221e)", range.toString()); reserializeAndAssert(range); } private static void assertUnboundedBelow(Range range) { assertFalse(range.hasLowerBound()); try { range.lowerEndpoint(); fail(); } catch (IllegalStateException expected) { } try { range.lowerBoundType(); fail(); } catch (IllegalStateException expected) { } } private static void assertUnboundedAbove(Range range) { assertFalse(range.hasUpperBound()); try { range.upperEndpoint(); fail(); } catch (IllegalStateException expected) { } try { range.upperBoundType(); fail(); } catch (IllegalStateException expected) { } } public void testOrderingCuts() { Cut a = Ranges.lessThan(0).lowerBound; Cut b = Ranges.atLeast(0).lowerBound; Cut c = Ranges.greaterThan(0).lowerBound; Cut d = Ranges.atLeast(1).lowerBound; Cut e = Ranges.greaterThan(1).lowerBound; Cut f = Ranges.greaterThan(1).upperBound; Helpers.testCompareToAndEquals(ImmutableList.of(a, b, c, d, e, f)); } public void testContainsAll() { Range range = Ranges.closed(3, 5); assertTrue(range.containsAll(asList(3, 3, 4, 5))); assertFalse(range.containsAll(asList(3, 3, 4, 5, 6))); // We happen to know that natural-order sorted sets use a different code // path, so we test that separately assertTrue(range.containsAll(ImmutableSortedSet.of(3, 3, 4, 5))); assertTrue(range.containsAll(ImmutableSortedSet.of(3))); assertTrue(range.containsAll(ImmutableSortedSet.of())); assertFalse(range.containsAll(ImmutableSortedSet.of(3, 3, 4, 5, 6))); assertTrue(Ranges.openClosed(3, 3).containsAll( Collections.emptySet())); } public void testEncloses_open() { Range range = Ranges.open(2, 5); assertTrue(range.encloses(range)); assertTrue(range.encloses(Ranges.open(2, 4))); assertTrue(range.encloses(Ranges.open(3, 5))); assertTrue(range.encloses(Ranges.closed(3, 4))); assertFalse(range.encloses(Ranges.openClosed(2, 5))); assertFalse(range.encloses(Ranges.closedOpen(2, 5))); assertFalse(range.encloses(Ranges.closed(1, 4))); assertFalse(range.encloses(Ranges.closed(3, 6))); assertFalse(range.encloses(Ranges.greaterThan(3))); assertFalse(range.encloses(Ranges.lessThan(3))); assertFalse(range.encloses(Ranges.atLeast(3))); assertFalse(range.encloses(Ranges.atMost(3))); assertFalse(range.encloses(Ranges.all())); } public void testEncloses_closed() { Range range = Ranges.closed(2, 5); assertTrue(range.encloses(range)); assertTrue(range.encloses(Ranges.open(2, 5))); assertTrue(range.encloses(Ranges.openClosed(2, 5))); assertTrue(range.encloses(Ranges.closedOpen(2, 5))); assertTrue(range.encloses(Ranges.closed(3, 5))); assertTrue(range.encloses(Ranges.closed(2, 4))); assertFalse(range.encloses(Ranges.open(1, 6))); assertFalse(range.encloses(Ranges.greaterThan(3))); assertFalse(range.encloses(Ranges.lessThan(3))); assertFalse(range.encloses(Ranges.atLeast(3))); assertFalse(range.encloses(Ranges.atMost(3))); assertFalse(range.encloses(Ranges.all())); } public void testIntersection_empty() { Range range = Ranges.closedOpen(3, 3); assertEquals(range, range.intersection(range)); try { range.intersection(Ranges.open(3, 5)); fail(); } catch (IllegalArgumentException expected) { } try { range.intersection(Ranges.closed(0, 2)); fail(); } catch (IllegalArgumentException expected) { } } public void testIntersection_deFactoEmpty() { Range range = Ranges.open(3, 4); assertEquals(range, range.intersection(range)); assertEquals(Ranges.openClosed(3, 3), range.intersection(Ranges.atMost(3))); assertEquals(Ranges.closedOpen(4, 4), range.intersection(Ranges.atLeast(4))); try { range.intersection(Ranges.lessThan(3)); fail(); } catch (IllegalArgumentException expected) { } try { range.intersection(Ranges.greaterThan(4)); fail(); } catch (IllegalArgumentException expected) { } range = Ranges.closed(3, 4); assertEquals(Ranges.openClosed(4, 4), range.intersection(Ranges.greaterThan(4))); } public void testIntersection_singleton() { Range range = Ranges.closed(3, 3); assertEquals(range, range.intersection(range)); assertEquals(range, range.intersection(Ranges.atMost(4))); assertEquals(range, range.intersection(Ranges.atMost(3))); assertEquals(range, range.intersection(Ranges.atLeast(3))); assertEquals(range, range.intersection(Ranges.atLeast(2))); assertEquals(Ranges.closedOpen(3, 3), range.intersection(Ranges.lessThan(3))); assertEquals(Ranges.openClosed(3, 3), range.intersection(Ranges.greaterThan(3))); try { range.intersection(Ranges.atLeast(4)); fail(); } catch (IllegalArgumentException expected) { } try { range.intersection(Ranges.atMost(2)); fail(); } catch (IllegalArgumentException expected) { } } public void testIntersection_general() { Range range = Ranges.closed(4, 8); // separate below try { range.intersection(Ranges.closed(0, 2)); fail(); } catch (IllegalArgumentException expected) { } // adjacent below assertEquals(Ranges.closedOpen(4, 4), range.intersection(Ranges.closedOpen(2, 4))); // overlap below assertEquals(Ranges.closed(4, 6), range.intersection(Ranges.closed(2, 6))); // enclosed with same start assertEquals(Ranges.closed(4, 6), range.intersection(Ranges.closed(4, 6))); // enclosed, interior assertEquals(Ranges.closed(5, 7), range.intersection(Ranges.closed(5, 7))); // enclosed with same end assertEquals(Ranges.closed(6, 8), range.intersection(Ranges.closed(6, 8))); // equal assertEquals(range, range.intersection(range)); // enclosing with same start assertEquals(range, range.intersection(Ranges.closed(4, 10))); // enclosing with same end assertEquals(range, range.intersection(Ranges.closed(2, 8))); // enclosing, exterior assertEquals(range, range.intersection(Ranges.closed(2, 10))); // overlap above assertEquals(Ranges.closed(6, 8), range.intersection(Ranges.closed(6, 10))); // adjacent above assertEquals(Ranges.openClosed(8, 8), range.intersection(Ranges.openClosed(8, 10))); // separate above try { range.intersection(Ranges.closed(10, 12)); fail(); } catch (IllegalArgumentException expected) { } } public void testSpan_general() { Range range = Ranges.closed(4, 8); // separate below assertEquals(Ranges.closed(0, 8), range.span(Ranges.closed(0, 2))); assertEquals(Ranges.atMost(8), range.span(Ranges.atMost(2))); // adjacent below assertEquals(Ranges.closed(2, 8), range.span(Ranges.closedOpen(2, 4))); assertEquals(Ranges.atMost(8), range.span(Ranges.lessThan(4))); // overlap below assertEquals(Ranges.closed(2, 8), range.span(Ranges.closed(2, 6))); assertEquals(Ranges.atMost(8), range.span(Ranges.atMost(6))); // enclosed with same start assertEquals(range, range.span(Ranges.closed(4, 6))); // enclosed, interior assertEquals(range, range.span(Ranges.closed(5, 7))); // enclosed with same end assertEquals(range, range.span(Ranges.closed(6, 8))); // equal assertEquals(range, range.span(range)); // enclosing with same start assertEquals(Ranges.closed(4, 10), range.span(Ranges.closed(4, 10))); assertEquals(Ranges.atLeast(4), range.span(Ranges.atLeast(4))); // enclosing with same end assertEquals(Ranges.closed(2, 8), range.span(Ranges.closed(2, 8))); assertEquals(Ranges.atMost(8), range.span(Ranges.atMost(8))); // enclosing, exterior assertEquals(Ranges.closed(2, 10), range.span(Ranges.closed(2, 10))); assertEquals(Ranges.all(), range.span(Ranges.all())); // overlap above assertEquals(Ranges.closed(4, 10), range.span(Ranges.closed(6, 10))); assertEquals(Ranges.atLeast(4), range.span(Ranges.atLeast(6))); // adjacent above assertEquals(Ranges.closed(4, 10), range.span(Ranges.openClosed(8, 10))); assertEquals(Ranges.atLeast(4), range.span(Ranges.greaterThan(8))); // separate above assertEquals(Ranges.closed(4, 12), range.span(Ranges.closed(10, 12))); assertEquals(Ranges.atLeast(4), range.span(Ranges.atLeast(10))); } public void testApply() { Predicate predicate = Ranges.closed(2, 3); assertFalse(predicate.apply(1)); assertTrue(predicate.apply(2)); assertTrue(predicate.apply(3)); assertFalse(predicate.apply(4)); } public void testEquals() { new EqualsTester() .addEqualityGroup(Ranges.open(1, 5), Ranges.range(1, OPEN, 5, OPEN)) .addEqualityGroup(Ranges.greaterThan(2), Ranges.greaterThan(2)) .addEqualityGroup(Ranges.all(), Ranges.all()) .addEqualityGroup("Phil") .testEquals(); } public void testLegacyComparable() { Range range = Ranges.closed(LegacyComparable.X, LegacyComparable.Y); } private static final DiscreteDomain UNBOUNDED_DOMAIN = new DiscreteDomain() { @Override public Integer next(Integer value) { return DiscreteDomains.integers().next(value); } @Override public Integer previous(Integer value) { return DiscreteDomains.integers().previous(value); } @Override public long distance(Integer start, Integer end) { return DiscreteDomains.integers().distance(start, end); } }; public void testAsSet_noMin() { Range range = Ranges.lessThan(0); try { range.asSet(UNBOUNDED_DOMAIN); fail(); } catch (IllegalArgumentException expected) {} } public void testAsSet_noMax() { Range range = Ranges.greaterThan(0); try { range.asSet(UNBOUNDED_DOMAIN); fail(); } catch (IllegalArgumentException expected) {} } public void testAsSet_empty() { assertEquals(ImmutableSet.of(), Ranges.closedOpen(1, 1).asSet(integers())); assertEquals(ImmutableSet.of(), Ranges.openClosed(5, 5).asSet(integers())); assertEquals(ImmutableSet.of(), Ranges.lessThan(Integer.MIN_VALUE).asSet(integers())); assertEquals(ImmutableSet.of(), Ranges.greaterThan(Integer.MAX_VALUE).asSet(integers())); } public void testCanonical() { assertEquals(Ranges.closedOpen(1, 5), Ranges.closed(1, 4).canonical(integers())); assertEquals(Ranges.closedOpen(1, 5), Ranges.open(0, 5).canonical(integers())); assertEquals(Ranges.closedOpen(1, 5), Ranges.closedOpen(1, 5).canonical(integers())); assertEquals(Ranges.closedOpen(1, 5), Ranges.openClosed(0, 4).canonical(integers())); assertEquals(Ranges.closedOpen(Integer.MIN_VALUE, 0), Ranges.closedOpen(Integer.MIN_VALUE, 0).canonical(integers())); assertEquals(Ranges.closedOpen(Integer.MIN_VALUE, 0), Ranges.lessThan(0).canonical(integers())); assertEquals(Ranges.closedOpen(Integer.MIN_VALUE, 1), Ranges.atMost(0).canonical(integers())); assertEquals(Ranges.atLeast(0), Ranges.atLeast(0).canonical(integers())); assertEquals(Ranges.atLeast(1), Ranges.greaterThan(0).canonical(integers())); assertEquals(Ranges.atLeast(Integer.MIN_VALUE), Ranges.all().canonical(integers())); } public void testCanonical_unboundedDomain() { assertEquals(Ranges.lessThan(0), Ranges.lessThan(0).canonical(UNBOUNDED_DOMAIN)); assertEquals(Ranges.lessThan(1), Ranges.atMost(0).canonical(UNBOUNDED_DOMAIN)); assertEquals(Ranges.atLeast(0), Ranges.atLeast(0).canonical(UNBOUNDED_DOMAIN)); assertEquals(Ranges.atLeast(1), Ranges.greaterThan(0).canonical(UNBOUNDED_DOMAIN)); assertEquals(Ranges.all(), Ranges.all().canonical(UNBOUNDED_DOMAIN)); } }