BiMapTestSuiteBuilder.java revision 0888a09821a98ac0680fad765217302858e70fa4
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
17package com.google.common.collect.testing.google;
18
19import com.google.common.collect.BiMap;
20import com.google.common.collect.testing.AbstractTester;
21import com.google.common.collect.testing.FeatureSpecificTestSuiteBuilder;
22import com.google.common.collect.testing.MapTestSuiteBuilder;
23import com.google.common.collect.testing.OneSizeTestContainerGenerator;
24import com.google.common.collect.testing.PerCollectionSizeTestSuiteBuilder;
25import com.google.common.collect.testing.SetTestSuiteBuilder;
26import com.google.common.collect.testing.features.CollectionFeature;
27import com.google.common.collect.testing.features.Feature;
28import com.google.common.collect.testing.features.MapFeature;
29import com.google.common.collect.testing.google.DerivedGoogleCollectionGenerators.BiMapValueSetGenerator;
30import com.google.common.collect.testing.google.DerivedGoogleCollectionGenerators.InverseBiMapGenerator;
31import com.google.common.collect.testing.google.DerivedGoogleCollectionGenerators.MapGenerator;
32import com.google.common.collect.testing.testers.SetCreationTester;
33
34import junit.framework.TestSuite;
35
36import java.util.ArrayList;
37import java.util.Collections;
38import java.util.HashSet;
39import java.util.List;
40import java.util.Map;
41import java.util.Map.Entry;
42import 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 */
50public 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