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 com.google.common.annotations.GwtCompatible;
     18 import com.google.common.annotations.GwtIncompatible;
     19 import com.google.common.collect.Maps;
     20 import com.google.common.util.concurrent.Futures;
     21 import com.google.common.util.concurrent.ListenableFuture;
     22 
     23 import java.util.Map;
     24 import java.util.concurrent.atomic.AtomicInteger;
     25 
     26 /**
     27  * Utility {@link CacheLoader} implementations intended for use in testing.
     28  *
     29  * @author mike nonemacher
     30  */
     31 @GwtCompatible(emulated = true)
     32 class TestingCacheLoaders {
     33 
     34   /**
     35    * Returns a {@link CacheLoader} that implements a naive {@link CacheLoader#loadAll}, delegating
     36    * {@link CacheLoader#load} calls to {@code loader}.
     37    */
     38   static <K, V> CacheLoader<K, V> bulkLoader(final CacheLoader<K, V> loader) {
     39     return new CacheLoader<K, V>() {
     40       @Override
     41       public V load(K key) throws Exception {
     42         return loader.load(key);
     43       }
     44 
     45       @Override
     46       public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
     47         Map<K, V> result = Maps.newHashMap(); // allow nulls
     48         for (K key : keys) {
     49           result.put(key, load(key));
     50         }
     51         return result;
     52       }
     53     };
     54   }
     55 
     56   /**
     57    * Returns a {@link CacheLoader} that returns the given {@code constant} for every request.
     58    */
     59   static <K, V> ConstantLoader<K, V> constantLoader(V constant) {
     60     return new ConstantLoader<K, V>(constant);
     61   }
     62 
     63   /**
     64    * Returns a {@link CacheLoader} that returns the given {@code constant} for every request.
     65    */
     66   static IncrementingLoader incrementingLoader() {
     67     return new IncrementingLoader();
     68   }
     69 
     70   /**
     71    * Returns a {@link CacheLoader} that throws the given error for every request.
     72    */
     73   static <K, V> CacheLoader<K, V> errorLoader(final Error e) {
     74     return new CacheLoader<K, V>() {
     75       @Override
     76       public V load(K key) {
     77         throw e;
     78       }
     79     };
     80   }
     81 
     82   /**
     83    * Returns a {@link CacheLoader} that throws the given exception for every request.
     84    */
     85   static <K, V> CacheLoader<K, V> exceptionLoader(final Exception e) {
     86     return new CacheLoader<K, V>() {
     87       @Override
     88       public V load(K key) throws Exception {
     89         throw e;
     90       }
     91     };
     92   }
     93 
     94   /**
     95    * Returns a {@link CacheLoader} that returns the key for every request.
     96    */
     97   static <T> IdentityLoader<T> identityLoader() {
     98     return new IdentityLoader<T>();
     99   }
    100 
    101   /**
    102    * Returns a {@code new Object()} for every request, and increments a counter for every request.
    103    * The count is accessible via {@link #getCount}.
    104    */
    105   static class CountingLoader extends CacheLoader<Object, Object> {
    106     private final AtomicInteger count = new AtomicInteger();
    107 
    108     @Override
    109     public Object load(Object from) {
    110       count.incrementAndGet();
    111       return new Object();
    112     }
    113 
    114     public int getCount() {
    115       return count.get();
    116     }
    117   }
    118 
    119   static final class ConstantLoader<K, V> extends CacheLoader<K, V> {
    120     private final V constant;
    121 
    122     ConstantLoader(V constant) {
    123       this.constant = constant;
    124     }
    125 
    126     @Override
    127     public V load(K key) {
    128       return constant;
    129     }
    130   }
    131 
    132   /**
    133    * Returns a {@code new Object()} for every request, and increments a counter for every request.
    134    * An {@code Integer} loader that returns the key for {@code load} requests, and increments the
    135    * old value on {@code reload} requests. The load counts are accessible via {@link #getLoadCount}
    136    * and {@link #getReloadCount}.
    137    */
    138   static class IncrementingLoader extends CacheLoader<Integer, Integer> {
    139     private final AtomicInteger countLoad = new AtomicInteger();
    140     private final AtomicInteger countReload = new AtomicInteger();
    141 
    142     @Override
    143     public Integer load(Integer key) {
    144       countLoad.incrementAndGet();
    145       return key;
    146     }
    147 
    148     @GwtIncompatible("reload")
    149     @Override
    150     public ListenableFuture<Integer> reload(Integer key, Integer oldValue) {
    151       countReload.incrementAndGet();
    152       return Futures.immediateFuture(oldValue + 1);
    153     }
    154 
    155     public int getLoadCount() {
    156       return countLoad.get();
    157     }
    158 
    159     public int getReloadCount() {
    160       return countReload.get();
    161     }
    162   }
    163 
    164   static final class IdentityLoader<T> extends CacheLoader<T, T> {
    165     @Override
    166     public T load(T key) {
    167       return key;
    168     }
    169   }
    170 }
    171