• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
19 import static com.google.common.collect.Maps.immutableEntry;
20 
21 import com.google.common.collect.testing.NavigableMapTestSuiteBuilder;
22 import com.google.common.collect.testing.SafeTreeMap;
23 import com.google.common.collect.testing.TestStringSortedMapGenerator;
24 import com.google.common.collect.testing.features.CollectionFeature;
25 import com.google.common.collect.testing.features.CollectionSize;
26 import com.google.common.collect.testing.features.MapFeature;
27 
28 import junit.framework.Test;
29 import junit.framework.TestSuite;
30 
31 import java.util.Collection;
32 import java.util.Iterator;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.NavigableMap;
36 import java.util.NavigableSet;
37 import java.util.Set;
38 import java.util.SortedMap;
39 
40 /**
41  * Tests for {@code ForwardingNavigableMap}.
42  *
43  * @author Robert Konigsberg
44  * @author Louis Wasserman
45  */
46 public class ForwardingNavigableMapTest extends ForwardingSortedMapTest {
47   static class StandardImplForwardingNavigableMap<K, V>
48       extends ForwardingNavigableMap<K, V> {
49     private final NavigableMap<K, V> backingMap;
50 
StandardImplForwardingNavigableMap(NavigableMap<K, V> backingMap)51     StandardImplForwardingNavigableMap(NavigableMap<K, V> backingMap) {
52       this.backingMap = backingMap;
53     }
54 
delegate()55     @Override protected NavigableMap<K, V> delegate() {
56       return backingMap;
57     }
58 
containsKey(Object key)59     @Override public boolean containsKey(Object key) {
60       return standardContainsKey(key);
61     }
62 
containsValue(Object value)63     @Override public boolean containsValue(Object value) {
64       return standardContainsValue(value);
65     }
66 
putAll(Map<? extends K, ? extends V> map)67     @Override public void putAll(Map<? extends K, ? extends V> map) {
68       standardPutAll(map);
69     }
70 
remove(Object object)71     @Override public V remove(Object object) {
72       return standardRemove(object);
73     }
74 
equals(Object object)75     @Override public boolean equals(Object object) {
76       return standardEquals(object);
77     }
78 
hashCode()79     @Override public int hashCode() {
80       return standardHashCode();
81     }
82 
keySet()83     @Override public Set<K> keySet() {
84       /*
85        * We can't use StandardKeySet, as NavigableMapTestSuiteBuilder assumes that our keySet is a
86        * NavigableSet. We test StandardKeySet in the superclass, so it's still covered.
87        */
88       return navigableKeySet();
89     }
90 
values()91     @Override public Collection<V> values() {
92       return new StandardValues();
93     }
94 
toString()95     @Override public String toString() {
96       return standardToString();
97     }
98 
entrySet()99     @Override public Set<Entry<K, V>> entrySet() {
100       return new StandardEntrySet() {
101         @Override
102         public Iterator<Entry<K, V>> iterator() {
103           return backingMap.entrySet().iterator();
104         }
105       };
106     }
107 
clear()108     @Override public void clear() {
109       standardClear();
110     }
111 
isEmpty()112     @Override public boolean isEmpty() {
113       return standardIsEmpty();
114     }
115 
subMap(K fromKey, K toKey)116     @Override public SortedMap<K, V> subMap(K fromKey, K toKey) {
117       return standardSubMap(fromKey, toKey);
118     }
119 
120     @Override
lowerEntry(K key)121     public Entry<K, V> lowerEntry(K key) {
122       return standardLowerEntry(key);
123     }
124 
125     @Override
lowerKey(K key)126     public K lowerKey(K key) {
127       return standardLowerKey(key);
128     }
129 
130     @Override
floorEntry(K key)131     public Entry<K, V> floorEntry(K key) {
132       return standardFloorEntry(key);
133     }
134 
135     @Override
floorKey(K key)136     public K floorKey(K key) {
137       return standardFloorKey(key);
138     }
139 
140     @Override
ceilingEntry(K key)141     public Entry<K, V> ceilingEntry(K key) {
142       return standardCeilingEntry(key);
143     }
144 
145     @Override
ceilingKey(K key)146     public K ceilingKey(K key) {
147       return standardCeilingKey(key);
148     }
149 
150     @Override
higherEntry(K key)151     public Entry<K, V> higherEntry(K key) {
152       return standardHigherEntry(key);
153     }
154 
155     @Override
higherKey(K key)156     public K higherKey(K key) {
157       return standardHigherKey(key);
158     }
159 
160     @Override
firstEntry()161     public Entry<K, V> firstEntry() {
162       return standardFirstEntry();
163     }
164 
165     /*
166      * We can't override lastEntry to delegate to standardLastEntry, as it would create an infinite
167      * loop. Instead, we test standardLastEntry manually below.
168      */
169 
170     @Override
pollFirstEntry()171     public Entry<K, V> pollFirstEntry() {
172       return standardPollFirstEntry();
173     }
174 
175     @Override
pollLastEntry()176     public Entry<K, V> pollLastEntry() {
177       return standardPollLastEntry();
178     }
179 
180     @Override
descendingMap()181     public NavigableMap<K, V> descendingMap() {
182       return new StandardDescendingMap();
183     }
184 
185     @Override
navigableKeySet()186     public NavigableSet<K> navigableKeySet() {
187       return new StandardNavigableKeySet();
188     }
189 
190     @Override
descendingKeySet()191     public NavigableSet<K> descendingKeySet() {
192       return standardDescendingKeySet();
193     }
194 
195     @Override
firstKey()196     public K firstKey() {
197       return standardFirstKey();
198     }
199 
200     @Override
headMap(K toKey)201     public SortedMap<K, V> headMap(K toKey) {
202       return standardHeadMap(toKey);
203     }
204 
205     @Override
lastKey()206     public K lastKey() {
207       return standardLastKey();
208     }
209 
210     @Override
tailMap(K fromKey)211     public SortedMap<K, V> tailMap(K fromKey) {
212       return standardTailMap(fromKey);
213     }
214   }
215 
216   static class StandardLastEntryForwardingNavigableMap<K, V>
217       extends ForwardingNavigableMap<K, V> {
218     private final NavigableMap<K, V> backingMap;
219 
220     StandardLastEntryForwardingNavigableMap(NavigableMap<K, V> backingMap) {
221       this.backingMap = backingMap;
222     }
223 
224     @Override protected NavigableMap<K, V> delegate() {
225       return backingMap;
226     }
227 
228     @Override
229     public Entry<K, V> lastEntry() {
230       return standardLastEntry();
231     }
232   }
233 
234   public static Test suite() {
235     TestSuite suite = new TestSuite();
236 
237     suite.addTestSuite(ForwardingNavigableMapTest.class);
238     suite.addTest(NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
239       @Override protected SortedMap<String, String> create(
240           Entry<String, String>[] entries) {
241         NavigableMap<String, String> map = new SafeTreeMap<String, String>();
242         for (Entry<String, String> entry : entries) {
243           map.put(entry.getKey(), entry.getValue());
244         }
245         return new StandardImplForwardingNavigableMap<String, String>(map);
246       }
247     }).named("ForwardingNavigableMap[SafeTreeMap] with no comparator and standard "
248         + "implementations").withFeatures(CollectionSize.ANY,
249         CollectionFeature.KNOWN_ORDER, MapFeature.ALLOWS_NULL_VALUES,
250         CollectionFeature.SUPPORTS_ITERATOR_REMOVE, MapFeature.GENERAL_PURPOSE)
251         .createTestSuite());
252     // TODO(user): add forwarding-to-ImmutableSortedMap test
253     return suite;
254   }
255 
256   @Override public void setUp() throws Exception {
257     super.setUp();
258     /*
259      * Class parameters must be raw, so we can't create a proxy with generic
260      * type arguments. The created proxy only records calls and returns null, so
261      * the type is irrelevant at runtime.
262      */
263     @SuppressWarnings("unchecked")
264     final NavigableMap<String, Boolean> sortedMap =
265         createProxyInstance(NavigableMap.class);
266     forward = new ForwardingNavigableMap<String, Boolean>() {
267       @Override protected NavigableMap<String, Boolean> delegate() {
268         return sortedMap;
269       }
270     };
271   }
272 
273   public void testStandardLastEntry() {
274     NavigableMap<String, Integer> forwarding =
275         new StandardLastEntryForwardingNavigableMap<String, Integer>(
276             new SafeTreeMap<String, Integer>());
277     assertNull(forwarding.lastEntry());
278     forwarding.put("b", 2);
279     assertEquals(immutableEntry("b", 2), forwarding.lastEntry());
280     forwarding.put("c", 3);
281     assertEquals(immutableEntry("c", 3), forwarding.lastEntry());
282     forwarding.put("a", 1);
283     assertEquals(immutableEntry("c", 3), forwarding.lastEntry());
284     forwarding.remove("c");
285     assertEquals(immutableEntry("b", 2), forwarding.lastEntry());
286   }
287 
288   public void testLowerEntry() {
289     forward().lowerEntry("key");
290     assertEquals("[lowerEntry(Object)]", getCalls());
291   }
292 
293   public void testLowerKey() {
294     forward().lowerKey("key");
295     assertEquals("[lowerKey(Object)]", getCalls());
296   }
297 
298   public void testFloorEntry() {
299     forward().floorEntry("key");
300     assertEquals("[floorEntry(Object)]", getCalls());
301   }
302 
303   public void testFloorKey() {
304     forward().floorKey("key");
305     assertEquals("[floorKey(Object)]", getCalls());
306   }
307 
308   public void testCeilingEntry() {
309     forward().ceilingEntry("key");
310     assertEquals("[ceilingEntry(Object)]", getCalls());
311   }
312 
313   public void testCeilingKey() {
314     forward().ceilingKey("key");
315     assertEquals("[ceilingKey(Object)]", getCalls());
316   }
317 
318   public void testHigherEntry() {
319     forward().higherEntry("key");
320     assertEquals("[higherEntry(Object)]", getCalls());
321   }
322 
323   public void testHigherKey() {
324     forward().higherKey("key");
325     assertEquals("[higherKey(Object)]", getCalls());
326   }
327 
328   public void testPollFirstEntry() {
329     forward().pollFirstEntry();
330     assertEquals("[pollFirstEntry]", getCalls());
331   }
332 
333   public void testPollLastEntry() {
334     forward().pollLastEntry();
335     assertEquals("[pollLastEntry]", getCalls());
336   }
337 
338   public void testFirstEntry() {
339     forward().firstEntry();
340     assertEquals("[firstEntry]", getCalls());
341   }
342 
343   public void testLastEntry() {
344     forward().lastEntry();
345     assertEquals("[lastEntry]", getCalls());
346   }
347 
348   public void testDescendingMap() {
349     forward().descendingMap();
350     assertEquals("[descendingMap]", getCalls());
351   }
352 
353   public void testNavigableKeySet() {
354     forward().navigableKeySet();
355     assertEquals("[navigableKeySet]", getCalls());
356   }
357 
358   public void testDescendingKeySet() {
359     forward().descendingKeySet();
360     assertEquals("[descendingKeySet]", getCalls());
361   }
362 
363   public void testSubMap_K_Bool_K_Bool() {
364     forward().subMap("a", false, "b", true);
365     assertEquals("[subMap(Object,boolean,Object,boolean)]", getCalls());
366   }
367 
368   public void testHeadMap_K_Bool() {
369     forward().headMap("a", false);
370     assertEquals("[headMap(Object,boolean)]", getCalls());
371   }
372 
373   public void testTailMap_K_Bool() {
374     forward().tailMap("a", false);
375     assertEquals("[tailMap(Object,boolean)]", getCalls());
376   }
377 
378   @Override NavigableMap<String, Boolean> forward() {
379     return (NavigableMap<String, Boolean>) super.forward();
380   }
381 }
382