1 /* 2 * Copyright (C) 2010 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 com.google.common.collect.Synchronized.SynchronizedNavigableMap; 20 import com.google.common.collect.Synchronized.SynchronizedNavigableSet; 21 import com.google.common.collect.Synchronized.SynchronizedSortedMap; 22 import com.google.common.collect.testing.NavigableMapTestSuiteBuilder; 23 import com.google.common.collect.testing.SafeTreeMap; 24 import com.google.common.collect.testing.TestStringSortedMapGenerator; 25 import com.google.common.collect.testing.features.CollectionFeature; 26 import com.google.common.collect.testing.features.CollectionSize; 27 import com.google.common.collect.testing.features.MapFeature; 28 import com.google.common.testing.SerializableTester; 29 30 import junit.framework.TestSuite; 31 32 import java.io.Serializable; 33 import java.util.Comparator; 34 import java.util.Map.Entry; 35 import java.util.NavigableMap; 36 import java.util.NavigableSet; 37 import java.util.SortedMap; 38 39 /** 40 * Tests for {@link Maps#synchronizedNavigableMap(NavigableMap)}. 41 * 42 * @author Louis Wasserman 43 */ 44 public class SynchronizedNavigableMapTest extends SynchronizedMapTest { 45 @Override protected <K, V> NavigableMap<K, V> create() { 46 @SuppressWarnings("unchecked") 47 NavigableMap<K, V> innermost = new SafeTreeMap<K, V>( 48 (Comparator<? super K>) Ordering.natural().nullsFirst()); 49 TestMap<K, V> inner = new TestMap<K, V>(innermost, mutex); 50 NavigableMap<K, V> outer = Synchronized.navigableMap(inner, mutex); 51 return outer; 52 } 53 54 static class TestEntry<K, V> extends ForwardingMapEntry<K, V> 55 implements Serializable { 56 private final Entry<K, V> delegate; 57 private final Object mutex; 58 59 TestEntry(Entry<K, V> delegate, Object mutex) { 60 this.delegate = delegate; 61 this.mutex = mutex; 62 } 63 64 @Override protected Entry<K, V> delegate() { 65 return delegate; 66 } 67 68 @Override public boolean equals(Object object) { 69 assertTrue(Thread.holdsLock(mutex)); 70 return super.equals(object); 71 } 72 73 @Override public K getKey() { 74 assertTrue(Thread.holdsLock(mutex)); 75 return super.getKey(); 76 } 77 78 @Override public V getValue() { 79 assertTrue(Thread.holdsLock(mutex)); 80 return super.getValue(); 81 } 82 83 @Override public int hashCode() { 84 assertTrue(Thread.holdsLock(mutex)); 85 return super.hashCode(); 86 } 87 88 @Override public V setValue(V value) { 89 assertTrue(Thread.holdsLock(mutex)); 90 return super.setValue(value); 91 } 92 93 private static final long serialVersionUID = 0; 94 } 95 96 static class TestMap<K, V> extends SynchronizedMapTest.TestMap<K, V> 97 implements NavigableMap<K, V> { 98 99 public TestMap(NavigableMap<K, V> delegate, Object mutex) { 100 super(delegate, mutex); 101 } 102 103 @Override protected NavigableMap<K, V> delegate() { 104 return (NavigableMap<K, V>) super.delegate(); 105 } 106 107 @Override public Entry<K, V> ceilingEntry(K key) { 108 assertTrue(Thread.holdsLock(mutex)); 109 return delegate().ceilingEntry(key); 110 } 111 112 @Override public K ceilingKey(K key) { 113 assertTrue(Thread.holdsLock(mutex)); 114 return delegate().ceilingKey(key); 115 } 116 117 @Override public NavigableSet<K> descendingKeySet() { 118 assertTrue(Thread.holdsLock(mutex)); 119 return delegate().descendingKeySet(); 120 } 121 122 @Override public NavigableMap<K, V> descendingMap() { 123 assertTrue(Thread.holdsLock(mutex)); 124 return delegate().descendingMap(); 125 } 126 127 @Override public Entry<K, V> firstEntry() { 128 assertTrue(Thread.holdsLock(mutex)); 129 return delegate().firstEntry(); 130 } 131 132 @Override public Entry<K, V> floorEntry(K key) { 133 assertTrue(Thread.holdsLock(mutex)); 134 return delegate().floorEntry(key); 135 } 136 137 @Override public K floorKey(K key) { 138 assertTrue(Thread.holdsLock(mutex)); 139 return delegate().floorKey(key); 140 } 141 142 @Override public NavigableMap<K, V> headMap(K toKey, boolean inclusive) { 143 assertTrue(Thread.holdsLock(mutex)); 144 return delegate().headMap(toKey, inclusive); 145 } 146 147 @Override public SortedMap<K, V> headMap(K toKey) { 148 return headMap(toKey, false); 149 } 150 151 @Override public Entry<K, V> higherEntry(K key) { 152 assertTrue(Thread.holdsLock(mutex)); 153 return delegate().higherEntry(key); 154 } 155 156 @Override public K higherKey(K key) { 157 assertTrue(Thread.holdsLock(mutex)); 158 return delegate().higherKey(key); 159 } 160 161 @Override public Entry<K, V> lastEntry() { 162 assertTrue(Thread.holdsLock(mutex)); 163 return delegate().lastEntry(); 164 } 165 166 @Override public Entry<K, V> lowerEntry(K key) { 167 assertTrue(Thread.holdsLock(mutex)); 168 return delegate().lowerEntry(key); 169 } 170 171 @Override public K lowerKey(K key) { 172 assertTrue(Thread.holdsLock(mutex)); 173 return delegate().lowerKey(key); 174 } 175 176 @Override public NavigableSet<K> navigableKeySet() { 177 assertTrue(Thread.holdsLock(mutex)); 178 return delegate().navigableKeySet(); 179 } 180 181 @Override public Entry<K, V> pollFirstEntry() { 182 assertTrue(Thread.holdsLock(mutex)); 183 return delegate().pollFirstEntry(); 184 } 185 186 @Override public Entry<K, V> pollLastEntry() { 187 assertTrue(Thread.holdsLock(mutex)); 188 return delegate().pollLastEntry(); 189 } 190 191 @Override public NavigableMap<K, V> subMap( 192 K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { 193 assertTrue(Thread.holdsLock(mutex)); 194 return delegate().subMap(fromKey, fromInclusive, toKey, toInclusive); 195 } 196 197 @Override public SortedMap<K, V> subMap(K fromKey, K toKey) { 198 return delegate().subMap(fromKey, true, toKey, false); 199 } 200 201 @Override public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) { 202 assertTrue(Thread.holdsLock(mutex)); 203 return delegate().tailMap(fromKey, inclusive); 204 } 205 206 @Override public SortedMap<K, V> tailMap(K fromKey) { 207 return tailMap(fromKey, true); 208 } 209 210 @Override public Comparator<? super K> comparator() { 211 assertTrue(Thread.holdsLock(mutex)); 212 return delegate().comparator(); 213 } 214 215 @Override public K firstKey() { 216 assertTrue(Thread.holdsLock(mutex)); 217 return delegate().firstKey(); 218 } 219 220 @Override public K lastKey() { 221 assertTrue(Thread.holdsLock(mutex)); 222 return delegate().lastKey(); 223 } 224 225 private static final long serialVersionUID = 0; 226 } 227 228 public static TestSuite suite() { 229 TestSuite suite = new TestSuite(); 230 suite.addTestSuite(SynchronizedNavigableMapTest.class); 231 suite.addTest( 232 NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() { 233 private final Object mutex = new Integer(1); 234 235 @Override protected SortedMap<String, String> create( 236 Entry<String, String>[] entries) { 237 NavigableMap<String, String> innermost = 238 new SafeTreeMap<String, String>(); 239 for (Entry<String, String> entry : entries) { 240 innermost.put(entry.getKey(), entry.getValue()); 241 } 242 TestMap<String, String> inner = 243 new TestMap<String, String>(innermost, mutex); 244 NavigableMap<String, String> outer = 245 Synchronized.navigableMap(inner, mutex); 246 return outer; 247 } 248 }).named("Maps.synchronizedNavigableMap[SafeTreeMap]") 249 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 250 MapFeature.GENERAL_PURPOSE, MapFeature.ALLOWS_NULL_VALUES, 251 CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 252 .createTestSuite()); 253 254 return suite; 255 } 256 257 public void testComparator() { 258 create().comparator(); 259 } 260 261 public void testCeilingEntry() { 262 create().ceilingEntry("a"); 263 } 264 265 public void testCeilingKey() { 266 create().ceilingKey("a"); 267 } 268 269 public void testDescendingKeySet() { 270 NavigableMap<String, Integer> map = create(); 271 NavigableSet<String> descendingKeySet = map.descendingKeySet(); 272 assertTrue(descendingKeySet instanceof SynchronizedNavigableSet); 273 assertSame( 274 mutex, ((SynchronizedNavigableSet<String>) descendingKeySet).mutex); 275 } 276 277 public void testDescendingMap() { 278 NavigableMap<String, Integer> map = create(); 279 NavigableMap<String, Integer> descendingMap = map.descendingMap(); 280 assertTrue(descendingMap instanceof SynchronizedNavigableMap); 281 assertSame(mutex, 282 ((SynchronizedNavigableMap<String, Integer>) descendingMap).mutex); 283 } 284 285 public void testFirstEntry() { 286 create().firstEntry(); 287 } 288 289 public void testFirstKey() { 290 NavigableMap<String, Integer> map = create(); 291 map.put("a", 1); 292 map.firstKey(); 293 } 294 295 public void testFloorEntry() { 296 create().floorEntry("a"); 297 } 298 299 public void testFloorKey() { 300 create().floorKey("a"); 301 } 302 303 public void testHeadMap_K() { 304 NavigableMap<String, Integer> map = create(); 305 SortedMap<String, Integer> headMap = map.headMap("a"); 306 assertTrue(headMap instanceof SynchronizedSortedMap); 307 assertSame(mutex, ((SynchronizedSortedMap<String, Integer>) headMap).mutex); 308 } 309 310 public void testHeadMap_K_B() { 311 NavigableMap<String, Integer> map = create(); 312 NavigableMap<String, Integer> headMap = map.headMap("a", true); 313 assertTrue(headMap instanceof SynchronizedNavigableMap); 314 assertSame( 315 mutex, ((SynchronizedNavigableMap<String, Integer>) headMap).mutex); 316 } 317 318 public void testHigherEntry() { 319 create().higherEntry("a"); 320 } 321 322 public void testHigherKey() { 323 create().higherKey("a"); 324 } 325 326 public void testLastEntry() { 327 create().lastEntry(); 328 } 329 330 public void testLastKey() { 331 NavigableMap<String, Integer> map = create(); 332 map.put("a", 1); 333 map.lastKey(); 334 } 335 336 public void testLowerEntry() { 337 create().lowerEntry("a"); 338 } 339 340 public void testLowerKey() { 341 create().lowerKey("a"); 342 } 343 344 public void testNavigableKeySet() { 345 NavigableMap<String, Integer> map = create(); 346 NavigableSet<String> navigableKeySet = map.navigableKeySet(); 347 assertTrue(navigableKeySet instanceof SynchronizedNavigableSet); 348 assertSame( 349 mutex, ((SynchronizedNavigableSet<String>) navigableKeySet).mutex); 350 } 351 352 public void testPollFirstEntry() { 353 create().pollFirstEntry(); 354 } 355 356 public void testPollLastEntry() { 357 create().pollLastEntry(); 358 } 359 360 public void testSubMap_K_K() { 361 NavigableMap<String, Integer> map = create(); 362 SortedMap<String, Integer> subMap = map.subMap("a", "b"); 363 assertTrue(subMap instanceof SynchronizedSortedMap); 364 assertSame(mutex, ((SynchronizedSortedMap<String, Integer>) subMap).mutex); 365 } 366 367 public void testSubMap_K_B_K_B() { 368 NavigableMap<String, Integer> map = create(); 369 NavigableMap<String, Integer> subMap = map.subMap("a", true, "b", false); 370 assertTrue(subMap instanceof SynchronizedNavigableMap); 371 assertSame( 372 mutex, ((SynchronizedNavigableMap<String, Integer>) subMap).mutex); 373 } 374 375 public void testTailMap_K() { 376 NavigableMap<String, Integer> map = create(); 377 SortedMap<String, Integer> subMap = map.tailMap("a"); 378 assertTrue(subMap instanceof SynchronizedSortedMap); 379 assertSame(mutex, ((SynchronizedSortedMap<String, Integer>) subMap).mutex); 380 } 381 382 public void testTailMap_K_B() { 383 NavigableMap<String, Integer> map = create(); 384 NavigableMap<String, Integer> subMap = map.tailMap("a", true); 385 assertTrue(subMap instanceof SynchronizedNavigableMap); 386 assertSame( 387 mutex, ((SynchronizedNavigableMap<String, Integer>) subMap).mutex); 388 } 389 390 @Override public void testSerialization() { 391 SerializableTester.reserializeAndAssert(create()); 392 } 393 } 394