001/* 002 * Copyright (C) 2012 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect.testing.google; 018 019import static com.google.common.base.Preconditions.checkArgument; 020import static com.google.common.collect.testing.Helpers.mapEntry; 021 022import com.google.common.annotations.GwtIncompatible; 023import com.google.common.collect.ImmutableList; 024import com.google.common.collect.ImmutableMultimap; 025import com.google.common.collect.Multimap; 026import com.google.common.collect.Multiset; 027import com.google.common.collect.testing.AbstractTester; 028import com.google.common.collect.testing.CollectionTestSuiteBuilder; 029import com.google.common.collect.testing.DerivedGenerator; 030import com.google.common.collect.testing.FeatureSpecificTestSuiteBuilder; 031import com.google.common.collect.testing.Helpers; 032import com.google.common.collect.testing.MapTestSuiteBuilder; 033import com.google.common.collect.testing.OneSizeTestContainerGenerator; 034import com.google.common.collect.testing.PerCollectionSizeTestSuiteBuilder; 035import com.google.common.collect.testing.SampleElements; 036import com.google.common.collect.testing.TestCollectionGenerator; 037import com.google.common.collect.testing.TestMapGenerator; 038import com.google.common.collect.testing.TestSubjectGenerator; 039import com.google.common.collect.testing.features.CollectionFeature; 040import com.google.common.collect.testing.features.CollectionSize; 041import com.google.common.collect.testing.features.Feature; 042import com.google.common.collect.testing.features.ListFeature; 043import com.google.common.collect.testing.features.MapFeature; 044import com.google.common.testing.SerializableTester; 045import java.util.ArrayList; 046import java.util.Collection; 047import java.util.Collections; 048import java.util.EnumSet; 049import java.util.HashMap; 050import java.util.HashSet; 051import java.util.Iterator; 052import java.util.LinkedHashMap; 053import java.util.List; 054import java.util.Map; 055import java.util.Map.Entry; 056import java.util.Set; 057import junit.framework.TestSuite; 058 059/** 060 * Creates, based on your criteria, a JUnit test suite that exhaustively tests a {@code Multimap} 061 * implementation. 062 * 063 * @author Louis Wasserman 064 */ 065@GwtIncompatible 066public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> 067 extends PerCollectionSizeTestSuiteBuilder< 068 MultimapTestSuiteBuilder<K, V, M>, TestMultimapGenerator<K, V, M>, M, Entry<K, V>> { 069 070 public static <K, V, M extends Multimap<K, V>> MultimapTestSuiteBuilder<K, V, M> using( 071 TestMultimapGenerator<K, V, M> generator) { 072 return new MultimapTestSuiteBuilder<K, V, M>().usingGenerator(generator); 073 } 074 075 // Class parameters must be raw. 076 @Override 077 protected List<Class<? extends AbstractTester>> getTesters() { 078 return ImmutableList.<Class<? extends AbstractTester>>of( 079 MultimapAsMapGetTester.class, 080 MultimapAsMapTester.class, 081 MultimapSizeTester.class, 082 MultimapClearTester.class, 083 MultimapContainsKeyTester.class, 084 MultimapContainsValueTester.class, 085 MultimapContainsEntryTester.class, 086 MultimapEntriesTester.class, 087 MultimapEqualsTester.class, 088 MultimapForEachTester.class, 089 MultimapGetTester.class, 090 MultimapKeySetTester.class, 091 MultimapKeysTester.class, 092 MultimapPutTester.class, 093 MultimapPutAllMultimapTester.class, 094 MultimapPutIterableTester.class, 095 MultimapReplaceValuesTester.class, 096 MultimapRemoveEntryTester.class, 097 MultimapRemoveAllTester.class, 098 MultimapToStringTester.class, 099 MultimapValuesTester.class); 100 } 101 102 @Override 103 protected List<TestSuite> createDerivedSuites( 104 FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<M, Entry<K, V>>> 105 parentBuilder) { 106 // TODO: Once invariant support is added, supply invariants to each of the 107 // derived suites, to check that mutations to the derived collections are 108 // reflected in the underlying map. 109 110 List<TestSuite> derivedSuites = super.createDerivedSuites(parentBuilder); 111 112 if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) { 113 derivedSuites.add( 114 MultimapTestSuiteBuilder.using( 115 new ReserializedMultimapGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 116 .withFeatures(computeReserializedMultimapFeatures(parentBuilder.getFeatures())) 117 .named(parentBuilder.getName() + " reserialized") 118 .suppressing(parentBuilder.getSuppressedTests()) 119 .createTestSuite()); 120 } 121 122 derivedSuites.add( 123 MapTestSuiteBuilder.using(new AsMapGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 124 .withFeatures(computeAsMapFeatures(parentBuilder.getFeatures())) 125 .named(parentBuilder.getName() + ".asMap") 126 .suppressing(parentBuilder.getSuppressedTests()) 127 .createTestSuite()); 128 129 derivedSuites.add(computeEntriesTestSuite(parentBuilder)); 130 derivedSuites.add(computeMultimapGetTestSuite(parentBuilder)); 131 derivedSuites.add(computeMultimapAsMapGetTestSuite(parentBuilder)); 132 derivedSuites.add(computeKeysTestSuite(parentBuilder)); 133 derivedSuites.add(computeValuesTestSuite(parentBuilder)); 134 135 return derivedSuites; 136 } 137 138 TestSuite computeValuesTestSuite( 139 FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<M, Entry<K, V>>> 140 parentBuilder) { 141 return CollectionTestSuiteBuilder.using( 142 new ValuesGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 143 .withFeatures(computeValuesFeatures(parentBuilder.getFeatures())) 144 .named(parentBuilder.getName() + ".values") 145 .suppressing(parentBuilder.getSuppressedTests()) 146 .createTestSuite(); 147 } 148 149 TestSuite computeEntriesTestSuite( 150 FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<M, Entry<K, V>>> 151 parentBuilder) { 152 return CollectionTestSuiteBuilder.using( 153 new EntriesGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 154 .withFeatures(computeEntriesFeatures(parentBuilder.getFeatures())) 155 .named(parentBuilder.getName() + ".entries") 156 .suppressing(parentBuilder.getSuppressedTests()) 157 .createTestSuite(); 158 } 159 160 TestSuite computeMultimapGetTestSuite( 161 FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<M, Entry<K, V>>> 162 parentBuilder) { 163 return CollectionTestSuiteBuilder.using( 164 new MultimapGetGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 165 .withFeatures(computeMultimapGetFeatures(parentBuilder.getFeatures())) 166 .named(parentBuilder.getName() + ".get[key]") 167 .suppressing(parentBuilder.getSuppressedTests()) 168 .createTestSuite(); 169 } 170 171 TestSuite computeMultimapAsMapGetTestSuite( 172 FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<M, Entry<K, V>>> 173 parentBuilder) { 174 Set<Feature<?>> features = computeMultimapAsMapGetFeatures(parentBuilder.getFeatures()); 175 if (Collections.disjoint(features, EnumSet.allOf(CollectionSize.class))) { 176 return new TestSuite(); 177 } else { 178 return CollectionTestSuiteBuilder.using( 179 new MultimapAsMapGetGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 180 .withFeatures(features) 181 .named(parentBuilder.getName() + ".asMap[].get[key]") 182 .suppressing(parentBuilder.getSuppressedTests()) 183 .createTestSuite(); 184 } 185 } 186 187 TestSuite computeKeysTestSuite( 188 FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<M, Entry<K, V>>> 189 parentBuilder) { 190 return MultisetTestSuiteBuilder.using( 191 new KeysGenerator<K, V, M>(parentBuilder.getSubjectGenerator())) 192 .withFeatures(computeKeysFeatures(parentBuilder.getFeatures())) 193 .named(parentBuilder.getName() + ".keys") 194 .suppressing(parentBuilder.getSuppressedTests()) 195 .createTestSuite(); 196 } 197 198 static Set<Feature<?>> computeDerivedCollectionFeatures(Set<Feature<?>> multimapFeatures) { 199 Set<Feature<?>> derivedFeatures = Helpers.copyToSet(multimapFeatures); 200 if (!derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) { 201 derivedFeatures.remove(CollectionFeature.SERIALIZABLE); 202 } 203 if (derivedFeatures.remove(MapFeature.SUPPORTS_REMOVE)) { 204 derivedFeatures.add(CollectionFeature.SUPPORTS_REMOVE); 205 } 206 return derivedFeatures; 207 } 208 209 static Set<Feature<?>> computeEntriesFeatures(Set<Feature<?>> multimapFeatures) { 210 Set<Feature<?>> result = computeDerivedCollectionFeatures(multimapFeatures); 211 if (multimapFeatures.contains(MapFeature.ALLOWS_NULL_ENTRY_QUERIES)) { 212 result.add(CollectionFeature.ALLOWS_NULL_QUERIES); 213 } 214 return result; 215 } 216 217 static Set<Feature<?>> computeValuesFeatures(Set<Feature<?>> multimapFeatures) { 218 Set<Feature<?>> result = computeDerivedCollectionFeatures(multimapFeatures); 219 if (multimapFeatures.contains(MapFeature.ALLOWS_NULL_VALUES)) { 220 result.add(CollectionFeature.ALLOWS_NULL_VALUES); 221 } 222 if (multimapFeatures.contains(MapFeature.ALLOWS_NULL_VALUE_QUERIES)) { 223 result.add(CollectionFeature.ALLOWS_NULL_QUERIES); 224 } 225 return result; 226 } 227 228 static Set<Feature<?>> computeKeysFeatures(Set<Feature<?>> multimapFeatures) { 229 Set<Feature<?>> result = computeDerivedCollectionFeatures(multimapFeatures); 230 if (multimapFeatures.contains(MapFeature.ALLOWS_NULL_KEYS)) { 231 result.add(CollectionFeature.ALLOWS_NULL_VALUES); 232 } 233 if (multimapFeatures.contains(MapFeature.ALLOWS_NULL_KEY_QUERIES)) { 234 result.add(CollectionFeature.ALLOWS_NULL_QUERIES); 235 } 236 return result; 237 } 238 239 private static Set<Feature<?>> computeReserializedMultimapFeatures( 240 Set<Feature<?>> multimapFeatures) { 241 Set<Feature<?>> derivedFeatures = Helpers.copyToSet(multimapFeatures); 242 derivedFeatures.remove(CollectionFeature.SERIALIZABLE); 243 derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS); 244 return derivedFeatures; 245 } 246 247 private static Set<Feature<?>> computeAsMapFeatures(Set<Feature<?>> multimapFeatures) { 248 Set<Feature<?>> derivedFeatures = Helpers.copyToSet(multimapFeatures); 249 derivedFeatures.remove(MapFeature.GENERAL_PURPOSE); 250 derivedFeatures.remove(MapFeature.SUPPORTS_PUT); 251 derivedFeatures.remove(MapFeature.ALLOWS_NULL_VALUES); 252 derivedFeatures.add(MapFeature.ALLOWS_NULL_VALUE_QUERIES); 253 derivedFeatures.add(MapFeature.REJECTS_DUPLICATES_AT_CREATION); 254 if (!derivedFeatures.contains(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) { 255 derivedFeatures.remove(CollectionFeature.SERIALIZABLE); 256 } 257 return derivedFeatures; 258 } 259 260 private static final ImmutableMultimap<Feature<?>, Feature<?>> GET_FEATURE_MAP = 261 ImmutableMultimap.<Feature<?>, Feature<?>>builder() 262 .put( 263 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 264 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION) 265 .put(MapFeature.GENERAL_PURPOSE, ListFeature.SUPPORTS_ADD_WITH_INDEX) 266 .put(MapFeature.GENERAL_PURPOSE, ListFeature.SUPPORTS_REMOVE_WITH_INDEX) 267 .put(MapFeature.GENERAL_PURPOSE, ListFeature.SUPPORTS_SET) 268 .put(MapFeature.ALLOWS_NULL_VALUE_QUERIES, CollectionFeature.ALLOWS_NULL_QUERIES) 269 .put(MapFeature.ALLOWS_NULL_VALUES, CollectionFeature.ALLOWS_NULL_VALUES) 270 .put(MapFeature.SUPPORTS_REMOVE, CollectionFeature.SUPPORTS_REMOVE) 271 .put(MapFeature.SUPPORTS_PUT, CollectionFeature.SUPPORTS_ADD) 272 .build(); 273 274 Set<Feature<?>> computeMultimapGetFeatures(Set<Feature<?>> multimapFeatures) { 275 Set<Feature<?>> derivedFeatures = Helpers.copyToSet(multimapFeatures); 276 for (Entry<Feature<?>, Feature<?>> entry : GET_FEATURE_MAP.entries()) { 277 if (derivedFeatures.contains(entry.getKey())) { 278 derivedFeatures.add(entry.getValue()); 279 } 280 } 281 if (derivedFeatures.remove(MultimapFeature.VALUE_COLLECTIONS_SUPPORT_ITERATOR_REMOVE)) { 282 derivedFeatures.add(CollectionFeature.SUPPORTS_ITERATOR_REMOVE); 283 } 284 if (!derivedFeatures.contains(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) { 285 derivedFeatures.remove(CollectionFeature.SERIALIZABLE); 286 } 287 derivedFeatures.removeAll(GET_FEATURE_MAP.keySet()); 288 return derivedFeatures; 289 } 290 291 Set<Feature<?>> computeMultimapAsMapGetFeatures(Set<Feature<?>> multimapFeatures) { 292 Set<Feature<?>> derivedFeatures = 293 Helpers.copyToSet(computeMultimapGetFeatures(multimapFeatures)); 294 if (derivedFeatures.remove(CollectionSize.ANY)) { 295 derivedFeatures.addAll(CollectionSize.ANY.getImpliedFeatures()); 296 } 297 derivedFeatures.remove(CollectionSize.ZERO); 298 return derivedFeatures; 299 } 300 301 private static class AsMapGenerator<K, V, M extends Multimap<K, V>> 302 implements TestMapGenerator<K, Collection<V>>, DerivedGenerator { 303 private final OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator; 304 305 public AsMapGenerator(OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 306 this.multimapGenerator = multimapGenerator; 307 } 308 309 @Override 310 public TestSubjectGenerator<?> getInnerGenerator() { 311 return multimapGenerator; 312 } 313 314 private Collection<V> createCollection(V v) { 315 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 316 .createCollection(Collections.singleton(v)); 317 } 318 319 @Override 320 public SampleElements<Entry<K, Collection<V>>> samples() { 321 SampleElements<K> sampleKeys = 322 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys(); 323 SampleElements<V> sampleValues = 324 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleValues(); 325 return new SampleElements<>( 326 mapEntry(sampleKeys.e0(), createCollection(sampleValues.e0())), 327 mapEntry(sampleKeys.e1(), createCollection(sampleValues.e1())), 328 mapEntry(sampleKeys.e2(), createCollection(sampleValues.e2())), 329 mapEntry(sampleKeys.e3(), createCollection(sampleValues.e3())), 330 mapEntry(sampleKeys.e4(), createCollection(sampleValues.e4()))); 331 } 332 333 @Override 334 public Map<K, Collection<V>> create(Object... elements) { 335 Set<K> keySet = new HashSet<>(); 336 List<Entry<K, V>> builder = new ArrayList<>(); 337 for (Object o : elements) { 338 Entry<K, Collection<V>> entry = (Entry<K, Collection<V>>) o; 339 keySet.add(entry.getKey()); 340 for (V v : entry.getValue()) { 341 builder.add(mapEntry(entry.getKey(), v)); 342 } 343 } 344 checkArgument(keySet.size() == elements.length, "Duplicate keys"); 345 return multimapGenerator.create(builder.toArray()).asMap(); 346 } 347 348 @SuppressWarnings("unchecked") 349 @Override 350 public Entry<K, Collection<V>>[] createArray(int length) { 351 return new Entry[length]; 352 } 353 354 @Override 355 public Iterable<Entry<K, Collection<V>>> order(List<Entry<K, Collection<V>>> insertionOrder) { 356 Map<K, Collection<V>> map = new HashMap<>(); 357 List<Entry<K, V>> builder = new ArrayList<>(); 358 for (Entry<K, Collection<V>> entry : insertionOrder) { 359 for (V v : entry.getValue()) { 360 builder.add(mapEntry(entry.getKey(), v)); 361 } 362 map.put(entry.getKey(), entry.getValue()); 363 } 364 Iterable<Entry<K, V>> ordered = multimapGenerator.order(builder); 365 LinkedHashMap<K, Collection<V>> orderedMap = new LinkedHashMap<>(); 366 for (Entry<K, V> entry : ordered) { 367 orderedMap.put(entry.getKey(), map.get(entry.getKey())); 368 } 369 return orderedMap.entrySet(); 370 } 371 372 @Override 373 public K[] createKeyArray(int length) { 374 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 375 .createKeyArray(length); 376 } 377 378 @SuppressWarnings("unchecked") 379 @Override 380 public Collection<V>[] createValueArray(int length) { 381 return new Collection[length]; 382 } 383 } 384 385 static class EntriesGenerator<K, V, M extends Multimap<K, V>> 386 implements TestCollectionGenerator<Entry<K, V>>, DerivedGenerator { 387 private final OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator; 388 389 public EntriesGenerator(OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 390 this.multimapGenerator = multimapGenerator; 391 } 392 393 @Override 394 public TestSubjectGenerator<?> getInnerGenerator() { 395 return multimapGenerator; 396 } 397 398 @Override 399 public SampleElements<Entry<K, V>> samples() { 400 return multimapGenerator.samples(); 401 } 402 403 @Override 404 public Collection<Entry<K, V>> create(Object... elements) { 405 return multimapGenerator.create(elements).entries(); 406 } 407 408 @SuppressWarnings("unchecked") 409 @Override 410 public Entry<K, V>[] createArray(int length) { 411 return new Entry[length]; 412 } 413 414 @Override 415 public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) { 416 return multimapGenerator.order(insertionOrder); 417 } 418 } 419 420 static class ValuesGenerator<K, V, M extends Multimap<K, V>> 421 implements TestCollectionGenerator<V> { 422 private final OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator; 423 424 public ValuesGenerator(OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 425 this.multimapGenerator = multimapGenerator; 426 } 427 428 @Override 429 public SampleElements<V> samples() { 430 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 431 .sampleValues(); 432 } 433 434 @Override 435 public Collection<V> create(Object... elements) { 436 K k = 437 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 438 .sampleKeys() 439 .e0(); 440 Entry<K, V>[] entries = new Entry[elements.length]; 441 for (int i = 0; i < elements.length; i++) { 442 entries[i] = mapEntry(k, (V) elements[i]); 443 } 444 return multimapGenerator.create((Object[]) entries).values(); 445 } 446 447 @SuppressWarnings("unchecked") 448 @Override 449 public V[] createArray(int length) { 450 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 451 .createValueArray(length); 452 } 453 454 @Override 455 public Iterable<V> order(List<V> insertionOrder) { 456 K k = 457 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 458 .sampleKeys() 459 .e0(); 460 List<Entry<K, V>> entries = new ArrayList<>(); 461 for (V v : insertionOrder) { 462 entries.add(mapEntry(k, v)); 463 } 464 Iterable<Entry<K, V>> ordered = multimapGenerator.order(entries); 465 List<V> orderedValues = new ArrayList<>(); 466 for (Entry<K, V> entry : ordered) { 467 orderedValues.add(entry.getValue()); 468 } 469 return orderedValues; 470 } 471 } 472 473 static class KeysGenerator<K, V, M extends Multimap<K, V>> 474 implements TestMultisetGenerator<K>, DerivedGenerator { 475 private final OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator; 476 477 public KeysGenerator(OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 478 this.multimapGenerator = multimapGenerator; 479 } 480 481 @Override 482 public TestSubjectGenerator<?> getInnerGenerator() { 483 return multimapGenerator; 484 } 485 486 @Override 487 public SampleElements<K> samples() { 488 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys(); 489 } 490 491 @Override 492 public Multiset<K> create(Object... elements) { 493 /* 494 * This is nasty and complicated, but it's the only way to make sure keys get mapped to enough 495 * distinct values. 496 */ 497 Entry[] entries = new Entry[elements.length]; 498 Map<K, Iterator<V>> valueIterators = new HashMap<>(); 499 for (int i = 0; i < elements.length; i++) { 500 @SuppressWarnings("unchecked") 501 K key = (K) elements[i]; 502 503 Iterator<V> valueItr = valueIterators.get(key); 504 if (valueItr == null) { 505 valueIterators.put(key, valueItr = sampleValuesIterator()); 506 } 507 entries[i] = mapEntry((K) elements[i], valueItr.next()); 508 } 509 return multimapGenerator.create((Object[]) entries).keys(); 510 } 511 512 private Iterator<V> sampleValuesIterator() { 513 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 514 .sampleValues() 515 .iterator(); 516 } 517 518 @SuppressWarnings("unchecked") 519 @Override 520 public K[] createArray(int length) { 521 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 522 .createKeyArray(length); 523 } 524 525 @Override 526 public Iterable<K> order(List<K> insertionOrder) { 527 Iterator<V> valueIter = sampleValuesIterator(); 528 List<Entry<K, V>> entries = new ArrayList<>(); 529 for (K k : insertionOrder) { 530 entries.add(mapEntry(k, valueIter.next())); 531 } 532 Iterable<Entry<K, V>> ordered = multimapGenerator.order(entries); 533 List<K> orderedValues = new ArrayList<>(); 534 for (Entry<K, V> entry : ordered) { 535 orderedValues.add(entry.getKey()); 536 } 537 return orderedValues; 538 } 539 } 540 541 static class MultimapGetGenerator<K, V, M extends Multimap<K, V>> 542 implements TestCollectionGenerator<V> { 543 final OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator; 544 545 public MultimapGetGenerator(OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 546 this.multimapGenerator = multimapGenerator; 547 } 548 549 @Override 550 public SampleElements<V> samples() { 551 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 552 .sampleValues(); 553 } 554 555 @Override 556 public V[] createArray(int length) { 557 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 558 .createValueArray(length); 559 } 560 561 @Override 562 public Iterable<V> order(List<V> insertionOrder) { 563 K k = 564 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 565 .sampleKeys() 566 .e0(); 567 List<Entry<K, V>> entries = new ArrayList<>(); 568 for (V v : insertionOrder) { 569 entries.add(mapEntry(k, v)); 570 } 571 Iterable<Entry<K, V>> orderedEntries = multimapGenerator.order(entries); 572 List<V> values = new ArrayList<>(); 573 for (Entry<K, V> entry : orderedEntries) { 574 values.add(entry.getValue()); 575 } 576 return values; 577 } 578 579 @Override 580 public Collection<V> create(Object... elements) { 581 Entry<K, V>[] array = multimapGenerator.createArray(elements.length); 582 K k = 583 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 584 .sampleKeys() 585 .e0(); 586 for (int i = 0; i < elements.length; i++) { 587 array[i] = mapEntry(k, (V) elements[i]); 588 } 589 return multimapGenerator.create((Object[]) array).get(k); 590 } 591 } 592 593 static class MultimapAsMapGetGenerator<K, V, M extends Multimap<K, V>> 594 extends MultimapGetGenerator<K, V, M> { 595 596 public MultimapAsMapGetGenerator( 597 OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 598 super(multimapGenerator); 599 } 600 601 @Override 602 public Collection<V> create(Object... elements) { 603 Entry<K, V>[] array = multimapGenerator.createArray(elements.length); 604 K k = 605 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 606 .sampleKeys() 607 .e0(); 608 for (int i = 0; i < elements.length; i++) { 609 array[i] = mapEntry(k, (V) elements[i]); 610 } 611 return multimapGenerator.create((Object[]) array).asMap().get(k); 612 } 613 } 614 615 private static class ReserializedMultimapGenerator<K, V, M extends Multimap<K, V>> 616 implements TestMultimapGenerator<K, V, M> { 617 private final OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator; 618 619 public ReserializedMultimapGenerator( 620 OneSizeTestContainerGenerator<M, Entry<K, V>> multimapGenerator) { 621 this.multimapGenerator = multimapGenerator; 622 } 623 624 @Override 625 public SampleElements<Entry<K, V>> samples() { 626 return multimapGenerator.samples(); 627 } 628 629 @Override 630 public Entry<K, V>[] createArray(int length) { 631 return multimapGenerator.createArray(length); 632 } 633 634 @Override 635 public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) { 636 return multimapGenerator.order(insertionOrder); 637 } 638 639 @Override 640 public M create(Object... elements) { 641 return SerializableTester.reserialize( 642 ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 643 .create(elements)); 644 } 645 646 @Override 647 public K[] createKeyArray(int length) { 648 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 649 .createKeyArray(length); 650 } 651 652 @Override 653 public V[] createValueArray(int length) { 654 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 655 .createValueArray(length); 656 } 657 658 @Override 659 public SampleElements<K> sampleKeys() { 660 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()).sampleKeys(); 661 } 662 663 @Override 664 public SampleElements<V> sampleValues() { 665 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 666 .sampleValues(); 667 } 668 669 @Override 670 public Collection<V> createCollection(Iterable<? extends V> values) { 671 return ((TestMultimapGenerator<K, V, M>) multimapGenerator.getInnerGenerator()) 672 .createCollection(values); 673 } 674 } 675}