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.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 suite()218 public static Test suite() { 219 TestSuite suite = new TestSuite(); 220 221 suite.addTest(transformSuite()); 222 suite.addTest(filterSuite()); 223 224 suite.addTest( 225 ListMultimapTestSuiteBuilder.using( 226 new TestStringListMultimapGenerator() { 227 @Override 228 protected ListMultimap<String, String> create(Entry<String, String>[] entries) { 229 ListMultimap<String, String> multimap = 230 Multimaps.synchronizedListMultimap( 231 ArrayListMultimap.<String, String>create()); 232 for (Entry<String, String> entry : entries) { 233 multimap.put(entry.getKey(), entry.getValue()); 234 } 235 return multimap; 236 } 237 }) 238 .named("synchronized ArrayListMultimap") 239 .withFeatures( 240 MapFeature.ALLOWS_NULL_KEYS, 241 MapFeature.ALLOWS_NULL_VALUES, 242 MapFeature.ALLOWS_ANY_NULL_QUERIES, 243 MapFeature.GENERAL_PURPOSE, 244 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 245 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 246 CollectionSize.ANY) 247 .createTestSuite()); 248 249 suite.addTest( 250 SetTestSuiteBuilder.using( 251 new TestStringSetGenerator() { 252 @Override 253 protected Set<String> create(String[] elements) { 254 PopulatableMapAsMultimap<Integer, String> multimap = 255 PopulatableMapAsMultimap.create(); 256 populateMultimapForGet(multimap, elements); 257 return multimap.build().get(3); 258 } 259 }) 260 .named("Multimaps.forMap.get") 261 .withFeatures(FOR_MAP_FEATURES_ONE) 262 .createTestSuite()); 263 264 suite.addTest( 265 SetTestSuiteBuilder.using( 266 new TestStringSetGenerator() { 267 @Override 268 protected Set<String> create(String[] elements) { 269 PopulatableMapAsMultimap<String, Integer> multimap = 270 PopulatableMapAsMultimap.create(); 271 populateMultimapForKeySet(multimap, elements); 272 return multimap.build().keySet(); 273 } 274 }) 275 .named("Multimaps.forMap.keySet") 276 .withFeatures(FOR_MAP_FEATURES_ANY) 277 .createTestSuite()); 278 279 // TODO: use collection testers on Multimaps.forMap.values 280 281 suite.addTest( 282 MultisetTestSuiteBuilder.using( 283 new TestStringMultisetGenerator() { 284 @Override 285 protected Multiset<String> create(String[] elements) { 286 PopulatableMapAsMultimap<String, Integer> multimap = 287 PopulatableMapAsMultimap.create(); 288 populateMultimapForKeys(multimap, elements); 289 return multimap.build().keys(); 290 } 291 }) 292 .named("Multimaps.forMap.keys") 293 .withFeatures(FOR_MAP_FEATURES_ANY) 294 .suppressing(getCountDuplicateInitializingMethods()) 295 .suppressing(getSetCountDuplicateInitializingMethods()) 296 .suppressing(getIteratorDuplicateInitializingMethods()) 297 .suppressing(getRemoveDuplicateInitializingMethods()) 298 .suppressing(getForEachEntryDuplicateInitializingMethods()) 299 .suppressing(getElementSetDuplicateInitializingMethods()) 300 .createTestSuite()); 301 302 // TODO: use collection testers on Multimaps.forMap.entries 303 304 return suite; 305 } 306 307 abstract static class TransformedMultimapGenerator<M extends Multimap<String, String>> 308 implements TestMultimapGenerator<String, String, M> { 309 310 @Override createKeyArray(int length)311 public String[] createKeyArray(int length) { 312 return new String[length]; 313 } 314 315 @Override createValueArray(int length)316 public String[] createValueArray(int length) { 317 return new String[length]; 318 } 319 320 @Override sampleKeys()321 public SampleElements<String> sampleKeys() { 322 return new SampleElements<>("one", "two", "three", "four", "five"); 323 } 324 325 @Override sampleValues()326 public SampleElements<String> sampleValues() { 327 return new SampleElements<>("january", "february", "march", "april", "may"); 328 } 329 330 @Override createCollection(Iterable<? extends String> values)331 public Collection<String> createCollection(Iterable<? extends String> values) { 332 return Lists.newArrayList(values); 333 } 334 335 @Override samples()336 public SampleElements<Entry<String, String>> samples() { 337 return new SampleElements<>( 338 mapEntry("one", "january"), 339 mapEntry("two", "february"), 340 mapEntry("three", "march"), 341 mapEntry("four", "april"), 342 mapEntry("five", "may")); 343 } 344 345 @Override create(Object... elements)346 public M create(Object... elements) { 347 Multimap<String, String> multimap = ArrayListMultimap.create(); 348 for (Object o : elements) { 349 @SuppressWarnings("unchecked") 350 Entry<String, String> entry = (Entry<String, String>) o; 351 multimap.put(entry.getKey(), Ascii.toUpperCase(entry.getValue())); 352 } 353 return transform(multimap); 354 } 355 transform(Multimap<String, String> multimap)356 abstract M transform(Multimap<String, String> multimap); 357 358 @SuppressWarnings("unchecked") 359 @Override createArray(int length)360 public Entry<String, String>[] createArray(int length) { 361 return (Entry<String, String>[]) new Entry<?, ?>[length]; 362 } 363 364 @Override order(List<Entry<String, String>> insertionOrder)365 public Iterable<Entry<String, String>> order(List<Entry<String, String>> insertionOrder) { 366 return insertionOrder; 367 } 368 369 static final Function<String, String> FUNCTION = 370 new Function<String, String>() { 371 @Override 372 public String apply(String value) { 373 return Ascii.toLowerCase(value); 374 } 375 }; 376 377 static final EntryTransformer<String, String, String> ENTRY_TRANSFORMER = 378 new EntryTransformer<String, String, String>() { 379 @Override 380 public String transformEntry(String key, String value) { 381 return Ascii.toLowerCase(value); 382 } 383 }; 384 } 385 386 abstract static class TransformedListMultimapGenerator 387 extends TransformedMultimapGenerator<ListMultimap<String, String>> 388 implements TestListMultimapGenerator<String, String> {} 389 transformSuite()390 private static Test transformSuite() { 391 TestSuite suite = new TestSuite("Multimaps.transform*"); 392 suite.addTest( 393 MultimapTestSuiteBuilder.using( 394 new TransformedMultimapGenerator<Multimap<String, String>>() { 395 @Override 396 Multimap<String, String> transform(Multimap<String, String> multimap) { 397 return Multimaps.transformValues(multimap, FUNCTION); 398 } 399 }) 400 .named("Multimaps.transformValues[Multimap]") 401 .withFeatures( 402 CollectionSize.ANY, 403 MapFeature.SUPPORTS_REMOVE, 404 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 405 MapFeature.ALLOWS_NULL_KEYS, 406 MapFeature.ALLOWS_ANY_NULL_QUERIES) 407 .createTestSuite()); 408 suite.addTest( 409 MultimapTestSuiteBuilder.using( 410 new TransformedMultimapGenerator<Multimap<String, String>>() { 411 @Override 412 Multimap<String, String> transform(Multimap<String, String> multimap) { 413 return Multimaps.transformEntries(multimap, ENTRY_TRANSFORMER); 414 } 415 }) 416 .named("Multimaps.transformEntries[Multimap]") 417 .withFeatures( 418 CollectionSize.ANY, 419 MapFeature.SUPPORTS_REMOVE, 420 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 421 MapFeature.ALLOWS_NULL_KEYS, 422 MapFeature.ALLOWS_ANY_NULL_QUERIES) 423 .createTestSuite()); 424 suite.addTest( 425 ListMultimapTestSuiteBuilder.using( 426 new TransformedListMultimapGenerator() { 427 @Override 428 ListMultimap<String, String> transform(Multimap<String, String> multimap) { 429 return Multimaps.transformValues( 430 (ListMultimap<String, String>) multimap, FUNCTION); 431 } 432 }) 433 .named("Multimaps.transformValues[ListMultimap]") 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.transformEntries( 447 (ListMultimap<String, String>) multimap, ENTRY_TRANSFORMER); 448 } 449 }) 450 .named("Multimaps.transformEntries[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 459 // TODO: use collection testers on Multimaps.forMap.entries 460 461 return suite; 462 } 463 464 abstract static class TestFilteredMultimapGenerator<M extends Multimap<String, Integer>> 465 implements TestMultimapGenerator<String, Integer, M> { 466 467 @Override samples()468 public SampleElements<Entry<String, Integer>> samples() { 469 return new SampleElements<>( 470 mapEntry("one", 114), 471 mapEntry("two", 37), 472 mapEntry("three", 42), 473 mapEntry("four", 19), 474 mapEntry("five", 82)); 475 } 476 477 @SuppressWarnings("unchecked") 478 @Override createArray(int length)479 public Entry<String, Integer>[] createArray(int length) { 480 return (Entry<String, Integer>[]) new Entry<?, ?>[length]; 481 } 482 483 @Override order(List<Entry<String, Integer>> insertionOrder)484 public Iterable<Entry<String, Integer>> order(List<Entry<String, Integer>> insertionOrder) { 485 return insertionOrder; 486 } 487 488 @Override createKeyArray(int length)489 public String[] createKeyArray(int length) { 490 return new String[length]; 491 } 492 493 @Override createValueArray(int length)494 public Integer[] createValueArray(int length) { 495 return new Integer[length]; 496 } 497 498 @Override sampleKeys()499 public SampleElements<String> sampleKeys() { 500 return new SampleElements<>("one", "two", "three", "four", "five"); 501 } 502 503 @Override sampleValues()504 public SampleElements<Integer> sampleValues() { 505 return new SampleElements<>(114, 37, 42, 19, 82); 506 } 507 } 508 509 abstract static class FilteredSetMultimapGenerator 510 extends TestFilteredMultimapGenerator<SetMultimap<String, Integer>> 511 implements TestSetMultimapGenerator<String, Integer> { 512 filter(SetMultimap<String, Integer> multimap)513 abstract SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap); 514 515 @Override create(Object... elements)516 public SetMultimap<String, Integer> create(Object... elements) { 517 SetMultimap<String, Integer> multimap = LinkedHashMultimap.create(); 518 for (Object o : elements) { 519 @SuppressWarnings("unchecked") 520 Entry<String, Integer> entry = (Entry<String, Integer>) o; 521 multimap.put(entry.getKey(), entry.getValue()); 522 } 523 return filter(multimap); 524 } 525 526 @Override createCollection(Iterable<? extends Integer> values)527 public Collection<Integer> createCollection(Iterable<? extends Integer> values) { 528 return Sets.newLinkedHashSet(values); 529 } 530 } 531 532 abstract static class FilteredListMultimapGenerator 533 extends TestFilteredMultimapGenerator<ListMultimap<String, Integer>> 534 implements TestListMultimapGenerator<String, Integer> { 535 536 @Override create(Object... elements)537 public ListMultimap<String, Integer> create(Object... elements) { 538 ListMultimap<String, Integer> multimap = LinkedListMultimap.create(); 539 for (Object o : elements) { 540 @SuppressWarnings("unchecked") 541 Entry<String, Integer> entry = (Entry<String, Integer>) o; 542 multimap.put(entry.getKey(), entry.getValue()); 543 } 544 return filter(multimap); 545 } 546 filter(ListMultimap<String, Integer> multimap)547 abstract ListMultimap<String, Integer> filter(ListMultimap<String, Integer> multimap); 548 549 @Override createCollection(Iterable<? extends Integer> values)550 public Collection<Integer> createCollection(Iterable<? extends Integer> values) { 551 return Lists.newArrayList(values); 552 } 553 } 554 filterSuite()555 private static Test filterSuite() { 556 TestSuite suite = new TestSuite("Multimaps.filter*"); 557 suite.addTest( 558 SetMultimapTestSuiteBuilder.using( 559 new FilteredSetMultimapGenerator() { 560 @Override 561 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 562 multimap.put("foo", 17); 563 multimap.put("bar", 32); 564 multimap.put("foo", 16); 565 return Multimaps.filterKeys( 566 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 567 } 568 }) 569 .named("Multimaps.filterKeys[SetMultimap, Predicate]") 570 .withFeatures( 571 CollectionSize.ANY, 572 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 573 MapFeature.GENERAL_PURPOSE, 574 MapFeature.ALLOWS_NULL_KEYS, 575 MapFeature.ALLOWS_NULL_VALUES, 576 MapFeature.ALLOWS_ANY_NULL_QUERIES) 577 .createTestSuite()); 578 579 suite.addTest( 580 ListMultimapTestSuiteBuilder.using( 581 new FilteredListMultimapGenerator() { 582 @Override 583 ListMultimap<String, Integer> filter(ListMultimap<String, Integer> multimap) { 584 multimap.put("foo", 17); 585 multimap.put("bar", 32); 586 multimap.put("foo", 16); 587 return Multimaps.filterKeys( 588 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 589 } 590 }) 591 .named("Multimaps.filterKeys[ListMultimap, Predicate]") 592 .withFeatures( 593 CollectionSize.ANY, 594 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 595 MapFeature.GENERAL_PURPOSE, 596 MapFeature.ALLOWS_NULL_KEYS, 597 MapFeature.ALLOWS_NULL_VALUES, 598 MapFeature.ALLOWS_ANY_NULL_QUERIES) 599 .createTestSuite()); 600 suite.addTest( 601 ListMultimapTestSuiteBuilder.using( 602 new FilteredListMultimapGenerator() { 603 @Override 604 ListMultimap<String, Integer> filter(ListMultimap<String, Integer> multimap) { 605 multimap.put("foo", 17); 606 multimap.put("bar", 32); 607 multimap.put("foo", 16); 608 multimap = 609 Multimaps.filterKeys(multimap, Predicates.not(Predicates.equalTo("foo"))); 610 return Multimaps.filterKeys( 611 multimap, Predicates.not(Predicates.equalTo("bar"))); 612 } 613 }) 614 .named("Multimaps.filterKeys[Multimaps.filterKeys[ListMultimap], Predicate]") 615 .withFeatures( 616 CollectionSize.ANY, 617 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 618 MapFeature.GENERAL_PURPOSE, 619 MapFeature.ALLOWS_NULL_KEYS, 620 MapFeature.ALLOWS_NULL_VALUES, 621 MapFeature.ALLOWS_ANY_NULL_QUERIES) 622 .createTestSuite()); 623 suite.addTest( 624 SetMultimapTestSuiteBuilder.using( 625 new FilteredSetMultimapGenerator() { 626 @Override 627 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 628 multimap.put("one", 314); 629 multimap.put("two", 159); 630 multimap.put("one", 265); 631 return Multimaps.filterValues( 632 multimap, Predicates.not(Predicates.in(ImmutableSet.of(314, 159, 265)))); 633 } 634 }) 635 .named("Multimaps.filterValues[SetMultimap, Predicate]") 636 .withFeatures( 637 CollectionSize.ANY, 638 MapFeature.GENERAL_PURPOSE, 639 MapFeature.ALLOWS_NULL_KEYS, 640 MapFeature.ALLOWS_NULL_VALUES, 641 MapFeature.ALLOWS_ANY_NULL_QUERIES) 642 .createTestSuite()); 643 suite.addTest( 644 SetMultimapTestSuiteBuilder.using( 645 new FilteredSetMultimapGenerator() { 646 @Override 647 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 648 ImmutableSetMultimap<String, Integer> badEntries = 649 ImmutableSetMultimap.of("foo", 314, "one", 159, "two", 265, "bar", 358); 650 multimap.putAll(badEntries); 651 return Multimaps.filterEntries( 652 multimap, Predicates.not(Predicates.in(badEntries.entries()))); 653 } 654 }) 655 .named("Multimaps.filterEntries[SetMultimap, Predicate]") 656 .withFeatures( 657 CollectionSize.ANY, 658 MapFeature.GENERAL_PURPOSE, 659 MapFeature.ALLOWS_NULL_KEYS, 660 MapFeature.ALLOWS_NULL_VALUES, 661 MapFeature.ALLOWS_ANY_NULL_QUERIES) 662 .createTestSuite()); 663 suite.addTest( 664 SetMultimapTestSuiteBuilder.using( 665 new FilteredSetMultimapGenerator() { 666 @Override 667 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 668 ImmutableSetMultimap<String, Integer> badEntries = 669 ImmutableSetMultimap.of("foo", 314, "one", 159, "two", 265, "bar", 358); 670 multimap.putAll(badEntries); 671 multimap = 672 Multimaps.filterKeys( 673 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 674 return Multimaps.filterEntries( 675 multimap, Predicates.not(Predicates.in(badEntries.entries()))); 676 } 677 }) 678 .named("Multimaps.filterEntries[Multimaps.filterKeys[SetMultimap]]") 679 .withFeatures( 680 CollectionSize.ANY, 681 MapFeature.GENERAL_PURPOSE, 682 MapFeature.ALLOWS_NULL_KEYS, 683 MapFeature.ALLOWS_NULL_VALUES, 684 MapFeature.ALLOWS_ANY_NULL_QUERIES) 685 .createTestSuite()); 686 suite.addTest( 687 SetMultimapTestSuiteBuilder.using( 688 new FilteredSetMultimapGenerator() { 689 @Override 690 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 691 ImmutableSetMultimap<String, Integer> badEntries = 692 ImmutableSetMultimap.of("foo", 314, "one", 159, "two", 265, "bar", 358); 693 multimap.putAll(badEntries); 694 multimap = 695 Multimaps.filterEntries( 696 multimap, 697 Predicates.not( 698 Predicates.in(ImmutableMap.of("one", 159, "two", 265).entrySet()))); 699 return Multimaps.filterKeys( 700 multimap, Predicates.not(Predicates.in(ImmutableSet.of("foo", "bar")))); 701 } 702 }) 703 .named("Multimaps.filterKeys[Multimaps.filterEntries[SetMultimap]]") 704 .withFeatures( 705 CollectionSize.ANY, 706 MapFeature.GENERAL_PURPOSE, 707 MapFeature.ALLOWS_NULL_KEYS, 708 MapFeature.ALLOWS_NULL_VALUES, 709 MapFeature.ALLOWS_ANY_NULL_QUERIES) 710 .createTestSuite()); 711 suite.addTest( 712 SetMultimapTestSuiteBuilder.using( 713 new FilteredSetMultimapGenerator() { 714 @Override 715 SetMultimap<String, Integer> filter(SetMultimap<String, Integer> multimap) { 716 ImmutableSetMultimap<String, Integer> badEntries = 717 ImmutableSetMultimap.of("foo", 314, "bar", 358); 718 multimap.putAll(badEntries); 719 multimap = 720 Multimaps.filterKeys(multimap, Predicates.not(Predicates.equalTo("foo"))); 721 multimap = 722 Multimaps.filterKeys(multimap, Predicates.not(Predicates.equalTo("bar"))); 723 return multimap; 724 } 725 }) 726 .named("Multimaps.filterKeys[Multimaps.filterKeys[SetMultimap]]") 727 .withFeatures( 728 CollectionSize.ANY, 729 MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE, 730 MapFeature.GENERAL_PURPOSE, 731 MapFeature.ALLOWS_NULL_KEYS, 732 MapFeature.ALLOWS_NULL_VALUES, 733 MapFeature.ALLOWS_ANY_NULL_QUERIES) 734 .createTestSuite()); 735 return suite; 736 } 737 } 738