1 package com.atlassian.vcache.internal.test;
2
3 import com.atlassian.vcache.DirectExternalCache;
4 import com.atlassian.vcache.PutPolicy;
5 import com.atlassian.vcache.TransactionalExternalCache;
6 import com.google.common.collect.Maps;
7 import org.junit.Rule;
8 import org.junit.Test;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 import java.util.Map;
13 import java.util.Optional;
14 import java.util.concurrent.CompletionStage;
15 import java.util.stream.Collectors;
16
17 import static com.atlassian.vcache.VCacheUtils.unsafeJoin;
18 import static com.atlassian.vcache.internal.test.CompletionStageSuccessful.successful;
19 import static com.atlassian.vcache.internal.test.CompletionStageSuccessful.successfulWith;
20 import static org.hamcrest.Matchers.containsInAnyOrder;
21 import static org.hamcrest.Matchers.is;
22 import static org.hamcrest.Matchers.not;
23 import static org.junit.Assert.assertThat;
24
25
26
27
28 public abstract class AbstractTransactionalExternalCacheIT {
29 protected static final String CACHE_NAME = "fragileSting";
30 private static final Logger log = LoggerFactory.getLogger(AbstractStableReadExternalCacheIT.class);
31
32 @Rule
33 public LoggingTestWatcher watcher = new LoggingTestWatcher(log);
34
35 protected abstract TransactionalExternalCache<String> cache();
36
37 protected abstract DirectExternalCache<String> directCache();
38
39 protected abstract void directCacheRefresh();
40
41 protected abstract void cacheTransactionSync();
42 protected abstract void cacheTransactionDiscard();
43
44 @Test
45 public void put_get_sync_successful2() {
46 cache().put("claira", "dancing", PutPolicy.PUT_ALWAYS);
47
48 final CompletionStage<Optional<String>> get1 = cache().get("claira");
49
50 assertThat(get1, successfulWith(is(Optional.of("dancing"))));
51
52
53 directCacheRefresh();
54 final CompletionStage<Optional<String>> get2 = directCache().get("claira");
55
56 assertThat(get2, successfulWith(is(Optional.empty())));
57
58
59 cacheTransactionSync();
60
61
62 directCacheRefresh();
63 final CompletionStage<Optional<String>> get3 = directCache().get("claira");
64
65 assertThat(get3, successfulWith(is(Optional.of("dancing"))));
66
67
68 final CompletionStage<Optional<String>> get4 = cache().get("claira");
69
70 assertThat(get4, successfulWith(is(Optional.of("dancing"))));
71 }
72
73 @Test
74 public void put_get_sync_unsuccessful2() throws Exception {
75 cache().put("claira", "dancing", PutPolicy.ADD_ONLY);
76
77 final CompletionStage<Optional<String>> get1 = cache().get("claira");
78
79 assertThat(get1, successfulWith(is(Optional.of("dancing"))));
80
81
82 directCacheRefresh();
83 final CompletionStage<Optional<String>> get2 = directCache().get("claira");
84
85 assertThat(get2, successfulWith(is(Optional.empty())));
86
87
88 final CompletionStage<Map<String, String>> get3 =
89 directCache().getBulk(keys -> Maps.asMap(keys, k -> k + "-1"), "claira", "josephine");
90
91 assertThat(get3, successful());
92 assertThat(unsafeJoin(get3).keySet(), containsInAnyOrder("claira", "josephine"));
93 assertThat(unsafeJoin(get3).values(), containsInAnyOrder("claira-1", "josephine-1"));
94
95
96 cacheTransactionSync();
97
98
99 directCacheRefresh();
100 final CompletionStage<Map<String, Optional<String>>> get4 = directCache().getBulk("claira", "josephine");
101
102 assertThat(get4, successful());
103 assertThat(unsafeJoin(get4).keySet(), containsInAnyOrder("claira", "josephine"));
104 assertThat(unsafeJoin(get4).values(), containsInAnyOrder(Optional.empty(), Optional.empty()));
105 }
106
107 @Test
108 public void getBulk_getBulkFunction_directPut_sync() throws Exception {
109 final CompletionStage<Boolean> put1 = directCache().put("claira", "dancing", PutPolicy.PUT_ALWAYS);
110
111 assertThat(put1, successful());
112
113 final CompletionStage<Map<String, Optional<String>>> get1 = cache().getBulk("claira", "josephine");
114
115 assertThat(get1, successful());
116 assertThat(unsafeJoin(get1).keySet(), containsInAnyOrder("claira", "josephine"));
117 assertThat(unsafeJoin(get1).values(), containsInAnyOrder(Optional.of("dancing"), Optional.empty()));
118
119 final CompletionStage<Map<String, String>> get2 =
120 cache().getBulk(keys -> Maps.asMap(keys, k -> "football"), "claira", "josephine");
121
122 assertThat(get2, successful());
123 assertThat(unsafeJoin(get2).keySet(), containsInAnyOrder("claira", "josephine"));
124 assertThat(unsafeJoin(get2).values(), containsInAnyOrder("dancing", "football"));
125
126
127 directCacheRefresh();
128 final CompletionStage<Boolean> put2 = directCache().put("josephine", "soccer", PutPolicy.ADD_ONLY);
129
130 assertThat(put2, successfulWith(is(true)));
131
132 cacheTransactionSync();
133
134
135 directCacheRefresh();
136 final CompletionStage<Map<String, Optional<String>>> get3 = directCache().getBulk("claira", "josephine");
137
138 assertThat(get3, successful());
139 assertThat(unsafeJoin(get3).keySet(), containsInAnyOrder("claira", "josephine"));
140 assertThat(unsafeJoin(get3).values(), containsInAnyOrder(Optional.empty(), Optional.empty()));
141 }
142
143 @Test
144 public void put_get_remove_get() {
145 cache().put("nirvana", "shotgun", PutPolicy.PUT_ALWAYS);
146
147 final CompletionStage<Optional<String>> get1 = cache().get("nirvana");
148
149 assertThat(get1, successfulWith(is(Optional.of("shotgun"))));
150
151 cache().remove("a", "b", "nirvana");
152
153 final CompletionStage<Optional<String>> get2 = cache().get("nirvana");
154
155 assertThat(get2, successfulWith(is(Optional.empty())));
156 }
157
158 @Test
159 public void getSupplier_removeAll_get() {
160 final CompletionStage<String> get1 = cache().get("vienna", () -> "sandwiches");
161
162 assertThat(get1, successfulWith(is("sandwiches")));
163
164 cache().removeAll();
165
166 final CompletionStage<Optional<String>> get2 = cache().get("vienna");
167
168 assertThat(get2, successfulWith(is(Optional.empty())));
169 }
170
171 @Test
172 public void getSupplier_removeAll_getSupplier_getSupplier() {
173 final CompletionStage<String> get1 = cache().get("vienna", () -> "sandwiches");
174
175 assertThat(get1, successfulWith(is("sandwiches")));
176
177 cache().removeAll();
178
179 final CompletionStage<Optional<String>> get2 = cache().get("vienna");
180
181 assertThat(get2, successfulWith(is(Optional.empty())));
182
183 final CompletionStage<String> get3 = cache().get("vienna", () -> "new value");
184
185 assertThat(get3, successfulWith(is("new value")));
186
187 final CompletionStage<String> get4 = cache().get("vienna", () -> "not used");
188
189 assertThat(get4, successfulWith(is("new value")));
190 }
191
192 @Test
193 public void getSupplier_removeAll_getBulk_getBulk() {
194 final CompletionStage<String> get1 = cache().get("vienna", () -> "sandwiches");
195
196 assertThat(get1, successfulWith(is("sandwiches")));
197
198 cache().removeAll();
199
200 final CompletionStage<Optional<String>> get2 = cache().get("vienna");
201
202 assertThat(get2, successfulWith(is(Optional.empty())));
203
204 final CompletionStage<Map<String, String>> get3 = cache().getBulk(keys -> Maps.asMap(keys, k -> k + "-1"), "vienna");
205
206 assertThat(get3, successful());
207 assertThat(unsafeJoin(get3).keySet(), containsInAnyOrder("vienna"));
208 assertThat(unsafeJoin(get3).values(), containsInAnyOrder("vienna-1"));
209
210 final CompletionStage<Map<String, String>> get4 = cache().getBulk(keys -> Maps.asMap(keys, k -> k + "-2"), "vienna");
211
212 assertThat(get4, successful());
213 assertThat(unsafeJoin(get4).keySet(), containsInAnyOrder("vienna"));
214 assertThat(unsafeJoin(get4).values(), containsInAnyOrder("vienna-1"));
215 }
216
217 @Test
218 public void put_get_discard() {
219 cache().put("josie", "surfing", PutPolicy.PUT_ALWAYS);
220
221 final CompletionStage<Optional<String>> get1 = cache().get("josie");
222
223 assertThat(get1, successfulWith(is(Optional.of("surfing"))));
224
225
226 directCacheRefresh();
227 final CompletionStage<Optional<String>> get2 = directCache().get("josie");
228
229 assertThat(get2, successfulWith(is(Optional.empty())));
230
231
232 cacheTransactionDiscard();
233
234
235 directCacheRefresh();
236 final CompletionStage<Optional<String>> get3 = directCache().get("josie");
237
238 assertThat(get3, successfulWith(is(Optional.empty())));
239 }
240
241 @Test
242 public void existing_remove_get() {
243 directCache().put("key", "existing", PutPolicy.PUT_ALWAYS);
244
245 final CompletionStage<Optional<String>> get1 = cache().get("key");
246
247 assertThat(get1, successfulWith(is(Optional.of("existing"))));
248
249 cache().remove("key");
250
251 final CompletionStage<Optional<String>> get2 = cache().get("key");
252
253 assertThat(get2, successfulWith(is(Optional.empty())));
254 }
255
256 @Test
257 public void existing_remove_getSupplier() {
258 directCache().put("key", "existing", PutPolicy.PUT_ALWAYS);
259
260 final CompletionStage<Optional<String>> get1 = cache().get("key");
261
262 assertThat(get1, successfulWith(is(Optional.of("existing"))));
263
264 cache().remove("key");
265
266 final CompletionStage<String> get2 = cache().get("key", () -> "new");
267
268 assertThat(get2, successfulWith(is("new")));
269 }
270
271 @Test
272 public void existing_remove_getBulk() {
273 directCache().put("key", "existing", PutPolicy.PUT_ALWAYS);
274
275 final CompletionStage<Optional<String>> get1 = cache().get("key");
276
277 assertThat(get1, successfulWith(is(Optional.of("existing"))));
278
279 cache().remove("key");
280
281 final CompletionStage<Map<String, String>> get2 = cache().getBulk(
282 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> k + "-new")),
283 "key", "extra");
284
285 assertThat(get2, successful());
286 assertThat(unsafeJoin(get2).keySet(), containsInAnyOrder("key", "extra"));
287 assertThat(unsafeJoin(get2).values(), containsInAnyOrder("key-new", "extra-new"));
288 }
289
290 @Test
291 public void existing_removeAll_get() {
292 directCache().put("key", "existing", PutPolicy.PUT_ALWAYS);
293
294 final CompletionStage<Optional<String>> get1 = cache().get("key");
295
296 assertThat(get1, successfulWith(is(Optional.of("existing"))));
297
298 cache().removeAll();
299
300 final CompletionStage<Optional<String>> get2 = cache().get("key");
301
302 assertThat(get2, successfulWith(is(Optional.empty())));
303 }
304
305 @Test
306 public void existing_removeAll_getSupplier() {
307 directCache().put("key", "existing", PutPolicy.PUT_ALWAYS);
308
309 final CompletionStage<Optional<String>> get1 = cache().get("key");
310
311 assertThat(get1, successfulWith(is(Optional.of("existing"))));
312
313 cache().removeAll();
314
315 final CompletionStage<String> get2 = cache().get("key", () -> "new");
316
317 assertThat(get2, successfulWith(is("new")));
318 }
319
320 @Test
321 public void existing_removeAll_getBulk() {
322 directCache().put("key", "existing", PutPolicy.PUT_ALWAYS);
323
324 final CompletionStage<Optional<String>> get1 = cache().get("key");
325
326 assertThat(get1, successfulWith(is(Optional.of("existing"))));
327
328 cache().removeAll();
329
330 final CompletionStage<Map<String, String>> get2 = cache().getBulk(
331 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> k + "-new")),
332 "key");
333
334 assertThat(get2, successful());
335 assertThat(unsafeJoin(get2).keySet(), containsInAnyOrder("key"));
336 assertThat(unsafeJoin(get2).values(), containsInAnyOrder("key-new"));
337 }
338
339 @Test
340 public void check_get_null_detection() {
341 assertThat(cache().get("kenny", () -> null), not(successful()));
342 assertThat(cache().getBulk(
343 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> null)),
344 "extra"),
345 not(successful()));
346 }
347
348 @SuppressWarnings("ConstantConditions")
349 @Test(expected = NullPointerException.class)
350 public void check_put_null_detection() {
351 cache().put("key", null, PutPolicy.ADD_ONLY);
352 }
353 }
354