| /* |
| * Copyright (C) 2009 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.collect.testing; |
| |
| import static java.util.Arrays.asList; |
| |
| import com.google.common.annotations.GwtIncompatible; |
| import com.google.common.collect.testing.features.CollectionFeature; |
| import com.google.common.collect.testing.features.CollectionSize; |
| import com.google.common.collect.testing.features.MapFeature; |
| import com.google.common.collect.testing.testers.MapEntrySetTester; |
| import java.io.Serializable; |
| import java.lang.reflect.Method; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.EnumMap; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.SortedMap; |
| import java.util.TreeMap; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentSkipListMap; |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| /** |
| * Generates a test suite covering the {@link Map} implementations in the {@link java.util} package. |
| * Can be subclassed to specify tests that should be suppressed. |
| * |
| * @author Kevin Bourrillion |
| */ |
| @GwtIncompatible |
| public class TestsForMapsInJavaUtil { |
| |
| public static Test suite() { |
| return new TestsForMapsInJavaUtil().allTests(); |
| } |
| |
| public Test allTests() { |
| TestSuite suite = new TestSuite("java.util Maps"); |
| suite.addTest(testsForCheckedMap()); |
| suite.addTest(testsForCheckedSortedMap()); |
| suite.addTest(testsForEmptyMap()); |
| suite.addTest(testsForSingletonMap()); |
| suite.addTest(testsForHashMap()); |
| suite.addTest(testsForHashtable()); |
| suite.addTest(testsForLinkedHashMap()); |
| suite.addTest(testsForTreeMapNatural()); |
| suite.addTest(testsForTreeMapWithComparator()); |
| suite.addTest(testsForUnmodifiableMap()); |
| suite.addTest(testsForUnmodifiableSortedMap()); |
| suite.addTest(testsForEnumMap()); |
| suite.addTest(testsForConcurrentHashMap()); |
| suite.addTest(testsForConcurrentSkipListMapNatural()); |
| suite.addTest(testsForConcurrentSkipListMapWithComparator()); |
| return suite; |
| } |
| |
| protected Collection<Method> suppressForCheckedMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForCheckedSortedMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForEmptyMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForSingletonMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForHashMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForHashtable() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForLinkedHashMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForTreeMapNatural() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForTreeMapWithComparator() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForUnmodifiableMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForUnmodifiableSortedMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForEnumMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForConcurrentHashMap() { |
| return Collections.emptySet(); |
| } |
| |
| protected Collection<Method> suppressForConcurrentSkipListMap() { |
| return asList( |
| MapEntrySetTester.getSetValueMethod(), |
| MapEntrySetTester.getSetValueWithNullValuesAbsentMethod(), |
| MapEntrySetTester.getSetValueWithNullValuesPresentMethod()); |
| } |
| |
| public Test testsForCheckedMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| Map<String, String> map = populate(new HashMap<String, String>(), entries); |
| return Collections.checkedMap(map, String.class, String.class); |
| } |
| }) |
| .named("checkedMap/HashMap") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_KEYS, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.ALLOWS_ANY_NULL_QUERIES, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| MapFeature.RESTRICTS_KEYS, |
| MapFeature.RESTRICTS_VALUES, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForCheckedMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForCheckedSortedMap() { |
| return SortedMapTestSuiteBuilder.using( |
| new TestStringSortedMapGenerator() { |
| @Override |
| protected SortedMap<String, String> create(Entry<String, String>[] entries) { |
| SortedMap<String, String> map = populate(new TreeMap<String, String>(), entries); |
| return Collections.checkedSortedMap(map, String.class, String.class); |
| } |
| }) |
| .named("checkedSortedMap/TreeMap, natural") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| MapFeature.RESTRICTS_KEYS, |
| MapFeature.RESTRICTS_VALUES, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForCheckedSortedMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForEmptyMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return Collections.emptyMap(); |
| } |
| }) |
| .named("emptyMap") |
| .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO) |
| .suppressing(suppressForEmptyMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForSingletonMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return Collections.singletonMap(entries[0].getKey(), entries[0].getValue()); |
| } |
| }) |
| .named("singletonMap") |
| .withFeatures( |
| MapFeature.ALLOWS_NULL_KEYS, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.ALLOWS_ANY_NULL_QUERIES, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ONE) |
| .suppressing(suppressForSingletonMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForHashMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return toHashMap(entries); |
| } |
| }) |
| .named("HashMap") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_KEYS, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.ALLOWS_ANY_NULL_QUERIES, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForHashMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForHashtable() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return populate(new Hashtable<String, String>(), entries); |
| } |
| }) |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| MapFeature.RESTRICTS_KEYS, |
| MapFeature.SUPPORTS_REMOVE, |
| CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| CollectionFeature.SERIALIZABLE, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.SUPPORTS_REMOVE, |
| CollectionSize.ANY) |
| .named("Hashtable") |
| .suppressing(suppressForHashtable()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForLinkedHashMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return populate(new LinkedHashMap<String, String>(), entries); |
| } |
| }) |
| .named("LinkedHashMap") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_KEYS, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.ALLOWS_ANY_NULL_QUERIES, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForLinkedHashMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForTreeMapNatural() { |
| return NavigableMapTestSuiteBuilder.using( |
| new TestStringSortedMapGenerator() { |
| @Override |
| protected SortedMap<String, String> create(Entry<String, String>[] entries) { |
| /* |
| * TODO(cpovirk): it would be nice to create an input Map and use |
| * the copy constructor here and in the other tests |
| */ |
| return populate(new TreeMap<String, String>(), entries); |
| } |
| }) |
| .named("TreeMap, natural") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForTreeMapNatural()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForTreeMapWithComparator() { |
| return NavigableMapTestSuiteBuilder.using( |
| new TestStringSortedMapGenerator() { |
| @Override |
| protected SortedMap<String, String> create(Entry<String, String>[] entries) { |
| return populate( |
| new TreeMap<String, String>(arbitraryNullFriendlyComparator()), entries); |
| } |
| }) |
| .named("TreeMap, with comparator") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_KEYS, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.ALLOWS_ANY_NULL_QUERIES, |
| MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForTreeMapWithComparator()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForUnmodifiableMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return Collections.unmodifiableMap(toHashMap(entries)); |
| } |
| }) |
| .named("unmodifiableMap/HashMap") |
| .withFeatures( |
| MapFeature.ALLOWS_NULL_KEYS, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.ALLOWS_ANY_NULL_QUERIES, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForUnmodifiableMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForUnmodifiableSortedMap() { |
| return MapTestSuiteBuilder.using( |
| new TestStringSortedMapGenerator() { |
| @Override |
| protected SortedMap<String, String> create(Entry<String, String>[] entries) { |
| SortedMap<String, String> map = populate(new TreeMap<String, String>(), entries); |
| return Collections.unmodifiableSortedMap(map); |
| } |
| }) |
| .named("unmodifiableSortedMap/TreeMap, natural") |
| .withFeatures( |
| MapFeature.ALLOWS_NULL_VALUES, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForUnmodifiableSortedMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForEnumMap() { |
| return MapTestSuiteBuilder.using( |
| new TestEnumMapGenerator() { |
| @Override |
| protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) { |
| return populate(new EnumMap<AnEnum, String>(AnEnum.class), entries); |
| } |
| }) |
| .named("EnumMap") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| MapFeature.ALLOWS_NULL_VALUES, |
| MapFeature.RESTRICTS_KEYS, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForEnumMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForConcurrentHashMap() { |
| return ConcurrentMapTestSuiteBuilder.using( |
| new TestStringMapGenerator() { |
| @Override |
| protected Map<String, String> create(Entry<String, String>[] entries) { |
| return populate(new ConcurrentHashMap<String, String>(), entries); |
| } |
| }) |
| .named("ConcurrentHashMap") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForConcurrentHashMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForConcurrentSkipListMapNatural() { |
| return ConcurrentNavigableMapTestSuiteBuilder.using( |
| new TestStringSortedMapGenerator() { |
| @Override |
| protected SortedMap<String, String> create(Entry<String, String>[] entries) { |
| return populate(new ConcurrentSkipListMap<String, String>(), entries); |
| } |
| }) |
| .named("ConcurrentSkipListMap, natural") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForConcurrentSkipListMap()) |
| .createTestSuite(); |
| } |
| |
| public Test testsForConcurrentSkipListMapWithComparator() { |
| return ConcurrentNavigableMapTestSuiteBuilder.using( |
| new TestStringSortedMapGenerator() { |
| @Override |
| protected SortedMap<String, String> create(Entry<String, String>[] entries) { |
| return populate( |
| new ConcurrentSkipListMap<String, String>(arbitraryNullFriendlyComparator()), |
| entries); |
| } |
| }) |
| .named("ConcurrentSkipListMap, with comparator") |
| .withFeatures( |
| MapFeature.GENERAL_PURPOSE, |
| CollectionFeature.SUPPORTS_ITERATOR_REMOVE, |
| CollectionFeature.KNOWN_ORDER, |
| CollectionFeature.SERIALIZABLE, |
| CollectionSize.ANY) |
| .suppressing(suppressForConcurrentSkipListMap()) |
| .createTestSuite(); |
| } |
| |
| // TODO: IdentityHashMap, AbstractMap |
| |
| private static Map<String, String> toHashMap(Entry<String, String>[] entries) { |
| return populate(new HashMap<String, String>(), entries); |
| } |
| |
| // TODO: call conversion constructors or factory methods instead of using |
| // populate() on an empty map |
| private static <T, M extends Map<T, String>> M populate(M map, Entry<T, String>[] entries) { |
| for (Entry<T, String> entry : entries) { |
| map.put(entry.getKey(), entry.getValue()); |
| } |
| return map; |
| } |
| |
| static <T> Comparator<T> arbitraryNullFriendlyComparator() { |
| return new NullFriendlyComparator<T>(); |
| } |
| |
| private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable { |
| @Override |
| public int compare(T left, T right) { |
| return String.valueOf(left).compareTo(String.valueOf(right)); |
| } |
| } |
| } |