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