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

Class Method, % Line, %
MapTestSuiteBuilder 100% (12/12) 96% (72/75)
MapTestSuiteBuilder$ReserializedMapGenerator 100% (7/7) 100% (9/9)
Total 100% (19/19) 96.4% (81/84)


1 /* 2  * Copyright (C) 2008 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; 18  19 import static com.google.common.collect.testing.DerivedCollectionGenerators.keySetGenerator; 20  21 import com.google.common.annotations.GwtIncompatible; 22 import com.google.common.collect.testing.DerivedCollectionGenerators.MapEntrySetGenerator; 23 import com.google.common.collect.testing.DerivedCollectionGenerators.MapValueCollectionGenerator; 24 import com.google.common.collect.testing.features.CollectionFeature; 25 import com.google.common.collect.testing.features.CollectionSize; 26 import com.google.common.collect.testing.features.Feature; 27 import com.google.common.collect.testing.features.MapFeature; 28 import com.google.common.collect.testing.testers.MapClearTester; 29 import com.google.common.collect.testing.testers.MapComputeIfAbsentTester; 30 import com.google.common.collect.testing.testers.MapComputeIfPresentTester; 31 import com.google.common.collect.testing.testers.MapComputeTester; 32 import com.google.common.collect.testing.testers.MapContainsKeyTester; 33 import com.google.common.collect.testing.testers.MapContainsValueTester; 34 import com.google.common.collect.testing.testers.MapCreationTester; 35 import com.google.common.collect.testing.testers.MapEntrySetTester; 36 import com.google.common.collect.testing.testers.MapEqualsTester; 37 import com.google.common.collect.testing.testers.MapForEachTester; 38 import com.google.common.collect.testing.testers.MapGetOrDefaultTester; 39 import com.google.common.collect.testing.testers.MapGetTester; 40 import com.google.common.collect.testing.testers.MapHashCodeTester; 41 import com.google.common.collect.testing.testers.MapIsEmptyTester; 42 import com.google.common.collect.testing.testers.MapMergeTester; 43 import com.google.common.collect.testing.testers.MapPutAllTester; 44 import com.google.common.collect.testing.testers.MapPutIfAbsentTester; 45 import com.google.common.collect.testing.testers.MapPutTester; 46 import com.google.common.collect.testing.testers.MapRemoveEntryTester; 47 import com.google.common.collect.testing.testers.MapRemoveTester; 48 import com.google.common.collect.testing.testers.MapReplaceAllTester; 49 import com.google.common.collect.testing.testers.MapReplaceEntryTester; 50 import com.google.common.collect.testing.testers.MapReplaceTester; 51 import com.google.common.collect.testing.testers.MapSerializationTester; 52 import com.google.common.collect.testing.testers.MapSizeTester; 53 import com.google.common.collect.testing.testers.MapToStringTester; 54 import com.google.common.testing.SerializableTester; 55 import java.util.Arrays; 56 import java.util.HashSet; 57 import java.util.List; 58 import java.util.Map; 59 import java.util.Map.Entry; 60 import java.util.Set; 61 import junit.framework.TestSuite; 62  63 /** 64  * Creates, based on your criteria, a JUnit test suite that exhaustively tests a Map implementation. 65  * 66  * @author George van den Driessche 67  */ 68 @GwtIncompatible 69 public class MapTestSuiteBuilder<K, V> 70  extends PerCollectionSizeTestSuiteBuilder< 71  MapTestSuiteBuilder<K, V>, TestMapGenerator<K, V>, Map<K, V>, Entry<K, V>> { 72  public static <K, V> MapTestSuiteBuilder<K, V> using(TestMapGenerator<K, V> generator) { 73  return new MapTestSuiteBuilder<K, V>().usingGenerator(generator); 74  } 75  76  @SuppressWarnings("unchecked") // Class parameters must be raw. 77  @Override 78  protected List<Class<? extends AbstractTester>> getTesters() { 79  return Arrays.<Class<? extends AbstractTester>>asList( 80  MapClearTester.class, 81  MapComputeTester.class, 82  MapComputeIfAbsentTester.class, 83  MapComputeIfPresentTester.class, 84  MapContainsKeyTester.class, 85  MapContainsValueTester.class, 86  MapCreationTester.class, 87  MapEntrySetTester.class, 88  MapEqualsTester.class, 89  MapForEachTester.class, 90  MapGetTester.class, 91  MapGetOrDefaultTester.class, 92  MapHashCodeTester.class, 93  MapIsEmptyTester.class, 94  MapMergeTester.class, 95  MapPutTester.class, 96  MapPutAllTester.class, 97  MapPutIfAbsentTester.class, 98  MapRemoveTester.class, 99  MapRemoveEntryTester.class, 100  MapReplaceTester.class, 101  MapReplaceAllTester.class, 102  MapReplaceEntryTester.class, 103  MapSerializationTester.class, 104  MapSizeTester.class, 105  MapToStringTester.class); 106  } 107  108  @Override 109  protected List<TestSuite> createDerivedSuites( 110  FeatureSpecificTestSuiteBuilder< 111  ?, ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> 112  parentBuilder) { 113  // TODO: Once invariant support is added, supply invariants to each of the 114  // derived suites, to check that mutations to the derived collections are 115  // reflected in the underlying map. 116  117  List<TestSuite> derivedSuites = super.createDerivedSuites(parentBuilder); 118  119  if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) { 120  derivedSuites.add( 121  MapTestSuiteBuilder.using( 122  new ReserializedMapGenerator<K, V>(parentBuilder.getSubjectGenerator())) 123  .withFeatures(computeReserializedMapFeatures(parentBuilder.getFeatures())) 124  .named(parentBuilder.getName() + " reserialized") 125  .suppressing(parentBuilder.getSuppressedTests()) 126  .createTestSuite()); 127  } 128  129  derivedSuites.add( 130  createDerivedEntrySetSuite( 131  new MapEntrySetGenerator<K, V>(parentBuilder.getSubjectGenerator())) 132  .withFeatures(computeEntrySetFeatures(parentBuilder.getFeatures())) 133  .named(parentBuilder.getName() + " entrySet") 134  .suppressing(parentBuilder.getSuppressedTests()) 135  .createTestSuite()); 136  137  derivedSuites.add( 138  createDerivedKeySetSuite(keySetGenerator(parentBuilder.getSubjectGenerator())) 139  .withFeatures(computeKeySetFeatures(parentBuilder.getFeatures())) 140  .named(parentBuilder.getName() + " keys") 141  .suppressing(parentBuilder.getSuppressedTests()) 142  .createTestSuite()); 143  144  derivedSuites.add( 145  createDerivedValueCollectionSuite( 146  new MapValueCollectionGenerator<K, V>(parentBuilder.getSubjectGenerator())) 147  .named(parentBuilder.getName() + " values") 148  .withFeatures(computeValuesCollectionFeatures(parentBuilder.getFeatures())) 149  .suppressing(parentBuilder.getSuppressedTests()) 150  .createTestSuite()); 151  152  return derivedSuites; 153  } 154  155  protected SetTestSuiteBuilder<Entry<K, V>> createDerivedEntrySetSuite( 156  TestSetGenerator<Entry<K, V>> entrySetGenerator) { 157  return SetTestSuiteBuilder.using(entrySetGenerator); 158  } 159  160  protected SetTestSuiteBuilder<K> createDerivedKeySetSuite(TestSetGenerator<K> keySetGenerator) { 161  return SetTestSuiteBuilder.using(keySetGenerator); 162  } 163  164  protected CollectionTestSuiteBuilder<V> createDerivedValueCollectionSuite( 165  TestCollectionGenerator<V> valueCollectionGenerator) { 166  return CollectionTestSuiteBuilder.using(valueCollectionGenerator); 167  } 168  169  private static Set<Feature<?>> computeReserializedMapFeatures(Set<Feature<?>> mapFeatures) { 170  Set<Feature<?>> derivedFeatures = Helpers.copyToSet(mapFeatures); 171  derivedFeatures.remove(CollectionFeature.SERIALIZABLE); 172  derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS); 173  return derivedFeatures; 174  } 175  176  private static Set<Feature<?>> computeEntrySetFeatures(Set<Feature<?>> mapFeatures) { 177  Set<Feature<?>> entrySetFeatures = computeCommonDerivedCollectionFeatures(mapFeatures); 178  if (mapFeatures.contains(MapFeature.ALLOWS_NULL_ENTRY_QUERIES)) { 179  entrySetFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES); 180  } 181  return entrySetFeatures; 182  } 183  184  private static Set<Feature<?>> computeKeySetFeatures(Set<Feature<?>> mapFeatures) { 185  Set<Feature<?>> keySetFeatures = computeCommonDerivedCollectionFeatures(mapFeatures); 186  187  // TODO(lowasser): make this trigger only if the map is a submap 188  // currently, the KeySetGenerator won't work properly for a subset of a keyset of a submap 189  keySetFeatures.add(CollectionFeature.SUBSET_VIEW); 190  if (mapFeatures.contains(MapFeature.ALLOWS_NULL_KEYS)) { 191  keySetFeatures.add(CollectionFeature.ALLOWS_NULL_VALUES); 192  } else if (mapFeatures.contains(MapFeature.ALLOWS_NULL_KEY_QUERIES)) { 193  keySetFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES); 194  } 195  196  return keySetFeatures; 197  } 198  199  private static Set<Feature<?>> computeValuesCollectionFeatures(Set<Feature<?>> mapFeatures) { 200  Set<Feature<?>> valuesCollectionFeatures = computeCommonDerivedCollectionFeatures(mapFeatures); 201  if (mapFeatures.contains(MapFeature.ALLOWS_NULL_VALUE_QUERIES)) { 202  valuesCollectionFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES); 203  } 204  if (mapFeatures.contains(MapFeature.ALLOWS_NULL_VALUES)) { 205  valuesCollectionFeatures.add(CollectionFeature.ALLOWS_NULL_VALUES); 206  } 207  208  return valuesCollectionFeatures; 209  } 210  211  public static Set<Feature<?>> computeCommonDerivedCollectionFeatures( 212  Set<Feature<?>> mapFeatures) { 213  mapFeatures = new HashSet<>(mapFeatures); 214  Set<Feature<?>> derivedFeatures = new HashSet<>(); 215  mapFeatures.remove(CollectionFeature.SERIALIZABLE); 216  if (mapFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) { 217  derivedFeatures.add(CollectionFeature.SERIALIZABLE); 218  } 219  if (mapFeatures.contains(MapFeature.SUPPORTS_REMOVE)) { 220  derivedFeatures.add(CollectionFeature.SUPPORTS_REMOVE); 221  } 222  if (mapFeatures.contains(MapFeature.REJECTS_DUPLICATES_AT_CREATION)) { 223  derivedFeatures.add(CollectionFeature.REJECTS_DUPLICATES_AT_CREATION); 224  } 225  if (mapFeatures.contains(MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION)) { 226  derivedFeatures.add(CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION); 227  } 228  // add the intersection of CollectionFeature.values() and mapFeatures 229  for (CollectionFeature feature : CollectionFeature.values()) { 230  if (mapFeatures.contains(feature)) { 231  derivedFeatures.add(feature); 232  } 233  } 234  // add the intersection of CollectionSize.values() and mapFeatures 235  for (CollectionSize size : CollectionSize.values()) { 236  if (mapFeatures.contains(size)) { 237  derivedFeatures.add(size); 238  } 239  } 240  return derivedFeatures; 241  } 242  243  private static class ReserializedMapGenerator<K, V> implements TestMapGenerator<K, V> { 244  private final OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>> mapGenerator; 245  246  public ReserializedMapGenerator( 247  OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>> mapGenerator) { 248  this.mapGenerator = mapGenerator; 249  } 250  251  @Override 252  public SampleElements<Entry<K, V>> samples() { 253  return mapGenerator.samples(); 254  } 255  256  @Override 257  public Entry<K, V>[] createArray(int length) { 258  return mapGenerator.createArray(length); 259  } 260  261  @Override 262  public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) { 263  return mapGenerator.order(insertionOrder); 264  } 265  266  @Override 267  public Map<K, V> create(Object... elements) { 268  return SerializableTester.reserialize(mapGenerator.create(elements)); 269  } 270  271  @Override 272  public K[] createKeyArray(int length) { 273  return ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).createKeyArray(length); 274  } 275  276  @Override 277  public V[] createValueArray(int length) { 278  return ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).createValueArray(length); 279  } 280  } 281 }