• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static java.util.Arrays.asList;
20 
21 import com.google.common.annotations.GwtIncompatible;
22 import com.google.common.collect.testing.features.CollectionFeature;
23 import com.google.common.collect.testing.features.CollectionSize;
24 import com.google.common.collect.testing.features.MapFeature;
25 import com.google.common.collect.testing.testers.MapEntrySetTester;
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.Hashtable;
34 import java.util.LinkedHashMap;
35 import java.util.Map;
36 import java.util.Map.Entry;
37 import java.util.NavigableMap;
38 import java.util.SortedMap;
39 import java.util.TreeMap;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.ConcurrentSkipListMap;
42 import junit.framework.Test;
43 import junit.framework.TestSuite;
44 
45 /**
46  * Generates a test suite covering the {@link Map} implementations in the {@link java.util} package.
47  * Can be subclassed to specify tests that should be suppressed.
48  *
49  * @author Kevin Bourrillion
50  */
51 @GwtIncompatible
52 public class TestsForMapsInJavaUtil {
53 
suite()54   public static Test suite() {
55     return new TestsForMapsInJavaUtil().allTests();
56   }
57 
allTests()58   public Test allTests() {
59     TestSuite suite = new TestSuite("java.util Maps");
60     suite.addTest(testsForCheckedMap());
61     suite.addTest(testsForCheckedNavigableMap());
62     suite.addTest(testsForCheckedSortedMap());
63     suite.addTest(testsForEmptyMap());
64     suite.addTest(testsForEmptyNavigableMap());
65     suite.addTest(testsForEmptySortedMap());
66     suite.addTest(testsForSingletonMap());
67     suite.addTest(testsForHashMap());
68     suite.addTest(testsForHashtable());
69     suite.addTest(testsForLinkedHashMap());
70     suite.addTest(testsForSynchronizedNavigableMap());
71     suite.addTest(testsForTreeMapNatural());
72     suite.addTest(testsForTreeMapWithComparator());
73     suite.addTest(testsForUnmodifiableMap());
74     suite.addTest(testsForUnmodifiableNavigableMap());
75     suite.addTest(testsForUnmodifiableSortedMap());
76     suite.addTest(testsForEnumMap());
77     suite.addTest(testsForConcurrentHashMap());
78     suite.addTest(testsForConcurrentSkipListMapNatural());
79     suite.addTest(testsForConcurrentSkipListMapWithComparator());
80     return suite;
81   }
82 
suppressForCheckedMap()83   protected Collection<Method> suppressForCheckedMap() {
84     return Collections.emptySet();
85   }
86 
suppressForCheckedNavigableMap()87   protected Collection<Method> suppressForCheckedNavigableMap() {
88     return Collections.emptySet();
89   }
90 
suppressForCheckedSortedMap()91   protected Collection<Method> suppressForCheckedSortedMap() {
92     return Collections.emptySet();
93   }
94 
suppressForEmptyMap()95   protected Collection<Method> suppressForEmptyMap() {
96     return Collections.emptySet();
97   }
98 
suppressForEmptyNavigableMap()99   private Collection<Method> suppressForEmptyNavigableMap() {
100     return Collections.emptySet();
101   }
102 
suppressForEmptySortedMap()103   private Collection<Method> suppressForEmptySortedMap() {
104     return Collections.emptySet();
105   }
106 
suppressForSingletonMap()107   protected Collection<Method> suppressForSingletonMap() {
108     return Collections.emptySet();
109   }
110 
suppressForHashMap()111   protected Collection<Method> suppressForHashMap() {
112     return Collections.emptySet();
113   }
114 
suppressForHashtable()115   protected Collection<Method> suppressForHashtable() {
116     return Collections.emptySet();
117   }
118 
suppressForLinkedHashMap()119   protected Collection<Method> suppressForLinkedHashMap() {
120     return Collections.emptySet();
121   }
122 
suppressForSynchronizedNavigableMap()123   protected Collection<Method> suppressForSynchronizedNavigableMap() {
124     return Collections.emptySet();
125   }
126 
suppressForTreeMapNatural()127   protected Collection<Method> suppressForTreeMapNatural() {
128     return Collections.emptySet();
129   }
130 
suppressForTreeMapWithComparator()131   protected Collection<Method> suppressForTreeMapWithComparator() {
132     return Collections.emptySet();
133   }
134 
suppressForUnmodifiableMap()135   protected Collection<Method> suppressForUnmodifiableMap() {
136     return Collections.emptySet();
137   }
138 
suppressForUnmodifiableNavigableMap()139   protected Collection<Method> suppressForUnmodifiableNavigableMap() {
140     return Collections.emptySet();
141   }
142 
suppressForUnmodifiableSortedMap()143   protected Collection<Method> suppressForUnmodifiableSortedMap() {
144     return Collections.emptySet();
145   }
146 
suppressForEnumMap()147   protected Collection<Method> suppressForEnumMap() {
148     return Collections.emptySet();
149   }
150 
suppressForConcurrentHashMap()151   protected Collection<Method> suppressForConcurrentHashMap() {
152     return Collections.emptySet();
153   }
154 
suppressForConcurrentSkipListMap()155   protected Collection<Method> suppressForConcurrentSkipListMap() {
156     return asList(
157         MapEntrySetTester.getSetValueMethod(),
158         MapEntrySetTester.getSetValueWithNullValuesAbsentMethod(),
159         MapEntrySetTester.getSetValueWithNullValuesPresentMethod());
160   }
161 
testsForCheckedMap()162   public Test testsForCheckedMap() {
163     return MapTestSuiteBuilder.using(
164             new TestStringMapGenerator() {
165               @Override
166               protected Map<String, String> create(Entry<String, String>[] entries) {
167                 Map<String, String> map = populate(new HashMap<String, String>(), entries);
168                 return Collections.checkedMap(map, String.class, String.class);
169               }
170             })
171         .named("checkedMap/HashMap")
172         .withFeatures(
173             MapFeature.GENERAL_PURPOSE,
174             MapFeature.ALLOWS_NULL_KEYS,
175             MapFeature.ALLOWS_NULL_VALUES,
176             MapFeature.ALLOWS_ANY_NULL_QUERIES,
177             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
178             MapFeature.RESTRICTS_KEYS,
179             MapFeature.RESTRICTS_VALUES,
180             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
181             CollectionFeature.SERIALIZABLE,
182             CollectionSize.ANY)
183         .suppressing(suppressForCheckedMap())
184         .createTestSuite();
185   }
186 
187   public Test testsForCheckedNavigableMap() {
188     return SortedMapTestSuiteBuilder.using(
189             new TestStringSortedMapGenerator() {
190               @Override
191               protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
192                 NavigableMap<String, String> map = populate(new TreeMap<String, String>(), entries);
193                 return Collections.checkedNavigableMap(map, String.class, String.class);
194               }
195             })
196         .named("checkedNavigableMap/TreeMap, natural")
197         .withFeatures(
198             MapFeature.GENERAL_PURPOSE,
199             MapFeature.ALLOWS_NULL_VALUES,
200             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
201             MapFeature.RESTRICTS_KEYS,
202             MapFeature.RESTRICTS_VALUES,
203             CollectionFeature.KNOWN_ORDER,
204             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
205             CollectionFeature.SERIALIZABLE,
206             CollectionSize.ANY)
207         .suppressing(suppressForCheckedNavigableMap())
208         .createTestSuite();
209   }
210 
211   public Test testsForCheckedSortedMap() {
212     return SortedMapTestSuiteBuilder.using(
213             new TestStringSortedMapGenerator() {
214               @Override
215               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
216                 SortedMap<String, String> map = populate(new TreeMap<String, String>(), entries);
217                 return Collections.checkedSortedMap(map, String.class, String.class);
218               }
219             })
220         .named("checkedSortedMap/TreeMap, natural")
221         .withFeatures(
222             MapFeature.GENERAL_PURPOSE,
223             MapFeature.ALLOWS_NULL_VALUES,
224             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
225             MapFeature.RESTRICTS_KEYS,
226             MapFeature.RESTRICTS_VALUES,
227             CollectionFeature.KNOWN_ORDER,
228             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
229             CollectionFeature.SERIALIZABLE,
230             CollectionSize.ANY)
231         .suppressing(suppressForCheckedSortedMap())
232         .createTestSuite();
233   }
234 
235   public Test testsForEmptyMap() {
236     return MapTestSuiteBuilder.using(
237             new TestStringMapGenerator() {
238               @Override
239               protected Map<String, String> create(Entry<String, String>[] entries) {
240                 return Collections.emptyMap();
241               }
242             })
243         .named("emptyMap")
244         .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO)
245         .suppressing(suppressForEmptyMap())
246         .createTestSuite();
247   }
248 
249   public Test testsForEmptyNavigableMap() {
250     return MapTestSuiteBuilder.using(
251             new TestStringSortedMapGenerator() {
252               @Override
253               protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
254                 return Collections.emptyNavigableMap();
255               }
256             })
257         .named("emptyNavigableMap")
258         .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO)
259         .suppressing(suppressForEmptyNavigableMap())
260         .createTestSuite();
261   }
262 
263   public Test testsForEmptySortedMap() {
264     return MapTestSuiteBuilder.using(
265             new TestStringSortedMapGenerator() {
266               @Override
267               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
268                 return Collections.emptySortedMap();
269               }
270             })
271         .named("emptySortedMap")
272         .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO)
273         .suppressing(suppressForEmptySortedMap())
274         .createTestSuite();
275   }
276 
277   public Test testsForSingletonMap() {
278     return MapTestSuiteBuilder.using(
279             new TestStringMapGenerator() {
280               @Override
281               protected Map<String, String> create(Entry<String, String>[] entries) {
282                 return Collections.singletonMap(entries[0].getKey(), entries[0].getValue());
283               }
284             })
285         .named("singletonMap")
286         .withFeatures(
287             MapFeature.ALLOWS_NULL_KEYS,
288             MapFeature.ALLOWS_NULL_VALUES,
289             MapFeature.ALLOWS_ANY_NULL_QUERIES,
290             CollectionFeature.SERIALIZABLE,
291             CollectionSize.ONE)
292         .suppressing(suppressForSingletonMap())
293         .createTestSuite();
294   }
295 
296   public Test testsForHashMap() {
297     return MapTestSuiteBuilder.using(
298             new TestStringMapGenerator() {
299               @Override
300               protected Map<String, String> create(Entry<String, String>[] entries) {
301                 return toHashMap(entries);
302               }
303             })
304         .named("HashMap")
305         .withFeatures(
306             MapFeature.GENERAL_PURPOSE,
307             MapFeature.ALLOWS_NULL_KEYS,
308             MapFeature.ALLOWS_NULL_VALUES,
309             MapFeature.ALLOWS_ANY_NULL_QUERIES,
310             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
311             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
312             CollectionFeature.SERIALIZABLE,
313             CollectionSize.ANY)
314         .suppressing(suppressForHashMap())
315         .createTestSuite();
316   }
317 
318   public Test testsForHashtable() {
319     return MapTestSuiteBuilder.using(
320             new TestStringMapGenerator() {
321               @Override
322               protected Map<String, String> create(Entry<String, String>[] entries) {
323                 return populate(new Hashtable<String, String>(), entries);
324               }
325             })
326         .withFeatures(
327             MapFeature.GENERAL_PURPOSE,
328             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
329             MapFeature.RESTRICTS_KEYS,
330             MapFeature.SUPPORTS_REMOVE,
331             CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
332             CollectionFeature.SERIALIZABLE,
333             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
334             CollectionFeature.SUPPORTS_REMOVE,
335             CollectionSize.ANY)
336         .named("Hashtable")
337         .suppressing(suppressForHashtable())
338         .createTestSuite();
339   }
340 
341   public Test testsForLinkedHashMap() {
342     return MapTestSuiteBuilder.using(
343             new TestStringMapGenerator() {
344               @Override
345               protected Map<String, String> create(Entry<String, String>[] entries) {
346                 return populate(new LinkedHashMap<String, String>(), entries);
347               }
348             })
349         .named("LinkedHashMap")
350         .withFeatures(
351             MapFeature.GENERAL_PURPOSE,
352             MapFeature.ALLOWS_NULL_KEYS,
353             MapFeature.ALLOWS_NULL_VALUES,
354             MapFeature.ALLOWS_ANY_NULL_QUERIES,
355             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
356             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
357             CollectionFeature.KNOWN_ORDER,
358             CollectionFeature.SERIALIZABLE,
359             CollectionSize.ANY)
360         .suppressing(suppressForLinkedHashMap())
361         .createTestSuite();
362   }
363 
364   /**
365    * Tests regular NavigableMap behavior of synchronizedNavigableMap(treeMap); does not test the
366    * fact that it's synchronized.
367    */
368   public Test testsForSynchronizedNavigableMap() {
369     return NavigableMapTestSuiteBuilder.using(
370             new TestStringSortedMapGenerator() {
371               @Override
372               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
373                 NavigableMap<String, String> delegate = populate(new TreeMap<>(), entries);
374                 return Collections.synchronizedNavigableMap(delegate);
375               }
376             })
377         .named("synchronizedNavigableMap/TreeMap, natural")
378         .withFeatures(
379             MapFeature.GENERAL_PURPOSE,
380             MapFeature.ALLOWS_NULL_VALUES,
381             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
382             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
383             CollectionFeature.KNOWN_ORDER,
384             CollectionFeature.SERIALIZABLE,
385             CollectionSize.ANY)
386         .suppressing(suppressForSynchronizedNavigableMap())
387         .createTestSuite();
388   }
389 
390   public Test testsForTreeMapNatural() {
391     return NavigableMapTestSuiteBuilder.using(
392             new TestStringSortedMapGenerator() {
393               @Override
394               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
395                 /*
396                  * TODO(cpovirk): it would be nice to create an input Map and use
397                  * the copy constructor here and in the other tests
398                  */
399                 return populate(new TreeMap<String, String>(), entries);
400               }
401             })
402         .named("TreeMap, natural")
403         .withFeatures(
404             MapFeature.GENERAL_PURPOSE,
405             MapFeature.ALLOWS_NULL_VALUES,
406             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
407             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
408             CollectionFeature.KNOWN_ORDER,
409             CollectionFeature.SERIALIZABLE,
410             CollectionSize.ANY)
411         .suppressing(suppressForTreeMapNatural())
412         .createTestSuite();
413   }
414 
415   public Test testsForTreeMapWithComparator() {
416     return NavigableMapTestSuiteBuilder.using(
417             new TestStringSortedMapGenerator() {
418               @Override
419               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
420                 return populate(
421                     new TreeMap<String, String>(arbitraryNullFriendlyComparator()), entries);
422               }
423             })
424         .named("TreeMap, with comparator")
425         .withFeatures(
426             MapFeature.GENERAL_PURPOSE,
427             MapFeature.ALLOWS_NULL_KEYS,
428             MapFeature.ALLOWS_NULL_VALUES,
429             MapFeature.ALLOWS_ANY_NULL_QUERIES,
430             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
431             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
432             CollectionFeature.KNOWN_ORDER,
433             CollectionFeature.SERIALIZABLE,
434             CollectionSize.ANY)
435         .suppressing(suppressForTreeMapWithComparator())
436         .createTestSuite();
437   }
438 
439   public Test testsForUnmodifiableMap() {
440     return MapTestSuiteBuilder.using(
441             new TestStringMapGenerator() {
442               @Override
443               protected Map<String, String> create(Entry<String, String>[] entries) {
444                 return Collections.unmodifiableMap(toHashMap(entries));
445               }
446             })
447         .named("unmodifiableMap/HashMap")
448         .withFeatures(
449             MapFeature.ALLOWS_NULL_KEYS,
450             MapFeature.ALLOWS_NULL_VALUES,
451             MapFeature.ALLOWS_ANY_NULL_QUERIES,
452             CollectionFeature.SERIALIZABLE,
453             CollectionSize.ANY)
454         .suppressing(suppressForUnmodifiableMap())
455         .createTestSuite();
456   }
457 
458   public Test testsForUnmodifiableNavigableMap() {
459     return MapTestSuiteBuilder.using(
460             new TestStringSortedMapGenerator() {
461               @Override
462               protected NavigableMap<String, String> create(Entry<String, String>[] entries) {
463                 return Collections.unmodifiableNavigableMap(populate(new TreeMap<>(), entries));
464               }
465             })
466         .named("unmodifiableNavigableMap/TreeMap, natural")
467         .withFeatures(
468             MapFeature.ALLOWS_NULL_VALUES,
469             CollectionFeature.KNOWN_ORDER,
470             CollectionFeature.SERIALIZABLE,
471             CollectionSize.ANY)
472         .suppressing(suppressForUnmodifiableNavigableMap())
473         .createTestSuite();
474   }
475 
476   public Test testsForUnmodifiableSortedMap() {
477     return MapTestSuiteBuilder.using(
478             new TestStringSortedMapGenerator() {
479               @Override
480               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
481                 SortedMap<String, String> map = populate(new TreeMap<String, String>(), entries);
482                 return Collections.unmodifiableSortedMap(map);
483               }
484             })
485         .named("unmodifiableSortedMap/TreeMap, natural")
486         .withFeatures(
487             MapFeature.ALLOWS_NULL_VALUES,
488             CollectionFeature.KNOWN_ORDER,
489             CollectionFeature.SERIALIZABLE,
490             CollectionSize.ANY)
491         .suppressing(suppressForUnmodifiableSortedMap())
492         .createTestSuite();
493   }
494 
495   public Test testsForEnumMap() {
496     return MapTestSuiteBuilder.using(
497             new TestEnumMapGenerator() {
498               @Override
499               protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
500                 return populate(new EnumMap<AnEnum, String>(AnEnum.class), entries);
501               }
502             })
503         .named("EnumMap")
504         .withFeatures(
505             MapFeature.GENERAL_PURPOSE,
506             MapFeature.ALLOWS_NULL_VALUES,
507             MapFeature.RESTRICTS_KEYS,
508             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
509             CollectionFeature.KNOWN_ORDER,
510             CollectionFeature.SERIALIZABLE,
511             CollectionSize.ANY)
512         .suppressing(suppressForEnumMap())
513         .createTestSuite();
514   }
515 
516   public Test testsForConcurrentHashMap() {
517     return MapTestSuiteBuilder.using(
518             new TestStringMapGenerator() {
519               @Override
520               protected Map<String, String> create(Entry<String, String>[] entries) {
521                 return populate(new ConcurrentHashMap<String, String>(), entries);
522               }
523             })
524         .named("ConcurrentHashMap")
525         .withFeatures(
526             MapFeature.GENERAL_PURPOSE,
527             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
528             CollectionFeature.SERIALIZABLE,
529             CollectionSize.ANY)
530         .suppressing(suppressForConcurrentHashMap())
531         .createTestSuite();
532   }
533 
534   public Test testsForConcurrentSkipListMapNatural() {
535     return NavigableMapTestSuiteBuilder.using(
536             new TestStringSortedMapGenerator() {
537               @Override
538               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
539                 return populate(new ConcurrentSkipListMap<String, String>(), entries);
540               }
541             })
542         .named("ConcurrentSkipListMap, natural")
543         .withFeatures(
544             MapFeature.GENERAL_PURPOSE,
545             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
546             CollectionFeature.KNOWN_ORDER,
547             CollectionFeature.SERIALIZABLE,
548             CollectionSize.ANY)
549         .suppressing(suppressForConcurrentSkipListMap())
550         .createTestSuite();
551   }
552 
553   public Test testsForConcurrentSkipListMapWithComparator() {
554     return NavigableMapTestSuiteBuilder.using(
555             new TestStringSortedMapGenerator() {
556               @Override
557               protected SortedMap<String, String> create(Entry<String, String>[] entries) {
558                 return populate(
559                     new ConcurrentSkipListMap<String, String>(arbitraryNullFriendlyComparator()),
560                     entries);
561               }
562             })
563         .named("ConcurrentSkipListMap, with comparator")
564         .withFeatures(
565             MapFeature.GENERAL_PURPOSE,
566             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
567             CollectionFeature.KNOWN_ORDER,
568             CollectionFeature.SERIALIZABLE,
569             CollectionSize.ANY)
570         .suppressing(suppressForConcurrentSkipListMap())
571         .createTestSuite();
572   }
573 
574   // TODO: IdentityHashMap, AbstractMap
575 
576   private static Map<String, String> toHashMap(Entry<String, String>[] entries) {
577     return populate(new HashMap<String, String>(), entries);
578   }
579 
580   // TODO: call conversion constructors or factory methods instead of using
581   // populate() on an empty map
582   private static <T, M extends Map<T, String>> M populate(M map, Entry<T, String>[] entries) {
583     for (Entry<T, String> entry : entries) {
584       map.put(entry.getKey(), entry.getValue());
585     }
586     return map;
587   }
588 
589   static <T> Comparator<T> arbitraryNullFriendlyComparator() {
590     return new NullFriendlyComparator<T>();
591   }
592 
593   private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable {
594     @Override
595     public int compare(T left, T right) {
596       return String.valueOf(left).compareTo(String.valueOf(right));
597     }
598   }
599 }
600