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.ThreadLocalRequestContextSupplier;
18  import com.atlassian.vcache.internal.core.WorkContextRequestContextSupplier;
19  import com.atlassian.vcache.internal.core.metrics.NoopMetricsCollector;
20  import com.atlassian.vcache.internal.guava.GuavaTestServiceSettings;
21  import com.atlassian.vcache.internal.guava.GuavaVCacheService;
22  import com.atlassian.vcache.internal.test.EmptyVCacheSettingsDefaultsProvider;
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  public class VCacheTestHelper {
50  
51      static ThreadLocalRequestContextSupplier threadLocalContextSupplier = ThreadLocalRequestContextSupplier.strictSupplier();
52      static WorkContextRequestContextSupplier workContextContextSupplier = new WorkContextRequestContextSupplier(() -> "myPartition");
53  
54      /**
55       * Build {@link com.atlassian.vcache.VCacheFactory} and set-up all necessary context. Please don't forget to call
56       * {@link #cleanContext()} after tests to clean up vcache context.
57       *
58       * @return {@link com.atlassian.vcache.VCacheFactory} suitable for testing.
59       */
60      public static VCacheFactory getFactory() {
61          try {
62              threadLocalContextSupplier.initThread("myPartition");
63          } catch (IllegalStateException ignored) {
64          }
65  
66          final DefaultVCacheCreationHandler handler = new DefaultVCacheCreationHandler(
67                  Integer.MAX_VALUE, Duration.ofDays(1), Integer.MAX_VALUE, ChangeRate.LOW_CHANGE, ChangeRate.LOW_CHANGE);
68  
69          return new GuavaVCacheService(threadLocalContextSupplier,
70                  workContextContextSupplier,
71                  new EmptyVCacheSettingsDefaultsProvider(),
72                  handler,
73                  new NoopMetricsCollector(),
74                  new PlainExternalCacheKeyGenerator("VCacheTest"),
75                  new GuavaTestServiceSettings(true),
76                  context -> { });
77      }
78  
79      /**
80       * Build {@link com.atlassian.vcache.VCacheFactory} and set-up all necessary context. Please don't forget to call
81       * {@link #cleanContext()} after tests to clean up vcache context.
82       *
83       * @param contextSupplier the context supplier to be used when creating caches.
84       * @return {@link com.atlassian.vcache.VCacheFactory} suitable for testing.
85       */
86      public static VCacheFactory getFactory(Supplier<RequestContext> contextSupplier) {
87  
88          final DefaultVCacheCreationHandler handler = new DefaultVCacheCreationHandler(
89                  Integer.MAX_VALUE, Duration.ofDays(1), Integer.MAX_VALUE, ChangeRate.LOW_CHANGE, ChangeRate.LOW_CHANGE);
90  
91          return new GuavaVCacheService(contextSupplier, contextSupplier,
92                  new EmptyVCacheSettingsDefaultsProvider(),
93                  handler,
94                  new NoopMetricsCollector(),
95                  new PlainExternalCacheKeyGenerator("VCacheTest"),
96                  new GuavaTestServiceSettings(true),
97                  context -> { });
98      }
99  
100 
101     /**
102      * Build {@link com.atlassian.vcache.VCacheFactory} and set-up all necessary context. Please don't forget to call
103      * {@link #cleanContext()} after tests to clean up vcache context.
104      *
105      * @return {@link com.atlassian.vcache.VCacheFactory} suitable for testing. Returned value is  mockito proxied object, so can be used
106      * to build test expectations.
107      */
108     public static VCacheFactory getProxiedFactory() {
109         return spy(getFactory());
110     }
111 
112     /**
113      * Build {@link DirectExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
114      *
115      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
116      * @param name name of the cache
117      * @param clazz class of cached objects
118      * @param <T> type of cached objects
119      * @return {@link DirectExternalCache} proxied by mockito.
120      */
121     public static <T extends Serializable> DirectExternalCache<T> getExternalCache(VCacheFactory mockVcacheFactory,
122                                                                                    String name, Class<T> clazz) {
123         return getExternalCache(mockVcacheFactory, name, clazz, new ExternalCacheSettingsBuilder().build());
124     }
125 
126     /**
127      * Build {@link DirectExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
128      *
129      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
130      * @param name name of the cache
131      * @param clazz class of cached objects
132      * @param settings cache settings
133      * @param <T> type of cached objects
134      * @return {@link DirectExternalCache} proxied by mockito.
135      */
136     public static <T extends Serializable> DirectExternalCache<T> getExternalCache(VCacheFactory mockVcacheFactory,
137                                                                                    String name, Class<T> clazz,
138                                                                                    ExternalCacheSettings settings) {
139         final DirectExternalCache<T> desiredCache = spy(mockVcacheFactory.getDirectExternalCache(name,
140                 JavaSerializationMarshalling.pair(clazz), settings));
141 
142         doReturn(desiredCache).when(mockVcacheFactory).getDirectExternalCache(eq(name), any(MarshallingPair.class),
143                 any(ExternalCacheSettings.class));
144 
145         return desiredCache;
146     }
147 
148     /**
149      * Build {@link JvmCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
150      *
151      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
152      * @param cacheName name of the cache
153      * @param <K> type of cache keys
154      * @param <V> type of cached objects
155      * @return {@link JvmCache} proxied by mockito.
156      */
157     public static <K, V> JvmCache<K, V> getJvmCache(VCacheFactory mockVcacheFactory, String cacheName) {
158         return  getJvmCache(mockVcacheFactory, cacheName, new JvmCacheSettingsBuilder().build());
159     }
160 
161     /**
162      * Build {@link JvmCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
163      *
164      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
165      * @param cacheName name of the cache
166      * @param settings cache settings
167      * @param <K> type of cache keys
168      * @param <V> type of cached objects
169      * @return {@link JvmCache} proxied by mockito.
170      */
171     public static <K, V> JvmCache<K, V> getJvmCache(VCacheFactory mockVcacheFactory, String cacheName,
172                                                     JvmCacheSettings settings) {
173         final JvmCache<K, V> desiredCache = spy(mockVcacheFactory.getJvmCache(cacheName, settings));
174         doReturn(desiredCache).when(mockVcacheFactory).getJvmCache(eq(cacheName), any(JvmCacheSettings.class));
175         return desiredCache;
176     }
177 
178     /**
179      * Build {@link TransactionalExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
180      *
181      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
182      * @param name name of the cache
183      * @param clazz class of cached objects
184      * @param <T> type of cached objects
185      * @return {@link TransactionalExternalCache} proxied by mockito.
186      */
187     public static <T extends Serializable> TransactionalExternalCache<T> getTransactionalCache(VCacheFactory mockVcacheFactory,
188                                                                                                String name, Class<T> clazz) {
189         return getTransactionalCache(mockVcacheFactory, name, clazz, new ExternalCacheSettingsBuilder().build());
190     }
191 
192     /**
193      * Build {@link TransactionalExternalCache} and set up mockito expectations for appropriate calls of {@link VCacheFactory}
194      *
195      * @param mockVcacheFactory mockito proxied or mocked {@link VCacheFactory}
196      * @param name name of the cache
197      * @param clazz class of cached objects
198      * @param settings cache settings
199      * @param <T> type of cached objects
200      * @return {@link TransactionalExternalCache} proxied by mockito.
201      */
202     public static <T extends Serializable> TransactionalExternalCache<T> getTransactionalCache(VCacheFactory mockVcacheFactory,
203                                                                                                String name, Class<T> clazz,
204                                                                                                ExternalCacheSettings settings) {
205         final TransactionalExternalCache<T> desiredCache = spy(mockVcacheFactory.getTransactionalExternalCache(name,
206                 JavaSerializationMarshalling.pair(clazz), settings));
207 
208         doReturn(desiredCache).when(mockVcacheFactory).getTransactionalExternalCache(eq(name), any(MarshallingPair.class),
209                 any(ExternalCacheSettings.class));
210 
211         return desiredCache;
212     }
213 
214     /**
215      * Clean up vcache context.
216      */
217     public static void cleanContext() {
218         threadLocalContextSupplier.clearThread();
219     }
220 }