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
97 return "SomeKey";
98 } else if (parameterClass.equals(String.class) && method.getName().equals("getSearchAttribute")) {
99
100 return "searchAttributeKey";
101 } else if (parameterClass.equals(Element.class)) {
102
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
155 skipMethods.add("calculateOffHeapSize");
156 skipMethods.add("getOffHeapStoreSize");
157
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 }