View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.constructs.nonstop;
18  
19  import static org.mockito.Matchers.any;
20  import static org.mockito.Mockito.mock;
21  import static org.mockito.Mockito.when;
22  
23  import java.io.Serializable;
24  import java.lang.reflect.Method;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.HashSet;
29  import java.util.List;
30  import java.util.Set;
31  
32  import junit.framework.TestCase;
33  import net.sf.ehcache.Cache;
34  import net.sf.ehcache.CacheManager;
35  import net.sf.ehcache.CacheManagerMockHelper;
36  import net.sf.ehcache.Ehcache;
37  import net.sf.ehcache.Element;
38  import net.sf.ehcache.Statistics;
39  import net.sf.ehcache.cluster.ClusterScheme;
40  import net.sf.ehcache.cluster.NoopCacheCluster;
41  import net.sf.ehcache.config.CacheConfiguration;
42  import net.sf.ehcache.config.Configuration;
43  import net.sf.ehcache.config.NonstopConfiguration;
44  import net.sf.ehcache.config.SearchAttribute;
45  import net.sf.ehcache.config.Searchable;
46  import net.sf.ehcache.config.TerracottaConfiguration;
47  import net.sf.ehcache.config.TerracottaConfiguration.StorageStrategy;
48  import net.sf.ehcache.store.Store;
49  
50  import org.slf4j.Logger;
51  import org.slf4j.LoggerFactory;
52  
53  /***
54   * Utility class
55   *
56   * @author Abhishek Sanoujam
57   */
58  public class NonstopTestUtil extends TestCase {
59  
60      private static final Logger LOG = LoggerFactory.getLogger(NonstopTestUtil.class);
61  
62      private CacheManager cacheManager;
63  
64      public static String getMethodSignature(Method method) {
65          StringBuilder sb = new StringBuilder();
66          sb.append(method.getName()).append('(');
67  
68          Class[] parameterTypes = method.getParameterTypes();
69          for (int j = 0; j < parameterTypes.length; j++) {
70              sb.append(parameterTypes[j].getName());
71              if (j < (parameterTypes.length - 1)) {
72                  sb.append(',');
73              }
74          }
75          sb.append(')');
76          return sb.toString();
77      }
78  
79      public static Object[] getMethodArguments(Method m) throws Exception {
80          Class<?>[] parameterTypes = m.getParameterTypes();
81          Object[] parameters = new Object[parameterTypes.length];
82          for (int i = 0; i < parameters.length; i++) {
83              try {
84                  parameters[i] = getArgumentInstanceFor(m, parameterTypes[i]);
85              } catch (InstantiationException e) {
86                  throw e;
87              } catch (IllegalAccessException e) {
88                  throw e;
89              }
90          }
91          return parameters;
92      }
93  
94      private static Object getArgumentInstanceFor(Method method, Class<?> parameterClass) throws Exception {
95          if (parameterClass.equals(Object.class) || parameterClass.equals(Serializable.class)) {
96              // isKeyInCache doesn't touch tc layer for null keys in LocalReadsBehavior
97              return "SomeKey";
98          } else if (parameterClass.equals(String.class) && method.getName().equals("getSearchAttribute")) {
99              // isKeyInCache doesn't touch tc layer for null keys in LocalReadsBehavior
100             return "searchAttributeKey";
101         } else if (parameterClass.equals(Element.class)) {
102             // put calls with null does not touch terracotta layer... use non-null arg
103             return new Element("someKey", "someValue");
104         } else if (parameterClass.equals(Boolean.TYPE)) {
105             return Boolean.FALSE;
106         } else if ((method.getName().equals("getSizeBasedOnAccuracy") || method.getName().equals("setStatisticsAccuracy"))
107                 && parameterClass.equals(Integer.TYPE)) {
108             return Statistics.STATISTICS_ACCURACY_BEST_EFFORT;
109         } else if (parameterClass.equals(Collection.class)) {
110           return Collections.emptySet();
111         } else {
112             String msg = "Unhandled parameter type for method: " + getMethodSignature(method) + ", type: " + parameterClass.getName();
113             throw new Exception(msg);
114         }
115     }
116 
117     /***
118      * @return all methods in Ehcache that potentially touches Terracotta layer
119      * @throws Exception
120      */
121     public static List<Method> getEhcacheMethodsTouchingStore() {
122         final List<Method> rv = new ArrayList<Method>();
123 
124         final MockStoreWithFlag mockStore = new MockStoreWithFlag();
125         Cache cache = getMockTerracottaStore(mockStore, null);
126 
127         final Set<String> skipMethods = new HashSet<String>();
128         skipMethods.add("setCacheManager");
129         skipMethods.add("setDiskStorePath");
130         skipMethods.add("setTransactionManagerLookup");
131         skipMethods.add("initialise");
132         skipMethods.add("registerCacheUsageListener");
133         skipMethods.add("removeCacheUsageListener");
134         skipMethods.add("setBootstrapCacheLoader");
135         skipMethods.add("registerCacheExtension");
136         skipMethods.add("unregisterCacheExtension");
137         skipMethods.add("registerCacheLoader");
138         skipMethods.add("unregisterCacheLoader");
139         skipMethods.add("registerCacheWriter");
140         skipMethods.add("unregisterCacheWriter");
141         skipMethods.add("setDisabled");
142         skipMethods.add("getWithLoader");
143         skipMethods.add("getAllWithLoader");
144         skipMethods.add("loadAll");
145         skipMethods.add("clone");
146         skipMethods.add("setName");
147         skipMethods.add("dispose");
148         skipMethods.add("setCacheExceptionHandler");
149         skipMethods.add("addPropertyChangeListener");
150         skipMethods.add("removePropertyChangeListener");
151         skipMethods.add("waitUntilClusterCoherent");
152         skipMethods.add("waitUntilClusterBulkLoadComplete");
153         skipMethods.add("calculateOnDiskSize");
154         // off-heap methods don't reach terracotta layer.. yet
155         skipMethods.add("calculateOffHeapSize");
156         skipMethods.add("getOffHeapStoreSize");
157         // methods that are no-op for ClusteredStore
158         skipMethods.add("bufferFull");
159         skipMethods.add("getInternalContext");
160         skipMethods.add("isElementOnDisk");
161         skipMethods.add("acquireReadLockOnKey");
162         skipMethods.add("acquireWriteLockOnKey");
163         skipMethods.add("releaseReadLockOnKey");
164         skipMethods.add("releaseWriteLockOnKey");
165         skipMethods.add("tryReadLockOnKey");
166         skipMethods.add("tryWriteLockOnKey");
167         skipMethods.add("isReadLockedByCurrentThread");
168         skipMethods.add("isWriteLockedByCurrentThread");
169         skipMethods.add("evictExpiredElements");
170 
171         new EhcacheMethodsInvoker() {
172 
173             @Override
174             protected void invokeOne(Ehcache ehcache, Method m) {
175                 mockStore.clearAccessFlag();
176                 if (skipMethods.contains(m.getName())) {
177                     LOG.info(" Skipped: " + getMethodSignature(m));
178                     return;
179                 }
180                 super.invokeOne(ehcache, m);
181                 if (mockStore.isAccessFlagMarked()) {
182                     rv.add(m);
183                 }
184             }
185 
186         }.invokeAll(cache);
187 
188         return rv;
189     }
190 
191     public static Cache getMockTerracottaStore(Store mockTerracottaStore, NonstopConfiguration nonstopConfiguration) {
192         CacheManager cacheManager = mock(CacheManager.class);
193         CacheConfiguration cacheConfiguration = new CacheConfiguration("someName", 10000);
194         TerracottaConfiguration terracottaConfiguration = new TerracottaConfiguration().clustered(true).storageStrategy(
195                 StorageStrategy.CLASSIC);
196         terracottaConfiguration.addNonstop(nonstopConfiguration);
197         cacheConfiguration.addTerracotta(terracottaConfiguration);
198         Searchable searchable = new Searchable();
199         SearchAttribute searchAttribute = new SearchAttribute();
200         searchAttribute.setName("searchAttributeKey");
201         searchable.addSearchAttribute(searchAttribute);
202         cacheConfiguration.addSearchable(searchable);
203 
204         Cache cache = new Cache(cacheConfiguration);
205 
206         when(cacheManager.getConfiguration()).thenReturn(new Configuration());
207         when(cacheManager.createTerracottaStore(cache)).thenReturn(mockTerracottaStore);
208         when(cacheManager.getCluster((ClusterScheme) any())).thenReturn(new NoopCacheCluster());
209 
210         CacheManagerMockHelper.mockGetNonstopExecutorService(cacheManager);
211 
212         cacheManager.addCache(cache);
213         cache.setCacheManager(cacheManager);
214         cache.initialise();
215         cache.registerCacheWriter(new MockCacheWriterFactory().createCacheWriter(cache, null));
216         return cache;
217     }
218 
219     public static class EhcacheMethodsInvoker {
220 
221         public void invokeAll(Ehcache ehcache) {
222             Method[] methods = Ehcache.class.getMethods();
223             for (Method m : methods) {
224                 invokeOne(ehcache, m);
225             }
226         }
227 
228         protected void invokeOne(Ehcache ehcache, Method m) {
229             try {
230                 Object[] args = getMethodArguments(m);
231                 m.invoke(ehcache, args);
232             } catch (Exception e) {
233                 throw new RuntimeException(e);
234             }
235         }
236 
237     }
238 
239 }