• 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;
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 
StandardImplForwardingMap(Map<K, V> backingMap)52     StandardImplForwardingMap(Map<K, V> backingMap) {
53       this.backingMap = backingMap;
54     }
55 
delegate()56     @Override protected Map<K, V> delegate() {
57       return backingMap;
58     }
59 
containsKey(Object key)60     @Override public boolean containsKey(Object key) {
61       return standardContainsKey(key);
62     }
63 
containsValue(Object value)64     @Override public boolean containsValue(Object value) {
65       return standardContainsValue(value);
66     }
67 
putAll(Map<? extends K, ? extends V> map)68     @Override public void putAll(Map<? extends K, ? extends V> map) {
69       standardPutAll(map);
70     }
71 
remove(Object object)72     @Override public V remove(Object object) {
73       return standardRemove(object);
74     }
75 
equals(Object object)76     @Override public boolean equals(Object object) {
77       return standardEquals(object);
78     }
79 
hashCode()80     @Override public int hashCode() {
81       return standardHashCode();
82     }
83 
keySet()84     @Override public Set<K> keySet() {
85       return new StandardKeySet();
86     }
87 
values()88     @Override public Collection<V> values() {
89       return new StandardValues();
90     }
91 
toString()92     @Override public String toString() {
93       return standardToString();
94     }
95 
entrySet()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 
clear()107     @Override public void clear() {
108       standardClear();
109     }
110 
isEmpty()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