• 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 
31 import junit.framework.TestCase;
32 
33 import java.util.Collection;
34 import java.util.Map.Entry;
35 import java.util.Set;
36 import java.util.concurrent.ExecutionException;
37 
38 /**
39  * {@link LoadingCache} tests that deal with empty caches.
40  *
41  * @author mike nonemacher
42  */
43 public class EmptyCachesTest extends TestCase {
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 e) {
94         // expected
95       }
96       checkEmpty(cache);
97     }
98   }
99 
testGetUnchecked_null()100   public void testGetUnchecked_null() {
101     for (LoadingCache<Object, Object> cache : caches()) {
102       try {
103         cache.getUnchecked(null);
104         fail("Expected NullPointerException");
105       } catch (NullPointerException e) {
106         // 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(null);
119         fail();
120       } catch (NullPointerException e) {
121         // expected
122       }
123       checkEmpty(cache);
124     }
125   }
126 
testKeySet_addNotSupported()127   public void testKeySet_addNotSupported() {
128     for (LoadingCache<Object, Object> cache : caches()) {
129       try {
130         cache.asMap().keySet().add(1);
131         fail();
132       } catch (UnsupportedOperationException e) {
133         // expected
134       }
135 
136       try {
137         cache.asMap().keySet().addAll(asList(1, 2));
138         fail();
139       } catch (UnsupportedOperationException e) {
140         // expected
141       }
142     }
143   }
144 
testKeySet_clear()145   public void testKeySet_clear() {
146     for (LoadingCache<Object, Object> cache : caches()) {
147       warmUp(cache, 0, 100);
148 
149       Set<Object> keys = cache.asMap().keySet();
150       keys.clear();
151       checkEmpty(keys);
152       checkEmpty(cache);
153     }
154   }
155 
testKeySet_empty_remove()156   public void testKeySet_empty_remove() {
157     for (LoadingCache<Object, Object> cache : caches()) {
158       Set<Object> keys = cache.asMap().keySet();
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 
testKeySet_remove()169   public void testKeySet_remove() {
170     for (LoadingCache<Object, Object> cache : caches()) {
171       cache.getUnchecked(1);
172       cache.getUnchecked(2);
173 
174       Set<Object> keys = cache.asMap().keySet();
175       // We don't know whether these are still in the cache, so we can't assert on the return
176       // values of these removes, but the cache should be empty after the removes, regardless.
177       keys.remove(1);
178       keys.remove(2);
179       assertFalse(keys.remove(null));
180       assertFalse(keys.remove(6));
181       assertFalse(keys.remove(-6));
182       assertFalse(keys.removeAll(asList(null, 0, 15, 1500)));
183       assertFalse(keys.retainAll(asList(null, 0, 15, 1500)));
184       checkEmpty(keys);
185       checkEmpty(cache);
186     }
187   }
188 
189   /* ---------------- Values -------------- */
190 
testValues_nullToArray()191   public void testValues_nullToArray() {
192     for (LoadingCache<Object, Object> cache : caches()) {
193       Collection<Object> values = cache.asMap().values();
194       try {
195         values.toArray(null);
196         fail();
197       } catch (NullPointerException e) {
198         // expected
199       }
200       checkEmpty(cache);
201     }
202   }
203 
testValues_addNotSupported()204   public void testValues_addNotSupported() {
205     for (LoadingCache<Object, Object> cache : caches()) {
206       try {
207         cache.asMap().values().add(1);
208         fail();
209       } catch (UnsupportedOperationException e) {
210         // expected
211       }
212 
213       try {
214         cache.asMap().values().addAll(asList(1, 2));
215         fail();
216       } catch (UnsupportedOperationException e) {
217         // expected
218       }
219     }
220   }
221 
testValues_clear()222   public void testValues_clear() {
223     for (LoadingCache<Object, Object> cache : caches()) {
224       warmUp(cache, 0, 100);
225 
226       Collection<Object> values = cache.asMap().values();
227       values.clear();
228       checkEmpty(values);
229       checkEmpty(cache);
230     }
231   }
232 
testValues_empty_remove()233   public void testValues_empty_remove() {
234     for (LoadingCache<Object, Object> cache : caches()) {
235       Collection<Object> values = cache.asMap().values();
236       assertFalse(values.remove(null));
237       assertFalse(values.remove(6));
238       assertFalse(values.remove(-6));
239       assertFalse(values.removeAll(asList(null, 0, 15, 1500)));
240       assertFalse(values.retainAll(asList(null, 0, 15, 1500)));
241       checkEmpty(values);
242       checkEmpty(cache);
243     }
244   }
245 
testValues_remove()246   public void testValues_remove() {
247     for (LoadingCache<Object, Object> cache : caches()) {
248       cache.getUnchecked(1);
249       cache.getUnchecked(2);
250 
251       Collection<Object> values = cache.asMap().keySet();
252       // We don't know whether these are still in the cache, so we can't assert on the return
253       // values of these removes, but the cache should be empty after the removes, regardless.
254       values.remove(1);
255       values.remove(2);
256       assertFalse(values.remove(null));
257       assertFalse(values.remove(6));
258       assertFalse(values.remove(-6));
259       assertFalse(values.removeAll(asList(null, 0, 15, 1500)));
260       assertFalse(values.retainAll(asList(null, 0, 15, 1500)));
261       checkEmpty(values);
262       checkEmpty(cache);
263     }
264   }
265 
266   /* ---------------- Entry Set -------------- */
267 
testEntrySet_nullToArray()268   public void testEntrySet_nullToArray() {
269     for (LoadingCache<Object, Object> cache : caches()) {
270       Set<Entry<Object, Object>> entries = cache.asMap().entrySet();
271       try {
272         entries.toArray(null);
273         fail();
274       } catch (NullPointerException e) {
275         // expected
276       }
277       checkEmpty(cache);
278     }
279   }
280 
testEntrySet_addNotSupported()281   public void testEntrySet_addNotSupported() {
282     for (LoadingCache<Object, Object> cache : caches()) {
283       try {
284         cache.asMap().entrySet().add(entryOf(1, 1));
285         fail();
286       } catch (UnsupportedOperationException e) {
287         // expected
288       }
289 
290       try {
291         cache.asMap().values().addAll(asList(entryOf(1, 1), entryOf(2, 2)));
292         fail();
293       } catch (UnsupportedOperationException e) {
294         // expected
295       }
296     }
297   }
298 
testEntrySet_clear()299   public void testEntrySet_clear() {
300     for (LoadingCache<Object, Object> cache : caches()) {
301       warmUp(cache, 0, 100);
302 
303       Set<Entry<Object, Object>> entrySet = cache.asMap().entrySet();
304       entrySet.clear();
305       checkEmpty(entrySet);
306       checkEmpty(cache);
307     }
308   }
309 
testEntrySet_empty_remove()310   public void testEntrySet_empty_remove() {
311     for (LoadingCache<Object, Object> cache : caches()) {
312       Set<Entry<Object, Object>> entrySet = cache.asMap().entrySet();
313       assertFalse(entrySet.remove(null));
314       assertFalse(entrySet.remove(entryOf(6, 6)));
315       assertFalse(entrySet.remove(entryOf(-6, -6)));
316       assertFalse(entrySet.removeAll(asList(null, entryOf(0, 0), entryOf(15, 15))));
317       assertFalse(entrySet.retainAll( asList(null, entryOf(0, 0), entryOf(15, 15))));
318       checkEmpty(entrySet);
319       checkEmpty(cache);
320     }
321   }
322 
testEntrySet_remove()323   public void testEntrySet_remove() {
324     for (LoadingCache<Object, Object> cache : caches()) {
325       cache.getUnchecked(1);
326       cache.getUnchecked(2);
327 
328       Set<Entry<Object, Object>> entrySet = cache.asMap().entrySet();
329       // We don't know whether these are still in the cache, so we can't assert on the return
330       // values of these removes, but the cache should be empty after the removes, regardless.
331       entrySet.remove(entryOf(1, 1));
332       entrySet.remove(entryOf(2, 2));
333       assertFalse(entrySet.remove(null));
334       assertFalse(entrySet.remove(entryOf(1, 1)));
335       assertFalse(entrySet.remove(entryOf(6, 6)));
336       assertFalse(entrySet.removeAll(asList(null, entryOf(1, 1), entryOf(15, 15))));
337       assertFalse(entrySet.retainAll(asList(null, entryOf(1, 1), entryOf(15, 15))));
338       checkEmpty(entrySet);
339       checkEmpty(cache);
340     }
341   }
342 
343   /* ---------------- Local utilities -------------- */
344 
345   /**
346    * Most of the tests in this class run against every one of these caches.
347    */
caches()348   private Iterable<LoadingCache<Object, Object>> caches() {
349     // lots of different ways to configure a LoadingCache
350     CacheBuilderFactory factory = cacheFactory();
351     return Iterables.transform(factory.buildAllPermutations(),
352         new Function<CacheBuilder<Object, Object>, LoadingCache<Object, Object>>() {
353           @Override public LoadingCache<Object, Object> apply(
354               CacheBuilder<Object, Object> builder) {
355             return builder.build(identityLoader());
356           }
357         });
358   }
359 
360   private CacheBuilderFactory cacheFactory() {
361     return new CacheBuilderFactory()
362         .withKeyStrengths(ImmutableSet.of(Strength.STRONG, Strength.WEAK))
363         .withValueStrengths(ImmutableSet.copyOf(Strength.values()))
364         .withConcurrencyLevels(ImmutableSet.of(1, 4, 16, 64))
365         .withMaximumSizes(ImmutableSet.of(0, 1, 10, 100, 1000))
366         .withInitialCapacities(ImmutableSet.of(0, 1, 10, 100, 1000))
367         .withExpireAfterWrites(ImmutableSet.of(
368             DurationSpec.of(0, SECONDS),
369             DurationSpec.of(1, SECONDS),
370             DurationSpec.of(1, DAYS)))
371         .withExpireAfterAccesses(ImmutableSet.of(
372             DurationSpec.of(0, SECONDS),
373             DurationSpec.of(1, SECONDS),
374             DurationSpec.of(1, DAYS)))
375         .withRefreshes(ImmutableSet.of(
376             DurationSpec.of(1, SECONDS),
377             DurationSpec.of(1, DAYS)));
378   }
379 
380   private void warmUp(LoadingCache<Object, Object> cache, int minimum, int maximum) {
381     for (int i = minimum; i < maximum; i++) {
382       cache.getUnchecked(i);
383     }
384   }
385 
386   private Entry<Object, Object> entryOf(Object key, Object value) {
387     return Maps.immutableEntry(key, value);
388   }
389 }
390