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