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