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