Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.liferay.portal.kernel.test.rule.NewEnvTestRule Maven / Gradle / Ivy
/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.kernel.test.rule;
import com.liferay.petra.process.ClassPathUtil;
import com.liferay.petra.process.ProcessCallable;
import com.liferay.petra.process.ProcessChannel;
import com.liferay.petra.process.ProcessConfig;
import com.liferay.petra.process.ProcessException;
import com.liferay.petra.process.ProcessExecutor;
import com.liferay.petra.process.local.LocalProcessExecutor;
import com.liferay.petra.process.local.LocalProcessLauncher;
import com.liferay.petra.string.CharPool;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MethodCache;
import com.liferay.portal.kernel.util.MethodKey;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.SystemProperties;
import com.liferay.portal.kernel.util.Validator;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.After;
import org.junit.Before;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
/**
* @author Shuyang Zhou
*/
public class NewEnvTestRule implements TestRule {
public static final NewEnvTestRule INSTANCE = new NewEnvTestRule();
@Override
public Statement apply(Statement statement, Description description) {
String methodName = description.getMethodName();
if (methodName == null) {
return statement;
}
NewEnv newEnv = findNewEnv(description);
if ((newEnv == null) || (newEnv.type() == NewEnv.Type.NONE)) {
return statement;
}
if (NewEnv.Type.CLASSLOADER == newEnv.type()) {
return new RunInNewClassLoaderStatement(statement, description);
}
ProcessConfig.Builder builder = new ProcessConfig.Builder();
builder.setArguments(createArguments(description));
builder.setBootstrapClassPath(CLASS_PATH);
builder.setRuntimeClassPath(CLASS_PATH);
setEnvironment(builder, description);
return new RunInNewJVMStatment(builder.build(), statement, description);
}
protected static void attachProcess(String message) {
if (Boolean.getBoolean("attached")) {
return;
}
LocalProcessLauncher.ProcessContext.attach(
message, 1000,
new LocalProcessLauncher.ShutdownHook() {
@Override
public boolean shutdown(
int shutdownCode, Throwable shutdownThrowable) {
System.exit(shutdownCode);
return true;
}
});
System.setProperty("attached", StringPool.TRUE);
}
protected static List getMethodKeys(
Class targetClass, Class annotationClass) {
TestClass testClass = new TestClass(targetClass);
List frameworkMethods = testClass.getAnnotatedMethods(
annotationClass);
List methodKeys = new ArrayList<>(frameworkMethods.size());
for (FrameworkMethod annotatedFrameworkMethod : frameworkMethods) {
methodKeys.add(new MethodKey(annotatedFrameworkMethod.getMethod()));
}
return methodKeys;
}
protected static void invoke(
ClassLoader classLoader, MethodKey methodKey, Object object)
throws Exception {
methodKey = methodKey.transform(classLoader);
Method method = methodKey.getMethod();
method.invoke(object);
}
protected NewEnvTestRule() {
}
protected List createArguments(Description description) {
List arguments = new ArrayList<>();
Class testClass = description.getTestClass();
NewEnv.JVMArgsLine jvmArgsLine = testClass.getAnnotation(
NewEnv.JVMArgsLine.class);
if (jvmArgsLine != null) {
arguments.addAll(processJVMArgsLine(jvmArgsLine));
}
jvmArgsLine = description.getAnnotation(NewEnv.JVMArgsLine.class);
if (jvmArgsLine != null) {
arguments.addAll(processJVMArgsLine(jvmArgsLine));
}
arguments.add("-Djava.net.preferIPv4Stack=true");
if (Boolean.getBoolean("jvm.debug")) {
arguments.add(_JPDA_OPTIONS);
arguments.add("-Djvm.debug=true");
}
arguments.add("-Dliferay.mode=test");
arguments.add("-Dsun.zip.disableMemoryMapping=true");
String whipAgentLine = System.getProperty("whip.agent");
if (Validator.isNotNull(whipAgentLine)) {
arguments.add(whipAgentLine);
arguments.add("-Dwhip.agent=" + whipAgentLine);
}
String fileName = System.getProperty("whip.datafile");
if (fileName != null) {
arguments.add("-Dwhip.datafile=" + fileName);
}
if (Boolean.getBoolean("whip.instrument.dump")) {
arguments.add("-Dwhip.instrument.dump=true");
}
if (Boolean.getBoolean("whip.static.instrument")) {
arguments.add("-Dwhip.static.instrument=true");
}
return arguments;
}
protected ClassLoader createClassLoader(Description description) {
try {
return new URLClassLoader(
ClassPathUtil.getClassPathURLs(CLASS_PATH), null);
}
catch (MalformedURLException murle) {
throw new RuntimeException(murle);
}
}
protected NewEnv findNewEnv(Description description) {
NewEnv newEnv = description.getAnnotation(NewEnv.class);
if (newEnv == null) {
Class testClass = description.getTestClass();
newEnv = testClass.getAnnotation(NewEnv.class);
}
return newEnv;
}
protected Map processEnvironmentVariables(
String[] variables) {
Map environmentMap = new HashMap<>();
for (String variable : variables) {
String resolvedVariable = resolveSystemProperty(variable);
String[] parts = StringUtil.split(resolvedVariable, CharPool.EQUAL);
if (parts.length != 2) {
throw new IllegalArgumentException(
StringBundler.concat(
"Wrong environment variable ", variable,
" resolved as ", resolvedVariable,
". Need to be \"key=value\" format"));
}
environmentMap.put(parts[0], parts[1]);
}
return environmentMap;
}
protected List processJVMArgsLine(NewEnv.JVMArgsLine jvmArgsLine) {
String[] jvmArgs = StringUtil.split(
jvmArgsLine.value(), StringPool.SPACE);
List jvmArgsList = new ArrayList<>(jvmArgs.length);
for (String jvmArg : jvmArgs) {
jvmArgsList.add(resolveSystemProperty(jvmArg));
}
return jvmArgsList;
}
protected ProcessCallable processProcessCallable(
ProcessCallable processCallable,
MethodKey testMethodKey) {
return processCallable;
}
protected String resolveSystemProperty(String value) {
Matcher matcher = _systemPropertyReplacePattern.matcher(value);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String key = matcher.group(1);
matcher.appendReplacement(
sb,
Matcher.quoteReplacement(
GetterUtil.getString(System.getProperty(key))));
}
matcher.appendTail(sb);
return sb.toString();
}
protected void setEnvironment(
ProcessConfig.Builder builder, Description description) {
Map environmentMap = new HashMap<>(System.getenv());
Class testClass = description.getTestClass();
NewEnv.Environment environment = testClass.getAnnotation(
NewEnv.Environment.class);
if (environment != null) {
Map map = processEnvironmentVariables(
environment.variables());
if (environment.append()) {
environmentMap.putAll(map);
}
else {
environmentMap = map;
}
}
environment = description.getAnnotation(NewEnv.Environment.class);
if (environment != null) {
Map map = processEnvironmentVariables(
environment.variables());
if (environment.append()) {
environmentMap.putAll(map);
}
else {
environmentMap = map;
}
}
builder.setEnvironment(environmentMap);
}
protected static final String CLASS_PATH = ClassPathUtil.getJVMClassPath(
true);
private static final String _JPDA_OPTIONS =
"-agentlib:jdwp=transport=dt_socket,address=8001,server=y,suspend=y";
private static final ProcessExecutor _processExecutor =
new LocalProcessExecutor();
private static final Pattern _systemPropertyReplacePattern =
Pattern.compile("\\$\\{(.*)\\}");
static {
Thread currentThread = Thread.currentThread();
ClassLoader contextClassLoader = currentThread.getContextClassLoader();
PortalClassLoaderUtil.setClassLoader(contextClassLoader);
}
private static class TestProcessCallable
implements ProcessCallable {
public TestProcessCallable(
String testClassName, List beforeMethodKeys,
MethodKey testMethodKey, List afterMethodKeys) {
_testClassName = testClassName;
_beforeMethodKeys = beforeMethodKeys;
_testMethodKey = testMethodKey;
_afterMethodKeys = afterMethodKeys;
}
@Override
public Serializable call() throws ProcessException {
attachProcess("Attached " + toString());
Thread currentThread = Thread.currentThread();
ClassLoader contextClassLoader =
currentThread.getContextClassLoader();
System.setProperty(
SystemProperties.SYSTEM_PROPERTIES_QUIET, StringPool.TRUE);
try {
Class clazz = contextClassLoader.loadClass(_testClassName);
Object object = clazz.newInstance();
for (MethodKey beforeMethodKey : _beforeMethodKeys) {
invoke(contextClassLoader, beforeMethodKey, object);
}
invoke(contextClassLoader, _testMethodKey, object);
for (MethodKey afterMethodKey : _afterMethodKeys) {
invoke(contextClassLoader, afterMethodKey, object);
}
}
catch (Exception e) {
throw new ProcessException(e);
}
return StringPool.BLANK;
}
@Override
public String toString() {
StringBundler sb = new StringBundler(4);
sb.append(_testClassName);
sb.append(StringPool.PERIOD);
sb.append(_testMethodKey.getMethodName());
sb.append("()");
return sb.toString();
}
private static final long serialVersionUID = 1L;
private final List _afterMethodKeys;
private final List _beforeMethodKeys;
private final String _testClassName;
private final MethodKey _testMethodKey;
}
private class RunInNewClassLoaderStatement
extends BaseTestRule.StatementWrapper {
public RunInNewClassLoaderStatement(
Statement statement, Description description) {
super(statement);
Class testClass = description.getTestClass();
_afterMethodKeys = getMethodKeys(testClass, After.class);
_beforeMethodKeys = getMethodKeys(testClass, Before.class);
_newClassLoader = createClassLoader(description);
_testClassName = testClass.getName();
_testMethodKey = new MethodKey(
testClass, description.getMethodName());
}
@Override
public void evaluate() throws Throwable {
MethodCache.reset();
Thread currentThread = Thread.currentThread();
ClassLoader contextClassLoader =
currentThread.getContextClassLoader();
currentThread.setContextClassLoader(_newClassLoader);
String quiet = System.getProperty(
SystemProperties.SYSTEM_PROPERTIES_QUIET);
System.setProperty(
SystemProperties.SYSTEM_PROPERTIES_QUIET, StringPool.TRUE);
try {
Class clazz = _newClassLoader.loadClass(_testClassName);
Object object = clazz.newInstance();
for (MethodKey beforeMethodKey : _beforeMethodKeys) {
invoke(_newClassLoader, beforeMethodKey, object);
}
invoke(_newClassLoader, _testMethodKey, object);
for (MethodKey afterMethodKey : _afterMethodKeys) {
invoke(_newClassLoader, afterMethodKey, object);
}
}
catch (InvocationTargetException ite) {
throw ite.getTargetException();
}
finally {
if (quiet == null) {
System.clearProperty(
SystemProperties.SYSTEM_PROPERTIES_QUIET);
}
else {
System.setProperty(
SystemProperties.SYSTEM_PROPERTIES_QUIET, quiet);
}
currentThread.setContextClassLoader(contextClassLoader);
MethodCache.reset();
}
}
private final List _afterMethodKeys;
private final List _beforeMethodKeys;
private final ClassLoader _newClassLoader;
private final String _testClassName;
private final MethodKey _testMethodKey;
}
private class RunInNewJVMStatment extends BaseTestRule.StatementWrapper {
public RunInNewJVMStatment(
ProcessConfig processConfig, Statement statement,
Description description) {
super(statement);
_processConfig = processConfig;
Class testClass = description.getTestClass();
_afterMethodKeys = getMethodKeys(testClass, After.class);
_beforeMethodKeys = getMethodKeys(testClass, Before.class);
_testClassName = testClass.getName();
_testMethodKey = new MethodKey(
testClass, description.getMethodName());
}
@Override
public void evaluate() throws Throwable {
ProcessCallable processCallable =
new TestProcessCallable(
_testClassName, _beforeMethodKeys, _testMethodKey,
_afterMethodKeys);
processCallable = processProcessCallable(
processCallable, _testMethodKey);
ProcessChannel processChannel =
_processExecutor.execute(_processConfig, processCallable);
Future future =
processChannel.getProcessNoticeableFuture();
try {
future.get();
}
catch (ExecutionException ee) {
Throwable cause = ee.getCause();
while (cause instanceof InvocationTargetException ||
cause instanceof ProcessException) {
cause = cause.getCause();
}
throw cause;
}
}
private final List _afterMethodKeys;
private final List _beforeMethodKeys;
private final ProcessConfig _processConfig;
private final String _testClassName;
private final MethodKey _testMethodKey;
}
}