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