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 
suite()47   public static Test suite() {
48     return new TestsForMapsInJavaUtil().allTests();
49   }
50 
allTests()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 
suppressForEmptyMap()62   protected Collection<Method> suppressForEmptyMap() {
63     return Collections.emptySet();
64   }
suppressForSingletonMap()65   protected Collection<Method> suppressForSingletonMap() {
66     return Collections.emptySet();
67   }
suppressForHashMap()68   protected Collection<Method> suppressForHashMap() {
69     return Collections.emptySet();
70   }
suppressForLinkedHashMap()71   protected Collection<Method> suppressForLinkedHashMap() {
72     return Collections.emptySet();
73   }
suppressForTreeMapNatural()74   protected Collection<Method> suppressForTreeMapNatural() {
75     return Collections.emptySet();
76   }
suppressForTreeMapWithComparator()77   protected Collection<Method> suppressForTreeMapWithComparator() {
78     return Collections.emptySet();
79   }
suppressForEnumMap()80   protected Collection<Method> suppressForEnumMap() {
81     return Collections.emptySet();
82   }
suppressForConcurrentHashMap()83   protected Collection<Method> suppressForConcurrentHashMap() {
84     return Collections.emptySet();
85   }
suppressForConcurrentSkipListMap()86   protected Collection<Method> suppressForConcurrentSkipListMap() {
87     return Collections.emptySet();
88   }
89 
testsForEmptyMap()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