• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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