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