1
package org.apache.maven.surefire.booter;
4
* Licensed to the Apache Software Foundation (ASF) under one
5
* or more contributor license agreements. See the NOTICE file
6
* distributed with this work for additional information
7
* regarding copyright ownership. The ASF licenses this file
8
* to you under the Apache License, Version 2.0 (the
9
* "License"); you may not use this file except in compliance
10
* with the License. You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing,
15
* software distributed under the License is distributed on an
16
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
* KIND, either express or implied. See the License for the
18
* specific language governing permissions and limitations
22
import java.io.PrintStream;
23
import org.apache.maven.surefire.providerapi.SurefireProvider;
24
import org.apache.maven.surefire.report.ReporterException;
25
import org.apache.maven.surefire.suite.RunResult;
26
import org.apache.maven.surefire.testset.TestSetFailedException;
27
import org.apache.maven.surefire.util.NestedRuntimeException;
28
import org.apache.maven.surefire.util.ReflectionUtils;
31
* Invokes surefire with the correct classloader setup.
33
* This part of the booter is always guaranteed to be in the
34
* same vm as the tests will be run in.
36
* @author Jason van Zyl
37
* @author Brett Porter
38
* @author Emmanuel Venisse
39
* @author Dan Fabulich
40
* @author Kristian Rosenvold
43
public class SurefireStarter
45
private final ProviderConfiguration providerConfiguration;
47
private final StartupConfiguration startupConfiguration;
49
private final static String SUREFIRE_TEST_CLASSPATH = "surefire.test.class.path";
51
private final StartupReportConfiguration startupReportConfiguration;
53
public SurefireStarter( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
54
StartupReportConfiguration startupReportConfiguration )
56
this.providerConfiguration = providerConfiguration;
57
this.startupConfiguration = startupConfiguration;
58
this.startupReportConfiguration = startupReportConfiguration;
61
public RunResult runSuitesInProcessWhenForked( TypeEncodedValue testSet )
62
throws SurefireExecutionException
64
writeSurefireTestClasspathProperty();
65
final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
68
// Why is the classloader structure created differently when a testSet is specified ?
69
// Smells like a legacy bug. Need to check issue tracker.
70
ClassLoader testsClassLoader = classpathConfiguration.createTestClassLoaderConditionallySystem(
71
startupConfiguration.useSystemClassLoader() );
73
ClassLoader surefireClassLoader = classpathConfiguration.createSurefireClassLoader( testsClassLoader );
75
SurefireReflector surefireReflector = new SurefireReflector( surefireClassLoader );
77
final Object forkingReporterFactory = createForkingReporterFactory( surefireReflector );
79
Object test = testSet.getDecodedValue();
81
return invokeProvider( test, testsClassLoader, surefireClassLoader, forkingReporterFactory );
84
private Object createForkingReporterFactory( SurefireReflector surefireReflector )
86
final Boolean trimStackTrace = this.providerConfiguration.getReporterConfiguration().isTrimStackTrace();
87
final PrintStream originalSystemOut =
88
this.providerConfiguration.getReporterConfiguration().getOriginalSystemOut();
89
return surefireReflector.createForkingReporterFactory( trimStackTrace, originalSystemOut );
92
// todo: Fix duplication in this method and runSuitesInProcess
93
// This should be fixed "at a higher level", because this whole way
94
// of organizing the code stinks.
96
public RunResult runSuitesInProcessWhenForked()
97
throws SurefireExecutionException
99
ClassLoader testsClassLoader = createInProcessTestClassLoader();
101
ClassLoader surefireClassLoader = createSurefireClassloader( testsClassLoader );
103
SurefireReflector surefireReflector = new SurefireReflector( surefireClassLoader );
105
final Object factory = createForkingReporterFactory( surefireReflector );
107
return invokeProvider( null, testsClassLoader, surefireClassLoader, factory );
110
public RunResult runSuitesInProcess()
111
throws SurefireExecutionException
113
// The test classloader must be constructed first to avoid issues with commons-logging until we properly
114
// separate the TestNG classloader
115
ClassLoader testsClassLoader = createInProcessTestClassLoader();
117
ClassLoader surefireClassLoader = createSurefireClassloader( testsClassLoader );
119
SurefireReflector surefireReflector = new SurefireReflector( surefireClassLoader );
121
final Object factory = surefireReflector.createReportingReporterFactory( startupReportConfiguration );
123
return invokeProvider( null, testsClassLoader, surefireClassLoader, factory );
126
private ClassLoader createSurefireClassloader( ClassLoader testsClassLoader )
127
throws SurefireExecutionException
129
final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
131
return classpathConfiguration.createSurefireClassLoader( testsClassLoader );
134
private ClassLoader createInProcessTestClassLoader()
135
throws SurefireExecutionException
137
writeSurefireTestClasspathProperty();
138
ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
139
if ( startupConfiguration.isManifestOnlyJarRequestedAndUsable() )
141
ClassLoader testsClassLoader = getClass().getClassLoader(); // ClassLoader.getSystemClassLoader()
142
// SUREFIRE-459, trick the app under test into thinking its classpath was conventional
143
// (instead of a single manifest-only jar)
144
System.setProperty( "surefire.real.class.path", System.getProperty( "java.class.path" ) );
145
classpathConfiguration.getTestClasspath().writeToSystemProperty( "java.class.path" );
146
return testsClassLoader;
150
return classpathConfiguration.createTestClassLoader();
154
private void writeSurefireTestClasspathProperty()
156
ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
157
classpathConfiguration.getTestClasspath().writeToSystemProperty( SUREFIRE_TEST_CLASSPATH );
160
private RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader, ClassLoader surefireClassLoader,
163
final PrintStream orgSystemOut = System.out;
164
final PrintStream orgSystemErr = System.err;
165
// Note that System.out/System.err are also read in the "ReporterConfiguration" instatiation
166
// in createProvider below. These are the same values as here.
168
ProviderFactory providerFactory =
169
new ProviderFactory( startupConfiguration, providerConfiguration, surefireClassLoader, testsClassLoader,
171
final SurefireProvider provider = providerFactory.createProvider();
175
return provider.invoke( testSet );
177
catch ( TestSetFailedException e )
179
throw new NestedRuntimeException( e );
181
catch ( ReporterException e )
183
throw new NestedRuntimeException( e );
187
if ( System.getSecurityManager() == null )
189
System.setOut( orgSystemOut );
190
System.setErr( orgSystemErr );