• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    */
bulkLoader(final CacheLoader<K, V> loader)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