View Javadoc

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   * Base test class for the {@link StableReadExternalCache}.
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          // Start from a clean slate
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          // Change will not be visible to main cache
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          // Add will fail as value exists from the other cache. However, we will now be able to see the
98          // value added by the other cache.
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         // Change will not be visible to main cache
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 }