Skip to content

Commit

Permalink
[SUREFIRE-1565] Surefire should support parameterized reportsDirectory
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibor17 committed Sep 10, 2018
1 parent b791068 commit be2be7e
Show file tree
Hide file tree
Showing 35 changed files with 496 additions and 275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
import static org.apache.commons.lang3.StringUtils.substringBeforeLast;
import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS;
import static org.apache.maven.plugin.surefire.util.DependencyScanner.filter;
import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders;
import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter;
import static org.apache.maven.shared.utils.StringUtils.isEmpty;
import static org.apache.maven.shared.utils.StringUtils.isNotBlank;
Expand Down Expand Up @@ -769,19 +770,6 @@ public abstract class AbstractSurefireMojo

private int effectiveForkCount = -1;

/**
* The placeholder that is replaced by the executing thread's running number. The thread number
* range starts with 1
* Deprecated.
*/
public static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";

/**
* The placeholder that is replaced by the executing fork's running number. The fork number
* range starts with 1
*/
public static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}";

protected abstract String getPluginName();

protected abstract int getRerunFailingTestsCount();
Expand Down Expand Up @@ -1215,16 +1203,12 @@ public static SurefireProperties createCopyAndReplaceForkNumPlaceholder(
SurefireProperties effectiveSystemProperties, int threadNumber )
{
SurefireProperties filteredProperties = new SurefireProperties( ( KeyValueSource) effectiveSystemProperties );
String threadNumberString = String.valueOf( threadNumber );
for ( Entry<Object, Object> entry : effectiveSystemProperties.entrySet() )
{
if ( entry.getValue() instanceof String )
{
String value = (String) entry.getValue();
value = value.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberString );
value = value.replace( FORK_NUMBER_PLACEHOLDER, threadNumberString );

filteredProperties.put( entry.getKey(), value );
filteredProperties.put( entry.getKey(), replaceThreadNumberPlaceholders( value, threadNumber ) );
}
}
return filteredProperties;
Expand Down Expand Up @@ -1846,13 +1830,14 @@ private Artifact getApiArtifact()
return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-api" );
}

private StartupReportConfiguration getStartupReportConfiguration( String configChecksum )
private StartupReportConfiguration getStartupReportConfiguration( String configChecksum, boolean isForkMode )
{
return new StartupReportConfiguration( isUseFile(), isPrintSummary(), getReportFormat(),
isRedirectTestOutputToFile(), isDisableXmlReport(),
getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix(),
getStatisticsFile( configChecksum ), requiresRunHistory(),
getRerunFailingTestsCount(), getReportSchemaLocation(), getEncoding() );
getRerunFailingTestsCount(), getReportSchemaLocation(), getEncoding(),
isForkMode );
}

private boolean isSpecificTestSpecified()
Expand Down Expand Up @@ -2102,7 +2087,7 @@ private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull
StartupConfiguration startupConfiguration =
createStartupConfiguration( provider, false, classLoaderConfiguration, scanResult );
String configChecksum = getConfigChecksum();
StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, true );
ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration,
getForkedProcessTimeoutInSeconds(), startupReportConfiguration, log );
Expand All @@ -2117,7 +2102,7 @@ private InPluginVMSurefireStarter createInprocessStarter( @Nonnull ProviderInfo
StartupConfiguration startupConfiguration =
createStartupConfiguration( provider, true, classLoaderConfiguration, scanResult );
String configChecksum = getConfigChecksum();
StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, false );
ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration,
getConsoleLogger() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ private Object createStartupReportConfiguration( @Nonnull StartupReportConfigura
Constructor<?> constructor = getConstructor( startupReportConfiguration, boolean.class, boolean.class,
String.class, boolean.class, boolean.class, File.class,
boolean.class, String.class, File.class, boolean.class,
int.class, String.class, String.class );
int.class, String.class, String.class, boolean.class );
//noinspection BooleanConstructorCall
Object[] params = { reporterConfiguration.isUseFile(), reporterConfiguration.isPrintSummary(),
reporterConfiguration.getReportFormat(), reporterConfiguration.isRedirectTestOutputToFile(),
reporterConfiguration.isDisableXmlReport(), reporterConfiguration.getReportsDirectory(),
reporterConfiguration.isTrimStackTrace(), reporterConfiguration.getReportNameSuffix(),
reporterConfiguration.getStatisticsFile(), reporterConfiguration.isRequiresRunHistory(),
reporterConfiguration.getRerunFailingTestsCount(), reporterConfiguration.getXsdSchemaLocation(),
reporterConfiguration.getEncoding().name() };
reporterConfiguration.getEncoding().name(), reporterConfiguration.isForkMode() };
return newInstance( constructor, params );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
import static org.apache.maven.plugin.surefire.report.ConsoleReporter.BRIEF;
import static org.apache.maven.plugin.surefire.report.ConsoleReporter.PLAIN;
import static org.apache.commons.lang3.StringUtils.trimToNull;
Expand All @@ -47,10 +48,6 @@
*/
public final class StartupReportConfiguration
{
public static final String BRIEF_REPORT_FORMAT = BRIEF;

public static final String PLAIN_REPORT_FORMAT = PLAIN;

private final PrintStream originalSystemOut;

private final PrintStream originalSystemErr;
Expand Down Expand Up @@ -84,14 +81,16 @@ public final class StartupReportConfiguration

private final Charset encoding;

private boolean isForkMode;

private StatisticsReporter statisticsReporter;

@SuppressWarnings( "checkstyle:parameternumber" )
public StartupReportConfiguration( boolean useFile, boolean printSummary, String reportFormat,
boolean redirectTestOutputToFile, boolean disableXmlReport,
@Nonnull File reportsDirectory, boolean trimStackTrace, String reportNameSuffix,
File statisticsFile, boolean requiresRunHistory,
int rerunFailingTestsCount, String xsdSchemaLocation, String encoding )
File statisticsFile, boolean requiresRunHistory, int rerunFailingTestsCount,
String xsdSchemaLocation, String encoding, boolean isForkMode )
{
this.useFile = useFile;
this.printSummary = printSummary;
Expand All @@ -109,6 +108,7 @@ public StartupReportConfiguration( boolean useFile, boolean printSummary, String
this.xsdSchemaLocation = xsdSchemaLocation;
String charset = trimToNull( encoding );
this.encoding = charset == null ? Charset.defaultCharset() : Charset.forName( charset );
this.isForkMode = isForkMode;
}

public boolean isUseFile()
Expand Down Expand Up @@ -151,39 +151,51 @@ public int getRerunFailingTestsCount()
return rerunFailingTestsCount;
}

public StatelessXmlReporter instantiateStatelessXmlReporter()
@Deprecated // rename to stateful
public StatelessXmlReporter instantiateStatelessXmlReporter( Integer forkNumber )
{
assert forkNumber == null || isForkMode;

// If forking TestNG the suites have same name 'TestSuite' and tend to override report statistics in stateful
// reporter, see Surefire1535TestNGParallelSuitesIT. The testClassMethodRunHistory should be isolated.
// In the in-plugin execution of parallel JUnit4.7 with rerun the map must be shared because reports and
// listeners are in ThreadLocal, see Surefire1122ParallelAndFlakyTestsIT.
Map<String, Map<String, List<WrappedReportEntry>>> testClassMethodRunHistory
= isForkMode
? new ConcurrentHashMap<String, Map<String, List<WrappedReportEntry>>>()
: this.testClassMethodRunHistory;

return isDisableXmlReport()
? null
: new StatelessXmlReporter( reportsDirectory, reportNameSuffix, trimStackTrace, rerunFailingTestsCount,
testClassMethodRunHistory, xsdSchemaLocation );
: new StatelessXmlReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, trimStackTrace,
rerunFailingTestsCount, testClassMethodRunHistory, xsdSchemaLocation );
}

public FileReporter instantiateFileReporter()
public FileReporter instantiateFileReporter( Integer forkNumber )
{
return isUseFile() && isBriefOrPlainFormat()
? new FileReporter( reportsDirectory, getReportNameSuffix(), encoding )
? new FileReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, encoding )
: null;
}

public boolean isBriefOrPlainFormat()
{
String fmt = getReportFormat();
return BRIEF_REPORT_FORMAT.equals( fmt ) || PLAIN_REPORT_FORMAT.equals( fmt );
return BRIEF.equals( fmt ) || PLAIN.equals( fmt );
}

public TestcycleConsoleOutputReceiver instantiateConsoleOutputFileReporter()
public TestcycleConsoleOutputReceiver instantiateConsoleOutputFileReporter( Integer forkNumber )
{
return isRedirectTestOutputToFile()
? new ConsoleOutputFileReporter( reportsDirectory, getReportNameSuffix() )
? new ConsoleOutputFileReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, forkNumber )
: new DirectConsoleOutput( originalSystemOut, originalSystemErr );
}

public synchronized StatisticsReporter getStatisticsReporter()
{
if ( statisticsReporter == null )
{
statisticsReporter = requiresRunHistory ? new StatisticsReporter( getStatisticsFile() ) : null;
statisticsReporter = requiresRunHistory ? new StatisticsReporter( statisticsFile ) : null;
}
return statisticsReporter;
}
Expand Down Expand Up @@ -217,4 +229,14 @@ public Charset getEncoding()
{
return encoding;
}

public boolean isForkMode()
{
return isForkMode;
}

private File resolveReportsDirectory( Integer forkNumber )
{
return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath( reportsDirectory, forkNumber );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.internal.DumpFileUtils;

import javax.annotation.Nonnull;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

import static java.util.Collections.unmodifiableList;
Expand All @@ -54,8 +58,14 @@ public final class SurefireHelper

public static final String DUMP_FILE_PREFIX = DUMP_FILE_DATE + "-jvmRun";

public static final String DUMP_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMP_FILE_EXT;

public static final String DUMPSTREAM_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMPSTREAM_FILE_EXT;

public static final String DUMPSTREAM_FILENAME = DUMP_FILE_DATE + DUMPSTREAM_FILE_EXT;

public static final String DUMP_FILENAME = DUMP_FILE_DATE + DUMP_FILE_EXT;

/**
* The maximum path that does not require long path prefix on Windows.<br>
* See {@code sun/nio/fs/WindowsPath} in
Expand All @@ -71,11 +81,25 @@ public final class SurefireHelper

private static final String[] DUMP_FILES_PRINT =
{
"[date]" + DUMP_FILE_EXT,
"[date]-jvmRun[N]" + DUMP_FILE_EXT,
"[date]" + DUMPSTREAM_FILE_EXT,
"[date]-jvmRun[N]" + DUMPSTREAM_FILE_EXT
};

/**
* The placeholder that is replaced by the executing thread's running number. The thread number
* range starts with 1
* Deprecated.
*/
private static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";

/**
* The placeholder that is replaced by the executing fork's running number. The fork number
* range starts with 1
*/
private static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}";

/**
* Do not instantiate.
*/
Expand All @@ -84,6 +108,31 @@ private SurefireHelper()
throw new IllegalAccessError( "Utility class" );
}

@Nonnull
public static String replaceThreadNumberPlaceholders( @Nonnull String argLine, int threadNumber )
{
String threadNumberAsString = String.valueOf( threadNumber );
return argLine.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberAsString )
.replace( FORK_NUMBER_PLACEHOLDER, threadNumberAsString );
}

public static File replaceForkThreadsInPath( File path, int replacement )
{
Deque<String> dirs = new LinkedList<String>();
File root = path;
while ( !root.exists() )
{
dirs.addFirst( replaceThreadNumberPlaceholders( root.getName(), replacement ) );
root = root.getParentFile();
}
File replacedPath = root;
for ( String dir : dirs )
{
replacedPath = new File( replacedPath, dir );
}
return replacedPath;
}

public static String[] getDumpFilesToPrint()
{
return DUMP_FILES_PRINT.clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.Collections;
import java.util.List;

import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CHILD_DELEGATION;
import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CLASSPATH;
import static org.apache.maven.surefire.booter.AbstractPathConfiguration.ENABLE_ASSERTIONS;
Expand Down Expand Up @@ -99,7 +100,7 @@ class BooterSerializer
*/
File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterConfiguration,
StartupConfiguration providerConfiguration, Object testSet, boolean readTestsFromInStream,
Long pid )
Long pid, int forkNumber )
throws IOException
{
SurefireProperties properties = new SurefireProperties( sourceProperties );
Expand Down Expand Up @@ -159,8 +160,9 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterCon

ReporterConfiguration reporterConfiguration = booterConfiguration.getReporterConfiguration();
boolean rep = reporterConfiguration.isTrimStackTrace();
File reportsDirectory = replaceForkThreadsInPath( reporterConfiguration.getReportsDirectory(), forkNumber );
properties.setProperty( ISTRIMSTACKTRACE, rep );
properties.setProperty( REPORTSDIRECTORY, reporterConfiguration.getReportsDirectory() );
properties.setProperty( REPORTSDIRECTORY, reportsDirectory );
ClassLoaderConfiguration classLoaderConfig = providerConfiguration.getClassLoaderConfiguration();
properties.setProperty( USESYSTEMCLASSLOADER, toString( classLoaderConfig.isUseSystemClassLoader() ) );
properties.setProperty( USEMANIFESTONLYJAR, toString( classLoaderConfig.isUseManifestOnlyJar() ) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
import java.util.Map.Entry;
import java.util.Properties;

import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.FORK_NUMBER_PLACEHOLDER;
import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER;
import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
import static org.apache.maven.plugin.surefire.util.Relocator.relocate;
import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders;
import static org.apache.maven.surefire.booter.Classpath.join;

/**
Expand Down Expand Up @@ -169,7 +169,7 @@ protected List<String> toCompleteClasspath( StartupConfiguration conf ) throws S
private File getWorkingDirectory( int forkNumber )
throws SurefireBooterForkException
{
File cwd = new File( replaceThreadNumberPlaceholder( getWorkingDirectory().getAbsolutePath(), forkNumber ) );
File cwd = replaceForkThreadsInPath( getWorkingDirectory(), forkNumber );

if ( !cwd.exists() && !cwd.mkdirs() )
{
Expand All @@ -184,14 +184,6 @@ private File getWorkingDirectory( int forkNumber )
return cwd;
}

@Nonnull
private static String replaceThreadNumberPlaceholder( @Nonnull String argLine, int threadNumber )
{
String threadNumberAsString = String.valueOf( threadNumber );
return argLine.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberAsString )
.replace( FORK_NUMBER_PLACEHOLDER, threadNumberAsString );
}

/**
* Replaces expressions <pre>@{property-name}</pre> with the corresponding properties
* from the model. This allows late evaluation of property values when the plugin is executed (as compared
Expand Down Expand Up @@ -331,7 +323,7 @@ protected Classpath getBooterClasspath()
private String newJvmArgLine( int forks )
{
String interpolatedArgs = stripNewLines( interpolateArgLineWithPropertyExpressions() );
String argsWithReplacedForkNumbers = replaceThreadNumberPlaceholder( interpolatedArgs, forks );
String argsWithReplacedForkNumbers = replaceThreadNumberPlaceholders( interpolatedArgs, forks );
return extendJvmArgLine( argsWithReplacedForkNumbers );
}

Expand Down
Loading

0 comments on commit be2be7e

Please sign in to comment.