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