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