• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>> {
using(TestBiMapGenerator<K, V> generator)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
getTesters()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
getImpliedFeatures()72     public Set<Feature<? super Void>> getImpliedFeatures() {
73       return Collections.emptySet();
74     }
75   }
76 
77   @Override
78   protected
79       List<TestSuite>
createDerivedSuites( FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>>> parentBuilder)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 
computeInverseFeatures(Set<Feature<?>> mapFeatures)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 
computeValuesSetFeatures( Set<Feature<?>> mapFeatures)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 
computeCommonDerivedCollectionFeatures( Set<Feature<?>> mapFeatures)155   private static Set<Feature<?>> computeCommonDerivedCollectionFeatures(
156       Set<Feature<?>> mapFeatures) {
157     return MapTestSuiteBuilder.computeCommonDerivedCollectionFeatures(mapFeatures);
158   }
159 }
160