1 package com.atlassian.vcache.internal.test;
2
3 import java.time.Duration;
4 import java.util.Map;
5 import java.util.Optional;
6 import java.util.concurrent.CompletableFuture;
7 import java.util.concurrent.ExecutionException;
8
9 import com.atlassian.vcache.ChangeRate;
10 import com.atlassian.vcache.DirectExternalCache;
11 import com.atlassian.vcache.ExternalCacheSettings;
12 import com.atlassian.vcache.ExternalCacheSettingsBuilder;
13 import com.atlassian.vcache.PutPolicy;
14 import com.atlassian.vcache.StableReadExternalCache;
15
16 import com.google.common.collect.Maps;
17 import org.hamcrest.Matchers;
18 import org.junit.Before;
19 import org.junit.Rule;
20 import org.junit.Test;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import static com.atlassian.vcache.internal.test.CompletableFutureSuccessful.successful;
25 import static com.atlassian.vcache.internal.test.CompletableFutureSuccessful.successfulWith;
26 import static org.hamcrest.MatcherAssert.assertThat;
27 import static org.hamcrest.Matchers.containsInAnyOrder;
28 import static org.hamcrest.Matchers.is;
29
30
31
32
33 public abstract class AbstractStableReadExternalCacheIT
34 {
35 private static final Logger log = LoggerFactory.getLogger(AbstractStableReadExternalCacheIT.class);
36 private static final String CACHE_NAME = "kids_hobbies";
37
38 @Rule
39 public LoggingTestWatcher watcher = new LoggingTestWatcher(log);
40
41 private StableReadExternalCache<String> cache;
42 private DirectExternalCache<String> directCache;
43
44 protected abstract StableReadExternalCache<String> createCache(String name, ExternalCacheSettings settings);
45 protected abstract DirectExternalCache<String> obtainDirectCache(String name, ExternalCacheSettings settings);
46
47 @Before
48 public void ensureCache()
49 {
50 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
51 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
52 .entryCountHint(5)
53 .defaultTtl(Duration.ofSeconds(5))
54 .dataChangeRateHint(ChangeRate.HIGH_CHANGE)
55 .build();
56 cache = createCache(CACHE_NAME, settings);
57
58 directCache = obtainDirectCache(CACHE_NAME, settings);
59
60
61 final CompletableFuture<Void> rm = directCache.removeAll();
62 assertThat(rm, successful());
63 }
64
65 @Test
66 public void single_cache_get_set() throws ExecutionException, InterruptedException
67 {
68 final CompletableFuture<Optional<String>> eldestGet = cache.get("claira");
69
70 assertThat(eldestGet, successfulWith(is(Optional.empty())));
71
72 final CompletableFuture<Boolean> eldestAdd = cache.put("claira", "dancing", PutPolicy.ADD_ONLY);
73
74 assertThat(eldestAdd, successfulWith(is(true)));
75
76 final CompletableFuture<Optional<String>> eldestGet2 = cache.get("claira");
77
78 assertThat(eldestGet2, successfulWith(is(Optional.of("dancing"))));
79 }
80
81 @Test
82 public void dual_cache_get_set() throws ExecutionException, InterruptedException
83 {
84 final CompletableFuture<Optional<String>> get1 = cache.get("claira");
85
86 assertThat(get1, successfulWith(is(Optional.empty())));
87
88
89 final CompletableFuture<Boolean> dput1 = directCache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
90
91 assertThat(dput1, successfulWith(is(true)));
92
93 final CompletableFuture<Optional<String>> get2 = cache.get("claira");
94
95 assertThat(get2, successfulWith(is(Optional.empty())));
96
97
98
99 final CompletableFuture<Boolean> put1 = cache.put("claira", "singing", PutPolicy.ADD_ONLY);
100
101 assertThat(put1, successfulWith(is(false)));
102
103 final CompletableFuture<Optional<String>> get3 = cache.get("claira");
104
105 assertThat(get3, successfulWith(is(Optional.of("dancing"))));
106 }
107
108 @Test
109 public void dual_cache_get_with_supplier() throws ExecutionException, InterruptedException
110 {
111 final CompletableFuture<Optional<String>> get1 = cache.get("claira");
112
113 assertThat(get1, successfulWith(is(Optional.empty())));
114
115 final CompletableFuture<String> get2 = cache.get("claira", () -> "dancing");
116
117 assertThat(get2, successfulWith(is("dancing")));
118
119 final CompletableFuture<Optional<String>> get3 = cache.get("claira");
120
121 assertThat(get3, successfulWith(is(Optional.of("dancing"))));
122
123
124 final CompletableFuture<Boolean> dput1 = directCache.put("claira", "singing", PutPolicy.PUT_ALWAYS);
125 assertThat(dput1, successfulWith(is(true)));
126
127 final CompletableFuture<Optional<String>> get4 = cache.get("claira");
128
129 assertThat(get4, successfulWith(is(Optional.of("dancing"))));
130
131 final CompletableFuture<String> get5 = cache.get("claira", () -> "riding");
132
133 assertThat(get5, successfulWith(is("dancing")));
134 }
135
136 @Test
137 public void dual_cache_get_with_supplier_take2() throws ExecutionException, InterruptedException
138 {
139 final CompletableFuture<Optional<String>> get1 = cache.get("claira");
140
141 assertThat(get1, successfulWith(is(Optional.empty())));
142
143 final CompletableFuture<Boolean> dput1 = directCache.put("claira", "singing", PutPolicy.PUT_ALWAYS);
144 assertThat(dput1, successfulWith(is(true)));
145
146 final CompletableFuture<String> get2 = cache.get("claira", () -> "riding");
147
148 assertThat(get2, successfulWith(is("singing")));
149 }
150
151 @Test
152 public void dual_cache_getBulk() throws ExecutionException, InterruptedException
153 {
154 final CompletableFuture<Boolean> dput1 = directCache.put("claira", "singing", PutPolicy.PUT_ALWAYS);
155 assertThat(dput1, successfulWith(is(true)));
156
157 final CompletableFuture<Map<String, Optional<String>>> get1 = cache.getBulk("claira", "josephine", "claira");
158
159 assertThat(get1, successful());
160 final Map<String, Optional<String>> map1 = get1.get();
161 assertThat(map1.keySet(), Matchers.containsInAnyOrder("claira", "josephine"));
162 assertThat(map1.get("claira"), is(Optional.of("singing")));
163 assertThat(map1.get("josephine"), is(Optional.empty()));
164
165 final CompletableFuture<Boolean> dput2 = directCache.put("josephine", "football", PutPolicy.PUT_ALWAYS);
166 assertThat(dput2, successfulWith(is(true)));
167
168 final CompletableFuture<Boolean> dput3 = directCache.put("jasmin", "skiing", PutPolicy.PUT_ALWAYS);
169 assertThat(dput3, successfulWith(is(true)));
170
171 final CompletableFuture<Map<String, Optional<String>>> get2 = cache.getBulk("claira", "josephine", "jasmin");
172
173 assertThat(get2, successful());
174 final Map<String, Optional<String>> map2 = get2.get();
175 assertThat(map2.keySet(), Matchers.containsInAnyOrder("claira", "josephine", "jasmin"));
176 assertThat(map2.get("claira"), is(Optional.of("singing")));
177 assertThat(map2.get("josephine"), is(Optional.empty()));
178 assertThat(map2.get("jasmin"), is(Optional.of("skiing")));
179 }
180
181 @Test
182 public void remove_normal() throws ExecutionException, InterruptedException
183 {
184 final CompletableFuture<Boolean> dput1 = directCache.put("claira", "singing", PutPolicy.PUT_ALWAYS);
185 assertThat(dput1, successfulWith(is(true)));
186
187 final CompletableFuture<Boolean> put1 = cache.put("josephine", "football", PutPolicy.PUT_ALWAYS);
188 assertThat(put1, successfulWith(is(true)));
189
190 final CompletableFuture<Map<String, Optional<String>>> get1 = cache.getBulk("claira", "josephine", "jasmin");
191
192 assertThat(get1, successful());
193 final Map<String, Optional<String>> map1 = get1.get();
194 assertThat(map1.keySet(), Matchers.containsInAnyOrder("claira", "josephine", "jasmin"));
195 assertThat(map1.get("claira"), is(Optional.of("singing")));
196 assertThat(map1.get("josephine"), is(Optional.of("football")));
197 assertThat(map1.get("jasmin"), is(Optional.empty()));
198
199 final CompletableFuture<Void> rm1 = cache.remove("jasmin", "claira", "claira", "josephine");
200
201 assertThat(rm1, successful());
202
203 final CompletableFuture<Map<String, Optional<String>>> dget1 = directCache.getBulk("claira", "josephine", "jasmin");
204
205 assertThat(dget1, successful());
206 final Map<String, Optional<String>> dmap1 = dget1.get();
207 assertThat(dmap1.keySet(), Matchers.containsInAnyOrder("claira", "josephine", "jasmin"));
208 assertThat(dmap1.get("claira"), is(Optional.empty()));
209 assertThat(dmap1.get("josephine"), is(Optional.empty()));
210 assertThat(dmap1.get("jasmin"), is(Optional.empty()));
211
212 final CompletableFuture<Map<String, Optional<String>>> get2 = cache.getBulk("claira", "josephine", "jasmin");
213
214 assertThat(get2, successful());
215 final Map<String, Optional<String>> map2 = get2.get();
216 assertThat(map2.keySet(), Matchers.containsInAnyOrder("claira", "josephine", "jasmin"));
217 assertThat(map2.get("claira"), is(Optional.empty()));
218 assertThat(map2.get("josephine"), is(Optional.empty()));
219 assertThat(map2.get("jasmin"), is(Optional.empty()));
220 }
221
222 @Test
223 public void simple_removeAll() throws ExecutionException, InterruptedException
224 {
225 final CompletableFuture<Boolean> put1 = cache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
226
227 assertThat(put1, successfulWith(is(true)));
228
229 final CompletableFuture<Optional<String>> get1 = cache.get("claira");
230
231 assertThat(get1, successfulWith(is(Optional.of("dancing"))));
232
233 final CompletableFuture<Void> rm1 = cache.removeAll();
234
235 assertThat(rm1, successful());
236
237 final CompletableFuture<Optional<String>> get2 = cache.get("claira");
238
239 assertThat(get2, successfulWith(is(Optional.empty())));
240 }
241
242 @Test
243 public void simple_getBulk_function() throws ExecutionException, InterruptedException
244 {
245 final CompletableFuture<Map<String, String>> get1 = cache.getBulk(
246 keys -> Maps.asMap(keys, k -> k + "-1"), "claira");
247
248 assertThat(get1, successful());
249 assertThat(get1.get().keySet(), containsInAnyOrder("claira"));
250 assertThat(get1.get().values(), containsInAnyOrder("claira-1"));
251
252 final CompletableFuture<Map<String, String>> get2 = cache.getBulk(
253 keys -> Maps.asMap(keys, k -> k + "-2"), "claira", "josephine", "claira");
254
255 assertThat(get2, successful());
256 assertThat(get2.get().keySet(), containsInAnyOrder("claira", "josephine"));
257 assertThat(get2.get().values(), containsInAnyOrder("claira-1", "josephine-2"));
258 }
259
260 @Test
261 public void dual_getBulk_function() throws ExecutionException, InterruptedException
262 {
263 final CompletableFuture<Map<String, String>> get1 = cache.getBulk(
264 keys -> Maps.asMap(keys, k -> k + "-1"), "claira");
265
266 assertThat(get1, successful());
267 assertThat(get1.get().keySet(), containsInAnyOrder("claira"));
268 assertThat(get1.get().values(), containsInAnyOrder("claira-1"));
269
270 final CompletableFuture<Boolean> mput1 = directCache.put("claira", "singing", PutPolicy.PUT_ALWAYS);
271 assertThat(mput1, successfulWith(is(true)));
272
273 final CompletableFuture<Map<String, String>> get2 = cache.getBulk(
274 keys -> Maps.asMap(keys, k -> k + "-2"), "claira", "josephine", "claira");
275
276 assertThat(get2, successful());
277 assertThat(get2.get().keySet(), containsInAnyOrder("claira", "josephine"));
278 assertThat(get2.get().values(), containsInAnyOrder("claira-1", "josephine-2"));
279
280 final CompletableFuture<Void> rm1 = cache.remove("claira");
281
282 assertThat(rm1, successful());
283
284 final CompletableFuture<Map<String, String>> get3 = cache.getBulk(
285 keys -> Maps.asMap(keys, k -> k + "-3"), "claira", "josephine", "jasmin");
286
287 assertThat(get3, successful());
288 assertThat(get3.get().keySet(), containsInAnyOrder("claira", "josephine", "jasmin"));
289 assertThat(get3.get().values(), containsInAnyOrder("claira-3", "josephine-2", "jasmin-3"));
290 }
291 }