Coverage Summary for Class: MultimapTestSuiteBuilder (com.google.common.collect.testing.google)

Class Method, % Line, %
MultimapTestSuiteBuilder 0% (0/18) 0% (0/119)
MultimapTestSuiteBuilder$AsMapGenerator 0% (0/9) 0% (0/43)
MultimapTestSuiteBuilder$EntriesGenerator 0% (0/6) 0% (0/7)
MultimapTestSuiteBuilder$KeysGenerator 0% (0/7) 0% (0/29)
MultimapTestSuiteBuilder$MultimapAsMapGetGenerator 0% (0/2) 0% (0/9)
MultimapTestSuiteBuilder$MultimapGetGenerator 0% (0/5) 0% (0/28)
MultimapTestSuiteBuilder$ReserializedMultimapGenerator 0% (0/10) 0% (0/17)
MultimapTestSuiteBuilder$ValuesGenerator 0% (0/5) 0% (0/28)
Total 0% (0/62) 0% (0/280)


1 /* 2  * Copyright (C) 2012 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.testing.google; 18  19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.collect.testing.Helpers.mapEntry; 21  22 import com.google.common.annotations.GwtIncompatible; 23 import com.google.common.collect.ImmutableList; 24 import com.google.common.collect.ImmutableMultimap; 25 import com.google.common.collect.Multimap; 26 import com.google.common.collect.Multiset; 27 import com.google.common.collect.testing.AbstractTester; 28 import com.google.common.collect.testing.CollectionTestSuiteBuilder; 29 import com.google.common.collect.testing.DerivedGenerator; 30 import com.google.common.collect.testing.FeatureSpecificTestSuiteBuilder; 31 import com.google.common.collect.testing.Helpers; 32 import com.google.common.collect.testing.MapTestSuiteBuilder; 33 import com.google.common.collect.testing.OneSizeTestContainerGenerator; 34 import com.google.common.collect.testing.PerCollectionSizeTestSuiteBuilder; 35 import com.google.common.collect.testing.SampleElements; 36 import com.google.common.collect.testing.TestCollectionGenerator; 37 import com.google.common.collect.testing.TestMapGenerator; 38 import com.google.common.collect.testing.TestSubjectGenerator; 39 import com.google.common.collect.testing.features.CollectionFeature; 40 import com.google.common.collect.testing.features.CollectionSize; 41 import com.google.common.collect.testing.features.Feature; 42 import com.google.common.collect.testing.features.ListFeature; 43 import com.google.common.collect.testing.features.MapFeature; 44 import com.google.common.testing.SerializableTester; 45 import java.util.ArrayList; 46 import java.util.Collection; 47 import java.util.Collections; 48 import java.util.EnumSet; 49 import java.util.HashMap; 50 import java.util.HashSet; 51 import java.util.Iterator; 52 import java.util.LinkedHashMap; 53 import java.util.List; 54 import java.util.Map; 55 import java.util.Map.Entry; 56 import java.util.Set; 57 import junit.framework.TestSuite; 58  59 /** 60  * Creates, based on your criteria, a JUnit test suite that exhaustively tests a {@code Multimap} 61  * implementation. 62  * 63  * @author Louis Wasserman 64  */ 65 @GwtIncompatible 66 public class MultimapTestSuiteBuilder<K, V, M extends Multimap<K, V>> 67  extends PerCollectionSizeTestSuiteBuilder< 68  MultimapTestSuiteBuilder<K, V, M>, TestMultimapGenerator<K, V, M>, M, Entry<K, V>> { 69  70  public static <K, V, M extends Multimap<K, V>> MultimapTestSuiteBuilder<K, V, M> using( 71  TestMultimapGenerator<K, V, M> generator) { 72  return new MultimapTestSuiteBuilder<K, V, M>().usingGenerator(generator); 73  } 74  75  // Class parameters must be raw. 76  @Override 77  protected List<Class<? extends AbstractTester>> getTesters() { 78  return ImmutableList.<Class<? extends AbstractTester>>of( 79  MultimapAsMapGetTester.class, 80  MultimapAsMapTester.class, 81  MultimapSizeTester.class, 82  MultimapClearTester.class, 83  MultimapContainsKeyTester.class, 84  MultimapContainsValueTester.class, 85  MultimapContainsEntryTester.class, 86  MultimapEntriesTester.class, 87  MultimapEqualsTester.class, 88  MultimapForEachTester.class, 89  MultimapGetTester.class, 90  MultimapKeySetTester.class, 91  MultimapKeysTester.class, 92  MultimapPutTester.class, 93  MultimapPutAllMultimapTester.class, 94  MultimapPutIterableTester.class, 95  MultimapReplaceValuesTester.class, 96  MultimapRemoveEntryTester.class, 97  MultimapRemoveAllTester.class, 98  MultimapToStringTester.class, 99  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 }