1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package com.google.common.cache;
16
17 import static com.google.common.cache.LocalCache.Strength.STRONG;
18 import static com.google.common.collect.Maps.immutableEntry;
19 import static com.google.common.truth.Truth.assertThat;
20
21 import com.google.common.base.Function;
22 import com.google.common.cache.LocalCache.Strength;
23 import com.google.common.cache.TestingRemovalListeners.CountingRemovalListener;
24 import com.google.common.collect.ImmutableSet;
25 import com.google.common.collect.Iterables;
26
27 import junit.framework.TestCase;
28
29 import java.lang.ref.WeakReference;
30
31
32
33
34
35
36
37 public class CacheReferencesTest extends TestCase {
38
39 private static final CacheLoader<Key,String> KEY_TO_STRING_LOADER =
40 new CacheLoader<Key, String>() {
41 @Override public String load(Key key) {
42 return key.toString();
43 }
44 };
45
46 private CacheBuilderFactory factoryWithAllKeyStrengths() {
47 return new CacheBuilderFactory()
48 .withKeyStrengths(ImmutableSet.of(STRONG, Strength.WEAK))
49 .withValueStrengths(ImmutableSet.of(STRONG, Strength.WEAK, Strength.SOFT));
50 }
51
52 private Iterable<LoadingCache<Key, String>> caches() {
53 CacheBuilderFactory factory = factoryWithAllKeyStrengths();
54 return Iterables.transform(factory.buildAllPermutations(),
55 new Function<CacheBuilder<Object, Object>, LoadingCache<Key, String>>() {
56 @Override public LoadingCache<Key, String> apply(CacheBuilder<Object, Object> builder) {
57 return builder.build(KEY_TO_STRING_LOADER);
58 }
59 });
60 }
61
62 public void testContainsKeyAndValue() {
63 for (LoadingCache<Key, String> cache : caches()) {
64
65 Key key = new Key(1);
66 String value = key.toString();
67 assertSame(value, cache.getUnchecked(key));
68 assertTrue(cache.asMap().containsKey(key));
69 assertTrue(cache.asMap().containsValue(value));
70 assertEquals(1, cache.size());
71 }
72 }
73
74 public void testClear() {
75 for (LoadingCache<Key, String> cache : caches()) {
76 Key key = new Key(1);
77 String value = key.toString();
78 assertSame(value, cache.getUnchecked(key));
79 assertFalse(cache.asMap().isEmpty());
80 cache.invalidateAll();
81 assertEquals(0, cache.size());
82 assertTrue(cache.asMap().isEmpty());
83 assertFalse(cache.asMap().containsKey(key));
84 assertFalse(cache.asMap().containsValue(value));
85 }
86 }
87
88 public void testKeySetEntrySetValues() {
89 for (LoadingCache<Key, String> cache : caches()) {
90 Key key1 = new Key(1);
91 String value1 = key1.toString();
92 Key key2 = new Key(2);
93 String value2 = key2.toString();
94 assertSame(value1, cache.getUnchecked(key1));
95 assertSame(value2, cache.getUnchecked(key2));
96 assertEquals(ImmutableSet.of(key1, key2), cache.asMap().keySet());
97 assertThat(cache.asMap().values()).has().exactly(value1, value2);
98 assertEquals(ImmutableSet.of(immutableEntry(key1, value1), immutableEntry(key2, value2)),
99 cache.asMap().entrySet());
100 }
101 }
102
103 public void testInvalidate() {
104 for (LoadingCache<Key, String> cache : caches()) {
105 Key key1 = new Key(1);
106 String value1 = key1.toString();
107 Key key2 = new Key(2);
108 String value2 = key2.toString();
109 assertSame(value1, cache.getUnchecked(key1));
110 assertSame(value2, cache.getUnchecked(key2));
111 cache.invalidate(key1);
112 assertFalse(cache.asMap().containsKey(key1));
113 assertTrue(cache.asMap().containsKey(key2));
114 assertEquals(1, cache.size());
115 assertEquals(ImmutableSet.of(key2), cache.asMap().keySet());
116 assertThat(cache.asMap().values()).has().item(value2);
117 assertEquals(ImmutableSet.of(immutableEntry(key2, value2)), cache.asMap().entrySet());
118 }
119 }
120
121
122
123 private void assertCleanup(LoadingCache<Integer, String> cache,
124 CountingRemovalListener<Integer, String> removalListener) {
125
126
127
128 long initialSize = cache.size();
129 assertTrue(initialSize == 1 || initialSize == 2);
130
131
132 byte[] filler = new byte[1024];
133 for (int i = 0; i < 500; i++) {
134 System.gc();
135
136 CacheTesting.drainReferenceQueues(cache);
137 if (cache.size() == 1) {
138 break;
139 }
140 try {
141 Thread.sleep(10);
142 } catch (InterruptedException e) { }
143 try {
144
145 filler = new byte[Math.max(filler.length, filler.length * 2)];
146 } catch (OutOfMemoryError e) {}
147 }
148
149 CacheTesting.processPendingNotifications(cache);
150 assertEquals(1, cache.size());
151 assertEquals(1, removalListener.getCount());
152 }
153
154
155
156 static class Key {
157 private final int value;
158 private WeakReference<String> toString;
159
160 Key(int value) {
161 this.value = value;
162 }
163
164 @Override public synchronized String toString() {
165 String s;
166 if (toString != null) {
167 s = toString.get();
168 if (s != null) {
169 return s;
170 }
171 }
172 s = Integer.toString(value);
173 toString = new WeakReference<String>(s);
174 return s;
175 }
176 }
177 }