org.apache.maven.surefire.booter.ProviderFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of surefire-booter Show documentation
Show all versions of surefire-booter Show documentation
API and Facilities used by forked tests running in JVM sub-process.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.surefire.booter;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.maven.surefire.api.provider.SurefireProvider;
import org.apache.maven.surefire.api.report.ReporterException;
import org.apache.maven.surefire.api.suite.RunResult;
import org.apache.maven.surefire.api.testset.TestSetFailedException;
import static org.apache.maven.surefire.api.util.ReflectionUtils.getMethod;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeGetter;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray2;
import static org.apache.maven.surefire.api.util.internal.ObjectUtils.isSecurityManagerSupported;
/**
* Creates the surefire provider.
*
*
* @author Kristian Rosenvold
*/
public class ProviderFactory {
private final StartupConfiguration startupConfiguration;
private final ProviderConfiguration providerConfiguration;
private final ClassLoader classLoader;
private final SurefireReflector surefireReflector;
private final Object reporterManagerFactory;
private static final Class>[] INVOKE_PARAMETERS = {Object.class};
private static final Class>[] INVOKE_EMPTY_PARAMETER_TYPES = {};
private static final Object[] INVOKE_EMPTY_PARAMETERS = {};
public ProviderFactory(
StartupConfiguration startupConfiguration,
ProviderConfiguration providerConfiguration,
ClassLoader testsClassLoader,
Object reporterManagerFactory) {
this.providerConfiguration = providerConfiguration;
this.startupConfiguration = startupConfiguration;
this.surefireReflector = new SurefireReflector(testsClassLoader);
this.classLoader = testsClassLoader;
this.reporterManagerFactory = reporterManagerFactory;
}
public static RunResult invokeProvider(
Object testSet,
ClassLoader testsClassLoader,
Object factory,
ProviderConfiguration providerConfiguration,
boolean insideFork,
StartupConfiguration startupConfig,
boolean restoreStreams)
throws TestSetFailedException, InvocationTargetException {
final PrintStream orgSystemOut = System.out;
final PrintStream orgSystemErr = System.err;
// Note that System.out/System.err are also read in the "ReporterConfiguration" instantiation
// in createProvider below. These are the same values as here.
try {
return new ProviderFactory(startupConfig, providerConfiguration, testsClassLoader, factory)
.createProvider(insideFork)
.invoke(testSet);
} finally {
if (restoreStreams && (!isSecurityManagerSupported() || System.getSecurityManager() == null)) {
System.setOut(orgSystemOut);
System.setErr(orgSystemErr);
}
}
}
public SurefireProvider createProvider(boolean isInsideFork) {
final Thread currentThread = Thread.currentThread();
final ClassLoader systemClassLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(classLoader);
// Note: Duplicated in ForkedBooter#createProviderInCurrentClassloader
Object o = surefireReflector.createBooterConfiguration(classLoader, isInsideFork);
surefireReflector.setReporterFactoryAware(o, reporterManagerFactory);
surefireReflector.setTestSuiteDefinitionAware(o, providerConfiguration.getTestSuiteDefinition());
surefireReflector.setProviderPropertiesAware(o, providerConfiguration.getProviderProperties());
surefireReflector.setReporterConfigurationAware(o, providerConfiguration.getReporterConfiguration());
surefireReflector.setTestClassLoaderAware(o, classLoader);
surefireReflector.setTestArtifactInfoAware(o, providerConfiguration.getTestArtifact());
surefireReflector.setRunOrderParameters(o, providerConfiguration.getRunOrderParameters());
surefireReflector.setIfDirScannerAware(o, providerConfiguration.getDirScannerParams());
surefireReflector.setMainCliOptions(o, providerConfiguration.getMainCliOptions());
surefireReflector.setSkipAfterFailureCount(o, providerConfiguration.getSkipAfterFailureCount());
if (isInsideFork) {
surefireReflector.setSystemExitTimeout(o, providerConfiguration.getSystemExitTimeout());
}
Object provider = surefireReflector.instantiateProvider(startupConfiguration.getActualClassName(), o);
currentThread.setContextClassLoader(systemClassLoader);
return new ProviderProxy(provider, classLoader);
}
private final class ProviderProxy implements SurefireProvider {
private final Object providerInOtherClassLoader;
private final ClassLoader testsClassLoader;
private ProviderProxy(Object providerInOtherClassLoader, ClassLoader testsClassLoader) {
this.providerInOtherClassLoader = providerInOtherClassLoader;
this.testsClassLoader = testsClassLoader;
}
@Override
public Iterable> getSuites() {
ClassLoader current = swapClassLoader(testsClassLoader);
try {
return invokeGetter(providerInOtherClassLoader, "getSuites");
} finally {
Thread.currentThread().setContextClassLoader(current);
}
}
@Override
public RunResult invoke(Object forkTestSet) throws ReporterException, InvocationTargetException {
ClassLoader current = swapClassLoader(testsClassLoader);
try {
Method invoke = getMethod(providerInOtherClassLoader.getClass(), "invoke", INVOKE_PARAMETERS);
Object result = invokeMethodWithArray2(providerInOtherClassLoader, invoke, forkTestSet);
return (RunResult) surefireReflector.convertIfRunResult(result);
} finally {
if (System.getSecurityManager() == null) {
Thread.currentThread().setContextClassLoader(current);
}
}
}
private ClassLoader swapClassLoader(ClassLoader newClassLoader) {
ClassLoader current = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(newClassLoader);
return current;
}
@Override
public void cancel() {
Class> providerType = providerInOtherClassLoader.getClass();
Method invoke = getMethod(providerType, "cancel", INVOKE_EMPTY_PARAMETER_TYPES);
invokeMethodWithArray(providerInOtherClassLoader, invoke, INVOKE_EMPTY_PARAMETERS);
}
}
}