Skip to content

Commits on Source 7

# Auto detect text files and perform LF normalization
* text=auto
* text eol=lf
*.xml text diff=xml
*.java text diff=java
*.html text diff=html
*.vm text
*.fml text
*.md text
*.css text
*.js text
*.sql text
......@@ -21,23 +21,28 @@
properties(
[
buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '0', daysToKeepStr: env.BRANCH_NAME == 'master' ? '30' : '7', numToKeepStr: '5')),
buildDiscarder(logRotator(artifactDaysToKeepStr: env.BRANCH_NAME == 'master' ? '30' : '7',
artifactNumToKeepStr: '10',
daysToKeepStr: env.BRANCH_NAME == 'master' ? '30' : '7',
numToKeepStr: '10')
),
disableConcurrentBuilds()
]
)
final def oses = ['linux', 'windows']
final def mavens = ['3.2.x', '3.3.x', '3.5.x']//env.BRANCH_NAME == 'master' ? ['3.2.x', '3.3.x', '3.5.x'] : ['3.5.x']
final def jdks = [7, 8, 9, 10]//env.BRANCH_NAME == 'master' ? [7, 8, 9, 10] : [9, 10]
final def oses = ['linux':'ubuntu', 'windows':'Windows && !windows-2012-3']
final def mavens = env.BRANCH_NAME == 'master' ? ['3.2.x', '3.3.x', '3.5.x'] : ['3.5.x']
final def jdks = [7, 8, 9, 10]
final def options = ['-e', '-V', '-B', '-nsu', '-P', 'run-its']
final def goals = ['clean', 'install', 'jacoco:report']
final Map stages = [:]
oses.eachWithIndex { os, indexOfOs ->
oses.eachWithIndex { osMapping, indexOfOs ->
mavens.eachWithIndex { maven, indexOfMaven ->
jdks.eachWithIndex { jdk, indexOfJdk ->
final String label = jenkinsEnv.labelForOS(os);
def os = osMapping.key
def label = osMapping.value
final String jdkTestName = jenkinsEnv.jdkFromVersion(os, jdk.toString())
final String jdkName = jenkinsEnv.jdkFromVersion(os, '8')
final String mvnName = jenkinsEnv.mvnFromVersion(os, maven)
......@@ -72,31 +77,35 @@ oses.eachWithIndex { os, indexOfOs ->
}
}
timeout(time: 10, unit: 'HOURS') {
timeout(time: 12, unit: 'HOURS') {
try {
parallel(stages)
// JENKINS-34376 seems to make it hard to detect the aborted builds
} catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
println "org.jenkinsci.plugins.workflow.steps.FlowInterruptedException: ${e}"
// this ambiguous condition means a user probably aborted
if (e.causes.size() == 0) {
currentBuild.result = "ABORTED"
currentBuild.result = 'ABORTED'
} else {
currentBuild.result = "FAILURE"
currentBuild.result = 'FAILURE'
}
throw e
} catch (hudson.AbortException e) {
println "hudson.AbortException: ${e}"
// this ambiguous condition means during a shell step, user probably aborted
if (e.getMessage().contains('script returned exit code 143')) {
currentBuild.result = "ABORTED"
currentBuild.result = 'ABORTED'
} else {
currentBuild.result = "FAILURE"
currentBuild.result = 'FAILURE'
}
throw e
} catch (InterruptedException e) {
currentBuild.result = "ABORTED"
println "InterruptedException: ${e}"
currentBuild.result = 'ABORTED'
throw e
} catch (Throwable e) {
currentBuild.result = "FAILURE"
println "Throwable: ${e}"
currentBuild.result = 'FAILURE'
throw e
} finally {
stage("notifications") {
......@@ -108,16 +117,15 @@ timeout(time: 10, unit: 'HOURS') {
def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvnName, goals, options, mavenOpts, boolean makeReports) {
cleanWs()
try {
def mvnLocalRepoDir = null
if (isUnix()) {
sh 'mkdir -p .m2'
mvnLocalRepoDir = "${pwd()}/.m2"
} else {
bat 'mkdir .m2'
mvnLocalRepoDir = "${pwd()}\\.m2"
}
def mvnLocalRepoDir = null
dir('.m2') {
mvnLocalRepoDir = "${pwd()}"
}
println "Maven Local Repository = ${mvnLocalRepoDir}."
assert mvnLocalRepoDir != null : 'Local Maven Repository is undefined.'
......@@ -174,14 +182,14 @@ def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvn
}
if (fileExists('maven-failsafe-plugin/target/it')) {
zip(zipFile: "it--maven-failsafe-plugin--${stageKey}.zip", dir: 'maven-failsafe-plugin/target/it', archive: true)
zip(zipFile: "maven-failsafe-plugin--${stageKey}.zip", dir: 'maven-failsafe-plugin/target/it', archive: true)
}
if (fileExists('surefire-its/target')) {
zip(zipFile: "it--surefire-its--${stageKey}.zip", dir: 'surefire-its/target', archive: true)
zip(zipFile: "surefire-its--${stageKey}.zip", dir: 'surefire-its/target', archive: true)
}
archiveArtifacts(artifacts: '*.zip', allowEmptyArchive: true, onlyIfSuccessful: false)
archiveArtifacts(artifacts: "*--${stageKey}.zip", allowEmptyArchive: true, onlyIfSuccessful: false)
}
stage("cleanup ${stageKey}") {
......
surefire (2.22.0-1) unstable; urgency=medium
* Team upload.
* New upstream release
- Refreshed the patches
- Ignore the new surefire-junit-platform plugin
-- Emmanuel Bourg <ebourg@apache.org> Sat, 06 Oct 2018 23:00:07 +0200
surefire (2.21.0-3) unstable; urgency=medium
* Team upload.
......
......@@ -38,6 +38,7 @@ surefire-providers/common-junit48/pom.xml --has-package-version
surefire-providers/surefire-junit3/pom.xml --has-package-version
surefire-providers/surefire-junit4/pom.xml --has-package-version
surefire-providers/surefire-junit47/pom.xml --has-package-version
surefire-providers/surefire-junit-platform/pom.xml --ignore
surefire-providers/surefire-testng/pom.xml --has-package-version
surefire-providers/surefire-testng-utils/pom.xml --has-package-version
surefire-report-parser/pom.xml --has-package-version
......
......@@ -5,7 +5,7 @@ Author: Emmanuel Bourg <ebourg@apache.org>
Forwarded: not-needed
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -1319,7 +1319,7 @@
@@ -1364,7 +1364,7 @@
return "org.apache.maven.surefire.testng.conf.TestNG60Configurator";
}
......@@ -14,7 +14,7 @@ Forwarded: not-needed
}
catch ( InvalidVersionSpecificationException invsex )
{
@@ -1987,13 +1987,6 @@
@@ -2032,13 +2032,6 @@
if ( artifact != null )
{
......
......@@ -3,8 +3,8 @@ Author: Emmanuel Bourg <ebourg@apache.org>
Forwarded: no
--- a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java
+++ b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportGenerator.java
@@ -27,7 +27,7 @@
import java.util.ResourceBundle;
@@ -26,7 +26,7 @@
import java.util.Map;
import org.apache.maven.doxia.markup.HtmlMarkup;
import org.apache.maven.doxia.sink.Sink;
-import org.apache.maven.doxia.sink.SinkEventAttributeSet;
......
......@@ -9,7 +9,7 @@ Forwarded: not-needed
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -1532,12 +1532,14 @@
@@ -1577,12 +1577,14 @@
private boolean isJunit47Compatible( Artifact artifact )
{
......@@ -25,4 +25,4 @@ Forwarded: not-needed
+ ( artifact != null && "4.x".equals( artifact.getVersion() ) ) );
}
static boolean isForkModeNever( String forkMode )
private static boolean isForkModeNever( String forkMode )
......@@ -3,7 +3,7 @@ Author: Emmanuel Bourg <ebourg@apache.org>
Bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8186647
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -2377,11 +2377,11 @@
@@ -2438,11 +2438,11 @@
* Generate the test classpath.
*
* @return List containing the classpath elements
......
......@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire</artifactId>
<version>2.21.0</version>
<version>2.22.0</version>
</parent>
<groupId>org.apache.maven.plugins</groupId>
......
......@@ -256,10 +256,11 @@ public class IntegrationTestMojo
private boolean useManifestOnlyJar;
/**
* The character encoding scheme to be applied.
* Deprecated since 2.20.1 and used encoding UTF-8 in <tt>failsafe-summary.xml</tt>.
* The character encoding scheme to be applied while generating test report
* files (see target/surefire-reports/yourTestName.txt).
* The report output files (*-out.txt) are still encoded with JVM's encoding used in standard out/err pipes.
*
* @deprecated since of 2.20.1
* @since 3.0.0-M1
*/
@Parameter( property = "encoding", defaultValue = "${project.reporting.outputEncoding}" )
private String encoding;
......@@ -703,6 +704,18 @@ public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
this.useManifestOnlyJar = useManifestOnlyJar;
}
@Override
public String getEncoding()
{
return encoding;
}
@Override
public void setEncoding( String encoding )
{
this.encoding = encoding;
}
// the following will be refactored out once the common code is all in one place
public boolean isTestFailureIgnore()
......
......@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire</artifactId>
<version>2.21.0</version>
<version>2.22.0</version>
</parent>
<artifactId>maven-surefire-common</artifactId>
......
......@@ -115,9 +115,11 @@
import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;
import static java.util.Collections.addAll;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
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.shared.utils.StringUtils.capitalizeFirstLetter;
import static org.apache.maven.shared.utils.StringUtils.isEmpty;
import static org.apache.maven.shared.utils.StringUtils.isNotBlank;
......@@ -485,6 +487,15 @@ public abstract class AbstractSurefireMojo
@Parameter( property = "junitArtifactName", defaultValue = "junit:junit" )
private String junitArtifactName;
/**
* Allows you to specify the name of the JUnit Platform artifact.
* If not set, {@code org.junit.platform:junit-platform-engine} will be used.
*
* @since 2.22.0
*/
@Parameter( property = "junitPlatformArtifactName", defaultValue = "org.junit.platform:junit-platform-engine" )
private String junitPlatformArtifactName;
/**
* Allows you to specify the name of the TestNG artifact. If not set, {@code org.testng:testng} will be used.
*
......@@ -731,8 +742,11 @@ public abstract class AbstractSurefireMojo
* List of dependencies to scan for test classes to include in the test run.
* The child elements of this element must be &lt;dependency&gt; elements, and the
* contents of each of these elements must be a string which follows the format:
*
* <br>
* <i>groupId:artifactId</i>. For example: <i>org.acme:project-a</i>.
* <br>
* Since version 2.22.0 you can scan for test classes from a project
* dependency of your multi-module project.
*
* @since 2.15
*/
......@@ -894,7 +908,13 @@ private DefaultScanResult scanDirectories()
return scanner.scan();
}
private DefaultScanResult scanDependencies()
@SuppressWarnings( "unchecked" )
List<Artifact> getProjectTestArtifacts()
{
return project.getTestArtifacts();
}
DefaultScanResult scanDependencies() throws MojoFailureException
{
if ( getDependenciesToScan() == null )
{
......@@ -904,16 +924,40 @@ private DefaultScanResult scanDependencies()
{
try
{
// @TODO noinspection unchecked, check MavenProject 3.x for Generics in surefire:3.0
@SuppressWarnings( "unchecked" )
List<File> dependenciesToScan =
DependencyScanner.filter( project.getTestArtifacts(), asList( getDependenciesToScan() ) );
DependencyScanner scanner = new DependencyScanner( dependenciesToScan, getIncludedAndExcludedTests() );
return scanner.scan();
DefaultScanResult result = null;
List<Artifact> dependenciesToScan =
filter( getProjectTestArtifacts(), asList( getDependenciesToScan() ) );
for ( Artifact artifact : dependenciesToScan )
{
String type = artifact.getType();
File out = artifact.getFile();
if ( out == null || !out.exists()
|| !( "jar".equals( type ) || out.isDirectory() || out.getName().endsWith( ".jar" ) ) )
{
continue;
}
if ( out.isFile() )
{
DependencyScanner scanner =
new DependencyScanner( singletonList( out ), getIncludedAndExcludedTests() );
result = result == null ? scanner.scan() : result.append( scanner.scan() );
}
else if ( out.isDirectory() )
{
DirectoryScanner scanner =
new DirectoryScanner( out, getIncludedAndExcludedTests() );
result = result == null ? scanner.scan() : result.append( scanner.scan() );
}
}
return result;
}
catch ( Exception e )
{
throw new RuntimeException( e );
throw new MojoFailureException( e.getLocalizedMessage(), e );
}
}
}
......@@ -1022,6 +1066,7 @@ protected List<ProviderInfo> createProviders()
Artifact junitDepArtifact = getJunitDepArtifact();
return new ProviderList( new DynamicProviderInfo( null ),
new TestNgProviderInfo( getTestNgArtifact() ),
new JUnitPlatformProviderInfo( getJunitPlatformArtifact() ),
new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
new JUnit3ProviderInfo() )
......@@ -1540,7 +1585,7 @@ private boolean isAnyJunit4( Artifact artifact )
return dependencyResolver.isWithinVersionSpec( artifact, "[4.0,)" );
}
static boolean isForkModeNever( String forkMode )
private static boolean isForkModeNever( String forkMode )
{
return FORK_NEVER.equals( forkMode );
}
......@@ -1807,7 +1852,7 @@ private StartupReportConfiguration getStartupReportConfiguration( String configC
isRedirectTestOutputToFile(), isDisableXmlReport(),
getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix(),
getStatisticsFile( configChecksum ), requiresRunHistory(),
getRerunFailingTestsCount(), getReportSchemaLocation() );
getRerunFailingTestsCount(), getReportSchemaLocation(), getEncoding() );
}
private boolean isSpecificTestSpecified()
......@@ -2033,6 +2078,21 @@ private Artifact getJunitDepArtifact()
return getProjectArtifactMap().get( "junit:junit-dep" );
}
private Artifact getJunitPlatformArtifact()
{
Artifact artifact = getProjectArtifactMap().get( getJunitPlatformArtifactName() );
Artifact projectArtifact = project.getArtifact();
String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId();
if ( artifact == null && projectArtifactName.equals( getJunitPlatformArtifactName() ) )
{
artifact = projectArtifact;
}
return artifact;
}
private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull ForkConfiguration forkConfiguration,
@Nonnull ClassLoaderConfiguration classLoaderConfiguration,
@Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log,
......@@ -2337,6 +2397,7 @@ private String getConfigChecksum()
checksum.add( isDisableXmlReport() );
checksum.add( isUseSystemClassLoader() );
checksum.add( isUseManifestOnlyJar() );
checksum.add( getEncoding() );
checksum.add( isEnableAssertions() );
checksum.add( getObjectFactory() );
checksum.add( getFailIfNoTests() );
......@@ -2659,7 +2720,8 @@ private void warnIfDefunctGroupsCombinations()
{
Artifact junitArtifact = getJunitArtifact();
boolean junit47Compatible = isJunit47Compatible( junitArtifact );
if ( !junit47Compatible )
boolean junit5PlatformCompatible = getJunitPlatformArtifact() != null;
if ( !junit47Compatible && !junit5PlatformCompatible )
{
if ( junitArtifact != null )
{
......@@ -2668,8 +2730,8 @@ private void warnIfDefunctGroupsCombinations()
+ "Check your dependency:tree to see if your project "
+ "is picking up an old junit version" );
}
throw new MojoFailureException( "groups/excludedGroups require TestNG or JUnit48+ on project test "
+ "classpath" );
throw new MojoFailureException( "groups/excludedGroups require TestNG, JUnit48+ or JUnit 5 "
+ "on project test classpath" );
}
}
......@@ -2872,6 +2934,40 @@ public Classpath getProviderClasspath()
}
final class JUnitPlatformProviderInfo
implements ProviderInfo
{
private final Artifact junitArtifact;
JUnitPlatformProviderInfo( Artifact junitArtifact )
{
this.junitArtifact = junitArtifact;
}
@Nonnull public String getProviderName()
{
return "org.apache.maven.surefire.junitplatform.JUnitPlatformProvider";
}
public boolean isApplicable()
{
return junitArtifact != null;
}
public void addProviderProperties() throws MojoExecutionException
{
convertGroupParameters();
}
public Classpath getProviderClasspath()
throws ArtifactResolutionException, ArtifactNotFoundException
{
return dependencyResolver.getProviderClasspath( "surefire-junit-platform",
surefireBooterArtifact.getBaseVersion(),
null );
}
}
final class JUnitCoreProviderInfo
implements ProviderInfo
{
......@@ -3328,6 +3424,17 @@ public void setJunitArtifactName( String junitArtifactName )
this.junitArtifactName = junitArtifactName;
}
public String getJunitPlatformArtifactName()
{
return junitPlatformArtifactName;
}
@SuppressWarnings( "UnusedDeclaration" )
public void setJunitPlatformArtifactName( String junitPlatformArtifactName )
{
this.junitPlatformArtifactName = junitPlatformArtifactName;
}
public String getTestNGArtifactName()
{
return testNGArtifactName;
......
......@@ -72,14 +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 );
int.class, String.class, String.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.getRerunFailingTestsCount(), reporterConfiguration.getXsdSchemaLocation(),
reporterConfiguration.getEncoding().name() };
return newInstance( constructor, params );
}
......
......@@ -30,12 +30,14 @@
import javax.annotation.Nonnull;
import java.io.File;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
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;
/**
* All the parameters used to construct reporters
......@@ -80,6 +82,8 @@ public final class StartupReportConfiguration
private final Map<String, Map<String, List<WrappedReportEntry>>> testClassMethodRunHistory
= new ConcurrentHashMap<String, Map<String, List<WrappedReportEntry>>>();
private final Charset encoding;
private StatisticsReporter statisticsReporter;
@SuppressWarnings( "checkstyle:parameternumber" )
......@@ -87,7 +91,7 @@ public StartupReportConfiguration( boolean useFile, boolean printSummary, String
boolean redirectTestOutputToFile, boolean disableXmlReport,
@Nonnull File reportsDirectory, boolean trimStackTrace, String reportNameSuffix,
File statisticsFile, boolean requiresRunHistory,
int rerunFailingTestsCount, String xsdSchemaLocation )
int rerunFailingTestsCount, String xsdSchemaLocation, String encoding )
{
this.useFile = useFile;
this.printSummary = printSummary;
......@@ -103,32 +107,8 @@ public StartupReportConfiguration( boolean useFile, boolean printSummary, String
this.originalSystemErr = System.err;
this.rerunFailingTestsCount = rerunFailingTestsCount;
this.xsdSchemaLocation = xsdSchemaLocation;
}
/**
* For testing purposes only.
*
* @return StartupReportConfiguration fo testing purposes
*/
public static StartupReportConfiguration defaultValue()
{
File target = new File( "./target" );
File statisticsFile = new File( target, "TESTHASH" );
return new StartupReportConfiguration( true, true, "PLAIN", false, false, target, false, null, statisticsFile,
false, 0, null );
}
/**
* For testing purposes only.
*
* @return StartupReportConfiguration fo testing purposes
*/
public static StartupReportConfiguration defaultNoXml()
{
File target = new File( "./target" );
File statisticsFile = new File( target, "TESTHASHxXML" );
return new StartupReportConfiguration( true, true, "PLAIN", false, true, target, false, null, statisticsFile,
false, 0, null );
String charset = trimToNull( encoding );
this.encoding = charset == null ? Charset.defaultCharset() : Charset.forName( charset );
}
public boolean isUseFile()
......@@ -182,7 +162,7 @@ public StatelessXmlReporter instantiateStatelessXmlReporter()
public FileReporter instantiateFileReporter()
{
return isUseFile() && isBriefOrPlainFormat()
? new FileReporter( reportsDirectory, getReportNameSuffix() )
? new FileReporter( reportsDirectory, getReportNameSuffix(), encoding )
: null;
}
......@@ -232,4 +212,9 @@ public String getXsdSchemaLocation()
{
return xsdSchemaLocation;
}
public Charset getEncoding()
{
return encoding;
}
}
......@@ -118,6 +118,10 @@ public interface SurefireExecutionParameters
void setUseManifestOnlyJar( boolean useManifestOnlyJar );
String getEncoding();
void setEncoding( String encoding );
Boolean getFailIfNoSpecifiedTests();
void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests );
......
......@@ -37,7 +37,7 @@ abstract class AbstractClasspathForkConfiguration
{
@SuppressWarnings( "checkstyle:parameternumber" )
public AbstractClasspathForkConfiguration( @Nonnull Classpath bootClasspath,
AbstractClasspathForkConfiguration( @Nonnull Classpath bootClasspath,
@Nonnull File tempDirectory,
@Nullable String debugLine,
@Nonnull File workingDirectory,
......
......@@ -162,7 +162,7 @@ private final class CloseableCloser
private final Thread inputStreamCloserHook;
public CloseableCloser( int jvmRun, Closeable... testProvidingInputStream )
CloseableCloser( int jvmRun, Closeable... testProvidingInputStream )
{
this.jvmRun = jvmRun;
this.testProvidingInputStream = new ConcurrentLinkedQueue<Closeable>();
......
......@@ -22,17 +22,18 @@
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.maven.surefire.booter.DumpErrorSingleton;
import org.apache.maven.surefire.report.ReportEntry;
import static org.apache.maven.plugin.surefire.report.FileReporter.getReportFile;
/**
* Surefire output consumer proxy that writes test output to a {@link java.io.File} for each test suite.
* <br>
* This class is not threadsafe, but can be serially handed off from thread to thread.
*
* @author Kristian Rosenvold
* @author Carlos Sanchez
......@@ -40,13 +41,20 @@
public class ConsoleOutputFileReporter
implements TestcycleConsoleOutputReceiver
{
private final File reportsDirectory;
private static final int STREAM_BUFFER_SIZE = 16 * 1024;
private static final int OPEN = 0;
private static final int CLOSED_TO_REOPEN = 1;
private static final int CLOSED = 2;
private final File reportsDirectory;
private final String reportNameSuffix;
private String reportEntryName;
private final AtomicStampedReference<FilterOutputStream> fileOutputStream =
new AtomicStampedReference<FilterOutputStream>( null, OPEN );
private OutputStream fileOutputStream;
private final ReentrantLock lock = new ReentrantLock();
private volatile String reportEntryName;
public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix )
{
......@@ -57,8 +65,15 @@ public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix
@Override
public void testSetStarting( ReportEntry reportEntry )
{
close();
reportEntryName = reportEntry.getName();
lock.lock();
try
{
closeNullReportFile( reportEntry );
}
finally
{
lock.unlock();
}
}
@Override
......@@ -67,39 +82,33 @@ public void testSetCompleted( ReportEntry report )
}
@Override
@SuppressWarnings( "checkstyle:emptyblock" )
public void close()
{
if ( fileOutputStream != null )
{
//noinspection EmptyCatchBlock
// The close() method is called in main Thread T2.
lock.lock();
try
{
fileOutputStream.flush();
}
catch ( IOException e )
{
closeReportFile();
}
finally
{
try
{
fileOutputStream.close();
}
catch ( IOException ignored )
{
}
}
fileOutputStream = null;
lock.unlock();
}
}
@Override
public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
{
lock.lock();
try
{
if ( fileOutputStream == null )
// This method is called in single thread T1 per fork JVM (see ThreadedStreamConsumer).
// The close() method is called in main Thread T2.
int[] status = new int[1];
FilterOutputStream os = fileOutputStream.get( status );
if ( status[0] != CLOSED )
{
if ( os == null )
{
if ( !reportsDirectory.exists() )
{
......@@ -107,13 +116,71 @@ public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
reportsDirectory.mkdirs();
}
File file = getReportFile( reportsDirectory, reportEntryName, reportNameSuffix, "-output.txt" );
fileOutputStream = new BufferedOutputStream( new FileOutputStream( file ), 16 * 1024 );
os = new BufferedOutputStream( new FileOutputStream( file ), STREAM_BUFFER_SIZE );
fileOutputStream.set( os, OPEN );
}
os.write( buf, off, len );
}
fileOutputStream.write( buf, off, len );
}
catch ( IOException e )
{
DumpErrorSingleton.getSingleton()
.dumpException( e );
throw new RuntimeException( e );
}
finally
{
lock.unlock();
}
}
@SuppressWarnings( "checkstyle:emptyblock" )
private void closeNullReportFile( ReportEntry reportEntry )
{
try
{
// close null-output.txt report file
close( true );
}
catch ( IOException ignored )
{
DumpErrorSingleton.getSingleton()
.dumpException( ignored );
}
finally
{
// prepare <class>-output.txt report file
reportEntryName = reportEntry.getName();
}
}
@SuppressWarnings( "checkstyle:emptyblock" )
private void closeReportFile()
{
try
{
close( false );
}
catch ( IOException ignored )
{
DumpErrorSingleton.getSingleton()
.dumpException( ignored );
}
}
private void close( boolean closeReattempt )
throws IOException
{
int[] status = new int[1];
FilterOutputStream os = fileOutputStream.get( status );
if ( status[0] != CLOSED )
{
fileOutputStream.set( null, closeReattempt ? CLOSED_TO_REOPEN : CLOSED );
if ( os != null && status[0] == OPEN )
{
os.close();
}
}
}
}
......@@ -22,7 +22,6 @@
import org.apache.maven.plugin.surefire.StartupReportConfiguration;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugin.surefire.log.api.Level;
import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
import org.apache.maven.shared.utils.logging.MessageBuilder;
import org.apache.maven.surefire.report.ReporterFactory;
......@@ -207,16 +206,6 @@ public RunStatistics getGlobalRunStatistics()
return globalStats;
}
/**
* For testing purposes only.
*
* @return DefaultReporterFactory for testing purposes
*/
public static DefaultReporterFactory defaultNoXml()
{
return new DefaultReporterFactory( StartupReportConfiguration.defaultNoXml(), new NullConsoleLogger() );
}
/**
* Get the result of a test based on all its runs. If it has success and failures/errors, then it is a flake;
* if it only has errors or failures, then count its result based on its first run
......@@ -258,14 +247,7 @@ else if ( resultType == ERROR )
}
else
{
if ( seenError )
{
return error;
}
else
{
return failure;
}
return seenError ? error : failure;
}
}
else if ( seenSuccess )
......
......@@ -24,9 +24,12 @@
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.List;
import static org.apache.maven.plugin.surefire.report.FileReporterUtils.stripIllegalFilenameChars;
......@@ -41,13 +44,14 @@
public class FileReporter
{
private final File reportsDirectory;
private final String reportNameSuffix;
private final Charset encoding;
public FileReporter( File reportsDirectory, String reportNameSuffix )
public FileReporter( File reportsDirectory, String reportNameSuffix, Charset encoding )
{
this.reportsDirectory = reportsDirectory;
this.reportNameSuffix = reportNameSuffix;
this.encoding = encoding;
}
private PrintWriter testSetStarting( ReportEntry report )
......@@ -61,7 +65,9 @@ private PrintWriter testSetStarting( ReportEntry report )
try
{
PrintWriter writer = new PrintWriter( new BufferedWriter( new FileWriter( reportFile ), 16 * 1024 ) );
Writer encodedStream = new OutputStreamWriter( new FileOutputStream( reportFile ), encoding );
PrintWriter writer = new PrintWriter( new BufferedWriter( encodedStream, 16 * 1024 ) );
writer.println( "-------------------------------------------------------------------------------" );
......@@ -77,7 +83,7 @@ private PrintWriter testSetStarting( ReportEntry report )
}
}
public static File getReportFile( File reportsDirectory, String reportEntryName, String reportNameSuffix,
static File getReportFile( File reportsDirectory, String reportEntryName, String reportNameSuffix,
String fileExtension )
{
String fileName =
......