TestsForMapsInJavaUtil.java revision 3c77433663281544363151bf284b0240dfd22a42
1/* 2 * Copyright (C) 2009 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; 18 19import com.google.common.collect.testing.features.CollectionFeature; 20import com.google.common.collect.testing.features.CollectionSize; 21import com.google.common.collect.testing.features.MapFeature; 22 23import junit.framework.Test; 24import junit.framework.TestSuite; 25 26import java.io.Serializable; 27import java.lang.reflect.Method; 28import java.util.Collection; 29import java.util.Collections; 30import java.util.Comparator; 31import java.util.EnumMap; 32import java.util.HashMap; 33import java.util.LinkedHashMap; 34import java.util.Map; 35import java.util.Map.Entry; 36import java.util.SortedMap; 37import java.util.TreeMap; 38import java.util.concurrent.ConcurrentHashMap; 39import java.util.concurrent.ConcurrentSkipListMap; 40 41/** 42 * Generates a test suite covering the {@link Map} implementations in the 43 * {@link java.util} package. Can be subclassed to specify tests that should 44 * be suppressed. 45 * 46 * @author Kevin Bourrillion 47 */ 48public class TestsForMapsInJavaUtil { 49 50 public static Test suite() { 51 return new TestsForMapsInJavaUtil().allTests(); 52 } 53 54 public Test allTests() { 55 TestSuite suite = new TestSuite("java.util Maps"); 56 suite.addTest(testsForEmptyMap()); 57 suite.addTest(testsForSingletonMap()); 58 suite.addTest(testsForHashMap()); 59 suite.addTest(testsForLinkedHashMap()); 60 suite.addTest(testsForTreeMapNatural()); 61 suite.addTest(testsForTreeMapWithComparator()); 62 suite.addTest(testsForEnumMap()); 63 suite.addTest(testsForConcurrentHashMap()); 64 suite.addTest(testsForConcurrentSkipListMapNatural()); 65 suite.addTest(testsForConcurrentSkipListMapWithComparator()); 66 return suite; 67 } 68 69 protected Collection<Method> suppressForEmptyMap() { 70 return Collections.emptySet(); 71 } 72 protected Collection<Method> suppressForSingletonMap() { 73 return Collections.emptySet(); 74 } 75 protected Collection<Method> suppressForHashMap() { 76 return Collections.emptySet(); 77 } 78 protected Collection<Method> suppressForLinkedHashMap() { 79 return Collections.emptySet(); 80 } 81 protected Collection<Method> suppressForTreeMapNatural() { 82 return Collections.emptySet(); 83 } 84 protected Collection<Method> suppressForTreeMapWithComparator() { 85 return Collections.emptySet(); 86 } 87 protected Collection<Method> suppressForEnumMap() { 88 return Collections.emptySet(); 89 } 90 protected Collection<Method> suppressForConcurrentHashMap() { 91 return Collections.emptySet(); 92 } 93 protected Collection<Method> suppressForConcurrentSkipListMap() { 94 return Collections.emptySet(); 95 } 96 97 public Test testsForEmptyMap() { 98 return MapTestSuiteBuilder 99 .using(new TestStringMapGenerator() { 100 @Override protected Map<String, String> create( 101 Entry<String, String>[] entries) { 102 return Collections.emptyMap(); 103 } 104 }) 105 .named("emptyMap") 106 .withFeatures( 107 CollectionFeature.SERIALIZABLE, 108 CollectionSize.ZERO) 109 .suppressing(suppressForEmptyMap()) 110 .createTestSuite(); 111 } 112 113 public Test testsForSingletonMap() { 114 return MapTestSuiteBuilder 115 .using(new TestStringMapGenerator() { 116 @Override protected Map<String, String> create( 117 Entry<String, String>[] entries) { 118 return Collections.singletonMap( 119 entries[0].getKey(), entries[0].getValue()); 120 } 121 }) 122 .named("singletonMap") 123 .withFeatures( 124 MapFeature.ALLOWS_NULL_KEYS, 125 MapFeature.ALLOWS_NULL_VALUES, 126 CollectionFeature.SERIALIZABLE, 127 CollectionSize.ONE) 128 .suppressing(suppressForSingletonMap()) 129 .createTestSuite(); 130 } 131 132 public Test testsForHashMap() { 133 return MapTestSuiteBuilder 134 .using(new TestStringMapGenerator() { 135 @Override protected Map<String, String> create( 136 Entry<String, String>[] entries) { 137 return toHashMap(entries); 138 } 139 }) 140 .named("HashMap") 141 .withFeatures( 142 MapFeature.GENERAL_PURPOSE, 143 MapFeature.ALLOWS_NULL_KEYS, 144 MapFeature.ALLOWS_NULL_VALUES, 145 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 146 CollectionFeature.SERIALIZABLE, 147 CollectionSize.ANY) 148 .suppressing(suppressForHashMap()) 149 .createTestSuite(); 150 } 151 152 public Test testsForLinkedHashMap() { 153 return MapTestSuiteBuilder 154 .using(new TestStringMapGenerator() { 155 @Override protected Map<String, String> create( 156 Entry<String, String>[] entries) { 157 return populate(new LinkedHashMap<String, String>(), entries); 158 } 159 }) 160 .named("LinkedHashMap") 161 .withFeatures( 162 MapFeature.GENERAL_PURPOSE, 163 MapFeature.ALLOWS_NULL_KEYS, 164 MapFeature.ALLOWS_NULL_VALUES, 165 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 166 CollectionFeature.KNOWN_ORDER, 167 CollectionFeature.SERIALIZABLE, 168 CollectionSize.ANY) 169 .suppressing(suppressForLinkedHashMap()) 170 .createTestSuite(); 171 } 172 173 public Test testsForTreeMapNatural() { 174 return NavigableMapTestSuiteBuilder 175 .using(new TestStringSortedMapGenerator() { 176 @Override protected SortedMap<String, String> create( 177 Entry<String, String>[] entries) { 178 /* 179 * TODO(cpovirk): it would be nice to create an input Map and use 180 * the copy constructor here and in the other tests 181 */ 182 return populate(new TreeMap<String, String>(), entries); 183 } 184 }) 185 .named("TreeMap, natural") 186 .withFeatures( 187 MapFeature.GENERAL_PURPOSE, 188 MapFeature.ALLOWS_NULL_VALUES, 189 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 190 CollectionFeature.KNOWN_ORDER, 191 CollectionFeature.SERIALIZABLE, 192 CollectionSize.ANY) 193 .suppressing(suppressForTreeMapNatural()) 194 .createTestSuite(); 195 } 196 197 public Test testsForTreeMapWithComparator() { 198 return NavigableMapTestSuiteBuilder 199 .using(new TestStringSortedMapGenerator() { 200 @Override protected SortedMap<String, String> create( 201 Entry<String, String>[] entries) { 202 return populate(new TreeMap<String, String>( 203 arbitraryNullFriendlyComparator()), entries); 204 } 205 }) 206 .named("TreeMap, with comparator") 207 .withFeatures( 208 MapFeature.GENERAL_PURPOSE, 209 MapFeature.ALLOWS_NULL_KEYS, 210 MapFeature.ALLOWS_NULL_VALUES, 211 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 212 CollectionFeature.KNOWN_ORDER, 213 CollectionFeature.SERIALIZABLE, 214 CollectionSize.ANY) 215 .suppressing(suppressForTreeMapWithComparator()) 216 .createTestSuite(); 217 } 218 219 public Test testsForEnumMap() { 220 return MapTestSuiteBuilder 221 .using(new TestEnumMapGenerator() { 222 @Override protected Map<AnEnum, String> create( 223 Entry<AnEnum, String>[] entries) { 224 return populate( 225 new EnumMap<AnEnum, String>(AnEnum.class), entries); 226 } 227 }) 228 .named("EnumMap") 229 .withFeatures( 230 MapFeature.GENERAL_PURPOSE, 231 MapFeature.ALLOWS_NULL_VALUES, 232 MapFeature.RESTRICTS_KEYS, 233 CollectionFeature.KNOWN_ORDER, 234 CollectionFeature.SERIALIZABLE, 235 CollectionSize.ANY) 236 .suppressing(suppressForEnumMap()) 237 .createTestSuite(); 238 } 239 240 public Test testsForConcurrentHashMap() { 241 return MapTestSuiteBuilder 242 .using(new TestStringMapGenerator() { 243 @Override protected Map<String, String> create( 244 Entry<String, String>[] entries) { 245 return populate(new ConcurrentHashMap<String, String>(), entries); 246 } 247 }) 248 .named("ConcurrentHashMap") 249 .withFeatures( 250 MapFeature.GENERAL_PURPOSE, 251 CollectionFeature.SERIALIZABLE, 252 CollectionSize.ANY) 253 .suppressing(suppressForConcurrentHashMap()) 254 .createTestSuite(); 255 } 256 257 public Test testsForConcurrentSkipListMapNatural() { 258 return NavigableMapTestSuiteBuilder 259 .using(new TestStringSortedMapGenerator() { 260 @Override protected SortedMap<String, String> create( 261 Entry<String, String>[] entries) { 262 return populate(new ConcurrentSkipListMap<String, String>(), entries); 263 } 264 }) 265 .named("ConcurrentSkipListMap, natural") 266 .withFeatures( 267 MapFeature.GENERAL_PURPOSE, 268 CollectionFeature.KNOWN_ORDER, 269 CollectionFeature.SERIALIZABLE, 270 CollectionSize.ANY) 271 .suppressing(suppressForConcurrentSkipListMap()) 272 .createTestSuite(); 273 } 274 275 public Test testsForConcurrentSkipListMapWithComparator() { 276 return NavigableMapTestSuiteBuilder 277 .using(new TestStringSortedMapGenerator() { 278 @Override protected SortedMap<String, String> create( 279 Entry<String, String>[] entries) { 280 return populate(new ConcurrentSkipListMap<String, String>( 281 arbitraryNullFriendlyComparator()), entries); 282 } 283 }) 284 .named("ConcurrentSkipListMap, with comparator") 285 .withFeatures( 286 MapFeature.GENERAL_PURPOSE, 287 CollectionFeature.KNOWN_ORDER, 288 CollectionFeature.SERIALIZABLE, 289 CollectionSize.ANY) 290 .suppressing(suppressForConcurrentSkipListMap()) 291 .createTestSuite(); 292 } 293 294 // TODO: IdentityHashMap, AbstractMap 295 296 private static Map<String, String> toHashMap( 297 Entry<String, String>[] entries) { 298 return populate(new HashMap<String, String>(), entries); 299 } 300 301 // TODO: call conversion constructors or factory methods instead of using 302 // populate() on an empty map 303 private static <T, M extends Map<T, String>> M populate( 304 M map, Entry<T, String>[] entries) { 305 for (Entry<T, String> entry : entries) { 306 map.put(entry.getKey(), entry.getValue()); 307 } 308 return map; 309 } 310 311 static <T> Comparator<T> arbitraryNullFriendlyComparator() { 312 return new NullFriendlyComparator<T>(); 313 } 314 315 private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable { 316 @Override 317 public int compare(T left, T right) { 318 return String.valueOf(left).compareTo(String.valueOf(right)); 319 } 320 } 321} 322