Home | History | Annotate | Download | only in collect
      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;
     18 import static org.easymock.EasyMock.anyObject;
     19 import static org.easymock.EasyMock.createMock;
     20 import static org.easymock.EasyMock.expect;
     21 import static org.easymock.EasyMock.expectLastCall;
     22 import static org.easymock.EasyMock.replay;
     23 import static org.easymock.EasyMock.verify;
     24 
     25 import com.google.common.collect.testing.MapTestSuiteBuilder;
     26 import com.google.common.collect.testing.TestStringMapGenerator;
     27 import com.google.common.collect.testing.features.CollectionFeature;
     28 import com.google.common.collect.testing.features.CollectionSize;
     29 import com.google.common.collect.testing.features.MapFeature;
     30 
     31 import junit.framework.Test;
     32 import junit.framework.TestSuite;
     33 
     34 import java.lang.reflect.InvocationTargetException;
     35 import java.util.Collection;
     36 import java.util.HashMap;
     37 import java.util.Iterator;
     38 import java.util.Map;
     39 import java.util.Map.Entry;
     40 import java.util.Set;
     41 
     42 /**
     43  * Unit test for {@link ForwardingMap}.
     44  *
     45  * @author Hayward Chan
     46  * @author Louis Wasserman
     47  */
     48 public class ForwardingMapTest extends ForwardingTestCase {
     49   static class StandardImplForwardingMap<K, V> extends ForwardingMap<K, V> {
     50     private final Map<K, V> backingMap;
     51 
     52     StandardImplForwardingMap(Map<K, V> backingMap) {
     53       this.backingMap = backingMap;
     54     }
     55 
     56     @Override protected Map<K, V> delegate() {
     57       return backingMap;
     58     }
     59 
     60     @Override public boolean containsKey(Object key) {
     61       return standardContainsKey(key);
     62     }
     63 
     64     @Override public boolean containsValue(Object value) {
     65       return standardContainsValue(value);
     66     }
     67 
     68     @Override public void putAll(Map<? extends K, ? extends V> map) {
     69       standardPutAll(map);
     70     }
     71 
     72     @Override public V remove(Object object) {
     73       return standardRemove(object);
     74     }
     75 
     76     @Override public boolean equals(Object object) {
     77       return standardEquals(object);
     78     }
     79 
     80     @Override public int hashCode() {
     81       return standardHashCode();
     82     }
     83 
     84     @Override public Set<K> keySet() {
     85       return new StandardKeySet();
     86     }
     87 
     88     @Override public Collection<V> values() {
     89       return new StandardValues();
     90     }
     91 
     92     @Override public String toString() {
     93       return standardToString();
     94     }
     95 
     96     @Override public Set<Entry<K, V>> entrySet() {
     97       return new StandardEntrySet() {
     98         @Override
     99         public Iterator<Entry<K, V>> iterator() {
    100           return delegate()
    101               .entrySet()
    102               .iterator();
    103         }
    104       };
    105     }
    106 
    107     @Override public void clear() {
    108       standardClear();
    109     }
    110 
    111     @Override public boolean isEmpty() {
    112       return standardIsEmpty();
    113     }
    114   }
    115 
    116   Map<String, Boolean> forward;
    117 
    118   public static Test suite() {
    119     TestSuite suite = new TestSuite();
    120 
    121     suite.addTestSuite(ForwardingMapTest.class);
    122     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    123 
    124       @Override protected Map<String, String> create(
    125           Entry<String, String>[] entries) {
    126         Map<String, String> map = Maps.newLinkedHashMap();
    127         for (Entry<String, String> entry : entries) {
    128           map.put(entry.getKey(), entry.getValue());
    129         }
    130         return new StandardImplForwardingMap<String, String>(map);
    131       }
    132 
    133     }).named("ForwardingMap[LinkedHashMap] with standard implementations")
    134         .withFeatures(CollectionSize.ANY, MapFeature.ALLOWS_NULL_VALUES,
    135             MapFeature.ALLOWS_NULL_KEYS, MapFeature.ALLOWS_ANY_NULL_QUERIES,
    136             MapFeature.GENERAL_PURPOSE,
    137             CollectionFeature.SUPPORTS_ITERATOR_REMOVE, CollectionFeature.KNOWN_ORDER)
    138         .createTestSuite());
    139     suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() {
    140 
    141       @Override protected Map<String, String> create(
    142           Entry<String, String>[] entries) {
    143         ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
    144         for (Entry<String, String> entry : entries) {
    145           builder.put(entry.getKey(), entry.getValue());
    146         }
    147         return new StandardImplForwardingMap<String, String>(builder.build());
    148       }
    149 
    150     }).named("ForwardingMap[ImmutableMap] with standard implementations")
    151         .withFeatures(
    152             CollectionSize.ANY, MapFeature.REJECTS_DUPLICATES_AT_CREATION,
    153             MapFeature.ALLOWS_ANY_NULL_QUERIES,
    154             CollectionFeature.KNOWN_ORDER)
    155         .createTestSuite());
    156 
    157     return suite;
    158   }
    159 
    160   @Override public void setUp() throws Exception {
    161     super.setUp();
    162     /*
    163      * Class parameters must be raw, so we can't create a proxy with generic
    164      * type arguments. The created proxy only records calls and returns null, so
    165      * the type is irrelevant at runtime.
    166      */
    167     @SuppressWarnings("unchecked")
    168     final Map<String, Boolean> map = createProxyInstance(Map.class);
    169     forward = new ForwardingMap<String, Boolean>() {
    170       @Override protected Map<String, Boolean> delegate() {
    171         return map;
    172       }
    173     };
    174   }
    175 
    176   public void testSize() {
    177     forward().size();
    178     assertEquals("[size]", getCalls());
    179   }
    180 
    181   public void testIsEmpty() {
    182     forward().isEmpty();
    183     assertEquals("[isEmpty]", getCalls());
    184   }
    185 
    186   public void testRemove() {
    187     forward().remove(null);
    188     assertEquals("[remove(Object)]", getCalls());
    189   }
    190 
    191   public void testClear() {
    192     forward().clear();
    193     assertEquals("[clear]", getCalls());
    194   }
    195 
    196   public void testContainsKey() {
    197     forward().containsKey("asdf");
    198     assertEquals("[containsKey(Object)]", getCalls());
    199   }
    200 
    201   public void testContainsValue() {
    202     forward().containsValue(false);
    203     assertEquals("[containsValue(Object)]", getCalls());
    204   }
    205 
    206   public void testGet_Object() {
    207     forward().get("asdf");
    208     assertEquals("[get(Object)]", getCalls());
    209   }
    210 
    211   public void testPut_Key_Value() {
    212     forward().put("key", false);
    213     assertEquals("[put(Object,Object)]", getCalls());
    214   }
    215 
    216   public void testPutAll_Map() {
    217     forward().putAll(new HashMap<String, Boolean>());
    218     assertEquals("[putAll(Map)]", getCalls());
    219   }
    220 
    221   public void testKeySet() {
    222     forward().keySet();
    223     assertEquals("[keySet]", getCalls());
    224   }
    225 
    226   public void testValues() {
    227     forward().values();
    228     assertEquals("[values]", getCalls());
    229   }
    230 
    231   public void testEntrySet() {
    232     forward().entrySet();
    233     assertEquals("[entrySet]", getCalls());
    234   }
    235 
    236   public void testToString() {
    237     forward().toString();
    238     assertEquals("[toString]", getCalls());
    239   }
    240 
    241   public void testEquals_Object() {
    242     forward().equals("asdf");
    243     assertEquals("[equals(Object)]", getCalls());
    244   }
    245 
    246   public void testHashCode() {
    247     forward().hashCode();
    248     assertEquals("[hashCode]", getCalls());
    249   }
    250 
    251   public void testStandardEntrySet() throws InvocationTargetException {
    252     @SuppressWarnings("unchecked")
    253     final Map<String, Boolean> map = createMock(Map.class);
    254     @SuppressWarnings("unchecked")
    255     final Set<Map.Entry<String, Boolean>> entrySet = createMock(Set.class);
    256     expect(map.containsKey(anyObject())).andReturn(false).anyTimes();
    257     expect(map.get(anyObject())).andReturn(null).anyTimes();
    258     expect(map.isEmpty()).andReturn(true).anyTimes();
    259     expect(map.remove(anyObject())).andReturn(null).anyTimes();
    260     expect(map.size()).andReturn(0).anyTimes();
    261     expect(entrySet.iterator())
    262         .andReturn(Iterators.<Entry<String, Boolean>>emptyIterator())
    263         .anyTimes();
    264     map.clear();
    265     expectLastCall().anyTimes();
    266 
    267     replay(map, entrySet);
    268 
    269     Map<String, Boolean> forward = new ForwardingMap<String, Boolean>() {
    270       @Override protected Map<String, Boolean> delegate() {
    271         return map;
    272       }
    273 
    274       @Override public Set<Entry<String, Boolean>> entrySet() {
    275         return new StandardEntrySet() {
    276           @Override
    277           public Iterator<Entry<String, Boolean>> iterator() {
    278             return entrySet.iterator();
    279           }
    280         };
    281       }
    282     };
    283     callAllPublicMethods(Set.class, forward.entrySet());
    284 
    285     verify(map, entrySet);
    286   }
    287 
    288   public void testStandardKeySet() throws InvocationTargetException {
    289     @SuppressWarnings("unchecked")
    290     Set<Entry<String, Boolean>> entrySet = createMock(Set.class);
    291     expect(entrySet.iterator()).andReturn(
    292         Iterators.<Entry<String, Boolean>>emptyIterator()).anyTimes();
    293 
    294     @SuppressWarnings("unchecked")
    295     final Map<String, Boolean> map = createMock(Map.class);
    296     expect(map.containsKey(anyObject())).andReturn(false).anyTimes();
    297     expect(map.isEmpty()).andReturn(true).anyTimes();
    298     expect(map.remove(anyObject())).andReturn(null).anyTimes();
    299     expect(map.size()).andReturn(0).anyTimes();
    300     expect(map.entrySet()).andReturn(entrySet).anyTimes();
    301     map.clear();
    302     expectLastCall().anyTimes();
    303 
    304     replay(entrySet, map);
    305 
    306     Map<String, Boolean> forward = new ForwardingMap<String, Boolean>() {
    307       @Override protected Map<String, Boolean> delegate() {
    308         return map;
    309       }
    310 
    311       @Override public Set<String> keySet() {
    312         return new StandardKeySet();
    313       }
    314     };
    315     callAllPublicMethods(Set.class, forward.keySet());
    316 
    317     verify(entrySet, map);
    318   }
    319 
    320   public void testStandardValues() throws InvocationTargetException {
    321     @SuppressWarnings("unchecked")
    322     Set<Entry<String, Boolean>> entrySet = createMock(Set.class);
    323     expect(entrySet.iterator()).andReturn(
    324         Iterators.<Entry<String, Boolean>>emptyIterator()).anyTimes();
    325 
    326     @SuppressWarnings("unchecked")
    327     final Map<String, Boolean> map = createMock(Map.class);
    328     expect(map.containsValue(anyObject())).andReturn(false).anyTimes();
    329     expect(map.isEmpty()).andReturn(true).anyTimes();
    330     expect(map.size()).andReturn(0).anyTimes();
    331     expect(map.entrySet()).andReturn(entrySet).anyTimes();
    332     map.clear();
    333     expectLastCall().anyTimes();
    334 
    335     replay(entrySet, map);
    336 
    337     Map<String, Boolean> forward = new ForwardingMap<String, Boolean>() {
    338       @Override protected Map<String, Boolean> delegate() {
    339         return map;
    340       }
    341 
    342       @Override public Collection<Boolean> values() {
    343         return new StandardValues();
    344       }
    345     };
    346     callAllPublicMethods(Collection.class, forward.values());
    347 
    348     verify(entrySet, map);
    349   }
    350 
    351   public void testToStringWithNullKeys() throws Exception {
    352     Map<String, String> hashmap = Maps.newHashMap();
    353     hashmap.put("foo", "bar");
    354     hashmap.put(null, "baz");
    355 
    356     StandardImplForwardingMap<String, String> forwardingMap =
    357         new StandardImplForwardingMap<String, String>(
    358             Maps.<String, String>newHashMap());
    359     forwardingMap.put("foo", "bar");
    360     forwardingMap.put(null, "baz");
    361 
    362     assertEquals(hashmap.toString(), forwardingMap.toString());
    363   }
    364 
    365   public void testToStringWithNullValues() throws Exception {
    366     Map<String, String> hashmap = Maps.newHashMap();
    367     hashmap.put("foo", "bar");
    368     hashmap.put("baz", null);
    369 
    370     StandardImplForwardingMap<String, String> forwardingMap =
    371         new StandardImplForwardingMap<String, String>(
    372             Maps.<String, String>newHashMap());
    373     forwardingMap.put("foo", "bar");
    374     forwardingMap.put("baz", null);
    375 
    376     assertEquals(hashmap.toString(), forwardingMap.toString());
    377   }
    378 
    379   Map<String, Boolean> forward() {
    380     return forward;
    381   }
    382 }
    383