1 package com.atlassian.vcache.internal.test;
2
3 import com.atlassian.vcache.ChangeRate;
4 import com.atlassian.vcache.DirectExternalCache;
5 import com.atlassian.vcache.ExternalCacheSettings;
6 import com.atlassian.vcache.ExternalCacheSettingsBuilder;
7 import com.atlassian.vcache.IdentifiedValue;
8 import com.atlassian.vcache.PutPolicy;
9 import com.atlassian.vcache.internal.LongMetric;
10 import com.atlassian.vcache.internal.MetricLabel;
11 import com.atlassian.vcache.internal.RequestMetrics;
12 import org.junit.Before;
13 import org.junit.Test;
14
15 import java.time.Duration;
16 import java.util.EnumMap;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.concurrent.CompletionStage;
20 import java.util.concurrent.ExecutionException;
21 import java.util.stream.Collectors;
22
23 import static com.atlassian.vcache.VCacheUtils.unsafeJoin;
24 import static com.atlassian.vcache.internal.test.CacheMetricsMatcher.hasMetric;
25 import static com.atlassian.vcache.internal.test.CacheMetricsMatcher.hasSize;
26 import static com.atlassian.vcache.internal.test.CompletionStageSuccessful.successful;
27 import static com.atlassian.vcache.internal.test.CompletionStageSuccessful.successfulWith;
28 import static org.hamcrest.MatcherAssert.assertThat;
29 import static org.hamcrest.Matchers.containsInAnyOrder;
30 import static org.hamcrest.Matchers.equalTo;
31 import static org.hamcrest.Matchers.greaterThan;
32 import static org.hamcrest.Matchers.is;
33 import static org.hamcrest.Matchers.isOneOf;
34 import static org.hamcrest.Matchers.not;
35 import static org.hamcrest.Matchers.notNullValue;
36 import static org.hamcrest.Matchers.nullValue;
37
38
39
40
41 @SuppressWarnings("OptionalGetWithoutIsPresent")
42 public abstract class AbstractDirectExternalCacheIT {
43 private static final String CACHE_NAME = "olympics";
44 private DirectExternalCache<String> cache;
45
46 protected abstract DirectExternalCache<String> createCache(String name, ExternalCacheSettings settings);
47 protected abstract RequestMetrics requestMetrics();
48
49 @Before
50 public void ensureCache() {
51 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
52 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
53 .entryCountHint(5)
54 .defaultTtl(Duration.ofMinutes(5))
55 .dataChangeRateHint(ChangeRate.HIGH_CHANGE)
56 .build();
57 cache = createCache(CACHE_NAME, settings);
58 final CompletionStage<Void> rm = cache.removeAll();
59 assertThat(rm, successful());
60 }
61
62 @Test
63 public void simple_get_set() throws ExecutionException, InterruptedException {
64 final CompletionStage<Optional<String>> eldestGet = cache.get("claira");
65
66 assertThat(eldestGet, successfulWith(is(Optional.empty())));
67
68 final CompletionStage<Boolean> eldestAdd = cache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
69
70 assertThat(eldestAdd, successfulWith(is(true)));
71
72 final CompletionStage<Optional<String>> eldestGet2 = cache.get("claira");
73
74 assertThat(eldestGet2, successfulWith(is(Optional.of("dancing"))));
75
76 final CompletionStage<Boolean> eldestAdd2 = cache.put("claira", "singing", PutPolicy.PUT_ALWAYS);
77
78 assertThat(eldestAdd2, successfulWith(is(true)));
79
80 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
81 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
82 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
83 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
84 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
85 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
86 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
87 assertThat(cacheMetrics, hasSize(is(5)));
88 }
89
90 @Test
91 public void simple_get_add() throws ExecutionException, InterruptedException {
92 final CompletionStage<Optional<String>> eldestGet = cache.get("claira");
93
94 assertThat(eldestGet, successfulWith(is(Optional.empty())));
95
96 final CompletionStage<Boolean> eldestAdd = cache.put("claira", "dancing", PutPolicy.ADD_ONLY);
97
98 assertThat(eldestAdd, successfulWith(is(true)));
99
100 final CompletionStage<Optional<String>> eldestGet2 = cache.get("claira");
101
102 assertThat(eldestGet2, successfulWith(is(Optional.of("dancing"))));
103
104 final CompletionStage<Boolean> eldestAdd2 = cache.put("claira", "singing", PutPolicy.ADD_ONLY);
105
106 assertThat(eldestAdd2, successfulWith(is(false)));
107
108 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
109 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
110 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
111 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
112 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
113 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
114 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
115 assertThat(cacheMetrics, hasSize(is(5)));
116 }
117
118 @Test
119 public void simple_get_with_supplier() throws ExecutionException, InterruptedException {
120 final CompletionStage<Optional<String>> eldestGet1 = cache.get("josephine");
121
122 assertThat(eldestGet1, successfulWith(is(Optional.empty())));
123
124 final CompletionStage<String> eldestGet2 = cache.get("josephine", () -> "football");
125
126 assertThat(eldestGet2, successfulWith(is("football")));
127
128 final CompletionStage<Optional<String>> eldestGet3 = cache.get("josephine");
129
130 assertThat(eldestGet3, successfulWith(is(Optional.of("football"))));
131
132 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
133 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
134 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(3L), greaterThan(0L)));
135 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
136 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_SUPPLIER_CALL, is(1L), greaterThan(0L)));
137 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
138 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(2L), is(2L)));
139 assertThat(cacheMetrics, hasSize(is(5)));
140 }
141
142 @Test
143 public void put_with_huge_key() throws ExecutionException, InterruptedException {
144 final String key = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
145 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
146 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
147 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
148 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
149 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
150 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
151 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
152 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
153 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
154 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
155 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
156 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
157 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
158 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
159 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
160 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
161 + "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
162
163 final CompletionStage<Boolean> hugeAdd = cache.put(key, "dancing", PutPolicy.ADD_ONLY);
164
165 assertThat(hugeAdd, successfulWith(is(true)));
166
167 final CompletionStage<Optional<String>> hugeGet = cache.get(key);
168
169 assertThat(hugeGet, successfulWith(is(Optional.of("dancing"))));
170
171 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
172 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
173 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(1L), greaterThan(0L)));
174 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
175 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
176 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
177 assertThat(cacheMetrics, hasSize(is(4)));
178 }
179
180 @Test
181 public void simple_getBulkIdentified() throws ExecutionException, InterruptedException {
182 final CompletionStage<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
183
184 assertThat(put1, successfulWith(is(true)));
185
186 final CompletionStage<Optional<IdentifiedValue<String>>> get1 = cache.getIdentified("josie");
187
188 assertThat(get1, successful());
189 final IdentifiedValue<String> iv1 = unsafeJoin(get1).get();
190 assertThat(iv1.identifier(), notNullValue());
191 assertThat(iv1.value(), is("football"));
192
193 final CompletionStage<Map<String, Optional<IdentifiedValue<String>>>> get2 =
194 cache.getBulkIdentified("claira", "josie", "jasmin");
195
196 assertThat(get2, successful());
197 final Map<String, Optional<IdentifiedValue<String>>> ivMap1 = unsafeJoin(get2);
198 assertThat(ivMap1.keySet(), containsInAnyOrder("jasmin", "claira", "josie"));
199 assertThat(ivMap1.get("claira"), is(Optional.empty()));
200 assertThat(ivMap1.get("jasmin"), is(Optional.empty()));
201 final IdentifiedValue<String> iv2 = ivMap1.get("josie").get();
202 assertThat(iv2.identifier(), notNullValue());
203 assertThat(iv2.identifier(), equalTo(iv1.identifier()));
204 assertThat(iv2.value(), is("football"));
205
206 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
207 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
208 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(2L), greaterThan(0L)));
209 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
210 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
211 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(2L), is(2L)));
212 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(2L)));
213 assertThat(cacheMetrics, hasSize(is(5)));
214 }
215
216 @Test
217 public void simple_getIdentified_removeIf() throws ExecutionException, InterruptedException {
218 final CompletionStage<Optional<IdentifiedValue<String>>> get1 = cache.getIdentified("josie");
219
220 assertThat(get1, successfulWith(is(Optional.empty())));
221
222 final CompletionStage<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
223
224 assertThat(put1, successfulWith(is(true)));
225
226 final CompletionStage<Optional<IdentifiedValue<String>>> get2 = cache.getIdentified("josie");
227
228 assertThat(get2, successful());
229 final IdentifiedValue<String> iv2 = unsafeJoin(get2).get();
230 assertThat(iv2.identifier(), notNullValue());
231 assertThat(iv2.value(), is("football"));
232
233 final CompletionStage<Boolean> rm1 = cache.removeIf("josie", iv2.identifier());
234
235 assertThat(rm1, successfulWith(is(true)));
236
237 final CompletionStage<Boolean> put2 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
238
239 assertThat(put2, successfulWith(is(true)));
240
241 final CompletionStage<Optional<IdentifiedValue<String>>> get3 = cache.getIdentified("josie");
242
243 assertThat(get3, successful());
244 final IdentifiedValue<String> iv3 = unsafeJoin(get3).get();
245 assertThat(iv3.identifier(), notNullValue());
246 assertThat(iv3.value(), is("football"));
247
248 final CompletionStage<Boolean> rm3 = cache.removeIf("josie", iv3.identifier());
249
250 assertThat(rm3, successfulWith(is(true)));
251
252 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
253 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
254 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(3L), greaterThan(0L)));
255 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REMOVE_CALL, is(2L), greaterThan(0L)));
256 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
257 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
258 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(2L), is(2L)));
259 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
260 assertThat(cacheMetrics, hasSize(is(6)));
261 }
262
263 @Test
264 public void simple_getIdentifiedSupplier_removeIf() throws ExecutionException, InterruptedException {
265 final CompletionStage<IdentifiedValue<String>> get1 = cache.getIdentified("josie", () -> "football");
266
267 assertThat(get1, successful());
268 final IdentifiedValue<String> iv1 = unsafeJoin(get1);
269 assertThat(iv1.identifier(), notNullValue());
270 assertThat(iv1.value(), is("football"));
271
272 final CompletionStage<Boolean> rm1 = cache.removeIf("josie", iv1.identifier());
273
274 assertThat(rm1, successfulWith(is(true)));
275
276 final CompletionStage<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
277
278 assertThat(put1, successfulWith(is(true)));
279
280 final CompletionStage<IdentifiedValue<String>> get2 = cache.getIdentified("josie", () -> "swimming");
281
282 assertThat(get2, successful());
283 final IdentifiedValue<String> iv2 = unsafeJoin(get2);
284 assertThat(iv2.identifier(), notNullValue());
285 assertThat(iv2.value(), is("football"));
286
287 final CompletionStage<Boolean> rm2 = cache.removeIf("josie", iv2.identifier());
288
289 assertThat(rm2, successfulWith(is(true)));
290
291 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
292 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
293 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(2L), greaterThan(0L)));
294 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REMOVE_CALL, is(2L), greaterThan(0L)));
295 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
296 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
297 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_SUPPLIER_CALL, is(1L), greaterThan(0L)));
298 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
299 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
300 assertThat(cacheMetrics, hasSize(is(7)));
301 }
302
303
304
305
306 @Test
307 public void exact_getIdentified_removeIf() throws ExecutionException, InterruptedException {
308 final CompletionStage<Boolean> putFirst = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
309
310 assertThat(putFirst, successfulWith(is(true)));
311
312 final CompletionStage<Optional<IdentifiedValue<String>>> getFirst = cache.getIdentified("josie");
313
314 assertThat(getFirst, successful());
315 final IdentifiedValue<String> ivFirst = unsafeJoin(getFirst).get();
316 assertThat(ivFirst.identifier(), notNullValue());
317 assertThat(ivFirst.value(), is("football"));
318
319 final CompletionStage<Boolean> putSecond = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
320
321 assertThat(putSecond, successfulWith(is(true)));
322
323 final CompletionStage<Boolean> rm1 = cache.removeIf("josie", ivFirst.identifier());
324
325 assertThat(rm1, successfulWith(is(false)));
326
327 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
328 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
329 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(1L), greaterThan(0L)));
330 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REMOVE_CALL, is(1L), greaterThan(0L)));
331 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
332 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
333 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
334 assertThat(cacheMetrics, hasSize(is(5)));
335 }
336
337 @Test
338 public void simple_getIdentified_replaceIf() throws ExecutionException, InterruptedException {
339 final CompletionStage<Boolean> put1 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
340
341 assertThat(put1, successfulWith(is(true)));
342
343 final CompletionStage<Optional<IdentifiedValue<String>>> get1 = cache.getIdentified("josie");
344
345 assertThat(get1, successful());
346 final IdentifiedValue<String> iv1 = unsafeJoin(get1).get();
347 assertThat(iv1.identifier(), notNullValue());
348 assertThat(iv1.value(), is("football"));
349
350 final CompletionStage<Boolean> rm1 = cache.replaceIf("josie", iv1.identifier(), "soccer");
351
352 assertThat(rm1, successfulWith(is(true)));
353
354 final CompletionStage<Boolean> put2 = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
355
356 assertThat(put2, successfulWith(is(true)));
357
358 final CompletionStage<Optional<IdentifiedValue<String>>> get3 = cache.getIdentified("josie");
359
360 assertThat(get3, successful());
361 final IdentifiedValue<String> iv3 = unsafeJoin(get3).get();
362 assertThat(iv3.identifier(), notNullValue());
363 assertThat(iv3.value(), is("football"));
364
365 final CompletionStage<Boolean> rm3 = cache.removeIf("josie", iv3.identifier());
366
367 assertThat(rm3, successfulWith(is(true)));
368
369 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
370 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
371 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(2L), greaterThan(0L)));
372 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REPLACE_CALL, is(1L), greaterThan(0L)));
373 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REMOVE_CALL, is(1L), greaterThan(0L)));
374 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
375 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
376 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(2L), is(2L)));
377 assertThat(cacheMetrics, hasSize(is(6)));
378 }
379
380
381
382
383 @Test
384 public void exact_getIdentified_replaceIf() throws ExecutionException, InterruptedException {
385 final CompletionStage<Boolean> putFirst = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
386
387 assertThat(putFirst, successfulWith(is(true)));
388
389 final CompletionStage<Optional<IdentifiedValue<String>>> getFirst = cache.getIdentified("josie");
390
391 assertThat(getFirst, successful());
392 final IdentifiedValue<String> ivFirst = unsafeJoin(getFirst).get();
393 assertThat(ivFirst.identifier(), notNullValue());
394 assertThat(ivFirst.value(), is("football"));
395
396 final CompletionStage<Boolean> putSecond = cache.put("josie", "football", PutPolicy.PUT_ALWAYS);
397
398 assertThat(putSecond, successfulWith(is(true)));
399
400 final CompletionStage<Boolean> rm1 = cache.replaceIf("josie", ivFirst.identifier(), "afl");
401
402 assertThat(rm1, successfulWith(is(false)));
403
404 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
405 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
406 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(1L), greaterThan(0L)));
407 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REPLACE_CALL, is(1L), greaterThan(0L)));
408 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
409 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
410 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
411 assertThat(cacheMetrics, hasSize(is(5)));
412 }
413
414 @Test
415 public void simple_put_remove() throws ExecutionException, InterruptedException {
416 final CompletionStage<Void> rm1 = cache.remove("claira");
417
418 assertThat(rm1, successful());
419 assertThat(unsafeJoin(rm1), nullValue());
420
421 final CompletionStage<Boolean> put1 = cache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
422
423 assertThat(put1, successfulWith(is(true)));
424
425 final CompletionStage<Void> rm2 = cache.remove("claira");
426
427 assertThat(rm2, successful());
428
429 final CompletionStage<Boolean> put2 = cache.put("claira", "dancing", PutPolicy.PUT_ALWAYS);
430
431 assertThat(put2, successfulWith(is(true)));
432
433 final CompletionStage<Optional<String>> get1 = cache.get("claira");
434
435 assertThat(get1, successfulWith(is(Optional.of("dancing"))));
436
437 final CompletionStage<Void> rm3 = cache.remove("josie", "claira", "jasmin");
438
439 assertThat(rm3, successful());
440
441 final CompletionStage<Optional<String>> get2 = cache.get("claira");
442
443 assertThat(get2, successfulWith(is(Optional.empty())));
444
445 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
446 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
447 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
448 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(2L), greaterThan(0L)));
449 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_CALL, is(3L), greaterThan(0L)));
450 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
451 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
452 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
453 assertThat(cacheMetrics, hasSize(is(6)));
454 }
455
456 @Test
457 public void simple_removeAll() throws ExecutionException, InterruptedException {
458 final CompletionStage<Boolean> put1 = cache.put("claira", "", PutPolicy.PUT_ALWAYS);
459
460 assertThat(put1, successfulWith(is(true)));
461
462 final CompletionStage<Optional<String>> get1 = cache.get("claira");
463
464 assertThat(get1, successfulWith(is(Optional.of(""))));
465
466 final CompletionStage<Void> rm1 = cache.removeAll();
467
468 assertThat(rm1, successful());
469
470 final CompletionStage<Optional<String>> get2 = cache.get("claira");
471
472 assertThat(get2, successfulWith(is(Optional.empty())));
473
474 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
475 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
476 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
477 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
478 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(2L), greaterThan(0L)));
479 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
480 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
481 assertThat(cacheMetrics, hasSize(is(5)));
482 }
483
484 @SuppressWarnings("unchecked")
485 @Test
486 public void simple_getBulk() throws ExecutionException, InterruptedException {
487 final CompletionStage<Map<String, Optional<String>>> get1 = cache.getBulk("claira", "jasmin", "josie", "josie");
488
489 assertThat(get1, successful());
490 assertThat(unsafeJoin(get1).keySet(), containsInAnyOrder("claira", "jasmin", "josie"));
491 assertThat(unsafeJoin(get1).values(), containsInAnyOrder(Optional.empty(), Optional.empty(), Optional.empty()));
492
493 final CompletionStage<Boolean> put1 = cache.put("claira", "youtube", PutPolicy.PUT_ALWAYS);
494
495 assertThat(put1, successfulWith(is(true)));
496
497 final CompletionStage<Map<String, Optional<String>>> get2 = cache.getBulk("jasmin", "claira", "josie", "claira");
498
499 assertThat(get2, successful());
500 assertThat(unsafeJoin(get2).keySet(), containsInAnyOrder("claira", "jasmin", "josie"));
501 assertThat(unsafeJoin(get2).values(), containsInAnyOrder(Optional.of("youtube"), Optional.empty(), Optional.empty()));
502
503 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
504 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
505 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
506 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
507 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
508 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(1L)));
509 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(2L), is(5L)));
510 assertThat(cacheMetrics, hasSize(is(5)));
511 }
512
513 @Test
514 public void simple_getBulkFactory() throws ExecutionException, InterruptedException {
515 final CompletionStage<Map<String, String>> get1 =
516 cache.getBulk(
517 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> k + "-1")),
518 "claira", "josie", "josie");
519
520 assertThat(get1, successful());
521 assertThat(unsafeJoin(get1).keySet(), containsInAnyOrder("claira", "josie"));
522 assertThat(unsafeJoin(get1).values(), containsInAnyOrder("claira-1", "josie-1"));
523
524 final CompletionStage<Map<String, String>> get2 =
525 cache.getBulk(
526 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> k + "-2")),
527 "claira", "josie", "jasmin");
528
529 assertThat(get2, successful());
530 assertThat(unsafeJoin(get2).keySet(), containsInAnyOrder("claira", "josie", "jasmin"));
531 assertThat(unsafeJoin(get2).values(), containsInAnyOrder("claira-1", "josie-1", "jasmin-2"));
532
533 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
534 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
535 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
536 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_FACTORY_CALL, is(2L), greaterThan(0L)));
537 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
538 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FACTORY_KEYS, is(2L), is(3L)));
539 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_HITS, is(1L), is(2L)));
540 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(2L), is(3L)));
541 assertThat(cacheMetrics, hasSize(is(6)));
542 }
543
544 @SuppressWarnings("ConstantConditions")
545 @Test
546 public void check_null_detection() {
547 assertThat(cache.get("kenny", () -> null), not(successful()));
548 assertThat(cache.getIdentified("norway", () -> null), not(successful()));
549 assertThat(cache.put("key", null, PutPolicy.ADD_ONLY), not(successful()));
550 assertThat(cache.getBulk(
551 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> null)),
552 "extra"),
553 not(successful()));
554
555 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
556 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
557 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_FACTORY_CALL, is(1L), greaterThan(0L)));
558 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_GET_CALL, is(2L), greaterThan(0L)));
559 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(1L), greaterThan(0L)));
560 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
561 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
562
563 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_SUPPLIER_CALL, isOneOf(1L, 2L), greaterThan(0L)));
564 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FACTORY_KEYS, is(1L), is(1L)));
565 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FAILED_GET, is(2L), is(2L)));
566 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FAILED_IDENTIFIED_GET, is(1L), is(1L)));
567 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FAILED_PUT, is(1L), is(1L)));
568 assertThat(cacheMetrics, hasSize(is(10)));
569 }
570
571 @SuppressWarnings("ConstantConditions")
572 @Test
573 public void check_null_detection_with_cas() {
574 final CompletionStage<IdentifiedValue<String>> geti = cache.getIdentified("temp", () -> "value");
575 assertThat(geti, successful());
576 assertThat(cache.replaceIf("temp", unsafeJoin(geti).identifier(), null), not(successful()));
577
578 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
579 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
580 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_GET_CALL, is(1L), greaterThan(0L)));
581 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_IDENTIFIED_REPLACE_CALL, is(1L), greaterThan(0L)));
582 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_SUPPLIER_CALL, is(1L), greaterThan(0L)));
583 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
584 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FAILED_IDENTIFIED_REPLACE, is(1L), is(1L)));
585 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_MISSES, is(1L), is(1L)));
586 assertThat(cacheMetrics, hasSize(is(6)));
587 }
588
589 @SuppressWarnings("ConstantConditions")
590 @Test
591 public void check_null_key() {
592 final CompletionStage<Boolean> put1 = cache.put(null, "value", PutPolicy.PUT_ALWAYS);
593 assertThat(put1, not(successful()));
594
595 final EnumMap<MetricLabel, ? extends LongMetric> cacheMetrics =
596 requestMetrics().allExternalCacheLongMetrics().get(CACHE_NAME);
597 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_PUT_CALL, is(1L), greaterThan(0L)));
598 assertThat(cacheMetrics, hasMetric(MetricLabel.TIMED_REMOVE_ALL_CALL, is(1L), greaterThan(0L)));
599 assertThat(cacheMetrics, hasMetric(MetricLabel.NUMBER_OF_FAILED_PUT, is(1L), is(1L)));
600 assertThat(cacheMetrics, hasSize(is(3)));
601 }
602
603 @Test
604 public void potential_deadlock() {
605 final CompletionStage<String> get = cache.get("lockType", () -> {
606
607 final CompletionStage<Void> rm = cache.remove("lockType");
608 assertThat(rm, successful());
609
610 return "lockwood";
611 });
612 assertThat(get, successfulWith(is("lockwood")));
613 }
614 }