1 /* 2 * Copyright (C) 2011 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.collect.testing.Helpers.mapEntry; 19 import static org.junit.Assert.assertThrows; 20 21 import com.google.common.annotations.GwtIncompatible; 22 import com.google.common.collect.testing.MapTestSuiteBuilder; 23 import com.google.common.collect.testing.SampleElements; 24 import com.google.common.collect.testing.TestMapGenerator; 25 import com.google.common.collect.testing.features.CollectionFeature; 26 import com.google.common.collect.testing.features.CollectionSize; 27 import com.google.common.collect.testing.features.MapFeature; 28 import java.util.List; 29 import java.util.Map; 30 import java.util.Map.Entry; 31 import java.util.NoSuchElementException; 32 import junit.framework.Test; 33 import junit.framework.TestCase; 34 import junit.framework.TestSuite; 35 36 /** 37 * Tests for {@code TreeRangeMap}. 38 * 39 * @author Louis Wasserman 40 */ 41 @GwtIncompatible // NavigableMap 42 public class TreeRangeMapTest extends TestCase { suite()43 public static Test suite() { 44 TestSuite suite = new TestSuite(); 45 suite.addTestSuite(TreeRangeMapTest.class); 46 suite.addTest( 47 MapTestSuiteBuilder.using( 48 new TestMapGenerator<Range<Integer>, String>() { 49 @Override 50 public SampleElements<Entry<Range<Integer>, String>> samples() { 51 return new SampleElements<>( 52 mapEntry(Range.singleton(0), "banana"), 53 mapEntry(Range.closedOpen(3, 5), "frisbee"), 54 mapEntry(Range.atMost(-1), "fruitcake"), 55 mapEntry(Range.open(10, 15), "elephant"), 56 mapEntry(Range.closed(20, 22), "umbrella")); 57 } 58 59 @Override 60 public Map<Range<Integer>, String> create(Object... elements) { 61 RangeMap<Integer, String> rangeMap = TreeRangeMap.create(); 62 for (Object o : elements) { 63 @SuppressWarnings("unchecked") 64 Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o; 65 rangeMap.put(entry.getKey(), entry.getValue()); 66 } 67 return rangeMap.asMapOfRanges(); 68 } 69 70 @SuppressWarnings("unchecked") 71 @Override 72 public Entry<Range<Integer>, String>[] createArray(int length) { 73 return new Entry[length]; 74 } 75 76 @Override 77 public Iterable<Entry<Range<Integer>, String>> order( 78 List<Entry<Range<Integer>, String>> insertionOrder) { 79 return Range.<Integer>rangeLexOrdering().onKeys().sortedCopy(insertionOrder); 80 } 81 82 @SuppressWarnings("unchecked") 83 @Override 84 public Range<Integer>[] createKeyArray(int length) { 85 return new Range[length]; 86 } 87 88 @Override 89 public String[] createValueArray(int length) { 90 return new String[length]; 91 } 92 }) 93 .named("TreeRangeMap.asMapOfRanges") 94 .withFeatures( 95 CollectionSize.ANY, 96 MapFeature.SUPPORTS_REMOVE, 97 MapFeature.ALLOWS_ANY_NULL_QUERIES, 98 CollectionFeature.KNOWN_ORDER, 99 CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 100 .createTestSuite()); 101 102 suite.addTest( 103 MapTestSuiteBuilder.using( 104 new TestMapGenerator<Range<Integer>, String>() { 105 @Override 106 public SampleElements<Entry<Range<Integer>, String>> samples() { 107 return new SampleElements<>( 108 mapEntry(Range.singleton(0), "banana"), 109 mapEntry(Range.closedOpen(3, 5), "frisbee"), 110 mapEntry(Range.atMost(-1), "fruitcake"), 111 mapEntry(Range.open(10, 15), "elephant"), 112 mapEntry(Range.closed(20, 22), "umbrella")); 113 } 114 115 @Override 116 public Map<Range<Integer>, String> create(Object... elements) { 117 RangeMap<Integer, String> rangeMap = TreeRangeMap.create(); 118 for (Object o : elements) { 119 @SuppressWarnings("unchecked") 120 Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o; 121 rangeMap.put(entry.getKey(), entry.getValue()); 122 } 123 return rangeMap.subRangeMap(Range.atMost(22)).asMapOfRanges(); 124 } 125 126 @SuppressWarnings("unchecked") 127 @Override 128 public Entry<Range<Integer>, String>[] createArray(int length) { 129 return new Entry[length]; 130 } 131 132 @Override 133 public Iterable<Entry<Range<Integer>, String>> order( 134 List<Entry<Range<Integer>, String>> insertionOrder) { 135 return Range.<Integer>rangeLexOrdering().onKeys().sortedCopy(insertionOrder); 136 } 137 138 @SuppressWarnings("unchecked") 139 @Override 140 public Range<Integer>[] createKeyArray(int length) { 141 return new Range[length]; 142 } 143 144 @Override 145 public String[] createValueArray(int length) { 146 return new String[length]; 147 } 148 }) 149 .named("TreeRangeMap.subRangeMap.asMapOfRanges") 150 .withFeatures( 151 CollectionSize.ANY, 152 MapFeature.SUPPORTS_REMOVE, 153 MapFeature.ALLOWS_ANY_NULL_QUERIES, 154 CollectionFeature.KNOWN_ORDER) 155 .createTestSuite()); 156 157 suite.addTest( 158 MapTestSuiteBuilder.using( 159 new TestMapGenerator<Range<Integer>, String>() { 160 @Override 161 public SampleElements<Entry<Range<Integer>, String>> samples() { 162 return new SampleElements<>( 163 mapEntry(Range.singleton(0), "banana"), 164 mapEntry(Range.closedOpen(3, 5), "frisbee"), 165 mapEntry(Range.atMost(-1), "fruitcake"), 166 mapEntry(Range.open(10, 15), "elephant"), 167 mapEntry(Range.closed(20, 22), "umbrella")); 168 } 169 170 @Override 171 public Map<Range<Integer>, String> create(Object... elements) { 172 RangeMap<Integer, String> rangeMap = TreeRangeMap.create(); 173 for (Object o : elements) { 174 @SuppressWarnings("unchecked") 175 Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o; 176 rangeMap.put(entry.getKey(), entry.getValue()); 177 } 178 return rangeMap.asDescendingMapOfRanges(); 179 } 180 181 @SuppressWarnings("unchecked") 182 @Override 183 public Entry<Range<Integer>, String>[] createArray(int length) { 184 return new Entry[length]; 185 } 186 187 @Override 188 public Iterable<Entry<Range<Integer>, String>> order( 189 List<Entry<Range<Integer>, String>> insertionOrder) { 190 return Range.<Integer>rangeLexOrdering() 191 .reverse() 192 .onKeys() 193 .sortedCopy(insertionOrder); 194 } 195 196 @SuppressWarnings("unchecked") 197 @Override 198 public Range<Integer>[] createKeyArray(int length) { 199 return new Range[length]; 200 } 201 202 @Override 203 public String[] createValueArray(int length) { 204 return new String[length]; 205 } 206 }) 207 .named("TreeRangeMap.asDescendingMapOfRanges") 208 .withFeatures( 209 CollectionSize.ANY, 210 MapFeature.SUPPORTS_REMOVE, 211 MapFeature.ALLOWS_ANY_NULL_QUERIES, 212 CollectionFeature.KNOWN_ORDER, 213 CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 214 .createTestSuite()); 215 216 suite.addTest( 217 MapTestSuiteBuilder.using( 218 new TestMapGenerator<Range<Integer>, String>() { 219 @Override 220 public SampleElements<Entry<Range<Integer>, String>> samples() { 221 return new SampleElements<>( 222 mapEntry(Range.singleton(0), "banana"), 223 mapEntry(Range.closedOpen(3, 5), "frisbee"), 224 mapEntry(Range.atMost(-1), "fruitcake"), 225 mapEntry(Range.open(10, 15), "elephant"), 226 mapEntry(Range.closed(20, 22), "umbrella")); 227 } 228 229 @Override 230 public Map<Range<Integer>, String> create(Object... elements) { 231 RangeMap<Integer, String> rangeMap = TreeRangeMap.create(); 232 for (Object o : elements) { 233 @SuppressWarnings("unchecked") 234 Entry<Range<Integer>, String> entry = (Entry<Range<Integer>, String>) o; 235 rangeMap.put(entry.getKey(), entry.getValue()); 236 } 237 return rangeMap.subRangeMap(Range.atMost(22)).asDescendingMapOfRanges(); 238 } 239 240 @SuppressWarnings("unchecked") 241 @Override 242 public Entry<Range<Integer>, String>[] createArray(int length) { 243 return new Entry[length]; 244 } 245 246 @Override 247 public Iterable<Entry<Range<Integer>, String>> order( 248 List<Entry<Range<Integer>, String>> insertionOrder) { 249 return Range.<Integer>rangeLexOrdering() 250 .reverse() 251 .onKeys() 252 .sortedCopy(insertionOrder); 253 } 254 255 @SuppressWarnings("unchecked") 256 @Override 257 public Range<Integer>[] createKeyArray(int length) { 258 return new Range[length]; 259 } 260 261 @Override 262 public String[] createValueArray(int length) { 263 return new String[length]; 264 } 265 }) 266 .named("TreeRangeMap.subRangeMap.asDescendingMapOfRanges") 267 .withFeatures( 268 CollectionSize.ANY, 269 MapFeature.SUPPORTS_REMOVE, 270 MapFeature.ALLOWS_ANY_NULL_QUERIES, 271 CollectionFeature.KNOWN_ORDER) 272 .createTestSuite()); 273 return suite; 274 } 275 276 private static final ImmutableList<Range<Integer>> RANGES; 277 private static final int MIN_BOUND = -1; 278 private static final int MAX_BOUND = 1; 279 280 static { 281 ImmutableList.Builder<Range<Integer>> builder = ImmutableList.builder(); 282 all()283 builder.add(Range.<Integer>all()); 284 285 // Add one-ended ranges 286 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 287 for (BoundType type : BoundType.values()) { Range.upTo(i, type)288 builder.add(Range.upTo(i, type)); Range.downTo(i, type)289 builder.add(Range.downTo(i, type)); 290 } 291 } 292 293 // Add two-ended ranges 294 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 295 for (int j = i; j <= MAX_BOUND; j++) { 296 for (BoundType lowerType : BoundType.values()) { 297 for (BoundType upperType : BoundType.values()) { 298 if (i == j & lowerType == OPEN & upperType == OPEN) { 299 continue; 300 } Range.range(i, lowerType, j, upperType)301 builder.add(Range.range(i, lowerType, j, upperType)); 302 } 303 } 304 } 305 } 306 RANGES = builder.build(); 307 } 308 testSpanSingleRange()309 public void testSpanSingleRange() { 310 for (Range<Integer> range : RANGES) { 311 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 312 rangeMap.put(range, 1); 313 314 try { 315 assertEquals(range, rangeMap.span()); 316 assertFalse(range.isEmpty()); 317 } catch (NoSuchElementException e) { 318 assertTrue(range.isEmpty()); 319 } 320 } 321 } 322 testSpanTwoRanges()323 public void testSpanTwoRanges() { 324 for (Range<Integer> range1 : RANGES) { 325 for (Range<Integer> range2 : RANGES) { 326 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 327 rangeMap.put(range1, 1); 328 rangeMap.put(range2, 2); 329 330 Range<Integer> expected; 331 if (range1.isEmpty()) { 332 if (range2.isEmpty()) { 333 expected = null; 334 } else { 335 expected = range2; 336 } 337 } else { 338 if (range2.isEmpty()) { 339 expected = range1; 340 } else { 341 expected = range1.span(range2); 342 } 343 } 344 345 try { 346 assertEquals(expected, rangeMap.span()); 347 assertNotNull(expected); 348 } catch (NoSuchElementException e) { 349 assertNull(expected); 350 } 351 } 352 } 353 } 354 testAllRangesAlone()355 public void testAllRangesAlone() { 356 for (Range<Integer> range : RANGES) { 357 Map<Integer, Integer> model = Maps.newHashMap(); 358 putModel(model, range, 1); 359 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 360 test.put(range, 1); 361 verify(model, test); 362 } 363 } 364 testAllRangePairs()365 public void testAllRangePairs() { 366 for (Range<Integer> range1 : RANGES) { 367 for (Range<Integer> range2 : RANGES) { 368 Map<Integer, Integer> model = Maps.newHashMap(); 369 putModel(model, range1, 1); 370 putModel(model, range2, 2); 371 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 372 test.put(range1, 1); 373 test.put(range2, 2); 374 verify(model, test); 375 } 376 } 377 } 378 testAllRangeTriples()379 public void testAllRangeTriples() { 380 for (Range<Integer> range1 : RANGES) { 381 for (Range<Integer> range2 : RANGES) { 382 for (Range<Integer> range3 : RANGES) { 383 Map<Integer, Integer> model = Maps.newHashMap(); 384 putModel(model, range1, 1); 385 putModel(model, range2, 2); 386 putModel(model, range3, 3); 387 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 388 test.put(range1, 1); 389 test.put(range2, 2); 390 test.put(range3, 3); 391 verify(model, test); 392 } 393 } 394 } 395 } 396 testPutAll()397 public void testPutAll() { 398 for (Range<Integer> range1 : RANGES) { 399 for (Range<Integer> range2 : RANGES) { 400 for (Range<Integer> range3 : RANGES) { 401 Map<Integer, Integer> model = Maps.newHashMap(); 402 putModel(model, range1, 1); 403 putModel(model, range2, 2); 404 putModel(model, range3, 3); 405 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 406 RangeMap<Integer, Integer> test2 = TreeRangeMap.create(); 407 // put range2 and range3 into test2, and then put test2 into test 408 test.put(range1, 1); 409 test2.put(range2, 2); 410 test2.put(range3, 3); 411 test.putAll(test2); 412 verify(model, test); 413 } 414 } 415 } 416 } 417 testPutAndRemove()418 public void testPutAndRemove() { 419 for (Range<Integer> rangeToPut : RANGES) { 420 for (Range<Integer> rangeToRemove : RANGES) { 421 Map<Integer, Integer> model = Maps.newHashMap(); 422 putModel(model, rangeToPut, 1); 423 removeModel(model, rangeToRemove); 424 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 425 test.put(rangeToPut, 1); 426 test.remove(rangeToRemove); 427 verify(model, test); 428 } 429 } 430 } 431 testPutTwoAndRemove()432 public void testPutTwoAndRemove() { 433 for (Range<Integer> rangeToPut1 : RANGES) { 434 for (Range<Integer> rangeToPut2 : RANGES) { 435 for (Range<Integer> rangeToRemove : RANGES) { 436 Map<Integer, Integer> model = Maps.newHashMap(); 437 putModel(model, rangeToPut1, 1); 438 putModel(model, rangeToPut2, 2); 439 removeModel(model, rangeToRemove); 440 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 441 test.put(rangeToPut1, 1); 442 test.put(rangeToPut2, 2); 443 test.remove(rangeToRemove); 444 verify(model, test); 445 } 446 } 447 } 448 } 449 450 // identical to testPutTwoAndRemove, 451 // verifies that putCoalescing() doesn't cause any mappings to change relative to put() testPutCoalescingTwoAndRemove()452 public void testPutCoalescingTwoAndRemove() { 453 for (Range<Integer> rangeToPut1 : RANGES) { 454 for (Range<Integer> rangeToPut2 : RANGES) { 455 for (Range<Integer> rangeToRemove : RANGES) { 456 Map<Integer, Integer> model = Maps.newHashMap(); 457 putModel(model, rangeToPut1, 1); 458 putModel(model, rangeToPut2, 2); 459 removeModel(model, rangeToRemove); 460 RangeMap<Integer, Integer> test = TreeRangeMap.create(); 461 test.putCoalescing(rangeToPut1, 1); 462 test.putCoalescing(rangeToPut2, 2); 463 test.remove(rangeToRemove); 464 verify(model, test); 465 } 466 } 467 } 468 } 469 testPutCoalescing()470 public void testPutCoalescing() { 471 // {[0..1): 1, [1..2): 1, [2..3): 2} -> {[0..2): 1, [2..3): 2} 472 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 473 rangeMap.putCoalescing(Range.closedOpen(0, 1), 1); 474 rangeMap.putCoalescing(Range.closedOpen(1, 2), 1); 475 rangeMap.putCoalescing(Range.closedOpen(2, 3), 2); 476 assertEquals( 477 ImmutableMap.of(Range.closedOpen(0, 2), 1, Range.closedOpen(2, 3), 2), 478 rangeMap.asMapOfRanges()); 479 } 480 testPutCoalescingEmpty()481 public void testPutCoalescingEmpty() { 482 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 483 rangeMap.put(Range.closedOpen(0, 1), 1); 484 rangeMap.put(Range.closedOpen(1, 2), 1); 485 assertEquals( 486 ImmutableMap.of(Range.closedOpen(0, 1), 1, Range.closedOpen(1, 2), 1), 487 rangeMap.asMapOfRanges()); 488 489 rangeMap.putCoalescing(Range.closedOpen(1, 1), 1); // empty range coalesces connected ranges 490 assertEquals(ImmutableMap.of(Range.closedOpen(0, 2), 1), rangeMap.asMapOfRanges()); 491 } 492 testPutCoalescingSubmapEmpty()493 public void testPutCoalescingSubmapEmpty() { 494 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 495 rangeMap.put(Range.closedOpen(0, 1), 1); 496 rangeMap.put(Range.closedOpen(1, 2), 1); 497 assertEquals( 498 ImmutableMap.of(Range.closedOpen(0, 1), 1, Range.closedOpen(1, 2), 1), 499 rangeMap.asMapOfRanges()); 500 501 RangeMap<Integer, Integer> subRangeMap = rangeMap.subRangeMap(Range.closedOpen(0, 2)); 502 subRangeMap.putCoalescing(Range.closedOpen(1, 1), 1); // empty range coalesces connected ranges 503 assertEquals(ImmutableMap.of(Range.closedOpen(0, 2), 1), subRangeMap.asMapOfRanges()); 504 assertEquals(ImmutableMap.of(Range.closedOpen(0, 2), 1), rangeMap.asMapOfRanges()); 505 } 506 testPutCoalescingComplex()507 public void testPutCoalescingComplex() { 508 // {[0..1): 1, [1..3): 1, [3..5): 1, [7..10): 2, [12..15): 2, [18..19): 3} 509 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 510 rangeMap.put(Range.closedOpen(0, 1), 1); 511 rangeMap.put(Range.closedOpen(1, 3), 1); 512 rangeMap.put(Range.closedOpen(3, 5), 1); 513 rangeMap.put(Range.closedOpen(7, 10), 2); 514 rangeMap.put(Range.closedOpen(12, 15), 2); 515 rangeMap.put(Range.closedOpen(18, 19), 3); 516 517 rangeMap.putCoalescing(Range.closedOpen(-5, -4), 0); // disconnected 518 rangeMap.putCoalescing(Range.closedOpen(-6, -5), 0); // lower than minimum 519 520 rangeMap.putCoalescing(Range.closedOpen(2, 4), 1); // between 521 rangeMap.putCoalescing(Range.closedOpen(9, 14), 0); // different value 522 rangeMap.putCoalescing(Range.closedOpen(17, 20), 3); // enclosing 523 524 rangeMap.putCoalescing(Range.closedOpen(22, 23), 4); // disconnected 525 rangeMap.putCoalescing(Range.closedOpen(23, 25), 4); // greater than minimum 526 527 // {[-6..-4): 0, [0..1): 1, [1..5): 1, [7..9): 2, 528 // [9..14): 0, [14..15): 2, [17..20): 3, [22..25): 4} 529 assertEquals( 530 new ImmutableMap.Builder<>() 531 .put(Range.closedOpen(-6, -4), 0) 532 .put(Range.closedOpen(0, 1), 1) // not coalesced 533 .put(Range.closedOpen(1, 5), 1) 534 .put(Range.closedOpen(7, 9), 2) 535 .put(Range.closedOpen(9, 14), 0) 536 .put(Range.closedOpen(14, 15), 2) 537 .put(Range.closedOpen(17, 20), 3) 538 .put(Range.closedOpen(22, 25), 4) 539 .build(), 540 rangeMap.asMapOfRanges()); 541 } 542 543 testSubRangeMapExhaustive()544 public void testSubRangeMapExhaustive() { 545 for (Range<Integer> range1 : RANGES) { 546 for (Range<Integer> range2 : RANGES) { 547 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 548 rangeMap.put(range1, 1); 549 rangeMap.put(range2, 2); 550 551 for (Range<Integer> subRange : RANGES) { 552 RangeMap<Integer, Integer> expected = TreeRangeMap.create(); 553 for (Entry<Range<Integer>, Integer> entry : rangeMap.asMapOfRanges().entrySet()) { 554 if (entry.getKey().isConnected(subRange)) { 555 expected.put(entry.getKey().intersection(subRange), entry.getValue()); 556 } 557 } 558 RangeMap<Integer, Integer> subRangeMap = rangeMap.subRangeMap(subRange); 559 assertEquals(expected, subRangeMap); 560 assertEquals(expected.asMapOfRanges(), subRangeMap.asMapOfRanges()); 561 assertEquals(expected.asDescendingMapOfRanges(), subRangeMap.asDescendingMapOfRanges()); 562 assertEquals( 563 ImmutableList.copyOf(subRangeMap.asMapOfRanges().entrySet()).reverse(), 564 ImmutableList.copyOf(subRangeMap.asDescendingMapOfRanges().entrySet())); 565 566 if (!expected.asMapOfRanges().isEmpty()) { 567 assertEquals(expected.span(), subRangeMap.span()); 568 } 569 570 for (int i = MIN_BOUND; i <= MAX_BOUND; i++) { 571 assertEquals(expected.get(i), subRangeMap.get(i)); 572 } 573 574 for (Range<Integer> query : RANGES) { 575 assertEquals( 576 expected.asMapOfRanges().get(query), subRangeMap.asMapOfRanges().get(query)); 577 } 578 } 579 } 580 } 581 } 582 testSubSubRangeMap()583 public void testSubSubRangeMap() { 584 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 585 rangeMap.put(Range.open(3, 7), 1); 586 rangeMap.put(Range.closed(9, 10), 2); 587 rangeMap.put(Range.closed(12, 16), 3); 588 RangeMap<Integer, Integer> sub1 = rangeMap.subRangeMap(Range.closed(5, 11)); 589 assertEquals( 590 ImmutableMap.of(Range.closedOpen(5, 7), 1, Range.closed(9, 10), 2), sub1.asMapOfRanges()); 591 RangeMap<Integer, Integer> sub2 = sub1.subRangeMap(Range.open(6, 15)); 592 assertEquals( 593 ImmutableMap.of(Range.open(6, 7), 1, Range.closed(9, 10), 2), sub2.asMapOfRanges()); 594 } 595 testSubRangeMapPut()596 public void testSubRangeMapPut() { 597 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 598 rangeMap.put(Range.open(3, 7), 1); 599 rangeMap.put(Range.closed(9, 10), 2); 600 rangeMap.put(Range.closed(12, 16), 3); 601 RangeMap<Integer, Integer> sub = rangeMap.subRangeMap(Range.closed(5, 11)); 602 assertEquals( 603 ImmutableMap.of(Range.closedOpen(5, 7), 1, Range.closed(9, 10), 2), sub.asMapOfRanges()); 604 sub.put(Range.closed(7, 9), 4); 605 assertEquals( 606 ImmutableMap.of( 607 Range.closedOpen(5, 7), 1, Range.closed(7, 9), 4, Range.openClosed(9, 10), 2), 608 sub.asMapOfRanges()); 609 assertEquals( 610 ImmutableMap.of( 611 Range.open(3, 7), 612 1, 613 Range.closed(7, 9), 614 4, 615 Range.openClosed(9, 10), 616 2, 617 Range.closed(12, 16), 618 3), 619 rangeMap.asMapOfRanges()); 620 621 assertThrows(IllegalArgumentException.class, () -> sub.put(Range.open(9, 12), 5)); 622 623 RangeMap<Integer, Integer> subSub = sub.subRangeMap(Range.closedOpen(5, 5)); 624 subSub.put(Range.closedOpen(5, 5), 6); // should be a no-op 625 assertEquals( 626 ImmutableMap.of( 627 Range.open(3, 7), 628 1, 629 Range.closed(7, 9), 630 4, 631 Range.openClosed(9, 10), 632 2, 633 Range.closed(12, 16), 634 3), 635 rangeMap.asMapOfRanges()); 636 } 637 testSubRangeMapPutCoalescing()638 public void testSubRangeMapPutCoalescing() { 639 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 640 rangeMap.put(Range.open(3, 7), 1); 641 rangeMap.put(Range.closed(9, 10), 2); 642 rangeMap.put(Range.closed(12, 16), 3); 643 RangeMap<Integer, Integer> sub = rangeMap.subRangeMap(Range.closed(5, 11)); 644 assertEquals( 645 ImmutableMap.of(Range.closedOpen(5, 7), 1, Range.closed(9, 10), 2), sub.asMapOfRanges()); 646 sub.putCoalescing(Range.closed(7, 9), 2); 647 assertEquals( 648 ImmutableMap.of(Range.closedOpen(5, 7), 1, Range.closed(7, 10), 2), sub.asMapOfRanges()); 649 assertEquals( 650 ImmutableMap.of(Range.open(3, 7), 1, Range.closed(7, 10), 2, Range.closed(12, 16), 3), 651 rangeMap.asMapOfRanges()); 652 653 sub.putCoalescing(Range.singleton(7), 1); 654 assertEquals( 655 ImmutableMap.of(Range.closed(5, 7), 1, Range.openClosed(7, 10), 2), sub.asMapOfRanges()); 656 assertEquals( 657 ImmutableMap.of( 658 Range.open(3, 5), 659 1, 660 Range.closed(5, 7), 661 1, 662 Range.openClosed(7, 10), 663 2, 664 Range.closed(12, 16), 665 3), 666 rangeMap.asMapOfRanges()); 667 668 assertThrows(IllegalArgumentException.class, () -> sub.putCoalescing(Range.open(9, 12), 5)); 669 } 670 testSubRangeMapRemove()671 public void testSubRangeMapRemove() { 672 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 673 rangeMap.put(Range.open(3, 7), 1); 674 rangeMap.put(Range.closed(9, 10), 2); 675 rangeMap.put(Range.closed(12, 16), 3); 676 RangeMap<Integer, Integer> sub = rangeMap.subRangeMap(Range.closed(5, 11)); 677 assertEquals( 678 ImmutableMap.of(Range.closedOpen(5, 7), 1, Range.closed(9, 10), 2), sub.asMapOfRanges()); 679 sub.remove(Range.closed(7, 9)); 680 assertEquals( 681 ImmutableMap.of(Range.closedOpen(5, 7), 1, Range.openClosed(9, 10), 2), 682 sub.asMapOfRanges()); 683 assertEquals( 684 ImmutableMap.of(Range.open(3, 7), 1, Range.openClosed(9, 10), 2, Range.closed(12, 16), 3), 685 rangeMap.asMapOfRanges()); 686 687 sub.remove(Range.closed(3, 9)); 688 assertEquals(ImmutableMap.of(Range.openClosed(9, 10), 2), sub.asMapOfRanges()); 689 assertEquals( 690 ImmutableMap.of(Range.open(3, 5), 1, Range.openClosed(9, 10), 2, Range.closed(12, 16), 3), 691 rangeMap.asMapOfRanges()); 692 } 693 testSubRangeMapClear()694 public void testSubRangeMapClear() { 695 RangeMap<Integer, Integer> rangeMap = TreeRangeMap.create(); 696 rangeMap.put(Range.open(3, 7), 1); 697 rangeMap.put(Range.closed(9, 10), 2); 698 rangeMap.put(Range.closed(12, 16), 3); 699 RangeMap<Integer, Integer> sub = rangeMap.subRangeMap(Range.closed(5, 11)); 700 sub.clear(); 701 assertEquals( 702 ImmutableMap.of(Range.open(3, 5), 1, Range.closed(12, 16), 3), rangeMap.asMapOfRanges()); 703 } 704 verify(Map<Integer, Integer> model, RangeMap<Integer, Integer> test)705 private void verify(Map<Integer, Integer> model, RangeMap<Integer, Integer> test) { 706 for (int i = MIN_BOUND - 1; i <= MAX_BOUND + 1; i++) { 707 assertEquals(model.get(i), test.get(i)); 708 709 Entry<Range<Integer>, Integer> entry = test.getEntry(i); 710 assertEquals(model.containsKey(i), entry != null); 711 if (entry != null) { 712 assertTrue(test.asMapOfRanges().entrySet().contains(entry)); 713 } 714 } 715 for (Range<Integer> range : test.asMapOfRanges().keySet()) { 716 assertFalse(range.isEmpty()); 717 } 718 } 719 putModel(Map<Integer, Integer> model, Range<Integer> range, int value)720 private static void putModel(Map<Integer, Integer> model, Range<Integer> range, int value) { 721 for (int i = MIN_BOUND - 1; i <= MAX_BOUND + 1; i++) { 722 if (range.contains(i)) { 723 model.put(i, value); 724 } 725 } 726 } 727 removeModel(Map<Integer, Integer> model, Range<Integer> range)728 private static void removeModel(Map<Integer, Integer> model, Range<Integer> range) { 729 for (int i = MIN_BOUND - 1; i <= MAX_BOUND + 1; i++) { 730 if (range.contains(i)) { 731 model.remove(i); 732 } 733 } 734 } 735 } 736