Home | History | Annotate | Download | only in testing
      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.SortedMap;
     37 import java.util.TreeMap;
     38 import java.util.concurrent.ConcurrentHashMap;
     39 import 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  */
     48 public 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             MapFeature.ALLOWS_ANY_NULL_QUERIES,
    127             CollectionFeature.SERIALIZABLE,
    128             CollectionSize.ONE)
    129         .suppressing(suppressForSingletonMap())
    130         .createTestSuite();
    131   }
    132 
    133   public Test testsForHashMap() {
    134     return MapTestSuiteBuilder
    135         .using(new TestStringMapGenerator() {
    136             @Override protected Map<String, String> create(
    137                 Entry<String, String>[] entries) {
    138               return toHashMap(entries);
    139             }
    140           })
    141         .named("HashMap")
    142         .withFeatures(
    143             MapFeature.GENERAL_PURPOSE,
    144             MapFeature.ALLOWS_NULL_KEYS,
    145             MapFeature.ALLOWS_NULL_VALUES,
    146             MapFeature.ALLOWS_ANY_NULL_QUERIES,
    147             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
    148             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    149             CollectionFeature.SERIALIZABLE,
    150             CollectionSize.ANY)
    151         .suppressing(suppressForHashMap())
    152         .createTestSuite();
    153   }
    154 
    155   public Test testsForLinkedHashMap() {
    156     return MapTestSuiteBuilder
    157         .using(new TestStringMapGenerator() {
    158             @Override protected Map<String, String> create(
    159                 Entry<String, String>[] entries) {
    160               return populate(new LinkedHashMap<String, String>(), entries);
    161             }
    162           })
    163         .named("LinkedHashMap")
    164         .withFeatures(
    165             MapFeature.GENERAL_PURPOSE,
    166             MapFeature.ALLOWS_NULL_KEYS,
    167             MapFeature.ALLOWS_NULL_VALUES,
    168             MapFeature.ALLOWS_ANY_NULL_QUERIES,
    169             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
    170             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    171             CollectionFeature.KNOWN_ORDER,
    172             CollectionFeature.SERIALIZABLE,
    173             CollectionSize.ANY)
    174         .suppressing(suppressForLinkedHashMap())
    175         .createTestSuite();
    176   }
    177 
    178   public Test testsForTreeMapNatural() {
    179     return NavigableMapTestSuiteBuilder
    180         .using(new TestStringSortedMapGenerator() {
    181             @Override protected SortedMap<String, String> create(
    182                 Entry<String, String>[] entries) {
    183               /*
    184                * TODO(cpovirk): it would be nice to create an input Map and use
    185                * the copy constructor here and in the other tests
    186                */
    187               return populate(new TreeMap<String, String>(), entries);
    188             }
    189           })
    190         .named("TreeMap, natural")
    191         .withFeatures(
    192             MapFeature.GENERAL_PURPOSE,
    193             MapFeature.ALLOWS_NULL_VALUES,
    194             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
    195             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    196             CollectionFeature.KNOWN_ORDER,
    197             CollectionFeature.SERIALIZABLE,
    198             CollectionSize.ANY)
    199         .suppressing(suppressForTreeMapNatural())
    200         .createTestSuite();
    201   }
    202 
    203   public Test testsForTreeMapWithComparator() {
    204     return NavigableMapTestSuiteBuilder
    205         .using(new TestStringSortedMapGenerator() {
    206             @Override protected SortedMap<String, String> create(
    207                 Entry<String, String>[] entries) {
    208               return populate(new TreeMap<String, String>(
    209                   arbitraryNullFriendlyComparator()), entries);
    210             }
    211           })
    212         .named("TreeMap, with comparator")
    213         .withFeatures(
    214             MapFeature.GENERAL_PURPOSE,
    215             MapFeature.ALLOWS_NULL_KEYS,
    216             MapFeature.ALLOWS_NULL_VALUES,
    217             MapFeature.ALLOWS_ANY_NULL_QUERIES,
    218             MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
    219             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    220             CollectionFeature.KNOWN_ORDER,
    221             CollectionFeature.SERIALIZABLE,
    222             CollectionSize.ANY)
    223         .suppressing(suppressForTreeMapWithComparator())
    224         .createTestSuite();
    225   }
    226 
    227   public Test testsForEnumMap() {
    228     return MapTestSuiteBuilder
    229         .using(new TestEnumMapGenerator() {
    230             @Override protected Map<AnEnum, String> create(
    231                 Entry<AnEnum, String>[] entries) {
    232               return populate(
    233                   new EnumMap<AnEnum, String>(AnEnum.class), entries);
    234             }
    235           })
    236         .named("EnumMap")
    237         .withFeatures(
    238             MapFeature.GENERAL_PURPOSE,
    239             MapFeature.ALLOWS_NULL_VALUES,
    240             MapFeature.RESTRICTS_KEYS,
    241             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    242             CollectionFeature.KNOWN_ORDER,
    243             CollectionFeature.SERIALIZABLE,
    244             CollectionSize.ANY)
    245         .suppressing(suppressForEnumMap())
    246         .createTestSuite();
    247   }
    248 
    249   public Test testsForConcurrentHashMap() {
    250     return MapTestSuiteBuilder
    251         .using(new TestStringMapGenerator() {
    252           @Override protected Map<String, String> create(
    253               Entry<String, String>[] entries) {
    254             return populate(new ConcurrentHashMap<String, String>(), entries);
    255           }
    256         })
    257         .named("ConcurrentHashMap")
    258         .withFeatures(
    259             MapFeature.GENERAL_PURPOSE,
    260             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    261             CollectionFeature.SERIALIZABLE,
    262             CollectionSize.ANY)
    263         .suppressing(suppressForConcurrentHashMap())
    264         .createTestSuite();
    265   }
    266 
    267   public Test testsForConcurrentSkipListMapNatural() {
    268     return NavigableMapTestSuiteBuilder
    269         .using(new TestStringSortedMapGenerator() {
    270           @Override protected SortedMap<String, String> create(
    271               Entry<String, String>[] entries) {
    272             return populate(new ConcurrentSkipListMap<String, String>(), entries);
    273           }
    274         })
    275         .named("ConcurrentSkipListMap, natural")
    276         .withFeatures(
    277             MapFeature.GENERAL_PURPOSE,
    278             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    279             CollectionFeature.KNOWN_ORDER,
    280             CollectionFeature.SERIALIZABLE,
    281             CollectionSize.ANY)
    282         .suppressing(suppressForConcurrentSkipListMap())
    283         .createTestSuite();
    284   }
    285 
    286   public Test testsForConcurrentSkipListMapWithComparator() {
    287     return NavigableMapTestSuiteBuilder
    288         .using(new TestStringSortedMapGenerator() {
    289           @Override protected SortedMap<String, String> create(
    290               Entry<String, String>[] entries) {
    291             return populate(new ConcurrentSkipListMap<String, String>(
    292                 arbitraryNullFriendlyComparator()), entries);
    293           }
    294         })
    295         .named("ConcurrentSkipListMap, with comparator")
    296         .withFeatures(
    297             MapFeature.GENERAL_PURPOSE,
    298             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    299             CollectionFeature.KNOWN_ORDER,
    300             CollectionFeature.SERIALIZABLE,
    301             CollectionSize.ANY)
    302         .suppressing(suppressForConcurrentSkipListMap())
    303         .createTestSuite();
    304   }
    305 
    306   // TODO: IdentityHashMap, AbstractMap
    307 
    308   private static Map<String, String> toHashMap(
    309       Entry<String, String>[] entries) {
    310     return populate(new HashMap<String, String>(), entries);
    311   }
    312 
    313   // TODO: call conversion constructors or factory methods instead of using
    314   // populate() on an empty map
    315   private static <T, M extends Map<T, String>> M populate(
    316       M map, Entry<T, String>[] entries) {
    317     for (Entry<T, String> entry : entries) {
    318       map.put(entry.getKey(), entry.getValue());
    319     }
    320     return map;
    321   }
    322 
    323   static <T> Comparator<T> arbitraryNullFriendlyComparator() {
    324     return new NullFriendlyComparator<T>();
    325   }
    326 
    327   private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable {
    328     @Override
    329     public int compare(T left, T right) {
    330       return String.valueOf(left).compareTo(String.valueOf(right));
    331     }
    332   }
    333 }
    334