1 /* 2 * Copyright (C) 2008 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import static com.google.common.collect.Maps.newHashMap; 20 import static com.google.common.collect.testing.Helpers.mapEntry; 21 import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES; 22 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE; 23 import static com.google.common.collect.testing.google.AbstractMultisetSetCountTester.getSetCountDuplicateInitializingMethods; 24 import static com.google.common.collect.testing.google.MultisetCountTester.getCountDuplicateInitializingMethods; 25 import static com.google.common.collect.testing.google.MultisetElementSetTester.getElementSetDuplicateInitializingMethods; 26 import static com.google.common.collect.testing.google.MultisetForEachEntryTester.getForEachEntryDuplicateInitializingMethods; 27 import static com.google.common.collect.testing.google.MultisetIteratorTester.getIteratorDuplicateInitializingMethods; 28 import static com.google.common.collect.testing.google.MultisetRemoveTester.getRemoveDuplicateInitializingMethods; 29 import static java.lang.reflect.Proxy.newProxyInstance; 30 31 import com.google.common.annotations.GwtIncompatible; 32 import com.google.common.base.Ascii; 33 import com.google.common.base.Function; 34 import com.google.common.base.Predicate; 35 import com.google.common.base.Predicates; 36 import com.google.common.base.Supplier; 37 import com.google.common.collect.Maps.EntryTransformer; 38 import com.google.common.collect.testing.SampleElements; 39 import com.google.common.collect.testing.SetTestSuiteBuilder; 40 import com.google.common.collect.testing.TestCollectionGenerator; 41 import com.google.common.collect.testing.TestListGenerator; 42 import com.google.common.collect.testing.TestStringSetGenerator; 43 import com.google.common.collect.testing.features.CollectionFeature; 44 import com.google.common.collect.testing.features.CollectionSize; 45 import com.google.common.collect.testing.features.Feature; 46 import com.google.common.collect.testing.features.MapFeature; 47 import com.google.common.collect.testing.google.ListMultimapTestSuiteBuilder; 48 import com.google.common.collect.testing.google.MultimapFeature; 49 import com.google.common.collect.testing.google.MultimapTestSuiteBuilder; 50 import com.google.common.collect.testing.google.MultisetTestSuiteBuilder; 51 import com.google.common.collect.testing.google.SetMultimapTestSuiteBuilder; 52 import com.google.common.collect.testing.google.TestListMultimapGenerator; 53 import com.google.common.collect.testing.google.TestMultimapGenerator; 54 import com.google.common.collect.testing.google.TestSetMultimapGenerator; 55 import com.google.common.collect.testing.google.TestStringListMultimapGenerator; 56 import com.google.common.collect.testing.google.TestStringMultisetGenerator; 57 import java.lang.reflect.InvocationHandler; 58 import java.lang.reflect.Method; 59 import java.util.Collection; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.Map.Entry; 63 import java.util.Set; 64 import java.util.TreeSet; 65 import junit.framework.Test; 66 import junit.framework.TestCase; 67 import junit.framework.TestSuite; 68 69 /** 70 * Run collection tests on wrappers from {@link Multimaps}. 71 * 72 * @author Jared Levy 73 */ 74 @GwtIncompatible // suite // TODO(cpovirk): set up collect/gwt/suites version 75 public class MultimapsCollectionTest extends TestCase { 76 77 private static final Feature<?>[] FOR_MAP_FEATURES_ONE = { 78 CollectionSize.ONE, 79 ALLOWS_NULL_VALUES, 80 SUPPORTS_REMOVE, 81 CollectionFeature.SUPPORTS_ITERATOR_REMOVE 82 }; 83 84 private static final Feature<?>[] FOR_MAP_FEATURES_ANY = { 85 CollectionSize.ANY, 86 ALLOWS_NULL_VALUES, 87 SUPPORTS_REMOVE, 88 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 89 MultisetTestSuiteBuilder.NoRecurse.NO_ENTRY_SET, // Cannot create entries with count > 1 90 }; 91 92 static final Supplier<TreeSet<String>> STRING_TREESET_FACTORY = 93 new Supplier<TreeSet<String>>() { 94 @Override 95 public TreeSet<String> get() { 96 return new TreeSet<>(Ordering.natural().nullsLast()); 97 } 98 }; 99 populateMultimapForGet(Multimap<Integer, String> multimap, String[] elements)100 static void populateMultimapForGet(Multimap<Integer, String> multimap, String[] elements) { 101 multimap.put(2, "foo"); 102 for (String element : elements) { 103 multimap.put(3, element); 104 } 105 } 106 populateMultimapForKeySet(Multimap<String, Integer> multimap, String[] elements)107 static void populateMultimapForKeySet(Multimap<String, Integer> multimap, String[] elements) { 108 for (String element : elements) { 109 multimap.put(element, 2); 110 multimap.put(element, 3); 111 } 112 } 113 populateMultimapForValues(Multimap<Integer, String> multimap, String[] elements)114 static void populateMultimapForValues(Multimap<Integer, String> multimap, String[] elements) { 115 for (int i = 0; i < elements.length; i++) { 116 multimap.put(i % 2, elements[i]); 117 } 118 } 119 populateMultimapForKeys(Multimap<String, Integer> multimap, String[] elements)120 static void populateMultimapForKeys(Multimap<String, Integer> multimap, String[] elements) { 121 for (int i = 0; i < elements.length; i++) { 122 multimap.put(elements[i], i); 123 } 124 } 125 126 /** 127 * Implements {@code Multimap.put()} -- and no other methods -- for a {@code Map} by ignoring all 128 * but the latest value for each key. This class exists only so that we can use {@link 129 * MultimapsCollectionTest#populateMultimapForGet(Multimap, String[])} and similar methods to 130 * populate a map to be passed to {@link Multimaps#forMap(Map)}. All tests should run against the 131 * result of {@link #build()}. 132 */ 133 private static final class PopulatableMapAsMultimap<K, V> extends ForwardingMultimap<K, V> { 134 final Map<K, V> map; 135 final SetMultimap<K, V> unusableDelegate; 136 create()137 static <K, V> PopulatableMapAsMultimap<K, V> create() { 138 return new PopulatableMapAsMultimap<>(); 139 } 140 141 @SuppressWarnings("unchecked") // all methods throw immediately PopulatableMapAsMultimap()142 PopulatableMapAsMultimap() { 143 this.map = newHashMap(); 144 this.unusableDelegate = 145 (SetMultimap<K, V>) 146 newProxyInstance( 147 SetMultimap.class.getClassLoader(), 148 new Class<?>[] {SetMultimap.class}, 149 new InvocationHandler() { 150 @Override 151 public Object invoke(Object proxy, Method method, Object[] args) 152 throws Throwable { 153 throw new UnsupportedOperationException(); 154 } 155 }); 156 } 157 158 @Override delegate()159 protected Multimap<K, V> delegate() { 160 return unusableDelegate; 161 } 162 163 @Override put(K key, V value)164 public boolean put(K key, V value) { 165 map.put(key, value); 166 return true; 167 } 168 build()169 SetMultimap<K, V> build() { 170 return Multimaps.forMap(map); 171 } 172 } 173 174 abstract static class TestEntriesGenerator 175 implements TestCollectionGenerator<Entry<String, Integer>> { 176 @Override samples()177 public SampleElements<Entry<String, Integer>> samples() { 178 return new SampleElements<>( 179 Maps.immutableEntry("bar", 1), 180 Maps.immutableEntry("bar", 2), 181 Maps.immutableEntry("foo", 3), 182 Maps.immutableEntry("bar", 3), 183 Maps.immutableEntry("cat", 2)); 184 } 185 186 @Override create(Object... elements)187 public Collection<Entry<String, Integer>> create(Object... elements) { 188 Multimap<String, Integer> multimap = createMultimap(); 189 for (Object element : elements) { 190 @SuppressWarnings("unchecked") 191 Entry<String, Integer> entry = (Entry<String, Integer>) element; 192 multimap.put(entry.getKey(), entry.getValue()); 193 } 194 return multimap.entries(); 195 } 196 createMultimap()197 abstract Multimap<String, Integer> createMultimap(); 198 199 @Override 200 @SuppressWarnings("unchecked") createArray(int length)201 public Entry<String, Integer>[] createArray(int length) { 202 return (Entry<String, Integer>[]) new Entry<?, ?>[length]; 203 } 204 205 @Override order(List<Entry<String, Integer>> insertionOrder)206 public List<Entry<String, Integer>> order(List<Entry<String, Integer>> insertionOrder) { 207 return insertionOrder; 208 } 209 } 210 211 public abstract static class TestEntriesListGenerator extends TestEntriesGenerator 212 implements TestListGenerator<Entry<String, Integer>> { 213 @Override create(Object... elements)214 public List<Entry<String, Integer>> create(Object... elements) { 215 return (List<Entry<String, Integer>>) super.create(elements); 216 } 217 } 218 219 private static final Predicate<Entry<Integer, String>> FILTER_GET_PREDICATE = 220 new Predicate<Entry<Integer, String>>() { 221 @Override 222 public boolean apply(Entry<Integer, String> entry) { 223 return !"badvalue".equals(entry.getValue()) && 55556 != entry.getKey(); 224 } 225 }; 226 227 private static final Predicate<Entry<String, Integer>> FILTER_KEYSET_PREDICATE = 228 new Predicate<Entry<String, Integer>>() { 229 @Override 230 public boolean apply(Entry<String, Integer> entry) { 231 return !"badkey".equals(entry.getKey()) && 55556 != entry.getValue(); 232 } 233 }; 234 suite()235 public static Test suite() { 236 TestSuite suite = new TestSuite(); 237 238 suite.addTest(transformSuite()); 239 suite.addTest(filterSuite()); 240 241 suite.addTest( 242 ListMultimapTestSuiteBuilder.using( 243 new TestStringListMultimapGenerator() { 244 @Override 245 protected ListMultimap<String, String> create(Entry<String, String>[] entries) { 246 ListMultimap<String, String> multimap = 247 Multimaps.synchronizedListMultimap( 248 ArrayListMultimap.<String, String>create()); 249 for (Entry<String, String> entry : entries) { 250 multimap.put(entry.getKey(), entry.getValue()); 251 } 252 return multimap; 253 } 254 }) 255 .named("synchronized ArrayListMultimap") 256 .withFeatures( 257 MapFeature.ALLOWS_NULL_KEYS, 258 MapFeature.ALLOWS_NULL_VALUES, 259 MapFeature.ALLOWS_ANY_NULL_QUERIES, 260 MapFeature.GENERAL_PURPOSE, 261 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 262 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 263 CollectionSize.ANY) 264 .createTestSuite()); 265 266 suite.addTest( 267 SetTestSuiteBuilder.using( 268 new TestStringSetGenerator() { 269 @Override 270 protected Set<String> create(String[] elements) { 271 PopulatableMapAsMultimap<Integer, String> multimap = 272 PopulatableMapAsMultimap.create(); 273 populateMultimapForGet(multimap, elements); 274 return multimap.build().get(3); 275 } 276 }) 277 .named("Multimaps.forMap.get") 278 .withFeatures(FOR_MAP_FEATURES_ONE) 279 .createTestSuite()); 280 281 suite.addTest( 282 SetTestSuiteBuilder.using( 283 new TestStringSetGenerator() { 284 @Override 285 protected Set<String> create(String[] elements) { 286 PopulatableMapAsMultimap<String, Integer> multimap = 287 PopulatableMapAsMultimap.create(); 288 populateMultimapForKeySet(multimap, elements); 289 return multimap.build().keySet(); 290 } 291 }) 292 .named("Multimaps.forMap.keySet") 293 .withFeatures(FOR_MAP_FEATURES_ANY) 294 .createTestSuite()); 295 296 // TODO: use collection testers on Multimaps.forMap.values 297 298 suite.addTest( 299 MultisetTestSuiteBuilder.using( 300 new TestStringMultisetGenerator() { 301 @Override 302 protected Multiset<String> create(String[] elements) { 303 PopulatableMapAsMultimap<String, Integer> multimap = 304 PopulatableMapAsMultimap.create(); 305 populateMultimapForKeys(multimap, elements); 306 return multimap.build().keys(); 307 } 308 }) 309 .named("Multimaps.forMap.keys") 310 .withFeatures(FOR_MAP_FEATURES_ANY) 311 .suppressing(getCountDuplicateInitializingMethods()) 312 .suppressing(getSetCountDuplicateInitializingMethods()) 313 .suppressing(getIteratorDuplicateInitializingMethods()) 314 .suppressing(getRemoveDuplicateInitializingMethods()) 315 .suppressing(getForEachEntryDuplicateInitializingMethods()) 316 .suppressing(getElementSetDuplicateInitializingMethods()) 317 .createTestSuite()); 318 319 // TODO: use collection testers on Multimaps.forMap.entries 320 321 return suite; 322 } 323 324 abstract static class TransformedMultimapGenerator<M extends Multimap<String, String>> 325 implements TestMultimapGenerator<String, String, M> { 326 327 @Override createKeyArray(int length)328 public String[] createKeyArray(int length) { 329 return new String[length]; 330 } 331 332 @Override createValueArray(int length)333 public String[] createValueArray(int length) { 334 return new String[length]; 335 } 336 337 @Override sampleKeys()338 public SampleElements<String> sampleKeys() { 339 return new SampleElements<>("one", "two", "three", "four", "five"); 340 } 341 342 @Override sampleValues()343 public SampleElements<String> sampleValues() { 344 return new SampleElements<>("january", "february", "march", "april", "may"); 345 } 346 347 @Override createCollection(Iterable<? extends String> values)348 public Collection<String> createCollection(Iterable<? extends String> values) { 349 return Lists.newArrayList(values); 350 } 351 352 @Override samples()353 public SampleElements<Entry<String, String>> samples() { 354 return new SampleElements<>( 355 mapEntry("one", "january"), 356 mapEntry("two", "february"), 357 mapEntry("three", "march"), 358 mapEntry("four", "april"), 359 mapEntry("five", "may")); 360 } 361 362 @Override create(Object... elements)363 public M create(Object... elements) { 364 Multimap<String, String> multimap = ArrayListMultimap.create(); 365 for (Object o : elements) { 366 @SuppressWarnings("unchecked") 367 Entry<String, String> entry = (Entry<String, String>) o; 368 multimap.put(entry.getKey(), Ascii.toUpperCase(entry.getValue())); 369 } 370 return transform(multimap); 371 } 372 transform(Multimap<String, String> multimap)373 abstract M transform(Multimap<String, String> multimap); 374 375 @SuppressWarnings("unchecked") 376 @Override createArray(int length)377 public Entry<String, String>[] createArray(int length) { 378 return new Entry[length]; 379 } 380 381 @Override order(List<Entry<String, String>> insertionOrder)382 public Iterable<Entry<String, String>> order(List<Entry<String, String>> insertionOrder) { 383 return insertionOrder; 384 } 385 386 static final Function<String, String> FUNCTION = 387 new Function<String, String>() { 388 @Override 389 public String apply(String value) { 390 return Ascii.toLowerCase(value); 391 } 392 }; 393 394 static final EntryTransformer<String, String, String> ENTRY_TRANSFORMER = 395 new EntryTransformer<String, String, String>() { 396 @Override 397 public String transformEntry(String key, String value) { 398 return Ascii.toLowerCase(value); 399 } 400 }; 401 } 402 403 abstract static class TransformedListMultimapGenerator 404 extends TransformedMultimapGenerator<ListMultimap<String, String>> 405 implements TestListMultimapGenerator<String, String> {} 406 transformSuite()407 private static Test transformSuite() { 408 TestSuite suite = new TestSuite("Multimaps.transform*"); 409 suite.addTest( 410 MultimapTestSuiteBuilder.using( 411 new TransformedMultimapGenerator<Multimap<String, String>>() { 412 @Override 413 Multimap<String, String> transform(Multimap<String, String> multimap) { 414 return Multimaps.transformValues(multimap, FUNCTION); 415 } 416 }) 417 .named("Multimaps.transformValues[Multimap]") 418 .withFeatures( 419 CollectionSize.ANY, 420 MapFeature.SUPPORTS_REMOVE, 421 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 422 MapFeature.ALLOWS_NULL_KEYS, 423 MapFeature.ALLOWS_ANY_NULL_QUERIES) 424 .createTestSuite()); 425 suite.addTest( 426 MultimapTestSuiteBuilder.using( 427 new TransformedMultimapGenerator<Multimap<String, String>>() { 428 @Override 429 Multimap<String, String> transform(Multimap<String, String> multimap) { 430 return Multimaps.transformEntries(multimap, ENTRY_TRANSFORMER); 431 } 432 }) 433 .named("Multimaps.transformEntries[Multimap]") 434 .withFeatures( 435 CollectionSize.ANY, 436 MapFeature.SUPPORTS_REMOVE, 437 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 438 MapFeature.ALLOWS_NULL_KEYS, 439 MapFeature.ALLOWS_ANY_NULL_QUERIES) 440 .createTestSuite()); 441 suite.addTest( 442 ListMultimapTestSuiteBuilder.using( 443 new TransformedListMultimapGenerator() { 444 @Override 445 ListMultimap<String, String> transform(Multimap<String, String> multimap) { 446 return Multimaps.transformValues( 447 (ListMultimap<String, String>) multimap, FUNCTION); 448 } 449 }) 450 .named("Multimaps.transformValues[ListMultimap]") 451 .withFeatures( 452 CollectionSize.ANY, 453 MapFeature.SUPPORTS_REMOVE, 454 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 455 MapFeature.ALLOWS_NULL_KEYS, 456 MapFeature.ALLOWS_ANY_NULL_QUERIES) 457 .createTestSuite()); 458 suite.addTest( 459 ListMultimapTestSuiteBuilder.using( 460 new TransformedListMultimapGenerator() { 461 @Override 462 ListMultimap<String, String> transform(Multimap<String, String> multimap) { 463 return Multimaps.transformEntries( 464 (ListMultimap<String, String>) multimap, ENTRY_TRANSFORMER); 465 } 466 }) 467 .named("Multimaps.transformEntries[ListMultimap]") 468 .withFeatures( 469 CollectionSize.ANY, 470 MapFeature.SUPPORTS_REMOVE, 471 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 472 MapFeature.ALLOWS_NULL_KEYS, 473 MapFeature.ALLOWS_ANY_NULL_QUERIES) 474 .createTestSuite()); 475 476 // TODO: use collection testers on Multimaps.forMap.entries 477 478 return suite; 479 } 480 481 abstract static class TestFilteredMultimapGenerator<M extends Multimap<String, Integer>> 482 implements TestMultimapGenerator<String, Integer, M> { 483 484 @Override samples()485 public SampleElements<Entry<String, Integer>> samples() { 486 return new SampleElements<>( 487 mapEntry("one", 114), 488 mapEntry("two", 37), 489 mapEntry("three", 42), 490 mapEntry("four", 19), 491 mapEntry("five", 82)); 492 } 493 494 @SuppressWarnings("unchecked") 495 @Override createArray(int length)496 public Entry<String, Integer>[] createArray(int length) { 497 return new Entry[length]; 498 } 499 500 @Override order(List<Entry<String, Integer>> insertionOrder)501 public Iterable<Entry<String, Integer>> order(List<Entry<String, Integer>> insertionOrder) { 502 return insertionOrder; 503 } 504 505 @Override createKeyArray(int length)506 public String[] createKeyArray(int length) { 507 return new String[length]; 508 } 509 510 @Override createValueArray(int length)511 public Integer[] createValueArray(int length) { 512 return new Integer[length]; 513 } 514 515 @Override sampleKeys()516 public SampleElements<String> sampleKeys() { 517 return new SampleElements<>("one", "two", "three", "four", "five"); 518 } 519 520 @Override sampleValues()521 public SampleElements<Integer> sampleValues() { 522 return new SampleElements<>(114, 37, 42, 19, 82); 523 } 524 } 525 526 abstract static class FilteredSetMultimapGenerator 527 extends TestFilteredMultimapGenerator<SetMultimap<String, Integer>> 528 implements TestSetMultimapGenerator<String, Integer> { 529 filter(SetMultimap<String, Integer> multimap)530 abstract SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap); 531 532 @Override create(Object... elements)533 public SetMultimap<String, Integer> create(Object... elements) { 534 SetMultimap<String, Integer> multimap = LinkedHashMultimap.create(); 535 for (Object o : elements) { 536 @SuppressWarnings("unchecked") 537 Entry<String, Integer> entry = (Entry<String, Integer>) o; 538 multimap.put(entry.getKey(), entry.getValue()); 539 } 540 return filter(multimap); 541 } 542 543 @Override createCollection(Iterable<? extends Integer> values)544 public Collection<Integer> createCollection(Iterable<? extends Integer> values) { 545 return Sets.newLinkedHashSet(values); 546 } 547 } 548 549 abstract static class FilteredListMultimapGenerator 550 extends TestFilteredMultimapGenerator<ListMultimap<String, Integer>> 551 implements TestListMultimapGenerator<String, Integer> { 552 553 @Override create(Object... elements)554 public ListMultimap<String, Integer> create(Object... elements) { 555 ListMultimap<String, Integer> multimap = LinkedListMultimap.create(); 556 for (Object o : elements) { 557 @SuppressWarnings("unchecked") 558 Entry<String, Integer> entry = (Entry<String, Integer>) o; 559 multimap.put(entry.getKey(), entry.getValue()); 560 } 561 return filter(multimap); 562 } 563 filter(ListMultimap<String, Integer> multimap)564 abstract ListMultimap<String, Integer> filter(ListMultimap<String, Integer> multimap); 565 566 @Override createCollection(Iterable<? extends Integer> values)567 public Collection<Integer> createCollection(Iterable<? extends Integer> values) { 568 return Lists.newArrayList(values); 569 } 570 } 571 filterSuite()572 private static Test filterSuite() { 573 TestSuite suite = new TestSuite("Multimaps.filter*"); 574 suite.addTest( 575 SetMultimapTestSuiteBuilder.using( 576 new FilteredSetMultimapGenerator() { 577 @Override 578 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 579 multimap.put("foo", 17); 580 multimap.put("bar", 32); 581 multimap.put("foo", 16); 582 return Multimaps.filterKeys( 583 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 584 } 585 }) 586 .named("Multimaps.filterKeys[SetMultimap, Predicate]") 587 .withFeatures( 588 CollectionSize.ANY, 589 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 590 MapFeature.GENERAL_PURPOSE, 591 MapFeature.ALLOWS_NULL_KEYS, 592 MapFeature.ALLOWS_NULL_VALUES, 593 MapFeature.ALLOWS_ANY_NULL_QUERIES) 594 .createTestSuite()); 595 596 suite.addTest( 597 ListMultimapTestSuiteBuilder.using( 598 new FilteredListMultimapGenerator() { 599 @Override 600 ListMultimap<String, Integer> filter(ListMultimap<String, Integer> multimap) { 601 multimap.put("foo", 17); 602 multimap.put("bar", 32); 603 multimap.put("foo", 16); 604 return Multimaps.filterKeys( 605 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 606 } 607 }) 608 .named("Multimaps.filterKeys[ListMultimap, Predicate]") 609 .withFeatures( 610 CollectionSize.ANY, 611 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 612 MapFeature.GENERAL_PURPOSE, 613 MapFeature.ALLOWS_NULL_KEYS, 614 MapFeature.ALLOWS_NULL_VALUES, 615 MapFeature.ALLOWS_ANY_NULL_QUERIES) 616 .createTestSuite()); 617 suite.addTest( 618 ListMultimapTestSuiteBuilder.using( 619 new FilteredListMultimapGenerator() { 620 @Override 621 ListMultimap<String, Integer> filter(ListMultimap<String, Integer> multimap) { 622 multimap.put("foo", 17); 623 multimap.put("bar", 32); 624 multimap.put("foo", 16); 625 multimap = 626 Multimaps.filterKeys(multimap, Predicates.not(Predicates.equalTo("foo"))); 627 return Multimaps.filterKeys( 628 multimap, Predicates.not(Predicates.equalTo("bar"))); 629 } 630 }) 631 .named("Multimaps.filterKeys[Multimaps.filterKeys[ListMultimap], Predicate]") 632 .withFeatures( 633 CollectionSize.ANY, 634 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 635 MapFeature.GENERAL_PURPOSE, 636 MapFeature.ALLOWS_NULL_KEYS, 637 MapFeature.ALLOWS_NULL_VALUES, 638 MapFeature.ALLOWS_ANY_NULL_QUERIES) 639 .createTestSuite()); 640 suite.addTest( 641 SetMultimapTestSuiteBuilder.using( 642 new FilteredSetMultimapGenerator() { 643 @Override 644 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 645 multimap.put("one", 314); 646 multimap.put("two", 159); 647 multimap.put("one", 265); 648 return Multimaps.filterValues( 649 multimap, Predicates.not(Predicates.in(ImmutableSet.of(314, 159, 265)))); 650 } 651 }) 652 .named("Multimaps.filterValues[SetMultimap, Predicate]") 653 .withFeatures( 654 CollectionSize.ANY, 655 MapFeature.GENERAL_PURPOSE, 656 MapFeature.ALLOWS_NULL_KEYS, 657 MapFeature.ALLOWS_NULL_VALUES, 658 MapFeature.ALLOWS_ANY_NULL_QUERIES) 659 .createTestSuite()); 660 suite.addTest( 661 SetMultimapTestSuiteBuilder.using( 662 new FilteredSetMultimapGenerator() { 663 @Override 664 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 665 ImmutableSetMultimap<String, Integer> badEntries = 666 ImmutableSetMultimap.of("foo", 314, "one", 159, "two", 265, "bar", 358); 667 multimap.putAll(badEntries); 668 return Multimaps.filterEntries( 669 multimap, Predicates.not(Predicates.in(badEntries.entries()))); 670 } 671 }) 672 .named("Multimaps.filterEntries[SetMultimap, Predicate]") 673 .withFeatures( 674 CollectionSize.ANY, 675 MapFeature.GENERAL_PURPOSE, 676 MapFeature.ALLOWS_NULL_KEYS, 677 MapFeature.ALLOWS_NULL_VALUES, 678 MapFeature.ALLOWS_ANY_NULL_QUERIES) 679 .createTestSuite()); 680 suite.addTest( 681 SetMultimapTestSuiteBuilder.using( 682 new FilteredSetMultimapGenerator() { 683 @Override 684 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 685 ImmutableSetMultimap<String, Integer> badEntries = 686 ImmutableSetMultimap.of("foo", 314, "one", 159, "two", 265, "bar", 358); 687 multimap.putAll(badEntries); 688 multimap = 689 Multimaps.filterKeys( 690 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 691 return Multimaps.filterEntries( 692 multimap, Predicates.not(Predicates.in(badEntries.entries()))); 693 } 694 }) 695 .named("Multimaps.filterEntries[Multimaps.filterKeys[SetMultimap]]") 696 .withFeatures( 697 CollectionSize.ANY, 698 MapFeature.GENERAL_PURPOSE, 699 MapFeature.ALLOWS_NULL_KEYS, 700 MapFeature.ALLOWS_NULL_VALUES, 701 MapFeature.ALLOWS_ANY_NULL_QUERIES) 702 .createTestSuite()); 703 suite.addTest( 704 SetMultimapTestSuiteBuilder.using( 705 new FilteredSetMultimapGenerator() { 706 @Override 707 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 708 ImmutableSetMultimap<String, Integer> badEntries = 709 ImmutableSetMultimap.of("foo", 314, "one", 159, "two", 265, "bar", 358); 710 multimap.putAll(badEntries); 711 multimap = 712 Multimaps.filterEntries( 713 multimap, 714 Predicates.not( 715 Predicates.in(ImmutableMap.of("one", 159, "two", 265).entrySet()))); 716 return Multimaps.filterKeys( 717 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 718 } 719 }) 720 .named("Multimaps.filterKeys[Multimaps.filterEntries[SetMultimap]]") 721 .withFeatures( 722 CollectionSize.ANY, 723 MapFeature.GENERAL_PURPOSE, 724 MapFeature.ALLOWS_NULL_KEYS, 725 MapFeature.ALLOWS_NULL_VALUES, 726 MapFeature.ALLOWS_ANY_NULL_QUERIES) 727 .createTestSuite()); 728 suite.addTest( 729 SetMultimapTestSuiteBuilder.using( 730 new FilteredSetMultimapGenerator() { 731 @Override 732 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 733 ImmutableSetMultimap<String, Integer> badEntries = 734 ImmutableSetMultimap.of("foo", 314, "bar", 358); 735 multimap.putAll(badEntries); 736 multimap = 737 Multimaps.filterKeys(multimap, Predicates.not(Predicates.equalTo("foo"))); 738 multimap = 739 Multimaps.filterKeys(multimap, Predicates.not(Predicates.equalTo("bar"))); 740 return multimap; 741 } 742 }) 743 .named("Multimaps.filterKeys[Multimaps.filterKeys[SetMultimap]]") 744 .withFeatures( 745 CollectionSize.ANY, 746 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 747 MapFeature.GENERAL_PURPOSE, 748 MapFeature.ALLOWS_NULL_KEYS, 749 MapFeature.ALLOWS_NULL_VALUES, 750 MapFeature.ALLOWS_ANY_NULL_QUERIES) 751 .createTestSuite()); 752 return suite; 753 } 754 } 755