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