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