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