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 import java.util.stream.Collectors;
9
10 import com.atlassian.vcache.ChangeRate;
11 import com.atlassian.vcache.DirectExternalCache;
12 import com.atlassian.vcache.ExternalCacheSettings;
13 import com.atlassian.vcache.ExternalCacheSettingsBuilder;
14 import com.atlassian.vcache.IdentifiedValue;
15 import com.atlassian.vcache.PutPolicy;
16
17 import org.junit.Before;
18 import org.junit.Test;
19
20 import static com.atlassian.vcache.internal.test.CompletableFutureSuccessful.successful;
21 import static com.atlassian.vcache.internal.test.CompletableFutureSuccessful.successfulWith;
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.containsInAnyOrder;
24 import static org.hamcrest.Matchers.equalTo;
25 import static org.hamcrest.Matchers.is;
26 import static org.hamcrest.Matchers.notNullValue;
27 import static org.hamcrest.Matchers.nullValue;
28
29
30
31
32 public abstract class AbstractDirectExternalCacheIT
33 {
34 private DirectExternalCache<String> cache;
35
36 protected abstract DirectExternalCache<String> createCache(String name, ExternalCacheSettings settings);
37
38 @Before
39 public void ensureCache()
40 {
41 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
42 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
43 .entryCountHint(5)
44 .defaultTtl(Duration.ofMinutes(5))
45 .dataChangeRateHint(ChangeRate.HIGH_CHANGE)
46 .build();
47 cache = createCache("abc", settings);
48 final CompletableFuture<Void> rm = cache.removeAll();
49 assertThat(rm, successful());
50 }
51
52 @Test
53 public void simple_get_set() throws ExecutionException, InterruptedException
54 {
55 final CompletableFuture<Optional<String>> eldestGet = cache.get("claira");
56
57 assertThat(eldestGet, successfulWith(is(Optional.empty())));
58
59 final CompletableFuture<Boolean> eldestAdd = cache.put("claira", "dancing", PutPolicy.ADD_ONLY);
60
61 assertThat(eldestAdd, successfulWith(is(true)));
62
63 final CompletableFuture<Optional<String>> eldestGet2 = cache.get("claira");
64
65 assertThat(eldestGet2, successfulWith(is(Optional.of("dancing"))));
66
67 final CompletableFuture<Boolean> eldestAdd2 = cache.put("claira", "singing", PutPolicy.ADD_ONLY);
68
69 assertThat(eldestAdd2, successfulWith(is(false)));
70 }
71
72 @Test
73 public void simple_get_with_supplier() throws ExecutionException, InterruptedException
74 {
75 final CompletableFuture<Optional<String>> eldestGet1 = cache.get("josephine");
76
77 assertThat(eldestGet1, successfulWith(is(Optional.empty())));
78
79 final CompletableFuture<String> eldestGet2 = cache.get("josephine", () -> "football");
80
81 assertThat(eldestGet2, successfulWith(is("football")));
82
83 final CompletableFuture<Optional<String>> eldestGet3 = cache.get("josephine");
84
85 assertThat(eldestGet3, successfulWith(is(Optional.of("football"))));
86 }
87
88 @Test
89 public void put_with_huge_key() throws ExecutionException, InterruptedException
90 {
91 final String key = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
92 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
93 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
94 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
95 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
96 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
97 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
98 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
99 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
100 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
101 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
102 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
103 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
104 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
105 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
106 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
107 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
108 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
109
110 final CompletableFuture<Boolean> hugeAdd = cache.put(key, "dancing", PutPolicy.ADD_ONLY);
111
112 assertThat(hugeAdd, successfulWith(is(true)));
113
114 final CompletableFuture<Optional<String>> hugeGet = cache.get(key);
115
116 assertThat(hugeGet, successfulWith(is(Optional.of("dancing"))));
117 }
118
119 @Test
120 public void simple_getBulkIdentified() throws ExecutionException, InterruptedException
121 {
122 final CompletableFuture<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
123
124 assertThat(put1, successfulWith(is(true)));
125
126 final CompletableFuture<Optional<IdentifiedValue<String>>> get1 = cache.getIdentified("josie");
127
128 assertThat(get1, successful());
129 final IdentifiedValue<String> iv1 = get1.get().get();
130 assertThat(iv1.identifier(), notNullValue());
131 assertThat(iv1.value(), is("football"));
132
133 final CompletableFuture<Map<String, Optional<IdentifiedValue<String>>>> get2 =
134 cache.getBulkIdentified("claira", "josie", "jasmin");
135
136 assertThat(get2, successful());
137 final Map<String, Optional<IdentifiedValue<String>>> ivMap1 = get2.get();
138 assertThat(ivMap1.keySet(), containsInAnyOrder("jasmin", "claira", "josie"));
139 assertThat(ivMap1.get("claira"), is(Optional.empty()));
140 assertThat(ivMap1.get("jasmin"), is(Optional.empty()));
141 final IdentifiedValue<String> iv2 = ivMap1.get("josie").get();
142 assertThat(iv2.identifier(), notNullValue());
143 assertThat(iv2.identifier(), equalTo(iv1.identifier()));
144 assertThat(iv2.value(), is("football"));
145 }
146
147 @Test
148 public void simple_getIdentified_removeIf() throws ExecutionException, InterruptedException
149 {
150 final CompletableFuture<Optional<IdentifiedValue<String>>> get1 = cache.getIdentified("josie");
151
152 assertThat(get1, successfulWith(is(Optional.empty())));
153
154 final CompletableFuture<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
155
156 assertThat(put1, successfulWith(is(true)));
157
158 final CompletableFuture<Optional<IdentifiedValue<String>>> get2 = cache.getIdentified("josie");
159
160 assertThat(get2, successful());
161 final IdentifiedValue<String> iv2 = get2.get().get();
162 assertThat(iv2.identifier(), notNullValue());
163 assertThat(iv2.value(), is("football"));
164
165 final CompletableFuture<Boolean> rm1 = cache.removeIf("josie", iv2.identifier());
166
167 assertThat(rm1, successfulWith(is(true)));
168
169 final CompletableFuture<Boolean> put2 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
170
171 assertThat(put2, successfulWith(is(true)));
172
173 final CompletableFuture<Boolean> rm2 = cache.removeIf("josie", iv2.identifier());
174
175 assertThat(rm2, successfulWith(is(false)));
176
177 final CompletableFuture<Optional<IdentifiedValue<String>>> get3 = cache.getIdentified("josie");
178
179 assertThat(get3, successful());
180 final IdentifiedValue<String> iv3 = get3.get().get();
181 assertThat(iv3.identifier(), notNullValue());
182 assertThat(iv3.value(), is("football"));
183
184 final CompletableFuture<Boolean> rm3 = cache.removeIf("josie", iv3.identifier());
185
186 assertThat(rm3, successfulWith(is(true)));
187 }
188
189 @Test
190 public void simple_getIdentified_replaceIf() throws ExecutionException, InterruptedException
191 {
192 final CompletableFuture<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
193
194 assertThat(put1, successfulWith(is(true)));
195
196 final CompletableFuture<Optional<IdentifiedValue<String>>> get1 = cache.getIdentified("josie");
197
198 assertThat(get1, successful());
199 final IdentifiedValue<String> iv1 = get1.get().get();
200 assertThat(iv1.identifier(), notNullValue());
201 assertThat(iv1.value(), is("football"));
202
203 final CompletableFuture<Boolean> rm1 = cache.replaceIf("josie", iv1.identifier(), "soccer");
204
205 assertThat(rm1, successfulWith(is(true)));
206
207 final CompletableFuture<Boolean> put2 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
208
209 assertThat(put2, successfulWith(is(true)));
210
211 final CompletableFuture<Boolean> rm2 = cache.removeIf("josie", iv1.identifier());
212
213 assertThat(rm2, successfulWith(is(false)));
214
215 final CompletableFuture<Optional<IdentifiedValue<String>>> get3 = cache.getIdentified("josie");
216
217 assertThat(get3, successful());
218 final IdentifiedValue<String> iv3 = get3.get().get();
219 assertThat(iv3.identifier(), notNullValue());
220 assertThat(iv3.value(), is("football"));
221
222 final CompletableFuture<Boolean> rm3 = cache.removeIf("josie", iv3.identifier());
223
224 assertThat(rm3, successfulWith(is(true)));
225 }
226
227 @Test
228 public void simple_put_remove() throws ExecutionException, InterruptedException
229 {
230 final CompletableFuture<Void> rm1 = cache.remove("claira");
231
232 assertThat(rm1, successful());
233 assertThat(rm1.get(), nullValue());
234
235 final CompletableFuture<Boolean> put1 = cache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
236
237 assertThat(put1, successfulWith(is(true)));
238
239 final CompletableFuture<Void> rm2 = cache.remove("claira");
240
241 assertThat(rm2, successful());
242
243 final CompletableFuture<Boolean> put2 = cache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
244
245 assertThat(put2, successfulWith(is(true)));
246
247 final CompletableFuture<Optional<String>> get1 = cache.get("claira");
248
249 assertThat(get1, successfulWith(is(Optional.of("dancing"))));
250
251 final CompletableFuture<Void> rm3 = cache.remove("josie", "claira", "jasmin");
252
253 assertThat(rm3, successful());
254
255 final CompletableFuture<Optional<String>> get2 = cache.get("claira");
256
257 assertThat(get2, successfulWith(is(Optional.empty())));
258 }
259
260 @Test
261 public void simple_removeAll() throws ExecutionException, InterruptedException
262 {
263 final CompletableFuture<Boolean> put1 = cache.put("claira", "", PutPolicy.PUT_ALWAYS);
264
265 assertThat(put1, successfulWith(is(true)));
266
267 final CompletableFuture<Optional<String>> get1 = cache.get("claira");
268
269 assertThat(get1, successfulWith(is(Optional.of(""))));
270
271 final CompletableFuture<Void> rm1 = cache.removeAll();
272
273 assertThat(rm1, successful());
274
275 final CompletableFuture<Optional<String>> get2 = cache.get("claira");
276
277 assertThat(get2, successfulWith(is(Optional.empty())));
278 }
279
280 @SuppressWarnings("unchecked")
281 @Test
282 public void simple_getBulk() throws ExecutionException, InterruptedException
283 {
284 final CompletableFuture<Map<String, Optional<String>>> get1 = cache.getBulk("claira", "jasmin", "josie", "josie");
285
286 assertThat(get1, successful());
287 assertThat(get1.get().keySet(), containsInAnyOrder("claira", "jasmin", "josie"));
288 assertThat(get1.get().values(), containsInAnyOrder(Optional.empty(), Optional.empty(), Optional.empty()));
289
290 final CompletableFuture<Boolean> put1 = cache.put("claira", "youtube", PutPolicy.PUT_ALWAYS);
291
292 assertThat(put1, successfulWith(is(true)));
293
294 final CompletableFuture<Map<String, Optional<String>>> get2 = cache.getBulk("jasmin", "claira", "josie", "claira");
295
296 assertThat(get2, successful());
297 assertThat(get2.get().keySet(), containsInAnyOrder("claira", "jasmin", "josie"));
298 assertThat(get2.get().values(), containsInAnyOrder(Optional.of("youtube"), Optional.empty(), Optional.empty()));
299 }
300
301 @Test
302 public void simple_getBulkFactory() throws ExecutionException, InterruptedException
303 {
304 final CompletableFuture<Map<String, String>> get1 =
305 cache.getBulk(
306 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> k + "-1")),
307 "claira", "josie", "josie");
308
309 assertThat(get1, successful());
310 assertThat(get1.get().keySet(), containsInAnyOrder("claira", "josie"));
311 assertThat(get1.get().values(), containsInAnyOrder("claira-1", "josie-1"));
312
313 final CompletableFuture<Map<String, String>> get2 =
314 cache.getBulk(
315 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> k + "-2")),
316 "claira", "josie", "jasmin");
317
318 assertThat(get2, successful());
319 assertThat(get2.get().keySet(), containsInAnyOrder("claira", "josie", "jasmin"));
320 assertThat(get2.get().values(), containsInAnyOrder("claira-1", "josie-1", "jasmin-2"));
321 }
322 }