1 /* 2 * Copyright (C) 2011 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.common.cache; 16 17 import static com.google.common.cache.CacheTesting.checkEmpty; 18 import static com.google.common.cache.TestingCacheLoaders.identityLoader; 19 import static java.util.Arrays.asList; 20 import static java.util.concurrent.TimeUnit.DAYS; 21 import static java.util.concurrent.TimeUnit.SECONDS; 22 23 import com.google.common.base.Function; 24 import com.google.common.cache.CacheBuilderFactory.DurationSpec; 25 import com.google.common.cache.LocalCache.Strength; 26 import com.google.common.collect.ImmutableSet; 27 import com.google.common.collect.Iterables; 28 import com.google.common.collect.Maps; 29 import com.google.common.testing.EqualsTester; 30 31 import junit.framework.TestCase; 32 33 import java.util.Collection; 34 import java.util.Map.Entry; 35 import java.util.Set; 36 import java.util.concurrent.ExecutionException; 37 38 /** 39 * {@link LoadingCache} tests that deal with empty caches. 40 * 41 * @author mike nonemacher 42 */ 43 44 public class EmptyCachesTest extends TestCase { 45 46 public void testEmpty() { 47 for (LoadingCache<Object, Object> cache : caches()) { 48 checkEmpty(cache); 49 } 50 } 51 52 public void testInvalidate_empty() { 53 for (LoadingCache<Object, Object> cache : caches()) { 54 cache.getUnchecked("a"); 55 cache.getUnchecked("b"); 56 cache.invalidate("a"); 57 cache.invalidate("b"); 58 cache.invalidate(0); 59 checkEmpty(cache); 60 } 61 } 62 63 public void testInvalidateAll_empty() { 64 for (LoadingCache<Object, Object> cache : caches()) { 65 cache.getUnchecked("a"); 66 cache.getUnchecked("b"); 67 cache.getUnchecked("c"); 68 cache.invalidateAll(); 69 checkEmpty(cache); 70 } 71 } 72 73 public void testEquals_null() { 74 for (LoadingCache<Object, Object> cache : caches()) { 75 assertFalse(cache.equals(null)); 76 } 77 } 78 79 public void testEqualsAndHashCode_different() { 80 for (CacheBuilder<Object, Object> builder : cacheFactory().buildAllPermutations()) { 81 // all caches should be different: instance equality 82 new EqualsTester() 83 .addEqualityGroup(builder.build(identityLoader())) 84 .addEqualityGroup(builder.build(identityLoader())) 85 .addEqualityGroup(builder.build(identityLoader())) 86 .testEquals(); 87 } 88 } 89 90 public void testGet_null() throws ExecutionException { 91 for (LoadingCache<Object, Object> cache : caches()) { 92 try { 93 cache.get(null); 94 fail("Expected NullPointerException"); 95 } catch (NullPointerException e) { 96 // expected 97 } 98 checkEmpty(cache); 99 } 100 } 101 102 public void testGetUnchecked_null() { 103 for (LoadingCache<Object, Object> cache : caches()) { 104 try { 105 cache.getUnchecked(null); 106 fail("Expected NullPointerException"); 107 } catch (NullPointerException e) { 108 // expected 109 } 110 checkEmpty(cache); 111 } 112 } 113 114 /* ---------------- Key Set -------------- */ 115 116 public void testKeySet_nullToArray() { 117 for (LoadingCache<Object, Object> cache : caches()) { 118 Set<Object> keys = cache.asMap().keySet(); 119 try { 120 keys.toArray(null); 121 fail(); 122 } catch (NullPointerException e) { 123 // expected 124 } 125 checkEmpty(cache); 126 } 127 } 128 129 public void testKeySet_addNotSupported() { 130 for (LoadingCache<Object, Object> cache : caches()) { 131 try { 132 cache.asMap().keySet().add(1); 133 fail(); 134 } catch (UnsupportedOperationException e) { 135 // expected 136 } 137 138 try { 139 cache.asMap().keySet().addAll(asList(1, 2)); 140 fail(); 141 } catch (UnsupportedOperationException e) { 142 // expected 143 } 144 } 145 } 146 147 public void testKeySet_clear() { 148 for (LoadingCache<Object, Object> cache : caches()) { 149 warmUp(cache, 0, 100); 150 151 Set<Object> keys = cache.asMap().keySet(); 152 keys.clear(); 153 checkEmpty(keys); 154 checkEmpty(cache); 155 } 156 } 157 158 public void testKeySet_empty_remove() { 159 for (LoadingCache<Object, Object> cache : caches()) { 160 Set<Object> keys = cache.asMap().keySet(); 161 assertFalse(keys.remove(null)); 162 assertFalse(keys.remove(6)); 163 assertFalse(keys.remove(-6)); 164 assertFalse(keys.removeAll(asList(null, 0, 15, 1500))); 165 assertFalse(keys.retainAll(asList(null, 0, 15, 1500))); 166 checkEmpty(keys); 167 checkEmpty(cache); 168 } 169 } 170 171 public void testKeySet_remove() { 172 for (LoadingCache<Object, Object> cache : caches()) { 173 cache.getUnchecked(1); 174 cache.getUnchecked(2); 175 176 Set<Object> keys = cache.asMap().keySet(); 177 // We don't know whether these are still in the cache, so we can't assert on the return 178 // values of these removes, but the cache should be empty after the removes, regardless. 179 keys.remove(1); 180 keys.remove(2); 181 assertFalse(keys.remove(null)); 182 assertFalse(keys.remove(6)); 183 assertFalse(keys.remove(-6)); 184 assertFalse(keys.removeAll(asList(null, 0, 15, 1500))); 185 assertFalse(keys.retainAll(asList(null, 0, 15, 1500))); 186 checkEmpty(keys); 187 checkEmpty(cache); 188 } 189 } 190 191 /* ---------------- Values -------------- */ 192 193 public void testValues_nullToArray() { 194 for (LoadingCache<Object, Object> cache : caches()) { 195 Collection<Object> values = cache.asMap().values(); 196 try { 197 values.toArray(null); 198 fail(); 199 } catch (NullPointerException e) { 200 // expected 201 } 202 checkEmpty(cache); 203 } 204 } 205 206 public void testValues_addNotSupported() { 207 for (LoadingCache<Object, Object> cache : caches()) { 208 try { 209 cache.asMap().values().add(1); 210 fail(); 211 } catch (UnsupportedOperationException e) { 212 // expected 213 } 214 215 try { 216 cache.asMap().values().addAll(asList(1, 2)); 217 fail(); 218 } catch (UnsupportedOperationException e) { 219 // expected 220 } 221 } 222 } 223 224 public void testValues_clear() { 225 for (LoadingCache<Object, Object> cache : caches()) { 226 warmUp(cache, 0, 100); 227 228 Collection<Object> values = cache.asMap().values(); 229 values.clear(); 230 checkEmpty(values); 231 checkEmpty(cache); 232 } 233 } 234 235 public void testValues_empty_remove() { 236 for (LoadingCache<Object, Object> cache : caches()) { 237 Collection<Object> values = cache.asMap().values(); 238 assertFalse(values.remove(null)); 239 assertFalse(values.remove(6)); 240 assertFalse(values.remove(-6)); 241 assertFalse(values.removeAll(asList(null, 0, 15, 1500))); 242 assertFalse(values.retainAll(asList(null, 0, 15, 1500))); 243 checkEmpty(values); 244 checkEmpty(cache); 245 } 246 } 247 248 public void testValues_remove() { 249 for (LoadingCache<Object, Object> cache : caches()) { 250 cache.getUnchecked(1); 251 cache.getUnchecked(2); 252 253 Collection<Object> values = cache.asMap().keySet(); 254 // We don't know whether these are still in the cache, so we can't assert on the return 255 // values of these removes, but the cache should be empty after the removes, regardless. 256 values.remove(1); 257 values.remove(2); 258 assertFalse(values.remove(null)); 259 assertFalse(values.remove(6)); 260 assertFalse(values.remove(-6)); 261 assertFalse(values.removeAll(asList(null, 0, 15, 1500))); 262 assertFalse(values.retainAll(asList(null, 0, 15, 1500))); 263 checkEmpty(values); 264 checkEmpty(cache); 265 } 266 } 267 268 /* ---------------- Entry Set -------------- */ 269 270 public void testEntrySet_nullToArray() { 271 for (LoadingCache<Object, Object> cache : caches()) { 272 Set<Entry<Object, Object>> entries = cache.asMap().entrySet(); 273 try { 274 entries.toArray(null); 275 fail(); 276 } catch (NullPointerException e) { 277 // expected 278 } 279 checkEmpty(cache); 280 } 281 } 282 283 public void testEntrySet_addNotSupported() { 284 for (LoadingCache<Object, Object> cache : caches()) { 285 try { 286 cache.asMap().entrySet().add(entryOf(1, 1)); 287 fail(); 288 } catch (UnsupportedOperationException e) { 289 // expected 290 } 291 292 try { 293 cache.asMap().values().addAll(asList(entryOf(1, 1), entryOf(2, 2))); 294 fail(); 295 } catch (UnsupportedOperationException e) { 296 // expected 297 } 298 } 299 } 300 301 public void testEntrySet_clear() { 302 for (LoadingCache<Object, Object> cache : caches()) { 303 warmUp(cache, 0, 100); 304 305 Set<Entry<Object, Object>> entrySet = cache.asMap().entrySet(); 306 entrySet.clear(); 307 checkEmpty(entrySet); 308 checkEmpty(cache); 309 } 310 } 311 312 public void testEntrySet_empty_remove() { 313 for (LoadingCache<Object, Object> cache : caches()) { 314 Set<Entry<Object, Object>> entrySet = cache.asMap().entrySet(); 315 assertFalse(entrySet.remove(null)); 316 assertFalse(entrySet.remove(entryOf(6, 6))); 317 assertFalse(entrySet.remove(entryOf(-6, -6))); 318 assertFalse(entrySet.removeAll(asList(null, entryOf(0, 0), entryOf(15, 15)))); 319 assertFalse(entrySet.retainAll(asList(null, entryOf(0, 0), entryOf(15, 15)))); 320 checkEmpty(entrySet); 321 checkEmpty(cache); 322 } 323 } 324 325 public void testEntrySet_remove() { 326 for (LoadingCache<Object, Object> cache : caches()) { 327 cache.getUnchecked(1); 328 cache.getUnchecked(2); 329 330 Set<Entry<Object, Object>> entrySet = cache.asMap().entrySet(); 331 // We don't know whether these are still in the cache, so we can't assert on the return 332 // values of these removes, but the cache should be empty after the removes, regardless. 333 entrySet.remove(entryOf(1, 1)); 334 entrySet.remove(entryOf(2, 2)); 335 assertFalse(entrySet.remove(null)); 336 assertFalse(entrySet.remove(entryOf(1, 1))); 337 assertFalse(entrySet.remove(entryOf(6, 6))); 338 assertFalse(entrySet.removeAll(asList(null, entryOf(1, 1), entryOf(15, 15)))); 339 assertFalse(entrySet.retainAll(asList(null, entryOf(1, 1), entryOf(15, 15)))); 340 checkEmpty(entrySet); 341 checkEmpty(cache); 342 } 343 } 344 345 /* ---------------- Local utilities -------------- */ 346 347 /** 348 * Most of the tests in this class run against every one of these caches. 349 */ 350 private Iterable<LoadingCache<Object, Object>> caches() { 351 // lots of different ways to configure a LoadingCache 352 CacheBuilderFactory factory = cacheFactory(); 353 return Iterables.transform(factory.buildAllPermutations(), 354 new Function<CacheBuilder<Object, Object>, LoadingCache<Object, Object>>() { 355 @Override public LoadingCache<Object, Object> apply( 356 CacheBuilder<Object, Object> builder) { 357 return builder.build(identityLoader()); 358 } 359 }); 360 } 361 362 private CacheBuilderFactory cacheFactory() { 363 return new CacheBuilderFactory() 364 .withKeyStrengths(ImmutableSet.of(Strength.STRONG, Strength.WEAK)) 365 .withValueStrengths(ImmutableSet.copyOf(Strength.values())) 366 .withConcurrencyLevels(ImmutableSet.of(1, 4, 16, 64)) 367 .withMaximumSizes(ImmutableSet.of(0, 1, 10, 100, 1000)) 368 .withInitialCapacities(ImmutableSet.of(0, 1, 10, 100, 1000)) 369 .withExpireAfterWrites(ImmutableSet.of( 370 DurationSpec.of(0, SECONDS), 371 DurationSpec.of(1, SECONDS), 372 DurationSpec.of(1, DAYS))) 373 .withExpireAfterAccesses(ImmutableSet.of( 374 DurationSpec.of(0, SECONDS), 375 DurationSpec.of(1, SECONDS), 376 DurationSpec.of(1, DAYS))) 377 .withRefreshes(ImmutableSet.of( 378 DurationSpec.of(1, SECONDS), 379 DurationSpec.of(1, DAYS))); 380 } 381 382 private void warmUp(LoadingCache<Object, Object> cache, int minimum, int maximum) { 383 for (int i = minimum; i < maximum; i++) { 384 cache.getUnchecked(i); 385 } 386 } 387 388 private Entry<Object, Object> entryOf(Object key, Object value) { 389 return Maps.immutableEntry(key, value); 390 } 391 } 392