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