001
014
015 package com.liferay.portal.kernel.test;
016
017 import com.liferay.portal.kernel.process.ClassPathUtil;
018 import com.liferay.portal.kernel.process.ProcessCallable;
019 import com.liferay.portal.kernel.process.ProcessException;
020 import com.liferay.portal.kernel.process.ProcessExecutor;
021 import com.liferay.portal.kernel.util.MethodKey;
022 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
023 import com.liferay.portal.kernel.util.StringBundler;
024 import com.liferay.portal.kernel.util.StringPool;
025
026 import java.io.Serializable;
027
028 import java.lang.reflect.InvocationTargetException;
029 import java.lang.reflect.Method;
030
031 import java.util.ArrayList;
032 import java.util.List;
033 import java.util.concurrent.ExecutionException;
034 import java.util.concurrent.Future;
035
036 import org.junit.After;
037 import org.junit.Before;
038 import org.junit.runner.manipulation.Sorter;
039 import org.junit.runners.BlockJUnit4ClassRunner;
040 import org.junit.runners.model.FrameworkMethod;
041 import org.junit.runners.model.InitializationError;
042 import org.junit.runners.model.Statement;
043 import org.junit.runners.model.TestClass;
044
045
048 public class NewJVMJUnitTestRunner extends BlockJUnit4ClassRunner {
049
050 public NewJVMJUnitTestRunner(Class<?> clazz) throws InitializationError {
051 super(clazz);
052
053 _classPath = ClassPathUtil.getJVMClassPath(false);
054
055 sort(new Sorter(new DescriptionComparator()));
056 }
057
058 protected static void attachProcess(String message) {
059 if (!Boolean.getBoolean("attached")) {
060 ProcessExecutor.ProcessContext.attach(
061 message, 1000,
062 new ProcessExecutor.ShutdownHook() {
063
064 public boolean shutdown(
065 int shutdownCode, Throwable shutdownThrowable) {
066
067 System.exit(shutdownCode);
068
069 return true;
070 }
071
072 });
073
074 System.setProperty("attached", StringPool.TRUE);
075 }
076 }
077
078 protected List<String> createArguments(FrameworkMethod frameworkMethod) {
079 List<String> arguments = new ArrayList<String>();
080
081 boolean junitDebug = Boolean.getBoolean("junit.debug");
082
083 if (junitDebug) {
084 arguments.add(_JPDA_OPTIONS);
085 }
086
087 arguments.add("-Djava.net.preferIPv4Stack=true");
088
089 String fileName = System.getProperty(
090 "net.sourceforge.cobertura.datafile");
091
092 if (fileName != null) {
093 arguments.add("-Dnet.sourceforge.cobertura.datafile=" + fileName);
094 }
095
096 return arguments;
097 }
098
099 @Override
100 protected Statement methodBlock(FrameworkMethod frameworkMethod) {
101 Thread currentThread = Thread.currentThread();
102
103 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
104
105 PortalClassLoaderUtil.setClassLoader(contextClassLoader);
106
107 TestClass testClass = getTestClass();
108
109 List<FrameworkMethod> beforeFrameworkMethods =
110 testClass.getAnnotatedMethods(Before.class);
111
112 List<FrameworkMethod> afterFrameworkMethods =
113 testClass.getAnnotatedMethods(After.class);
114
115 List<String> arguments = createArguments(frameworkMethod);
116
117 Class<?> clazz = testClass.getJavaClass();
118
119 return new RunInNewJVMStatment(
120 _classPath, arguments, clazz, beforeFrameworkMethods,
121 frameworkMethod, afterFrameworkMethods);
122 }
123
124 protected ProcessCallable<Serializable> processProcessCallable(
125 ProcessCallable<Serializable> processCallable,
126 MethodKey testMethodKey) {
127
128 return processCallable;
129 }
130
131 private static final String _JPDA_OPTIONS =
132 "-agentlib:jdwp=transport=dt_socket,address=8001,server=y,suspend=y";
133
134 private String _classPath;
135
136 private static class TestProcessCallable
137 implements ProcessCallable<Serializable> {
138
139 public TestProcessCallable(
140 String testClassName, List<MethodKey> beforeMethodKeys,
141 MethodKey testMethodKey, List<MethodKey> afterMethodKeys) {
142
143 _testClassName = testClassName;
144 _beforeMethodKeys = beforeMethodKeys;
145 _testMethodKey = testMethodKey;
146 _afterMethodKeys = afterMethodKeys;
147 }
148
149 public Serializable call() throws ProcessException {
150 attachProcess("Attached " + toString());
151
152 Thread currentThread = Thread.currentThread();
153
154 ClassLoader contextClassLoader =
155 currentThread.getContextClassLoader();
156
157 try {
158 Class<?> clazz = contextClassLoader.loadClass(_testClassName);
159
160 Object object = clazz.newInstance();
161
162 for (MethodKey beforeMethodKey : _beforeMethodKeys) {
163 beforeMethodKey = beforeMethodKey.transform(
164 contextClassLoader);
165
166 _invoke(beforeMethodKey, object);
167 }
168
169 MethodKey testMethodKey = _testMethodKey.transform(
170 contextClassLoader);
171
172 _invoke(testMethodKey, object);
173
174 for (MethodKey afterMethodKey : _afterMethodKeys) {
175 afterMethodKey = afterMethodKey.transform(
176 contextClassLoader);
177
178 _invoke(afterMethodKey, object);
179 }
180 }
181 catch (Exception e) {
182 throw new ProcessException(e);
183 }
184
185 return StringPool.BLANK;
186 }
187
188 @Override
189 public String toString() {
190 StringBundler sb = new StringBundler(4);
191
192 sb.append(_testClassName);
193 sb.append(StringPool.PERIOD);
194 sb.append(_testMethodKey.getMethodName());
195 sb.append("()");
196
197 return sb.toString();
198 }
199
200 private void _invoke(MethodKey methodKey, Object object)
201 throws Exception {
202
203 Method method = methodKey.getMethod();
204
205 method.invoke(object);
206 }
207
208 private static final long serialVersionUID = 1L;
209
210 private List<MethodKey> _afterMethodKeys;
211 private List<MethodKey> _beforeMethodKeys;
212 private String _testClassName;
213 private MethodKey _testMethodKey;
214
215 }
216
217 private class RunInNewJVMStatment extends Statement {
218
219 public RunInNewJVMStatment(
220 String classPath, List<String> arguments, Class<?> testClass,
221 List<FrameworkMethod> beforeFrameworkMethods,
222 FrameworkMethod testFrameworkMethod,
223 List<FrameworkMethod> afterFrameworkMethods) {
224
225 _classPath = classPath;
226 _arguments = arguments;
227 _testClassName = testClass.getName();
228
229 _beforeMethodKeys = new ArrayList<MethodKey>(
230 beforeFrameworkMethods.size());
231
232 for (FrameworkMethod frameworkMethod : beforeFrameworkMethods) {
233 _beforeMethodKeys.add(
234 new MethodKey(frameworkMethod.getMethod()));
235 }
236
237 _testMethodKey = new MethodKey(testFrameworkMethod.getMethod());
238
239 _afterMethodKeys = new ArrayList<MethodKey>(
240 afterFrameworkMethods.size());
241
242 for (FrameworkMethod frameworkMethod : afterFrameworkMethods) {
243 _afterMethodKeys.add(
244 new MethodKey(frameworkMethod.getMethod()));
245 }
246 }
247
248 @Override
249 public void evaluate() throws Throwable {
250 ProcessCallable<Serializable> processCallable =
251 new TestProcessCallable(
252 _testClassName, _beforeMethodKeys, _testMethodKey,
253 _afterMethodKeys);
254
255 processCallable = processProcessCallable(
256 processCallable, _testMethodKey);
257
258 Future<String> future = ProcessExecutor.execute(
259 _classPath, _arguments, processCallable);
260
261 try {
262 future.get();
263 }
264 catch (ExecutionException ee) {
265 Throwable cause = ee.getCause();
266
267 while ((cause instanceof ProcessException) ||
268 (cause instanceof InvocationTargetException)) {
269
270 cause = cause.getCause();
271 }
272
273 throw cause;
274 }
275 }
276
277 private List<MethodKey> _afterMethodKeys;
278 private List<String> _arguments;
279 private List<MethodKey> _beforeMethodKeys;
280 private String _classPath;
281 private String _testClassName;
282 private MethodKey _testMethodKey;
283
284 }
285
286 }