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 com.google.common.annotations.GwtCompatible; 18import com.google.common.annotations.GwtIncompatible; 19import com.google.common.collect.Maps; 20import com.google.common.util.concurrent.Futures; 21import com.google.common.util.concurrent.ListenableFuture; 22 23import java.util.Map; 24import 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) 32class 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