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.collect.BoundType.OPEN; 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.junit.Assert.assertThrows; 20 21 import com.google.common.annotations.GwtIncompatible; 22 import com.google.common.testing.SerializableTester; 23 import java.util.Map.Entry; 24 import java.util.NoSuchElementException; 25 import junit.framework.TestCase; 26 27 /** 28 * Tests for {@code ImmutableRangeMap}. 29 * 30 * @author Louis Wasserman 31 */ 32 @GwtIncompatible // NavigableMap 33 public class ImmutableRangeMapTest extends TestCase { 34 private static final ImmutableList<Range<Integer>> RANGES; 35 private static final int MIN_BOUND = 0; 36 private static final int MAX_BOUND = 10; 37 38 static { 39 ImmutableList.Builder<Range<Integer>> builder = ImmutableList.builder(); 40 all()41 builder.add(Range.<Integer>all()); 42 43 // Add one-ended ranges 44 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 45 for (BoundType type : BoundType.values()) { Range.upTo(i, type)46 builder.add(Range.upTo(i, type)); Range.downTo(i, type)47 builder.add(Range.downTo(i, type)); 48 } 49 } 50 51 // Add two-ended ranges 52 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 53 for (int j = i + 1; j <= MAX_BOUND; j++) { 54 for (BoundType lowerType : BoundType.values()) { 55 for (BoundType upperType : BoundType.values()) { 56 if (i == j & lowerType == OPEN & upperType == OPEN) { 57 continue; 58 } Range.range(i, lowerType, j, upperType)59 builder.add(Range.range(i, lowerType, j, upperType)); 60 } 61 } 62 } 63 } 64 RANGES = builder.build(); 65 } 66 testBuilderRejectsEmptyRanges()67 public void testBuilderRejectsEmptyRanges() { 68 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 69 final int ii = i; 70 ImmutableRangeMap.Builder<Integer, Integer> builder = ImmutableRangeMap.builder(); 71 assertThrows(IllegalArgumentException.class, () -> builder.put(Range.closedOpen(ii, ii), 1)); 72 assertThrows(IllegalArgumentException.class, () -> builder.put(Range.openClosed(ii, ii), 1)); 73 } 74 } 75 testOverlapRejection()76 public void testOverlapRejection() { 77 for (Range<Integer> range1 : RANGES) { 78 for (Range<Integer> range2 : RANGES) { 79 boolean expectRejection = 80 range1.isConnected(range2) && !range1.intersection(range2).isEmpty(); 81 ImmutableRangeMap.Builder<Integer, Integer> builder = ImmutableRangeMap.builder(); 82 builder.put(range1, 1).put(range2, 2); 83 try { 84 ImmutableRangeMap<Integer, Integer> unused = builder.build(); 85 assertFalse(expectRejection); 86 } catch (IllegalArgumentException e) { 87 assertTrue(expectRejection); 88 } 89 } 90 } 91 } 92 testGet()93 public void testGet() { 94 for (Range<Integer> range1 : RANGES) { 95 for (Range<Integer> range2 : RANGES) { 96 if (!range1.isConnected(range2) || range1.intersection(range2).isEmpty()) { 97 ImmutableRangeMap<Integer, Integer> rangeMap = 98 ImmutableRangeMap.<Integer, Integer>builder().put(range1, 1).put(range2, 2).build(); 99 100 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 101 Integer expectedValue = null; 102 if (range1.contains(i)) { 103 expectedValue = 1; 104 } else if (range2.contains(i)) { 105 expectedValue = 2; 106 } 107 108 assertEquals(expectedValue, rangeMap.get(i)); 109 } 110 } 111 } 112 } 113 } 114 testSpanEmpty()115 public void testSpanEmpty() { 116 assertThrows(NoSuchElementException.class, () -> ImmutableRangeMap.of().span()); 117 } 118 testSpanSingleRange()119 public void testSpanSingleRange() { 120 for (Range<Integer> range : RANGES) { 121 RangeMap<Integer, Integer> rangemap = 122 ImmutableRangeMap.<Integer, Integer>builder().put(range, 1).build(); 123 assertEquals(range, rangemap.span()); 124 } 125 } 126 testSpanTwoRanges()127 public void testSpanTwoRanges() { 128 for (Range<Integer> range1 : RANGES) { 129 for (Range<Integer> range2 : RANGES) { 130 if (!range1.isConnected(range2) || range1.intersection(range2).isEmpty()) { 131 RangeMap<Integer, Integer> rangemap = 132 ImmutableRangeMap.<Integer, Integer>builder().put(range1, 1).put(range2, 2).build(); 133 assertEquals(range1.span(range2), rangemap.span()); 134 } 135 } 136 } 137 } 138 testGetEntry()139 public void testGetEntry() { 140 for (Range<Integer> range1 : RANGES) { 141 for (Range<Integer> range2 : RANGES) { 142 if (!range1.isConnected(range2) || range1.intersection(range2).isEmpty()) { 143 ImmutableRangeMap<Integer, Integer> rangeMap = 144 ImmutableRangeMap.<Integer, Integer>builder().put(range1, 1).put(range2, 2).build(); 145 146 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 147 Entry<Range<Integer>, Integer> expectedEntry = null; 148 if (range1.contains(i)) { 149 expectedEntry = Maps.immutableEntry(range1, 1); 150 } else if (range2.contains(i)) { 151 expectedEntry = Maps.immutableEntry(range2, 2); 152 } 153 154 assertEquals(expectedEntry, rangeMap.getEntry(i)); 155 } 156 } 157 } 158 } 159 } 160 testGetLargeRangeMap()161 public void testGetLargeRangeMap() { 162 ImmutableRangeMap.Builder<Integer, Integer> builder = ImmutableRangeMap.builder(); 163 for (int i = 0; i < 100; i++) { 164 builder.put(Range.closedOpen(i, i + 1), i); 165 } 166 ImmutableRangeMap<Integer, Integer> map = builder.build(); 167 for (int i = 0; i < 100; i++) { 168 assertEquals(Integer.valueOf(i), map.get(i)); 169 } 170 } 171 172 @AndroidIncompatible // slow testAsMapOfRanges()173 public void testAsMapOfRanges() { 174 for (Range<Integer> range1 : RANGES) { 175 for (Range<Integer> range2 : RANGES) { 176 if (!range1.isConnected(range2) || range1.intersection(range2).isEmpty()) { 177 ImmutableRangeMap<Integer, Integer> rangeMap = 178 ImmutableRangeMap.<Integer, Integer>builder().put(range1, 1).put(range2, 2).build(); 179 180 ImmutableMap<Range<Integer>, Integer> expectedAsMap = 181 ImmutableMap.of(range1, 1, range2, 2); 182 ImmutableMap<Range<Integer>, Integer> asMap = rangeMap.asMapOfRanges(); 183 ImmutableMap<Range<Integer>, Integer> descendingMap = rangeMap.asDescendingMapOfRanges(); 184 assertEquals(expectedAsMap, asMap); 185 assertEquals(expectedAsMap, descendingMap); 186 SerializableTester.reserializeAndAssert(asMap); 187 SerializableTester.reserializeAndAssert(descendingMap); 188 assertEquals( 189 ImmutableList.copyOf(asMap.entrySet()).reverse(), 190 ImmutableList.copyOf(descendingMap.entrySet())); 191 192 for (Range<Integer> query : RANGES) { 193 assertEquals(expectedAsMap.get(query), asMap.get(query)); 194 } 195 } 196 } 197 } 198 } 199 200 testSubRangeMap()201 public void testSubRangeMap() { 202 for (Range<Integer> range1 : RANGES) { 203 for (Range<Integer> range2 : RANGES) { 204 if (!range1.isConnected(range2) || range1.intersection(range2).isEmpty()) { 205 for (Range<Integer> subRange : RANGES) { 206 ImmutableRangeMap<Integer, Integer> rangeMap = 207 ImmutableRangeMap.<Integer, Integer>builder().put(range1, 1).put(range2, 2).build(); 208 209 ImmutableRangeMap.Builder<Integer, Integer> expectedBuilder = 210 ImmutableRangeMap.builder(); 211 for (Entry<Range<Integer>, Integer> entry : rangeMap.asMapOfRanges().entrySet()) { 212 if (entry.getKey().isConnected(subRange) 213 && !entry.getKey().intersection(subRange).isEmpty()) { 214 expectedBuilder.put(entry.getKey().intersection(subRange), entry.getValue()); 215 } 216 } 217 218 ImmutableRangeMap<Integer, Integer> expected = expectedBuilder.build(); 219 assertEquals(expected, rangeMap.subRangeMap(subRange)); 220 } 221 } 222 } 223 } 224 } 225 testSerialization()226 public void testSerialization() { 227 ImmutableRangeMap<Integer, Integer> emptyRangeMap = ImmutableRangeMap.of(); 228 SerializableTester.reserializeAndAssert(emptyRangeMap); 229 230 ImmutableRangeMap<Integer, Integer> nonEmptyRangeMap = 231 new ImmutableRangeMap.Builder<Integer, Integer>() 232 .put(Range.closed(2, 4), 5) 233 .put(Range.open(6, 7), 3) 234 .put(Range.closedOpen(8, 10), 4) 235 .put(Range.openClosed(15, 17), 2) 236 .build(); 237 238 ImmutableMap<Range<Integer>, Integer> test = nonEmptyRangeMap.asMapOfRanges(); 239 240 for (Range<Integer> range : test.keySet()) { 241 SerializableTester.reserializeAndAssert(range); 242 } 243 244 SerializableTester.reserializeAndAssert(test.keySet()); 245 246 SerializableTester.reserializeAndAssert(nonEmptyRangeMap); 247 } 248 249 // TODO(b/172823566): Use mainline testToImmutableRangeMap once CollectorTester is usable to java7 testToImmutableRangeMap()250 public void testToImmutableRangeMap() { 251 Range<Integer> rangeOne = Range.closedOpen(1, 5); 252 Range<Integer> rangeTwo = Range.openClosed(6, 7); 253 254 ImmutableRangeMap.Builder<Integer, Integer> zis = 255 ImmutableRangeMap.<Integer, Integer>builder().put(rangeOne, 1); 256 ImmutableRangeMap.Builder<Integer, Integer> zat = 257 ImmutableRangeMap.<Integer, Integer>builder().put(rangeTwo, 6); 258 259 ImmutableRangeMap<Integer, Integer> rangeMap = zis.combine(zat).build(); 260 261 assertThat(rangeMap.asMapOfRanges().entrySet()) 262 .containsExactly(Maps.immutableEntry(rangeOne, 1), Maps.immutableEntry(rangeTwo, 6)) 263 .inOrder(); 264 } 265 } 266