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