View Javadoc

1   package com.atlassian.vcache.internal.test.utils;
2   
3   import com.atlassian.marshalling.api.MarshallingPair;
4   import com.atlassian.marshalling.jdk.JavaSerializationMarshalling;
5   import com.atlassian.vcache.ChangeRate;
6   import com.atlassian.vcache.DirectExternalCache;
7   import com.atlassian.vcache.ExternalCacheSettings;
8   import com.atlassian.vcache.ExternalCacheSettingsBuilder;
9   import com.atlassian.vcache.JvmCache;
10  import com.atlassian.vcache.JvmCacheSettings;
11  import com.atlassian.vcache.JvmCacheSettingsBuilder;
12  import com.atlassian.vcache.TransactionalExternalCache;
13  import com.atlassian.vcache.VCacheFactory;
14  import com.atlassian.vcache.internal.RequestContext;
15  import com.atlassian.vcache.internal.core.DefaultVCacheCreationHandler;
16  import com.atlassian.vcache.internal.core.PlainExternalCacheKeyGenerator;
17  import com.atlassian.vcache.internal.core.WorkContextRequestContextSupplier;
18  import com.atlassian.vcache.internal.core.metrics.NoopMetricsCollector;
19  import com.atlassian.vcache.internal.guava.GuavaTestServiceSettings;
20  import com.atlassian.vcache.internal.guava.GuavaVCacheService;
21  import com.atlassian.vcache.internal.test.EmptyVCacheSettingsDefaultsProvider;
22  import com.atlassian.vcache.internal.test.ThreadLocalRequestContextSupplier;
23  
24  import java.io.Serializable;
25  import java.time.Duration;
26  import java.util.function.Supplier;
27  
28  import static org.mockito.Matchers.any;
29  import static org.mockito.Matchers.eq;
30  import static org.mockito.Mockito.doReturn;
31  import static org.mockito.Mockito.spy;
32  
33  /**
34   * Test helper provides functionality to help create appropriate vcache mocks for unit tests. Each test class will need to open
35   * the WorkContext doorway using:
36   * <p>
37   * {@code @Rule public EstablishWorkContext context = new EstablishWorkContext();}
38   * <p>
39   * Example:
40   * vcacheFactory = VCachesTestHelper.getProxiedFactory();
41   * cache = VCachesTestHelper.getExternalCache(factory, "TestDECache", String.class);; //it also builds expectations for cache creation calls
42   * ...
43   * doReturn(result(cachedString)).when(cache).get(eq(key), any(Supplier.class));
44   * ...
45   * cache.put("key", value, PutPolicy.PUT_ALWAYS);
46   *
47   * @since 1.5.0
48   */
49  @SuppressWarnings("checkstyle:MagicNumber")
50  public class VCacheTestHelper {
51  
52      private static final ThreadLocalRequestContextSupplier THREAD_LOCAL_REQUEST_CONTEXT_SUPPLIER = ThreadLocalRequestContextSupplier.strictSupplier();
53      private static final WorkContextRequestContextSupplier workContextContextSupplier = new WorkContextRequestContextSupplier(() -> "myPartition");
54  
55      /**
56       * Build {@link com.atlassian.vcache.VCacheFactory} and set-up all necessary context. Please don't forget to call
57       * {@link #cleanContext()} after tests to clean up vcache context.
58       *
59       * @return {@link com.atlassian.vcache.VCacheFactory} suitable for testing.
60       */
61      public static VCacheFactory getFactory() {
62          try {
63              THREAD_LOCAL_REQUEST_CONTEXT_SUPPLIER.initThread("myPartition");
64          } catch (IllegalStateException ignored) {
65          }
66  
67          final DefaultVCacheCreationHandler handler = new DefaultVCacheCreationHandler(
68                  Integer.MAX_VALUE, Duration.ofDays(1), Integer.MAX_VALUE, ChangeRate.LOW_CHANGE, ChangeRate.LOW_CHANGE);
69  
70          return new GuavaVCacheService(THREAD_LOCAL_REQUEST_CONTEXT_SUPPLIER,
71                  workContextContextSupplier,
72                  new EmptyVCacheSettingsDefaultsProvider(),
73                  handler,
74                  new NoopMetricsCollector(),
75                  new PlainExternalCacheKeyGenerator("VCacheTest"),
76                  new GuavaTestServiceSettings(true, Duration.ofSeconds(30)),
77                  context -> { });
78      }
79  
80      /**
81       * Build {@link com.atlassian.vcache.VCacheFactory} and set-up all necessary context. Please don't forget to call
82       * {@link #cleanContext()} after tests to clean up vcache context.
83       *
84       * @param contextSupplier the context supplier to be used when creating caches.
85       * @return {@link com.atlassian.vcache.VCacheFactory} suitable for testing.
86       */
87      public static VCacheFactory getFactory(Supplier<RequestContext> contextSupplier) {
88  
89          final DefaultVCacheCreationHandler handler = new DefaultVCacheCreationHandler(
90                  Integer.MAX_VALUE, Duration.ofDays(1), Integer.MAX_VALUE, ChangeRate.LOW_CHANGE, ChangeRate.LOW_CHANGE);
91  
92          return new GuavaVCacheService(contextSupplier, contextSupplier,
93                  new EmptyVCacheSettingsDefaultsProvider(),
94                  handler,
95                  new NoopMetricsCollector(),
96                  new PlainExternalCacheKeyGenerator("VCacheTest"),
97                  new GuavaTestServiceSettings(true, Duration.ofSeconds(30)),
98                  context -> { });
99      }
100 
101 
102     /**
103      * Build {@link com.atlassian.vcache.VCacheFactory} and set-up all necessary context. Please don't forget to call
104      * {@link #cleanContext()} after tests to clean up vcache context.
105      *
106      * @return {@link com.atlassian.vcache.VCacheFactory} suitable for testing. Returned value is  mockito proxied object, so can be used
107      * to build test expectations.
108      */
109     public static VCacheFactory getProxiedFactory() {
110         return spy(getFactory());
111     }
112 
113     /**
114      * Build {@link DirectExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
115      *
116      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
117      * @param name name of the cache
118      * @param clazz class of cached objects
119      * @param <T> type of cached objects
120      * @return {@link DirectExternalCache} proxied by mockito.
121      */
122     public static <T extends Serializable> DirectExternalCache<T> getExternalCache(VCacheFactory mockVcacheFactory,
123                                                                                    String name, Class<T> clazz) {
124         return getExternalCache(mockVcacheFactory, name, clazz, new ExternalCacheSettingsBuilder().build());
125     }
126 
127     /**
128      * Build {@link DirectExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
129      *
130      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
131      * @param name name of the cache
132      * @param clazz class of cached objects
133      * @param settings cache settings
134      * @param <T> type of cached objects
135      * @return {@link DirectExternalCache} proxied by mockito.
136      */
137     public static <T extends Serializable> DirectExternalCache<T> getExternalCache(VCacheFactory mockVcacheFactory,
138                                                                                    String name, Class<T> clazz,
139                                                                                    ExternalCacheSettings settings) {
140         final DirectExternalCache<T> desiredCache = spy(mockVcacheFactory.getDirectExternalCache(name,
141                 JavaSerializationMarshalling.pair(clazz), settings));
142 
143         doReturn(desiredCache).when(mockVcacheFactory).getDirectExternalCache(eq(name), any(MarshallingPair.class),
144                 any(ExternalCacheSettings.class));
145 
146         return desiredCache;
147     }
148 
149     /**
150      * Build {@link JvmCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
151      *
152      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
153      * @param cacheName name of the cache
154      * @param <K> type of cache keys
155      * @param <V> type of cached objects
156      * @return {@link JvmCache} proxied by mockito.
157      */
158     public static <K, V> JvmCache<K, V> getJvmCache(VCacheFactory mockVcacheFactory, String cacheName) {
159         return  getJvmCache(mockVcacheFactory, cacheName, new JvmCacheSettingsBuilder().build());
160     }
161 
162     /**
163      * Build {@link JvmCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
164      *
165      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
166      * @param cacheName name of the cache
167      * @param settings cache settings
168      * @param <K> type of cache keys
169      * @param <V> type of cached objects
170      * @return {@link JvmCache} proxied by mockito.
171      */
172     public static <K, V> JvmCache<K, V> getJvmCache(VCacheFactory mockVcacheFactory, String cacheName,
173                                                     JvmCacheSettings settings) {
174         final JvmCache<K, V> desiredCache = spy(mockVcacheFactory.getJvmCache(cacheName, settings));
175         doReturn(desiredCache).when(mockVcacheFactory).getJvmCache(eq(cacheName), any(JvmCacheSettings.class));
176         return desiredCache;
177     }
178 
179     /**
180      * Build {@link TransactionalExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
181      *
182      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
183      * @param name name of the cache
184      * @param clazz class of cached objects
185      * @param <T> type of cached objects
186      * @return {@link TransactionalExternalCache} proxied by mockito.
187      */
188     public static <T extends Serializable> TransactionalExternalCache<T> getTransactionalCache(VCacheFactory mockVcacheFactory,
189                                                                                                String name, Class<T> clazz) {
190         return getTransactionalCache(mockVcacheFactory, name, clazz, new ExternalCacheSettingsBuilder().build());
191     }
192 
193     /**
194      * Build {@link TransactionalExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
195      *
196      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
197      * @param name name of the cache
198      * @param clazz class of cached objects
199      * @param settings cache settings
200      * @param <T> type of cached objects
201      * @return {@link TransactionalExternalCache} proxied by mockito.
202      */
203     public static <T extends Serializable> TransactionalExternalCache<T> getTransactionalCache(VCacheFactory mockVcacheFactory,
204                                                                                                String name, Class<T> clazz,
205                                                                                                ExternalCacheSettings settings) {
206         final TransactionalExternalCache<T> desiredCache = spy(mockVcacheFactory.getTransactionalExternalCache(name,
207                 JavaSerializationMarshalling.pair(clazz), settings));
208 
209         doReturn(desiredCache).when(mockVcacheFactory).getTransactionalExternalCache(eq(name), any(MarshallingPair.class),
210                 any(ExternalCacheSettings.class));
211 
212         return desiredCache;
213     }
214 
215     /**
216      * Clean up vcache context.
217      */
218     public static void cleanContext() {
219         THREAD_LOCAL_REQUEST_CONTEXT_SUPPLIER.clearThread();
220     }
221 }