Home | History | Annotate | Download | only in cache
      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