Home | History | Annotate | Download | only in google
      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 com.google.common.collect.BiMap;
     20 import com.google.common.collect.testing.AbstractTester;
     21 import com.google.common.collect.testing.FeatureSpecificTestSuiteBuilder;
     22 import com.google.common.collect.testing.MapTestSuiteBuilder;
     23 import com.google.common.collect.testing.OneSizeTestContainerGenerator;
     24 import com.google.common.collect.testing.PerCollectionSizeTestSuiteBuilder;
     25 import com.google.common.collect.testing.SetTestSuiteBuilder;
     26 import com.google.common.collect.testing.features.CollectionFeature;
     27 import com.google.common.collect.testing.features.Feature;
     28 import com.google.common.collect.testing.features.MapFeature;
     29 import com.google.common.collect.testing.google.DerivedGoogleCollectionGenerators.BiMapValueSetGenerator;
     30 import com.google.common.collect.testing.google.DerivedGoogleCollectionGenerators.InverseBiMapGenerator;
     31 import com.google.common.collect.testing.google.DerivedGoogleCollectionGenerators.MapGenerator;
     32 import com.google.common.collect.testing.testers.SetCreationTester;
     33 
     34 import junit.framework.TestSuite;
     35 
     36 import java.util.ArrayList;
     37 import java.util.Collections;
     38 import java.util.HashSet;
     39 import java.util.List;
     40 import java.util.Map;
     41 import java.util.Map.Entry;
     42 import java.util.Set;
     43 
     44 /**
     45  * Creates, based on your criteria, a JUnit test suite that exhaustively tests a {@code BiMap}
     46  * implementation.
     47  *
     48  * @author Louis Wasserman
     49  */
     50 public class BiMapTestSuiteBuilder<K, V>
     51     extends PerCollectionSizeTestSuiteBuilder<BiMapTestSuiteBuilder<K, V>,
     52             TestBiMapGenerator<K, V>, BiMap<K, V>, Map.Entry<K, V>> {
     53   public static <K, V> BiMapTestSuiteBuilder<K, V> using(TestBiMapGenerator<K, V> generator) {
     54     return new BiMapTestSuiteBuilder<K, V>().usingGenerator(generator);
     55   }
     56 
     57   @Override
     58   protected List<Class<? extends AbstractTester>> getTesters() {
     59     List<Class<? extends AbstractTester>> testers =
     60         new ArrayList<Class<? extends AbstractTester>>();
     61     testers.add(BiMapPutTester.class);
     62     testers.add(BiMapInverseTester.class);
     63     testers.add(BiMapRemoveTester.class);
     64     testers.add(BiMapClearTester.class);
     65     return testers;
     66   }
     67 
     68   enum NoRecurse implements Feature<Void> {
     69     INVERSE;
     70 
     71     @Override
     72     public Set<Feature<? super Void>> getImpliedFeatures() {
     73       return Collections.emptySet();
     74     }
     75   }
     76 
     77   @Override
     78   protected
     79       List<TestSuite>
     80       createDerivedSuites(
     81           FeatureSpecificTestSuiteBuilder<?,
     82               ? extends OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>>> parentBuilder) {
     83     List<TestSuite> derived = super.createDerivedSuites(parentBuilder);
     84     // TODO(cpovirk): consider using this approach (derived suites instead of extension) in
     85     // ListTestSuiteBuilder, etc.?
     86     derived.add(MapTestSuiteBuilder
     87         .using(new MapGenerator<K, V>(parentBuilder.getSubjectGenerator()))
     88         .withFeatures(parentBuilder.getFeatures())
     89         .named(parentBuilder.getName() + " [Map]")
     90         .suppressing(parentBuilder.getSuppressedTests())
     91         .suppressing(SetCreationTester.class.getMethods())
     92            // BiMap.entrySet() duplicate-handling behavior is too confusing for SetCreationTester
     93         .createTestSuite());
     94     /*
     95      * TODO(cpovirk): the Map tests duplicate most of this effort by using a
     96      * CollectionTestSuiteBuilder on values(). It would be nice to avoid that
     97      */
     98     derived.add(SetTestSuiteBuilder
     99         .using(new BiMapValueSetGenerator<K, V>(parentBuilder.getSubjectGenerator()))
    100         .withFeatures(computeValuesSetFeatures(parentBuilder.getFeatures()))
    101         .named(parentBuilder.getName() + " values [Set]")
    102         .suppressing(parentBuilder.getSuppressedTests())
    103         .suppressing(SetCreationTester.class.getMethods())
    104           // BiMap.values() duplicate-handling behavior is too confusing for SetCreationTester
    105         .createTestSuite());
    106     if (!parentBuilder.getFeatures().contains(NoRecurse.INVERSE)) {
    107       derived.add(BiMapTestSuiteBuilder
    108           .using(new InverseBiMapGenerator<K, V>(parentBuilder.getSubjectGenerator()))
    109           .withFeatures(computeInverseFeatures(parentBuilder.getFeatures()))
    110           .named(parentBuilder.getName() + " inverse")
    111           .suppressing(parentBuilder.getSuppressedTests())
    112           .createTestSuite());
    113     }
    114 
    115     return derived;
    116   }
    117 
    118   private static Set<Feature<?>> computeInverseFeatures(Set<Feature<?>> mapFeatures) {
    119     Set<Feature<?>> inverseFeatures = new HashSet<Feature<?>>(mapFeatures);
    120 
    121     boolean nullKeys = inverseFeatures.remove(MapFeature.ALLOWS_NULL_KEYS);
    122     boolean nullValues = inverseFeatures.remove(MapFeature.ALLOWS_NULL_VALUES);
    123 
    124     if (nullKeys) {
    125       inverseFeatures.add(MapFeature.ALLOWS_NULL_VALUES);
    126     }
    127     if (nullValues) {
    128       inverseFeatures.add(MapFeature.ALLOWS_NULL_KEYS);
    129     }
    130 
    131     inverseFeatures.add(NoRecurse.INVERSE);
    132     inverseFeatures.remove(CollectionFeature.KNOWN_ORDER);
    133     inverseFeatures.add(MapFeature.REJECTS_DUPLICATES_AT_CREATION);
    134 
    135     return inverseFeatures;
    136   }
    137 
    138   // TODO(user): can we eliminate the duplication from MapTestSuiteBuilder here?
    139 
    140   private static Set<Feature<?>> computeValuesSetFeatures(
    141       Set<Feature<?>> mapFeatures) {
    142     Set<Feature<?>> valuesCollectionFeatures =
    143         computeCommonDerivedCollectionFeatures(mapFeatures);
    144     valuesCollectionFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES);
    145 
    146     if (mapFeatures.contains(MapFeature.ALLOWS_NULL_VALUES)) {
    147       valuesCollectionFeatures.add(CollectionFeature.ALLOWS_NULL_VALUES);
    148     }
    149 
    150     valuesCollectionFeatures.add(CollectionFeature.REJECTS_DUPLICATES_AT_CREATION);
    151 
    152     return valuesCollectionFeatures;
    153   }
    154 
    155   private static Set<Feature<?>> computeCommonDerivedCollectionFeatures(
    156       Set<Feature<?>> mapFeatures) {
    157     return MapTestSuiteBuilder.computeCommonDerivedCollectionFeatures(mapFeatures);
    158   }
    159 }
    160