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 List<MethodKey> _afterMethodKeys;
209 private List<MethodKey> _beforeMethodKeys;
210 private String _testClassName;
211 private MethodKey _testMethodKey;
212
213 }
214
215 private class RunInNewJVMStatment extends Statement {
216
217 public RunInNewJVMStatment(
218 String classPath, List<String> arguments, Class<?> testClass,
219 List<FrameworkMethod> beforeFrameworkMethods,
220 FrameworkMethod testFrameworkMethod,
221 List<FrameworkMethod> afterFrameworkMethods) {
222
223 _classPath = classPath;
224 _arguments = arguments;
225 _testClassName = testClass.getName();
226
227 _beforeMethodKeys = new ArrayList<MethodKey>(
228 beforeFrameworkMethods.size());
229
230 for (FrameworkMethod frameworkMethod : beforeFrameworkMethods) {
231 _beforeMethodKeys.add(
232 new MethodKey(frameworkMethod.getMethod()));
233 }
234
235 _testMethodKey = new MethodKey(testFrameworkMethod.getMethod());
236
237 _afterMethodKeys = new ArrayList<MethodKey>(
238 afterFrameworkMethods.size());
239
240 for (FrameworkMethod frameworkMethod : afterFrameworkMethods) {
241 _afterMethodKeys.add(
242 new MethodKey(frameworkMethod.getMethod()));
243 }
244 }
245
246 @Override
247 public void evaluate() throws Throwable {
248 ProcessCallable<Serializable> processCallable =
249 new TestProcessCallable(
250 _testClassName, _beforeMethodKeys, _testMethodKey,
251 _afterMethodKeys);
252
253 processCallable = processProcessCallable(
254 processCallable, _testMethodKey);
255
256 Future<String> future = ProcessExecutor.execute(
257 _classPath, _arguments, processCallable);
258
259 try {
260 future.get();
261 }
262 catch (ExecutionException ee) {
263 Throwable cause = ee.getCause();
264
265 while ((cause instanceof ProcessException) ||
266 (cause instanceof InvocationTargetException)) {
267
268 cause = cause.getCause();
269 }
270
271 throw cause;
272 }
273 }
274
275 private List<MethodKey> _afterMethodKeys;
276 private List<String> _arguments;
277 private List<MethodKey> _beforeMethodKeys;
278 private String _classPath;
279 private String _testClassName;
280 private MethodKey _testMethodKey;
281
282 }
283
284 }