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