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