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 17 package com.google.common.collect.testing; 18 19 import com.google.common.collect.testing.features.CollectionFeature; 20 import com.google.common.collect.testing.features.CollectionSize; 21 import com.google.common.collect.testing.features.MapFeature; 22 23 import junit.framework.Test; 24 import junit.framework.TestSuite; 25 26 import java.io.Serializable; 27 import java.lang.reflect.Method; 28 import java.util.Collection; 29 import java.util.Collections; 30 import java.util.Comparator; 31 import java.util.EnumMap; 32 import java.util.HashMap; 33 import java.util.LinkedHashMap; 34 import java.util.Map; 35 import java.util.Map.Entry; 36 import java.util.concurrent.ConcurrentHashMap; 37 38 /** 39 * Generates a test suite covering the {@link Map} implementations in the 40 * {@link java.util} package. Can be subclassed to specify tests that should 41 * be suppressed. 42 * 43 * @author Kevin Bourrillion 44 */ 45 public class TestsForMapsInJavaUtil { 46 47 public static Test suite() { 48 return new TestsForMapsInJavaUtil().allTests(); 49 } 50 51 public Test allTests() { 52 TestSuite suite = new TestSuite("java.util Maps"); 53 suite.addTest(testsForEmptyMap()); 54 suite.addTest(testsForSingletonMap()); 55 suite.addTest(testsForHashMap()); 56 suite.addTest(testsForLinkedHashMap()); 57 suite.addTest(testsForEnumMap()); 58 suite.addTest(testsForConcurrentHashMap()); 59 return suite; 60 } 61 62 protected Collection<Method> suppressForEmptyMap() { 63 return Collections.emptySet(); 64 } 65 protected Collection<Method> suppressForSingletonMap() { 66 return Collections.emptySet(); 67 } 68 protected Collection<Method> suppressForHashMap() { 69 return Collections.emptySet(); 70 } 71 protected Collection<Method> suppressForLinkedHashMap() { 72 return Collections.emptySet(); 73 } 74 protected Collection<Method> suppressForTreeMapNatural() { 75 return Collections.emptySet(); 76 } 77 protected Collection<Method> suppressForTreeMapWithComparator() { 78 return Collections.emptySet(); 79 } 80 protected Collection<Method> suppressForEnumMap() { 81 return Collections.emptySet(); 82 } 83 protected Collection<Method> suppressForConcurrentHashMap() { 84 return Collections.emptySet(); 85 } 86 protected Collection<Method> suppressForConcurrentSkipListMap() { 87 return Collections.emptySet(); 88 } 89 90 public Test testsForEmptyMap() { 91 return MapTestSuiteBuilder 92 .using(new TestStringMapGenerator() { 93 @Override protected Map<String, String> create( 94 Entry<String, String>[] entries) { 95 return Collections.emptyMap(); 96 } 97 }) 98 .named("emptyMap") 99 .withFeatures( 100 CollectionFeature.SERIALIZABLE, 101 CollectionSize.ZERO) 102 .suppressing(suppressForEmptyMap()) 103 .createTestSuite(); 104 } 105 106 public Test testsForSingletonMap() { 107 return MapTestSuiteBuilder 108 .using(new TestStringMapGenerator() { 109 @Override protected Map<String, String> create( 110 Entry<String, String>[] entries) { 111 return Collections.singletonMap( 112 entries[0].getKey(), entries[0].getValue()); 113 } 114 }) 115 .named("singletonMap") 116 .withFeatures( 117 MapFeature.ALLOWS_NULL_KEYS, 118 MapFeature.ALLOWS_NULL_VALUES, 119 MapFeature.ALLOWS_ANY_NULL_QUERIES, 120 CollectionFeature.SERIALIZABLE, 121 CollectionSize.ONE) 122 .suppressing(suppressForSingletonMap()) 123 .createTestSuite(); 124 } 125 126 public Test testsForHashMap() { 127 return MapTestSuiteBuilder 128 .using(new TestStringMapGenerator() { 129 @Override protected Map<String, String> create( 130 Entry<String, String>[] entries) { 131 return toHashMap(entries); 132 } 133 }) 134 .named("HashMap") 135 .withFeatures( 136 MapFeature.GENERAL_PURPOSE, 137 MapFeature.ALLOWS_NULL_KEYS, 138 MapFeature.ALLOWS_NULL_VALUES, 139 MapFeature.ALLOWS_ANY_NULL_QUERIES, 140 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 141 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 142 CollectionFeature.SERIALIZABLE, 143 CollectionSize.ANY) 144 .suppressing(suppressForHashMap()) 145 .createTestSuite(); 146 } 147 148 public Test testsForLinkedHashMap() { 149 return MapTestSuiteBuilder 150 .using(new TestStringMapGenerator() { 151 @Override protected Map<String, String> create( 152 Entry<String, String>[] entries) { 153 return populate(new LinkedHashMap<String, String>(), entries); 154 } 155 }) 156 .named("LinkedHashMap") 157 .withFeatures( 158 MapFeature.GENERAL_PURPOSE, 159 MapFeature.ALLOWS_NULL_KEYS, 160 MapFeature.ALLOWS_NULL_VALUES, 161 MapFeature.ALLOWS_ANY_NULL_QUERIES, 162 MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 163 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 164 CollectionFeature.KNOWN_ORDER, 165 CollectionFeature.SERIALIZABLE, 166 CollectionSize.ANY) 167 .suppressing(suppressForLinkedHashMap()) 168 .createTestSuite(); 169 } 170 171 public Test testsForEnumMap() { 172 return MapTestSuiteBuilder 173 .using(new TestEnumMapGenerator() { 174 @Override protected Map<AnEnum, String> create( 175 Entry<AnEnum, String>[] entries) { 176 return populate( 177 new EnumMap<AnEnum, String>(AnEnum.class), entries); 178 } 179 }) 180 .named("EnumMap") 181 .withFeatures( 182 MapFeature.GENERAL_PURPOSE, 183 MapFeature.ALLOWS_NULL_VALUES, 184 MapFeature.RESTRICTS_KEYS, 185 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 186 CollectionFeature.KNOWN_ORDER, 187 CollectionFeature.SERIALIZABLE, 188 CollectionSize.ANY) 189 .suppressing(suppressForEnumMap()) 190 .createTestSuite(); 191 } 192 193 public Test testsForConcurrentHashMap() { 194 return MapTestSuiteBuilder 195 .using(new TestStringMapGenerator() { 196 @Override protected Map<String, String> create( 197 Entry<String, String>[] entries) { 198 return populate(new ConcurrentHashMap<String, String>(), entries); 199 } 200 }) 201 .named("ConcurrentHashMap") 202 .withFeatures( 203 MapFeature.GENERAL_PURPOSE, 204 CollectionFeature.SUPPORTS_ITERATOR_REMOVE, 205 CollectionFeature.SERIALIZABLE, 206 CollectionSize.ANY) 207 .suppressing(suppressForConcurrentHashMap()) 208 .createTestSuite(); 209 } 210 211 // TODO: IdentityHashMap, AbstractMap 212 213 private static Map<String, String> toHashMap( 214 Entry<String, String>[] entries) { 215 return populate(new HashMap<String, String>(), entries); 216 } 217 218 // TODO: call conversion constructors or factory methods instead of using 219 // populate() on an empty map 220 private static <T, M extends Map<T, String>> M populate( 221 M map, Entry<T, String>[] entries) { 222 for (Entry<T, String> entry : entries) { 223 map.put(entry.getKey(), entry.getValue()); 224 } 225 return map; 226 } 227 228 static <T> Comparator<T> arbitraryNullFriendlyComparator() { 229 return new NullFriendlyComparator<T>(); 230 } 231 232 private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable { 233 @Override 234 public int compare(T left, T right) { 235 return String.valueOf(left).compareTo(String.valueOf(right)); 236 } 237 } 238 } 239