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