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