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