View Javadoc

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   * Base test class for the {@link com.atlassian.vcache.TransactionalExternalCache}.
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          // Now use the directCache to verify no data has been written
53          directCacheRefresh();
54          final CompletionStage<Optional<String>> get2 = directCache().get("claira");
55  
56          assertThat(get2, successfulWith(is(Optional.empty())));
57  
58          // Now sync the changes
59          cacheTransactionSync();
60  
61          // And check the changes are now visible
62          directCacheRefresh();
63          final CompletionStage<Optional<String>> get3 = directCache().get("claira");
64  
65          assertThat(get3, successfulWith(is(Optional.of("dancing"))));
66  
67          // Now check another lookup will succeed with the transactional cache
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); // Must be ADD_ONLY
76  
77          final CompletionStage<Optional<String>> get1 = cache().get("claira");
78  
79          assertThat(get1, successfulWith(is(Optional.of("dancing"))));
80  
81          // Now use the directCache to verify no data has been written
82          directCacheRefresh();
83          final CompletionStage<Optional<String>> get2 = directCache().get("claira");
84  
85          assertThat(get2, successfulWith(is(Optional.empty())));
86  
87          // Now add values to the backing cache using the directCache
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          // Now sync the changes
96          cacheTransactionSync();
97  
98          // And check the cache is empty
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         // Now add an entry to the backend cache for "josephine" and verify one does not exist yet
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         // Now verify nothing in the cache, due to panic when added josephine
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 put_get_discard() {
173         cache().put("josie", "surfing", PutPolicy.PUT_ALWAYS);
174 
175         final CompletionStage<Optional<String>> get1 = cache().get("josie");
176 
177         assertThat(get1, successfulWith(is(Optional.of("surfing"))));
178 
179         // Now use the directCache to verify no data has been written
180         directCacheRefresh();
181         final CompletionStage<Optional<String>> get2 = directCache().get("josie");
182 
183         assertThat(get2, successfulWith(is(Optional.empty())));
184 
185         // Now discard the changes
186         cacheTransactionDiscard();
187 
188         // And check the changes are not visible
189         directCacheRefresh();
190         final CompletionStage<Optional<String>> get3 = directCache().get("josie");
191 
192         assertThat(get3, successfulWith(is(Optional.empty())));
193     }
194 
195     @Test
196     public void check_get_null_detection() {
197         assertThat(cache().get("kenny", () -> null), not(successful()));
198         assertThat(cache().getBulk(
199                 strings -> strings.stream().collect(Collectors.toMap(k -> k, k -> null)),
200                 "extra"),
201                 not(successful()));
202     }
203 
204     @SuppressWarnings("ConstantConditions")
205     @Test(expected = NullPointerException.class)
206     public void check_put_null_detection() {
207         cache().put("key", null, PutPolicy.ADD_ONLY);
208     }
209 }
210