You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2015/09/06 22:58:32 UTC
[01/17] maven-surefire git commit: [SUREFIRE] added missing interface
MainCliOptionsAware
Repository: maven-surefire
Updated Branches:
refs/heads/master e89a0ae2d -> 86b253ba4
[SUREFIRE] added missing interface MainCliOptionsAware
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/668b1b92
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/668b1b92
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/668b1b92
Branch: refs/heads/master
Commit: 668b1b927de52dab37e36762cb8c718474eda3f1
Parents: e89a0ae
Author: Tibor17 <ti...@lycos.com>
Authored: Fri Jul 24 23:22:35 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:53 2015 +0200
----------------------------------------------------------------------
.../surefire/booter/BaseProviderFactory.java | 2 +-
.../surefire/booter/MainCliOptionsAware.java | 35 ++++++++++++++++++++
.../surefire/booter/SurefireReflector.java | 13 ++++++++
.../maven/surefire/booter/ProviderFactory.java | 1 +
4 files changed, 50 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/668b1b92/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
index a3ba5db..980f6d9 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
@@ -45,7 +45,7 @@ import java.util.Map;
*/
public class BaseProviderFactory
implements DirectoryScannerParametersAware, ReporterConfigurationAware, SurefireClassLoadersAware, TestRequestAware,
- ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware
+ ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware, MainCliOptionsAware
{
private static final int ROOT_CHANNEL = 0;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/668b1b92/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
new file mode 100644
index 0000000..b3b3c9d
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
@@ -0,0 +1,35 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.surefire.cli.CommandLineOption;
+
+import java.util.List;
+
+/**
+ * CLI options in plugin (main) JVM process.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public interface MainCliOptionsAware
+{
+ void setMainCliOptions( List<CommandLineOption> mainCliOptions );
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/668b1b92/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
index 912babe..0e53a8f 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
@@ -26,6 +26,8 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
+
+import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.providerapi.ProviderParameters;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.report.ReporterFactory;
@@ -80,6 +82,8 @@ public class SurefireReflector
private final Class<?> testListResolver;
+ private final Class<?> mainCliOptions;
+
public SurefireReflector( ClassLoader surefireClassLoader )
{
@@ -102,6 +106,7 @@ public class SurefireReflector
runResult = surefireClassLoader.loadClass( RunResult.class.getName() );
booterParameters = surefireClassLoader.loadClass( ProviderParameters.class.getName() );
testListResolver = surefireClassLoader.loadClass( TestListResolver.class.getName() );
+ mainCliOptions = surefireClassLoader.loadClass( MainCliOptionsAware.class.getName() );
}
catch ( ClassNotFoundException e )
{
@@ -263,6 +268,14 @@ public class SurefireReflector
}
}
+ public void setMainCliOptions( Object o, List<CommandLineOption> options )
+ {
+ if ( mainCliOptions.isAssignableFrom( o.getClass() ) )
+ {
+ ReflectionUtils.invokeSetter( o, "setMainCliOptions", List.class, options );
+ }
+ }
+
public void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams )
{
final Object param = createDirectoryScannerParameters( dirScannerParams );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/668b1b92/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
index d529980..c5d93ab 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
@@ -100,6 +100,7 @@ public class ProviderFactory
surefireReflector.setTestArtifactInfoAware( o, providerConfiguration.getTestArtifact() );
surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
+ surefireReflector.setMainCliOptions( o, providerConfiguration.getMainCliOptions() );
Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
currentThread.setContextClassLoader( systemClassLoader );
[07/17] maven-surefire git commit: [SUREFIRE-580] Allow "fail fast"
or stop running on first failure
Posted by ti...@apache.org.
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
index 77f41be..d481bb2 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
@@ -23,6 +23,8 @@ import org.apache.maven.surefire.booter.ProviderParameterNames;
import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.testng.conf.Configurator;
+import org.apache.maven.surefire.testng.utils.FailFastListener;
+import org.apache.maven.surefire.testng.utils.Stoppable;
import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.ReflectionUtils;
@@ -44,6 +46,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static org.apache.maven.surefire.util.ReflectionUtils.instantiate;
+
/**
* Contains utility methods for executing TestNG.
*
@@ -69,7 +73,7 @@ public class TestNGExecutor
public static void run( Class<?>[] testClasses, String testSourceDirectory,
Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
RunListener reportManager, TestNgTestSuite suite, File reportsDirectory,
- TestListResolver methodFilter, List<CommandLineOption> mainCliOptions )
+ TestListResolver methodFilter, List<CommandLineOption> mainCliOptions, boolean isFailFast )
throws TestSetFailedException
{
TestNG testng = new TestNG( true );
@@ -119,7 +123,7 @@ public class TestNGExecutor
testng.setXmlSuites( xmlSuites );
configurator.configure( testng, options );
- postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
+ postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast );
testng.run();
}
@@ -260,13 +264,14 @@ public class TestNGExecutor
public static void run( List<String> suiteFiles, String testSourceDirectory,
Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
- RunListener reportManager, TestNgTestSuite suite, File reportsDirectory )
+ RunListener reportManager, TestNgTestSuite suite, File reportsDirectory,
+ boolean isFailFast )
throws TestSetFailedException
{
TestNG testng = new TestNG( true );
Configurator configurator = getConfigurator( options.get( "testng.configurator" ) );
configurator.configure( testng, options );
- postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
+ postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast );
testng.setTestSuites( suiteFiles );
testng.run();
}
@@ -291,8 +296,8 @@ public class TestNGExecutor
}
}
- private static void postConfigure( TestNG testNG, String sourcePath, RunListener reportManager,
- TestNgTestSuite suite, File reportsDirectory )
+ private static void postConfigure( TestNG testNG, String sourcePath, final RunListener reportManager,
+ TestNgTestSuite suite, File reportsDirectory, boolean skipAfterFailure )
throws TestSetFailedException
{
// turn off all TestNG output
@@ -301,7 +306,22 @@ public class TestNGExecutor
TestNGReporter reporter = createTestNGReporter( reportManager, suite );
testNG.addListener( (Object) reporter );
- // FIXME: use classifier to decide if we need to pass along the source dir (onyl for JDK14)
+ if ( skipAfterFailure )
+ {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ testNG.addListener( instantiate( cl, "org.apache.maven.surefire.testng.utils.FailFastNotifier",
+ Object.class ) );
+ Stoppable stoppable = new Stoppable()
+ {
+ public void pleaseStop()
+ {
+ reportManager.testExecutionSkippedByUser();
+ }
+ };
+ testNG.addListener( new FailFastListener( stoppable ) );
+ }
+
+ // FIXME: use classifier to decide if we need to pass along the source dir (only for JDK14)
if ( sourcePath != null )
{
testNG.setSourcePath( sourcePath );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
index d28d6ac..8777ceb 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
@@ -24,12 +24,16 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.MasterProcessListener;
+import org.apache.maven.surefire.booter.MasterProcessReader;
import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.providerapi.AbstractProvider;
import org.apache.maven.surefire.providerapi.ProviderParameters;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.report.ReporterFactory;
import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton;
import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.testset.TestSetFailedException;
@@ -37,6 +41,8 @@ import org.apache.maven.surefire.util.RunOrderCalculator;
import org.apache.maven.surefire.util.ScanResult;
import org.apache.maven.surefire.util.TestsToRun;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.SKIP_SINCE_NEXT_TEST;
+
/**
* @author Kristian Rosenvold
* @noinspection UnusedDeclaration
@@ -58,12 +64,16 @@ public class TestNGProvider
private final RunOrderCalculator runOrderCalculator;
- private List<CommandLineOption> mainCliOptions;
+ private final List<CommandLineOption> mainCliOptions;
+
+ private final MasterProcessReader commandsReader;
private TestsToRun testsToRun;
public TestNGProvider( ProviderParameters booterParameters )
{
+ // don't start a thread in MasterProcessReader while we are in in-plugin process
+ commandsReader = booterParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
providerParameters = booterParameters;
testClassLoader = booterParameters.getTestClassLoader();
runOrderCalculator = booterParameters.getRunOrderCalculator();
@@ -77,44 +87,55 @@ public class TestNGProvider
public RunResult invoke( Object forkTestSet )
throws TestSetFailedException
{
-
- final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
-
- if ( isTestNGXmlTestSuite( testRequest ) )
+ try
{
- TestNGXmlTestSuite testNGXmlTestSuite = getXmlSuite();
- testNGXmlTestSuite.locateTestSets( testClassLoader );
- if ( forkTestSet != null && testRequest == null )
+ if ( isFailFast() && commandsReader != null )
{
- testNGXmlTestSuite.execute( (String) forkTestSet, reporterFactory );
+ registerPleaseStopListener();
}
- else
- {
- testNGXmlTestSuite.execute( reporterFactory );
- }
- }
- else
- {
- if ( testsToRun == null )
+
+ final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
+
+ if ( isTestNGXmlTestSuite( testRequest ) )
{
- if ( forkTestSet instanceof TestsToRun )
+ TestNGXmlTestSuite testNGXmlTestSuite = newXmlSuite();
+ testNGXmlTestSuite.locateTestSets( testClassLoader );
+ if ( forkTestSet != null && testRequest == null )
{
- testsToRun = (TestsToRun) forkTestSet;
+ testNGXmlTestSuite.execute( (String) forkTestSet, reporterFactory );
}
- else if ( forkTestSet instanceof Class )
+ else
{
- testsToRun = TestsToRun.fromClass( (Class) forkTestSet );
+ testNGXmlTestSuite.execute( reporterFactory );
}
- else
+ }
+ else
+ {
+ if ( testsToRun == null )
{
- testsToRun = scanClassPath();
+ if ( forkTestSet instanceof TestsToRun )
+ {
+ testsToRun = (TestsToRun) forkTestSet;
+ }
+ else if ( forkTestSet instanceof Class )
+ {
+ testsToRun = TestsToRun.fromClass( (Class) forkTestSet );
+ }
+ else
+ {
+ testsToRun = scanClassPath();
+ }
}
+ TestNGDirectoryTestSuite suite = newDirectorySuite();
+ suite.execute( testsToRun, reporterFactory );
}
- TestNGDirectoryTestSuite suite = getDirectorySuite();
- suite.execute( testsToRun, reporterFactory );
- }
- return reporterFactory.close();
+ return reporterFactory.close();
+ }
+ finally
+ {
+ closeCommandsReader();
+ }
}
boolean isTestNGXmlTestSuite( TestRequest testSuiteDefinition )
@@ -123,18 +144,45 @@ public class TestNGProvider
return suiteXmlFiles != null && !suiteXmlFiles.isEmpty() && !hasSpecificTests();
}
- private TestNGDirectoryTestSuite getDirectorySuite()
+ private boolean isFailFast()
+ {
+ return providerParameters.getSkipAfterFailureCount() > 0;
+ }
+
+ private void closeCommandsReader()
+ {
+ if ( commandsReader != null )
+ {
+ commandsReader.stop();
+ }
+ }
+
+ private MasterProcessListener registerPleaseStopListener()
+ {
+ MasterProcessListener listener = new MasterProcessListener()
+ {
+ public void update( Command command )
+ {
+ FailFastEventsSingleton.getInstance().setSkipOnNextTest();
+ }
+ };
+ commandsReader.addListener( SKIP_SINCE_NEXT_TEST, listener );
+ return listener;
+ }
+
+ private TestNGDirectoryTestSuite newDirectorySuite()
{
return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties,
reporterConfiguration.getReportsDirectory(), createMethodFilter(),
- runOrderCalculator, scanResult, mainCliOptions );
+ runOrderCalculator, scanResult, mainCliOptions, isFailFast() );
}
- private TestNGXmlTestSuite getXmlSuite()
+ private TestNGXmlTestSuite newXmlSuite()
{
- return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(), testRequest.getTestSourceDirectory().toString(),
+ return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(),
+ testRequest.getTestSourceDirectory().toString(),
providerProperties,
- reporterConfiguration.getReportsDirectory() );
+ reporterConfiguration.getReportsDirectory(), isFailFast() );
}
@SuppressWarnings( "unchecked" )
@@ -144,7 +192,7 @@ public class TestNGProvider
{
try
{
- return getXmlSuite().locateTestSets( testClassLoader ).keySet();
+ return newXmlSuite().locateTestSets( testClassLoader ).keySet();
}
catch ( TestSetFailedException e )
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
index 552e482..bf105fe 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
@@ -49,6 +49,8 @@ public class TestNGXmlTestSuite
private final File reportsDirectory;
+ private final boolean isFailFast;
+
// Not really used
private Map<File, String> testSets;
@@ -57,15 +59,13 @@ public class TestNGXmlTestSuite
* xml file(s). The XML files are suite definitions files according to TestNG DTD.
*/
public TestNGXmlTestSuite( List<File> suiteFiles, String testSourceDirectory, Map<String, String> confOptions,
- File reportsDirectory )
+ File reportsDirectory, boolean isFailFast )
{
this.suiteFiles = suiteFiles;
-
this.options = confOptions;
-
this.testSourceDirectory = testSourceDirectory;
-
this.reportsDirectory = reportsDirectory;
+ this.isFailFast = isFailFast;
}
public void execute( ReporterFactory reporterManagerFactory )
@@ -80,8 +80,8 @@ public class TestNGXmlTestSuite
ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
TestNGDirectoryTestSuite.startTestSuite( reporter, this );
- TestNGExecutor.run( this.suiteFilePaths, this.testSourceDirectory, this.options, reporter, this,
- reportsDirectory );
+ TestNGExecutor.run( suiteFilePaths, testSourceDirectory, options, reporter, this, reportsDirectory,
+ isFailFast );
TestNGDirectoryTestSuite.finishTestSuite( reporter, this );
}
[08/17] maven-surefire git commit: [SUREFIRE-580] Allow "fail fast"
or stop running on first failure
Posted by ti...@apache.org.
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
index 276f3d4..b54f56c 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
@@ -31,6 +31,10 @@ import org.junit.runner.notification.Failure;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.getAnnotatedIgnoreValue;
+import static org.apache.maven.surefire.report.SimpleReportEntry.ignored;
+import static org.apache.maven.surefire.report.SimpleReportEntry.withException;
+
/**
* RunListener for JUnit4, delegates to our own RunListener
*
@@ -72,10 +76,8 @@ public class JUnit4RunListener
public void testIgnored( Description description )
throws Exception
{
- final String reason = JUnit4Reflector.getAnnotatedIgnoreValue( description );
- final SimpleReportEntry report =
- SimpleReportEntry.ignored( getClassName( description ), description.getDisplayName(), reason );
- reporter.testSkipped( report );
+ String reason = getAnnotatedIgnoreValue( description );
+ reporter.testSkipped( ignored( getClassName( description ), description.getDisplayName(), reason ) );
}
/**
@@ -104,33 +106,29 @@ public class JUnit4RunListener
{
testHeader = "Failure when constructing test";
}
- ReportEntry report = SimpleReportEntry.withException( getClassName( failure.getDescription() ), testHeader,
- createStackTraceWriter( failure ) );
+
+ ReportEntry report =
+ withException( getClassName( failure.getDescription() ), testHeader, createStackTraceWriter( failure ) );
if ( failure.getException() instanceof AssertionError )
{
- this.reporter.testFailed( report );
+ reporter.testFailed( report );
}
else
{
- this.reporter.testError( report );
+ reporter.testError( report );
}
- failureFlag.set( true );
- }
- protected StackTraceWriter createStackTraceWriter( Failure failure )
- {
- return new JUnit4StackTraceWriter( failure );
+ failureFlag.set( true );
}
@SuppressWarnings( { "UnusedDeclaration" } )
public void testAssumptionFailure( Failure failure )
{
- this.reporter.testAssumptionFailure( createReportEntry( failure.getDescription() ) );
+ reporter.testAssumptionFailure( createReportEntry( failure.getDescription() ) );
failureFlag.set( true );
}
-
/**
* Called after a specific test has finished.
*
@@ -146,12 +144,15 @@ public class JUnit4RunListener
}
}
- protected SimpleReportEntry createReportEntry( Description description )
+ /**
+ * Delegates to {@link RunListener#testExecutionSkippedByUser()}.
+ */
+ public void testExecutionSkippedByUser()
{
- return new SimpleReportEntry( getClassName( description ), description.getDisplayName() );
+ reporter.testExecutionSkippedByUser();
}
- public String getClassName( Description description )
+ private static String getClassName( Description description )
{
String name = extractClassName( description );
if ( name == null || isInsaneJunitNullString( name ) )
@@ -170,34 +171,30 @@ public class JUnit4RunListener
return name;
}
- private boolean isInsaneJunitNullString( String value )
+ protected StackTraceWriter createStackTraceWriter( Failure failure )
{
- return "null".equals( value );
+ return new JUnit4StackTraceWriter( failure );
+ }
+
+ protected SimpleReportEntry createReportEntry( Description description )
+ {
+ return new SimpleReportEntry( getClassName( description ), description.getDisplayName() );
}
public static String extractClassName( Description description )
{
String displayName = description.getDisplayName();
Matcher m = PARENS.matcher( displayName );
- if ( !m.find() )
- {
- return displayName;
- }
- return m.group( 1 );
+ return m.find() ? m.group( 1 ) : displayName;
}
public static String extractMethodName( Description description )
{
String displayName = description.getDisplayName();
int i = displayName.indexOf( "(" );
- if ( i >= 0 )
- {
- return displayName.substring( 0, i );
- }
- return displayName;
+ return i >= 0 ? displayName.substring( 0, i ) : displayName;
}
-
public static void rethrowAnyTestMechanismFailures( Result run )
throws TestSetFailedException
{
@@ -214,4 +211,9 @@ public class JUnit4RunListener
}
}
}
+
+ private static boolean isInsaneJunitNullString( String value )
+ {
+ return "null".equals( value );
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
new file mode 100644
index 0000000..e9136e1
--- /dev/null
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
@@ -0,0 +1,106 @@
+package org.apache.maven.surefire.common.junit4;
+
+/*
+ * 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.
+ */
+
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Extends {@link RunNotifier JUnit notifier},
+ * encapsulates several different types of {@link RunListener JUnit listeners}, and
+ * fires events to listeners.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class Notifier
+ extends RunNotifier
+{
+ private final Collection<RunListener> listeners = new ArrayList<RunListener>();
+
+ private JUnit4RunListener reporter;
+
+ @Override
+ public void pleaseStop()
+ {
+ super.pleaseStop();
+ reporter.testExecutionSkippedByUser();
+ }
+
+ /**
+ * Adds reporter listener to the bottom of queue and retrieves old reporter if any exists.
+ *
+ * @param reporter registered listener
+ * @return old listener; or null if did not exist
+ */
+ public JUnit4RunListener setReporter( JUnit4RunListener reporter )
+ {
+ JUnit4RunListener old = this.reporter;
+ this.reporter = reporter;
+ addListener( reporter );
+ return old;
+ }
+
+ @Override
+ public void addListener( RunListener listener )
+ {
+ listeners.add( listener );
+ super.addListener( listener );
+ }
+
+ public Notifier addListeners( Collection<RunListener> given )
+ {
+ for ( RunListener listener : given )
+ {
+ addListener( listener );
+ }
+ return this;
+ }
+
+ public Notifier addListeners( RunListener... given )
+ {
+ for ( RunListener listener : given )
+ {
+ addListener( listener );
+ }
+ return this;
+ }
+
+ @Override
+ public void removeListener( RunListener listener )
+ {
+ listeners.remove( listener );
+ super.removeListener( listener );
+ }
+
+ public void removeListeners()
+ {
+ for ( Iterator<RunListener> it = listeners.iterator(); it.hasNext(); )
+ {
+ RunListener listener = it.next();
+ it.remove();
+ super.removeListener( listener );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java
index 04484e0..99d7aae 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java
@@ -26,7 +26,7 @@ import org.apache.maven.surefire.report.ReportEntry;
import org.apache.maven.surefire.report.RunListener;
/**
- * Internal use only
+ * Internal tests use only.
*/
public class MockReporter
implements RunListener
@@ -83,6 +83,15 @@ public class MockReporter
testIgnored.incrementAndGet();
}
+ public void testExecutionSkippedByUser()
+ {
+ }
+
+ public void testSkippedByUser( ReportEntry report )
+ {
+ testSkipped( report );
+ }
+
public int getTestSucceeded()
{
return testSucceeded.get();
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
index 28b5fed..df4819c 100644
--- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
+++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
@@ -47,6 +47,34 @@ public class JUnit4Reflector40Test
{
}
}
+
+ public void testCreateIgnored()
+ {
+ Ignore ignore = JUnit4Reflector.createIgnored( "error" );
+ assertNotNull( ignore );
+ assertNotNull( ignore.value() );
+ assertEquals( "error", ignore.value() );
+ }
+
+ public void testCreateDescription()
+ {
+ Ignore ignore = JUnit4Reflector.createIgnored( "error" );
+ Description description = JUnit4Reflector.createDescription( "exception", ignore );
+ assertEquals( "exception", description.getDisplayName() );
+ assertEquals( "exception", description.toString() );
+ assertEquals( 0, description.getChildren().size() );
+ // JUnit 4 description does not get annotations
+ Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( description );
+ assertNull( annotatedIgnore );
+ }
+
+ public void testCreatePureDescription()
+ {
+ Description description = JUnit4Reflector.createDescription( "exception" );
+ assertEquals( "exception", description.getDisplayName() );
+ assertEquals( "exception", description.toString() );
+ assertEquals( 0, description.getChildren().size() );
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java b/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java
index aac3655..9ca397e 100644
--- a/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java
+++ b/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java
@@ -100,6 +100,15 @@ public class JUnitTestSetTest
throw new IllegalStateException();
}
+ public void testExecutionSkippedByUser()
+ {
+ }
+
+ public void testSkippedByUser( ReportEntry report )
+ {
+ testSkipped( report );
+ }
+
public List getSucceededTests()
{
return succeededTests;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
new file mode 100644
index 0000000..d45b678
--- /dev/null
+++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
@@ -0,0 +1,48 @@
+package org.apache.maven.surefire.junit4;
+
+/*
+ * 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.
+ */
+
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+
+/**
+ * Calling {@link RunNotifier#pleaseStop()} if failure appeared.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+final class JUnit4FailFastListener
+ extends RunListener
+{
+ private final RunNotifier notifier;
+
+ JUnit4FailFastListener( RunNotifier notifier )
+ {
+ this.notifier = notifier;
+ }
+
+ @Override
+ public void testFailure( Failure failure )
+ throws Exception
+ {
+ notifier.pleaseStop();
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
index 3f0e57f..e8f041d 100644
--- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
+++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
@@ -19,22 +19,20 @@ package org.apache.maven.surefire.junit4;
* under the License.
*/
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.MasterProcessListener;
+import org.apache.maven.surefire.booter.MasterProcessReader;
import org.apache.maven.surefire.common.junit4.ClassMethod;
-import org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil;
-import org.apache.maven.surefire.common.junit4.JUnit4Reflector;
import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
-import org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory;
import org.apache.maven.surefire.common.junit4.JUnit4TestChecker;
import org.apache.maven.surefire.common.junit4.JUnitTestFailureListener;
+import org.apache.maven.surefire.common.junit4.Notifier;
import org.apache.maven.surefire.providerapi.AbstractProvider;
import org.apache.maven.surefire.providerapi.ProviderParameters;
-import org.apache.maven.surefire.report.ConsoleOutputCapture;
import org.apache.maven.surefire.report.ConsoleOutputReceiver;
import org.apache.maven.surefire.report.PojoStackTraceWriter;
import org.apache.maven.surefire.report.ReportEntry;
@@ -49,13 +47,28 @@ import org.apache.maven.surefire.util.RunOrderCalculator;
import org.apache.maven.surefire.util.ScanResult;
import org.apache.maven.surefire.util.TestsToRun;
import org.junit.runner.Description;
-import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
-import org.junit.runner.notification.RunNotifier;
-
+import org.junit.runner.notification.StoppedByUserException;
+
+import static org.apache.maven.surefire.booter.MasterProcessCommand.SKIP_SINCE_NEXT_TEST;
+import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.createSuiteDescription;
+import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.cutTestClassAndMethod;
+import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTests;
+import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createDescription;
+import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createIgnored;
+import static org.apache.maven.surefire.common.junit4.JUnit4RunListener.rethrowAnyTestMechanismFailures;
+import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
+import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
+import static org.apache.maven.surefire.report.SimpleReportEntry.withException;
import static org.apache.maven.surefire.testset.TestListResolver.toClassFileName;
+import static org.apache.maven.surefire.util.TestsToRun.fromClass;
+import static org.junit.runner.Request.aClass;
+import static org.junit.runner.Request.method;
+import static java.lang.reflect.Modifier.isAbstract;
+import static java.lang.reflect.Modifier.isInterface;
+import static java.util.Collections.unmodifiableCollection;
/**
* @author Kristian Rosenvold
@@ -67,7 +80,7 @@ public class JUnit4Provider
private final ClassLoader testClassLoader;
- private final List<org.junit.runner.notification.RunListener> customRunListeners;
+ private final Collection<org.junit.runner.notification.RunListener> customRunListeners;
private final JUnit4TestChecker jUnit4TestChecker;
@@ -81,16 +94,20 @@ public class JUnit4Provider
private final int rerunFailingTestsCount;
+ private final MasterProcessReader commandsReader;
+
private TestsToRun testsToRun;
public JUnit4Provider( ProviderParameters booterParameters )
{
+ // don't start a thread in MasterProcessReader while we are in in-plugin process
+ commandsReader = booterParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
providerParameters = booterParameters;
testClassLoader = booterParameters.getTestClassLoader();
scanResult = booterParameters.getScanResult();
runOrderCalculator = booterParameters.getRunOrderCalculator();
String listeners = booterParameters.getProviderProperties().get( "listener" );
- customRunListeners = JUnit4RunListenerFactory.createCustomListeners( listeners );
+ customRunListeners = unmodifiableCollection( createCustomListeners( listeners ) );
jUnit4TestChecker = new JUnit4TestChecker( testClassLoader );
TestRequest testRequest = booterParameters.getTestRequest();
testResolver = testRequest.getTestListResolver();
@@ -100,6 +117,11 @@ public class JUnit4Provider
public RunResult invoke( Object forkTestSet )
throws TestSetFailedException
{
+ if ( isRerunFailingTests() && isFailFast() )
+ {
+ throw new TestSetFailedException( "don't enable parameters rerunFailingTestsCount, skipAfterFailureCount" );
+ }
+
if ( testsToRun == null )
{
if ( forkTestSet instanceof TestsToRun )
@@ -108,7 +130,7 @@ public class JUnit4Provider
}
else if ( forkTestSet instanceof Class )
{
- testsToRun = TestsToRun.fromClass( (Class) forkTestSet );
+ testsToRun = fromClass( (Class) forkTestSet );
}
else
{
@@ -118,48 +140,102 @@ public class JUnit4Provider
upgradeCheck();
- final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
+ ReporterFactory reporterFactory = providerParameters.getReporterFactory();
RunListener reporter = reporterFactory.createReporter();
- ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
-
- JUnit4RunListener jUnit4TestSetReporter = new JUnit4RunListener( reporter );
+ startCapture( (ConsoleOutputReceiver) reporter );
+ Notifier notifier = new Notifier();
+ notifier.setReporter( new JUnit4RunListener( reporter ) );
+ if ( isFailFast() )
+ {
+ notifier.addListener( new JUnit4FailFastListener( notifier ) );
+ }
Result result = new Result();
- RunNotifier runNotifier = getRunNotifier( jUnit4TestSetReporter, result, customRunListeners );
-
- runNotifier.fireTestRunStarted( testsToRun.allowEagerReading()
- ? createTestsDescription()
- : JUnit4Reflector.createDescription( UNDETERMINED_TESTS_DESCRIPTION ) );
+ notifier.addListeners( customRunListeners )
+ .addListener( result.createListener() );
- for ( Class aTestsToRun : testsToRun )
+ if ( isFailFast() && commandsReader != null )
{
- executeTestSet( aTestsToRun, reporter, runNotifier );
+ registerPleaseStopJunitListener( notifier );
}
- runNotifier.fireTestRunFinished( result );
+ try
+ {
+ notifier.fireTestRunStarted( testsToRun.allowEagerReading()
+ ? createTestsDescription()
+ : createDescription( UNDETERMINED_TESTS_DESCRIPTION ) );
- JUnit4RunListener.rethrowAnyTestMechanismFailures( result );
+ for ( Class aTestsToRun : testsToRun )
+ {
+ executeTestSet( aTestsToRun, reporter, notifier );
+ }
+ }
+ finally
+ {
+ notifier.fireTestRunFinished( result );
+ notifier.removeListeners();
+ closeCommandsReader();
+ }
- closeRunNotifier( jUnit4TestSetReporter, customRunListeners );
+ rethrowAnyTestMechanismFailures( result );
return reporterFactory.close();
}
- private void executeTestSet( Class<?> clazz, RunListener reporter, RunNotifier listeners )
+ private boolean isRerunFailingTests()
+ {
+ return rerunFailingTestsCount > 0;
+ }
+
+ private boolean isFailFast()
+ {
+ return providerParameters.getSkipAfterFailureCount() > 0;
+ }
+
+ private void closeCommandsReader()
+ {
+ if ( commandsReader != null )
+ {
+ commandsReader.stop();
+ }
+ }
+
+ private MasterProcessListener registerPleaseStopJunitListener( final Notifier notifier )
+ {
+ MasterProcessListener listener = new MasterProcessListener()
+ {
+ public void update( Command command )
+ {
+ notifier.pleaseStop();
+ }
+ };
+ commandsReader.addListener( SKIP_SINCE_NEXT_TEST, listener );
+ return listener;
+ }
+
+ private void executeTestSet( Class<?> clazz, RunListener reporter, Notifier notifier )
{
final ReportEntry report = new SimpleReportEntry( getClass().getName(), clazz.getName() );
reporter.testSetStarting( report );
try
{
- executeWithRerun( clazz, listeners );
+ executeWithRerun( clazz, notifier );
}
catch ( Throwable e )
{
- String reportName = report.getName();
- String reportSourceName = report.getSourceName();
- PojoStackTraceWriter stackWriter = new PojoStackTraceWriter( reportSourceName, reportName, e );
- reporter.testError( SimpleReportEntry.withException( reportSourceName, reportName, stackWriter ) );
+ if ( isFailFast() && e instanceof StoppedByUserException )
+ {
+ String reason = e.getClass().getName();
+ notifier.fireTestIgnored( createDescription( clazz.getName(), createIgnored( reason ) ) );
+ }
+ else
+ {
+ String reportName = report.getName();
+ String reportSourceName = report.getSourceName();
+ PojoStackTraceWriter stackWriter = new PojoStackTraceWriter( reportSourceName, reportName, e );
+ reporter.testError( withException( reportSourceName, reportName, stackWriter ) );
+ }
}
finally
{
@@ -167,55 +243,28 @@ public class JUnit4Provider
}
}
- private void executeWithRerun( Class<?> clazz, RunNotifier listeners ) throws TestSetFailedException
+ private void executeWithRerun( Class<?> clazz, Notifier notifier ) throws TestSetFailedException
{
JUnitTestFailureListener failureListener = new JUnitTestFailureListener();
- listeners.addListener( failureListener );
+ notifier.addListener( failureListener );
boolean hasMethodFilter = testResolver != null && testResolver.hasMethodPatterns();
- execute( clazz, listeners, hasMethodFilter ? new TestResolverFilter() : new NullFilter() );
+ execute( clazz, notifier, hasMethodFilter ? new TestResolverFilter() : new NullFilter() );
// Rerun failing tests if rerunFailingTestsCount is larger than 0
- if ( rerunFailingTestsCount > 0 )
+ if ( isRerunFailingTests() )
{
for ( int i = 0; i < rerunFailingTestsCount && !failureListener.getAllFailures().isEmpty(); i++ )
{
- Set<ClassMethod> failedTests =
- JUnit4ProviderUtil.generateFailingTests( failureListener.getAllFailures() );
+ Set<ClassMethod> failedTests = generateFailingTests( failureListener.getAllFailures() );
failureListener.reset();
if ( !failedTests.isEmpty() )
{
- executeFailedMethod( listeners, failedTests );
+ executeFailedMethod( notifier, failedTests );
}
}
}
}
- private static RunNotifier getRunNotifier( org.junit.runner.notification.RunListener main, Result result,
- List<org.junit.runner.notification.RunListener> others )
- {
- RunNotifier notifier = new RunNotifier();
- notifier.addListener( main );
- notifier.addListener( result.createListener() );
- for ( org.junit.runner.notification.RunListener listener : others )
- {
- notifier.addListener( listener );
- }
- return notifier;
- }
-
- // I am not entirely sure as to why we do this explicit freeing, it's one of those
- // pieces of code that just seem to linger on in here ;)
- private static void closeRunNotifier( org.junit.runner.notification.RunListener main,
- Iterable<org.junit.runner.notification.RunListener> others )
- {
- RunNotifier notifier = new RunNotifier();
- notifier.removeListener( main );
- for ( org.junit.runner.notification.RunListener listener : others )
- {
- notifier.removeListener( listener );
- }
- }
-
public Iterable<Class<?>> getSuites()
{
testsToRun = scanClassPath();
@@ -258,7 +307,7 @@ public class JUnit4Provider
{
classes.add( clazz );
}
- return JUnit4ProviderUtil.createSuiteDescription( classes );
+ return createSuiteDescription( classes );
}
private static boolean isJUnit4UpgradeCheck()
@@ -266,12 +315,12 @@ public class JUnit4Provider
return System.getProperty( "surefire.junit4.upgradecheck" ) != null;
}
- private static void execute( Class<?> testClass, RunNotifier notifier, Filter filter )
+ private static void execute( Class<?> testClass, Notifier notifier, Filter filter )
{
final int classModifiers = testClass.getModifiers();
- if ( !Modifier.isAbstract( classModifiers ) && !Modifier.isInterface( classModifiers ) )
+ if ( !isAbstract( classModifiers ) && !isInterface( classModifiers ) )
{
- Runner runner = Request.aClass( testClass ).filterWith( filter ).getRunner();
+ Runner runner = aClass( testClass ).filterWith( filter ).getRunner();
if ( countTestsInRunner( runner.getDescription() ) != 0 )
{
runner.run( notifier );
@@ -279,7 +328,7 @@ public class JUnit4Provider
}
}
- private void executeFailedMethod( RunNotifier notifier, Set<ClassMethod> failedMethods )
+ private void executeFailedMethod( Notifier notifier, Set<ClassMethod> failedMethods )
throws TestSetFailedException
{
for ( ClassMethod failedMethod : failedMethods )
@@ -288,7 +337,7 @@ public class JUnit4Provider
{
Class<?> methodClass = Class.forName( failedMethod.getClazz(), true, testClassLoader );
String methodName = failedMethod.getMethod();
- Request.method( methodClass, methodName ).getRunner().run( notifier );
+ method( methodClass, methodName ).getRunner().run( notifier );
}
catch ( ClassNotFoundException e )
{
@@ -353,7 +402,7 @@ public class JUnit4Provider
public boolean shouldRun( Description description )
{
// class: Java class name; method: 1. "testMethod" or 2. "testMethod[5+whatever]" in @Parameterized
- final ClassMethod cm = JUnit4ProviderUtil.cutTestClassAndMethod( description );
+ final ClassMethod cm = cutTestClassAndMethod( description );
final boolean isSuite = description.isSuite();
final boolean isValidTest = description.isTest() && cm.isValid();
final String clazz = cm.getClazz();
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
index 7254364..5886317 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java
@@ -113,6 +113,12 @@ public abstract class ConcurrentRunListener
testMethod.detachFromCurrentThread();
}
+ public void testExecutionSkippedByUser()
+ {
+ // cannot guarantee proper call to all listeners
+ reporterManagerThreadLocal.get().testExecutionSkippedByUser();
+ }
+
public void testAssumptionFailure( ReportEntry failure )
{
final TestMethod testMethod = getOrCreateThreadAttachedTestMethod( failure );
@@ -180,19 +186,15 @@ public abstract class ConcurrentRunListener
return reporterManagerThreadLocal.get();
}
-
public static ConcurrentRunListener createInstance( Map<String, TestSet> classMethodCounts,
- ReporterFactory reporterManagerFactory,
+ ReporterFactory reporterFactory,
boolean parallelClasses, boolean parallelBoth,
ConsoleLogger consoleLogger )
throws TestSetFailedException
{
- if ( parallelClasses )
- {
- return new ClassesParallelRunListener( classMethodCounts, reporterManagerFactory, consoleLogger );
- }
- return new MethodsParallelRunListener( classMethodCounts, reporterManagerFactory, !parallelBoth,
- consoleLogger );
+ return parallelClasses
+ ? new ClassesParallelRunListener( classMethodCounts, reporterFactory, consoleLogger )
+ : new MethodsParallelRunListener( classMethodCounts, reporterFactory, !parallelBoth, consoleLogger );
}
@@ -210,5 +212,4 @@ public abstract class ConcurrentRunListener
consoleLogger.info( new String( buf, off, len ) );
}
}
-
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/FilteringRequest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/FilteringRequest.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/FilteringRequest.java
new file mode 100644
index 0000000..5e1c192
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/FilteringRequest.java
@@ -0,0 +1,54 @@
+package org.apache.maven.surefire.junitcore;
+
+/*
+ * 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.
+ */
+
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+
+/**
+ * Moved nested class from {@link JUnitCoreWrapper}.
+ */
+final class FilteringRequest
+ extends Request
+{
+ private Runner filteredRunner;
+
+ public FilteringRequest( Request req, Filter filter )
+ {
+ try
+ {
+ Runner runner = req.getRunner();
+ filter.apply( runner );
+ filteredRunner = runner;
+ }
+ catch ( NoTestsRemainException e )
+ {
+ filteredRunner = null;
+ }
+ }
+
+ @Override
+ public Runner getRunner()
+ {
+ return filteredRunner;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
new file mode 100644
index 0000000..dda6b68
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
@@ -0,0 +1,65 @@
+package org.apache.maven.surefire.junitcore;
+
+/*
+ * 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.
+ */
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Calling {@link Stoppable#pleaseStop()} if failure appeared.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+final class JUnit47FailFastListener
+ extends RunListener
+{
+ private final Stoppable stoppable;
+
+ private final ConcurrentLinkedQueue<String> testClassNames = new ConcurrentLinkedQueue<String>();
+
+ JUnit47FailFastListener( Stoppable stoppable )
+ {
+ this.stoppable = stoppable;
+ }
+
+ Queue<String> getRemainingTestClasses()
+ {
+ return testClassNames;
+ }
+
+ @Override
+ public void testStarted( Description description )
+ throws Exception
+ {
+ testClassNames.remove( description.getClassName() );
+ }
+
+ @Override
+ public void testFailure( Failure failure )
+ throws Exception
+ {
+ stoppable.pleaseStop();
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
new file mode 100644
index 0000000..7f1a03a
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
@@ -0,0 +1,90 @@
+package org.apache.maven.surefire.junitcore;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.surefire.common.junit4.Notifier;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.junit.runner.Result;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * JUnitCore solves bugs in original junit class {@link org.junit.runner.JUnitCore}.<p>
+ * The notifier method {@link org.junit.runner.notification.RunNotifier#fireTestRunFinished}
+ * is called anyway in finally block.
+ * This class provides method {@link #pleaseStop()} without any need to retrieve
+ * {@link org.junit.runner.notification.RunNotifier} outside.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ * @see https://github.com/junit-team/junit/issues/1186
+ */
+class JUnitCore
+ implements Stoppable
+{
+ private final Notifier notifier;
+
+ JUnitCore( Notifier notifier )
+ {
+ this.notifier = notifier;
+ }
+
+ Result run( Runner runner )
+ throws TestSetFailedException
+ {
+ Result result = new Result();
+ RunListener listener = result.createListener();
+ notifier.addFirstListener( listener );
+ try
+ {
+ notifier.fireTestRunStarted( runner.getDescription() );
+ runner.run( notifier );
+ }
+ catch ( Throwable e )
+ {
+ afterException( e );
+ }
+ finally
+ {
+ notifier.fireTestRunFinished( result );
+ notifier.removeListener( listener );
+ afterFinished();
+ }
+ return result;
+ }
+
+ protected void afterException( Throwable e )
+ throws TestSetFailedException
+ {
+ throw new TestSetFailedException( e );
+ }
+
+ protected void afterFinished()
+ {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void pleaseStop()
+ {
+ notifier.pleaseStop();
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
index 43b8a1e..243cca0 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
@@ -19,14 +19,18 @@ package org.apache.maven.surefire.junitcore;
* under the License.
*/
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil;
-import org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory;
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.MasterProcessListener;
+import org.apache.maven.surefire.booter.MasterProcessReader;
+import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
import org.apache.maven.surefire.common.junit4.JUnitTestFailureListener;
+import org.apache.maven.surefire.common.junit4.Notifier;
import org.apache.maven.surefire.common.junit48.FilterFactory;
import org.apache.maven.surefire.common.junit48.JUnit48Reflector;
import org.apache.maven.surefire.common.junit48.JUnit48TestChecker;
@@ -34,9 +38,7 @@ import org.apache.maven.surefire.providerapi.AbstractProvider;
import org.apache.maven.surefire.providerapi.ProviderParameters;
import org.apache.maven.surefire.report.ConsoleLogger;
import org.apache.maven.surefire.report.ConsoleOutputCapture;
-import org.apache.maven.surefire.report.ConsoleOutputReceiver;
import org.apache.maven.surefire.report.ReporterFactory;
-import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.suite.RunResult;
import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestSetFailedException;
@@ -45,6 +47,14 @@ import org.apache.maven.surefire.util.ScanResult;
import org.apache.maven.surefire.util.ScannerFilter;
import org.apache.maven.surefire.util.TestsToRun;
import org.junit.runner.manipulation.Filter;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+import static org.apache.maven.surefire.booter.MasterProcessCommand.SKIP_SINCE_NEXT_TEST;
+import static org.apache.maven.surefire.junitcore.ConcurrentRunListener.createInstance;
+import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTests;
+import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
+import static java.util.Collections.unmodifiableCollection;
/**
* @author Kristian Rosenvold
@@ -59,7 +69,7 @@ public class JUnitCoreProvider
private final ScannerFilter scannerFilter;
- private final List<org.junit.runner.notification.RunListener> customRunListeners;
+ private final Collection<RunListener> customRunListeners;
private final ProviderParameters providerParameters;
@@ -67,16 +77,19 @@ public class JUnitCoreProvider
private final int rerunFailingTestsCount;
- private TestsToRun testsToRun;
-
private final JUnit48Reflector jUnit48Reflector;
private final RunOrderCalculator runOrderCalculator;
private final TestListResolver testResolver;
+ private final MasterProcessReader commandsReader;
+
+ private TestsToRun testsToRun;
+
public JUnitCoreProvider( ProviderParameters providerParameters )
{
+ commandsReader = providerParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
this.providerParameters = providerParameters;
testClassLoader = providerParameters.getTestClassLoader();
scanResult = providerParameters.getScanResult();
@@ -85,8 +98,8 @@ public class JUnitCoreProvider
scannerFilter = new JUnit48TestChecker( testClassLoader );
testResolver = providerParameters.getTestRequest().getTestListResolver();
rerunFailingTestsCount = providerParameters.getTestRequest().getRerunFailingTestsCount();
- customRunListeners = JUnit4RunListenerFactory.createCustomListeners(
- providerParameters.getProviderProperties().get( "listener" ) );
+ String listeners = providerParameters.getProviderProperties().get( "listener" );
+ customRunListeners = unmodifiableCollection( createCustomListeners( listeners ) );
jUnit48Reflector = new JUnit48Reflector( testClassLoader );
}
@@ -104,6 +117,11 @@ public class JUnitCoreProvider
public RunResult invoke( Object forkTestSet )
throws TestSetFailedException
{
+ if ( isRerunFailingTests() && isFailFast() )
+ {
+ throw new TestSetFailedException( "don't enable parameters rerunFailingTestsCount, skipAfterFailureCount" );
+ }
+
final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
final ConsoleLogger consoleLogger = providerParameters.getConsoleLogger();
@@ -127,55 +145,96 @@ public class JUnitCoreProvider
}
}
- customRunListeners.add( 0, getRunListener( reporterFactory, consoleLogger ) );
+ Notifier notifier = new Notifier();
+ notifier.setReporter( createRunListener( reporterFactory, consoleLogger ) );
// Add test failure listener
JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener();
- customRunListeners.add( 0, testFailureListener );
+ notifier.addListener( testFailureListener );
- JUnitCoreWrapper.execute( consoleLogger, testsToRun, jUnitCoreParameters, customRunListeners, filter );
+ if ( isFailFast() && commandsReader != null )
+ {
+ registerPleaseStopJunitListener( notifier );
+ }
- // Rerun failing tests if rerunFailingTestsCount is larger than 0
- if ( rerunFailingTestsCount > 0 )
+ try
{
- for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
+ JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, consoleLogger, isFailFast() );
+
+ core.execute( testsToRun, customRunListeners, filter );
+
+ // Rerun failing tests if rerunFailingTestsCount is larger than 0
+ if ( isRerunFailingTests() )
{
- Map<Class<?>, Set<String>> failingTests =
- JUnit4ProviderUtil.generateFailingTests( testFailureListener.getAllFailures(), testClassLoader );
- testFailureListener.reset();
- final FilterFactory filterFactory = new FilterFactory( testClassLoader );
- Filter failingMethodsFilter = filterFactory.createFailingMethodFilter( failingTests );
- JUnitCoreWrapper.execute( consoleLogger, testsToRun, jUnitCoreParameters, customRunListeners,
- failingMethodsFilter );
+ for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
+ {
+ List<Failure> failures = testFailureListener.getAllFailures();
+ Map<Class<?>, Set<String>> failingTests = generateFailingTests( failures, testClassLoader );
+ testFailureListener.reset();
+ final FilterFactory filterFactory = new FilterFactory( testClassLoader );
+ Filter failingMethodsFilter = filterFactory.createFailingMethodFilter( failingTests );
+ core.execute( testsToRun, failingMethodsFilter );
+ }
}
}
+ finally
+ {
+ notifier.removeListeners();
+ closeCommandsReader();
+ }
return reporterFactory.close();
}
- private org.junit.runner.notification.RunListener getRunListener( ReporterFactory reporterFactory,
- ConsoleLogger consoleLogger )
+ private boolean isRerunFailingTests()
+ {
+ return rerunFailingTestsCount > 0;
+ }
+
+ private boolean isFailFast()
+ {
+ return providerParameters.getSkipAfterFailureCount() > 0;
+ }
+
+ private void closeCommandsReader()
+ {
+ if ( commandsReader != null )
+ {
+ commandsReader.stop();
+ }
+ }
+
+ private MasterProcessListener registerPleaseStopJunitListener( final Notifier stoppable )
+ {
+ MasterProcessListener listener = new MasterProcessListener()
+ {
+ public void update( Command command )
+ {
+ stoppable.pleaseStop();
+ }
+ };
+ commandsReader.addListener( SKIP_SINCE_NEXT_TEST, listener );
+ return listener;
+ }
+
+ private JUnit4RunListener createRunListener( ReporterFactory reporterFactory, ConsoleLogger consoleLogger )
throws TestSetFailedException
{
- org.junit.runner.notification.RunListener jUnit4RunListener;
if ( isSingleThreaded() )
{
NonConcurrentRunListener rm = new NonConcurrentRunListener( reporterFactory.createReporter() );
ConsoleOutputCapture.startCapture( rm );
- jUnit4RunListener = rm;
+ return rm;
}
else
{
final Map<String, TestSet> testSetMap = new ConcurrentHashMap<String, TestSet>();
- RunListener listener =
- ConcurrentRunListener.createInstance( testSetMap, reporterFactory,
- isParallelTypes(),
- isParallelMethodsAndTypes(), consoleLogger );
- ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) listener );
+ ConcurrentRunListener listener = createInstance( testSetMap, reporterFactory, isParallelTypes(),
+ isParallelMethodsAndTypes(), consoleLogger );
+ ConsoleOutputCapture.startCapture( listener );
- jUnit4RunListener = new JUnitCoreRunListener( listener, testSetMap );
+ return new JUnitCoreRunListener( listener, testSetMap );
}
- return jUnit4RunListener;
}
private boolean isParallelMethodsAndTypes()
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
index bf2f71a..e0c9f9e 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
@@ -19,79 +19,103 @@ package org.apache.maven.surefire.junitcore;
* under the License.
*/
-import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
+import org.apache.maven.surefire.common.junit4.Notifier;
import org.apache.maven.surefire.junitcore.pc.ParallelComputer;
import org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder;
import org.apache.maven.surefire.report.ConsoleLogger;
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.TestsToRun;
+import org.junit.Ignore;
import org.junit.runner.Computer;
-import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
-import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
-import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.StoppedByUserException;
-import java.util.List;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Queue;
+import java.util.Random;
+
+import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createDescription;
+import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createIgnored;
+import static org.apache.maven.surefire.common.junit4.JUnit4RunListener.rethrowAnyTestMechanismFailures;
/**
* Encapsulates access to JUnitCore
*
* @author Kristian Rosenvold
*/
-
-class JUnitCoreWrapper
+final class JUnitCoreWrapper
{
- public static void execute( ConsoleLogger logger, TestsToRun testsToRun, JUnitCoreParameters jUnitCoreParameters,
- List<RunListener> listeners, Filter filter )
+ private final Notifier notifier;
+ private final JUnitCoreParameters jUnitCoreParameters;
+ private final ConsoleLogger logger;
+ private final boolean failFast;
+
+ private Object o = new Random().nextInt();
+
+ JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleLogger logger,
+ boolean failFast )
+ {
+ this.notifier = notifier;
+ this.jUnitCoreParameters = jUnitCoreParameters;
+ this.logger = logger;
+ this.failFast = failFast;
+ }
+
+ void execute( TestsToRun testsToRun, Filter filter )
+ throws TestSetFailedException
+ {
+ execute( testsToRun, Collections.<RunListener>emptyList(), filter );
+ }
+
+ void execute( TestsToRun testsToRun, Collection<RunListener> listeners, Filter filter )
throws TestSetFailedException
{
- JUnitCore junitCore = createJUnitCore( listeners );
if ( testsToRun.allowEagerReading() )
{
- executeEager( logger, testsToRun, filter, jUnitCoreParameters, junitCore );
+ executeEager( testsToRun, filter, listeners );
}
else
{
- executeLazy( logger, testsToRun, filter, jUnitCoreParameters, junitCore );
+ executeLazy( testsToRun, filter, listeners );
}
}
- private static JUnitCore createJUnitCore( List<RunListener> listeners )
+ private JUnitCore createJUnitCore( final Notifier notifier, Collection<RunListener> listeners )
{
- JUnitCore junitCore = new JUnitCore();
- for ( RunListener runListener : listeners )
- {
- junitCore.addListener( runListener );
- }
+ JUnitCore junitCore = new JUnitCore( notifier );
+
+ // custom listeners added last
+ notifier.addListeners( listeners );
+
return junitCore;
}
- private static void executeEager( ConsoleLogger logger, TestsToRun testsToRun, Filter filter,
- JUnitCoreParameters jUnitCoreParameters, JUnitCore junitCore )
+ private void executeEager( TestsToRun testsToRun, Filter filter, Collection<RunListener> listeners )
throws TestSetFailedException
{
+ JUnitCore junitCore = createJUnitCore( notifier, listeners );
Class<?>[] tests = testsToRun.getLocatedClasses();
- Computer computer = createComputer( logger, jUnitCoreParameters );
- createRequestAndRun( filter, computer, junitCore, tests );
+ Computer computer = createComputer();
+ createRequestAndRun( filter, computer, junitCore.withReportedTests( tests ), tests );
}
- private static void executeLazy( ConsoleLogger logger, TestsToRun testsToRun, Filter filter,
- JUnitCoreParameters jUnitCoreParameters, JUnitCore junitCore )
+ private void executeLazy( TestsToRun testsToRun, Filter filter, Collection<RunListener> listeners )
throws TestSetFailedException
{
+ JUnitCore junitCore = createJUnitCore( notifier, listeners );
// in order to support LazyTestsToRun, the iterator must be used
- for ( Class clazz : testsToRun )
+ for ( Class<?> clazz : testsToRun )
{
- Computer computer = createComputer( logger, jUnitCoreParameters );
- createRequestAndRun( filter, computer, junitCore, clazz );
+ Computer computer = createComputer();
+ createRequestAndRun( filter, computer, junitCore.withReportedTests( clazz ), clazz );
}
}
- private static void createRequestAndRun( Filter filter, Computer computer, JUnitCore junitCore,
- Class<?>... classesToRun )
+ private void createRequestAndRun( Filter filter, Computer computer, JUnitCore junitCore, Class<?>... classesToRun )
throws TestSetFailedException
{
Request req = Request.classes( computer, classesToRun );
@@ -105,8 +129,8 @@ class JUnitCoreWrapper
}
}
- Result run = junitCore.run( req );
- JUnit4RunListener.rethrowAnyTestMechanismFailures( run );
+ Result run = junitCore.run( req.getRunner() );
+ rethrowAnyTestMechanismFailures( run );
if ( computer instanceof ParallelComputer )
{
@@ -118,37 +142,78 @@ class JUnitCoreWrapper
}
}
- private static Computer createComputer( ConsoleLogger logger, JUnitCoreParameters parameters )
- throws TestSetFailedException
+ private Computer createComputer()
{
- return parameters.isNoThreading()
+ return jUnitCoreParameters.isNoThreading()
? Computer.serial()
- : new ParallelComputerBuilder( logger, parameters ).buildComputer();
+ : new ParallelComputerBuilder( logger, jUnitCoreParameters ).buildComputer();
}
- private static class FilteringRequest
- extends Request
+ private final class JUnitCore
+ extends org.apache.maven.surefire.junitcore.JUnitCore
{
- private Runner filteredRunner;
+ private final JUnit47FailFastListener failFastListener;
- public FilteringRequest( Request req, Filter filter )
+ JUnitCore( Notifier notifier )
{
- try
+ super( notifier );
+ failFastListener = failFast ? new JUnit47FailFastListener( this ) : null;
+ if ( failFastListener != null )
{
- Runner runner = req.getRunner();
- filter.apply( runner );
- filteredRunner = runner;
+ notifier.addListener( failFastListener );
}
- catch ( NoTestsRemainException e )
+ }
+
+ JUnitCore withReportedTests( Class<?>... tests )
+ {
+ Queue<String> stoppedTests = getRemainingTestClasses();
+ if ( stoppedTests != null )
+ {
+ for ( Class<?> test : tests )
+ {
+ stoppedTests.add( test.getName() );
+ }
+ }
+ return this;
+ }
+
+ @Override
+ @SuppressWarnings( "checkstyle:innerassignment" )
+ protected void afterException( Throwable e )
+ throws TestSetFailedException
+ {
+ if ( failFast && e instanceof StoppedByUserException )
+ {
+ Queue<String> stoppedTests = getRemainingTestClasses();
+ if ( stoppedTests != null )
+ {
+ String reason = e.getClass().getName();
+ Ignore reasonForIgnoredTest = createIgnored( reason );
+ for ( String clazz; ( clazz = stoppedTests.poll() ) != null; )
+ {
+ notifier.fireTestIgnored( createDescription( clazz, reasonForIgnoredTest ) );
+ }
+ }
+ }
+ else
{
- filteredRunner = null;
+ super.afterException( e );
}
}
@Override
- public Runner getRunner()
+ protected void afterFinished()
+ {
+ Queue<String> stoppedTests = getRemainingTestClasses();
+ if ( stoppedTests != null )
+ {
+ stoppedTests.clear();
+ }
+ }
+
+ private Queue<String> getRemainingTestClasses()
{
- return filteredRunner;
+ return failFastListener == null ? null : failFastListener.getRemainingTestClasses();
}
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java
new file mode 100644
index 0000000..2450e64
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java
@@ -0,0 +1,32 @@
+package org.apache.maven.surefire.junitcore;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+interface Stoppable
+{
+ /**
+ * Delegates this call to {@link org.junit.runner.notification.RunNotifier#pleaseStop()}.
+ */
+ void pleaseStop();
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java
index 7d4b102..896af3e 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java
@@ -49,6 +49,37 @@ public class JUnit4Reflector481Test
Description.createTestDescription( IgnoreWithDescription.class, "testSomething2", annotations );
Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( desc );
assertNotNull( annotatedIgnore );
+ assertEquals(
+ "testSomething2" + "(org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription)",
+ desc.getDisplayName() );
+ assertEquals( "testSomething2"
+ + "(org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription)",
+ desc.toString() );
+ assertEquals( "org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription",
+ desc.getClassName() );
+ assertEquals( "testSomething2", desc.getMethodName() );
+ assertEquals( 0, desc.getChildren().size() );
+ assertEquals( 2, desc.getAnnotations().size() );
+ assertSame( annotatedIgnore, desc.getAnnotation( Ignore.class ) );
+ assertEquals( reason, annotatedIgnore.value() );
+ }
+
+ @Test
+ public void testGetAnnotatedIgnoreWithoutClass()
+ {
+ final Method testSomething2 =
+ ReflectionUtils.getMethod( IgnoreWithDescription.class, "testSomething2", EMPTY_CLASS_ARRAY );
+ final Annotation[] annotations = testSomething2.getAnnotations();
+ Description desc = Description.createSuiteDescription( "testSomething2", annotations );
+ Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( desc );
+ assertNotNull( annotatedIgnore );
+ assertEquals( "testSomething2", desc.getDisplayName() );
+ assertEquals( "testSomething2", desc.toString() );
+ assertEquals( "testSomething2", desc.getClassName() );
+ assertNull( desc.getMethodName() );
+ assertEquals( 0, desc.getChildren().size() );
+ assertEquals( 2, desc.getAnnotations().size() );
+ assertSame( annotatedIgnore, desc.getAnnotation( Ignore.class ) );
assertEquals( reason, annotatedIgnore.value() );
}
@@ -64,5 +95,26 @@ public class JUnit4Reflector481Test
}
}
+ @Test
+ public void testCreatePureDescription()
+ {
+ Description description = JUnit4Reflector.createDescription( "exception" );
+ assertEquals( "exception", description.getDisplayName() );
+ assertEquals( "exception", description.toString() );
+ assertEquals( 0, description.getChildren().size() );
+ }
+ @Test
+ public void testCreateDescription()
+ {
+ Ignore ignore = JUnit4Reflector.createIgnored( "error" );
+ Description description = JUnit4Reflector.createDescription( "exception", ignore );
+ assertEquals( "exception", description.getDisplayName() );
+ assertEquals( "exception", description.toString() );
+ assertEquals( "exception", description.getClassName() );
+ assertEquals( 0, description.getChildren().size() );
+ Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( description );
+ assertNotNull( annotatedIgnore );
+ assertEquals( "error", annotatedIgnore.value() );
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
index 538b31a..01aa81f 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
import org.apache.maven.surefire.booter.BaseProviderFactory;
import org.apache.maven.surefire.booter.ProviderParameterNames;
+import org.apache.maven.surefire.common.junit4.Notifier;
import org.apache.maven.surefire.report.ConsoleLogger;
import org.apache.maven.surefire.report.DefaultConsoleReporter;
import org.apache.maven.surefire.report.ReporterConfiguration;
@@ -111,7 +112,8 @@ public class Surefire746Test
// JUnitCoreWrapper#execute() is calling JUnit4RunListener#rethrowAnyTestMechanismFailures()
// and rethrows a failure which happened in listener
exception.expect( TestSetFailedException.class );
- JUnitCoreWrapper.execute( new Logger(), testsToRun, jUnitCoreParameters, customRunListeners, null );
+ new JUnitCoreWrapper( new Notifier(), jUnitCoreParameters, new Logger(), false )
+ .execute( testsToRun, customRunListeners, null );
}
finally
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng-utils/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/pom.xml b/surefire-providers/surefire-testng-utils/pom.xml
index 64d8518..8fc1513 100644
--- a/surefire-providers/surefire-testng-utils/pom.xml
+++ b/surefire-providers/surefire-testng-utils/pom.xml
@@ -49,7 +49,7 @@
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
- <version>5.7</version>
+ <version>5.10</version>
<classifier>jdk15</classifier>
<scope>provided</scope>
</dependency>
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastEventsSingleton.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastEventsSingleton.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastEventsSingleton.java
new file mode 100644
index 0000000..523ce8f
--- /dev/null
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastEventsSingleton.java
@@ -0,0 +1,53 @@
+package org.apache.maven.surefire.testng.utils;
+
+/*
+ * 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.
+ */
+
+/**
+ * Stores and retrieves atomic events
+ * used by {@link FailFastNotifier} and TestNG provider.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public final class FailFastEventsSingleton
+{
+ private static final FailFastEventsSingleton INSTANCE = new FailFastEventsSingleton();
+
+ private volatile boolean skipAfterFailure;
+
+ private FailFastEventsSingleton()
+ {
+ }
+
+ public static FailFastEventsSingleton getInstance()
+ {
+ return INSTANCE;
+ }
+
+ public boolean isSkipAfterFailure()
+ {
+ return skipAfterFailure;
+ }
+
+ public void setSkipOnNextTest()
+ {
+ this.skipAfterFailure = true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
new file mode 100644
index 0000000..d3d5c00
--- /dev/null
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
@@ -0,0 +1,77 @@
+package org.apache.maven.surefire.testng.utils;
+
+/*
+ * 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.
+ */
+
+import org.testng.ITestContext;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+/**
+ * Sends an even in {@link FailFastEventsSingleton} that failure has appeared.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class FailFastListener
+ implements ITestListener
+{
+ private final Stoppable stoppable;
+
+ public FailFastListener( Stoppable stoppable )
+ {
+ this.stoppable = stoppable;
+ }
+
+ public void onTestStart( ITestResult result )
+ {
+
+ }
+
+ public void onTestSuccess( ITestResult result )
+ {
+
+ }
+
+ public void onTestFailure( ITestResult result )
+ {
+ FailFastEventsSingleton.getInstance().setSkipOnNextTest();
+ stoppable.pleaseStop();
+ }
+
+ public void onTestSkipped( ITestResult result )
+ {
+
+ }
+
+ public void onTestFailedButWithinSuccessPercentage( ITestResult result )
+ {
+
+ }
+
+ public void onStart( ITestContext context )
+ {
+
+ }
+
+ public void onFinish( ITestContext context )
+ {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastNotifier.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastNotifier.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastNotifier.java
new file mode 100644
index 0000000..735c2ce
--- /dev/null
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastNotifier.java
@@ -0,0 +1,50 @@
+package org.apache.maven.surefire.testng.utils;
+
+/*
+ * 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.
+ */
+
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.ITestResult;
+import org.testng.SkipException;
+
+/**
+ * Notifies TestNG core skipping remaining tests after first failure has appeared.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class FailFastNotifier
+ implements IInvokedMethodListener
+{
+
+ public void beforeInvocation( IInvokedMethod iInvokedMethod, ITestResult iTestResult )
+ {
+ if ( FailFastEventsSingleton.getInstance().isSkipAfterFailure() )
+ {
+ throw new SkipException( "Skipped after failure. See parameter [skipAfterFailureCount] "
+ + "in surefire or failsafe plugin." );
+ }
+ }
+
+ public void afterInvocation( IInvokedMethod iInvokedMethod, ITestResult iTestResult )
+ {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
new file mode 100644
index 0000000..c7be682
--- /dev/null
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
@@ -0,0 +1,32 @@
+package org.apache.maven.surefire.testng.utils;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public interface Stoppable
+{
+ /**
+ * Delegates this call to {@link org.apache.maven.surefire.report.RunListener#testExecutionSkippedByUser()}.
+ */
+ void pleaseStop();
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
index 678280f..5297276 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
@@ -79,9 +79,11 @@ public class TestNGDirectoryTestSuite
private final List<CommandLineOption> mainCliOptions;
+ private final boolean isFailFast;
+
public TestNGDirectoryTestSuite( String testSourceDirectory, Map<String, String> confOptions, File reportsDirectory,
TestListResolver methodFilter, RunOrderCalculator runOrderCalculator,
- ScanResult scanResult, List<CommandLineOption> mainCliOptions )
+ ScanResult scanResult, List<CommandLineOption> mainCliOptions, boolean isFailFast )
{
this.runOrderCalculator = runOrderCalculator;
this.options = confOptions;
@@ -94,6 +96,7 @@ public class TestNGDirectoryTestSuite
this.junitTestAnnotation = findJUnitTestAnnotation();
this.junitOptions = createJUnitOptions();
this.mainCliOptions = mainCliOptions;
+ this.isFailFast = isFailFast;
}
public void execute( TestsToRun testsToRun, ReporterFactory reporterManagerFactory )
@@ -128,7 +131,7 @@ public class TestNGDirectoryTestSuite
final Map<String, String> optionsToUse = isJUnitTest( testClass ) ? junitOptions : options;
TestNGExecutor.run( new Class<?>[]{ testClass }, testSourceDirectory, optionsToUse, reporter, this,
- reportsDirectory, methodFilter, mainCliOptions );
+ reportsDirectory, methodFilter, mainCliOptions, isFailFast );
finishTestSuite( reporter, this );
}
@@ -218,14 +221,14 @@ public class TestNGDirectoryTestSuite
Class<?>[] testClasses = testNgTestClasses.toArray( new Class<?>[testNgTestClasses.size()] );
TestNGExecutor.run( testClasses, testSourceDirectory, options, reporterManager, this,
- testNgReportsDirectory, methodFilter, mainCliOptions );
+ testNgReportsDirectory, methodFilter, mainCliOptions, isFailFast );
if ( !junitTestClasses.isEmpty() )
{
testClasses = junitTestClasses.toArray( new Class[junitTestClasses.size()] );
TestNGExecutor.run( testClasses, testSourceDirectory, junitOptions, reporterManager, this,
- junitReportsDirectory, methodFilter, mainCliOptions );
+ junitReportsDirectory, methodFilter, mainCliOptions, isFailFast );
}
finishTestSuite( reporterManager, this );
@@ -295,7 +298,7 @@ public class TestNGDirectoryTestSuite
startTestSuite( reporter, this );
TestNGExecutor.run( new Class<?>[] { testSet.getTestClass() }, testSourceDirectory, options, reporter,
- this, reportsDirectory, methodFilter, mainCliOptions );
+ this, reportsDirectory, methodFilter, mainCliOptions, isFailFast );
finishTestSuite( reporter, this );
}
[17/17] maven-surefire git commit: [SUREFIRE-580] fixed compilation
error
Posted by ti...@apache.org.
[SUREFIRE-580] fixed compilation error
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/86b253ba
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/86b253ba
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/86b253ba
Branch: refs/heads/master
Commit: 86b253ba460ca1b943e54badbec2071385201e93
Parents: 62c7cd0
Author: Tibor17 <ti...@lycos.com>
Authored: Sun Sep 6 22:12:53 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:05 2015 +0200
----------------------------------------------------------------------
.../org/apache/maven/surefire/junitcore/Surefire746Test.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/86b253ba/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
index 01aa81f..46213df 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java
@@ -23,7 +23,9 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
import org.apache.maven.surefire.booter.BaseProviderFactory;
import org.apache.maven.surefire.booter.ProviderParameterNames;
+import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
import org.apache.maven.surefire.common.junit4.Notifier;
+import org.apache.maven.surefire.junit4.MockReporter;
import org.apache.maven.surefire.report.ConsoleLogger;
import org.apache.maven.surefire.report.DefaultConsoleReporter;
import org.apache.maven.surefire.report.ReporterConfiguration;
@@ -112,7 +114,8 @@ public class Surefire746Test
// JUnitCoreWrapper#execute() is calling JUnit4RunListener#rethrowAnyTestMechanismFailures()
// and rethrows a failure which happened in listener
exception.expect( TestSetFailedException.class );
- new JUnitCoreWrapper( new Notifier(), jUnitCoreParameters, new Logger(), false )
+ JUnit4RunListener dummy = new JUnit4RunListener( new MockReporter() );
+ new JUnitCoreWrapper( new Notifier( dummy, 0 ), jUnitCoreParameters, new Logger(), false )
.execute( testsToRun, customRunListeners, null );
}
finally
[03/17] maven-surefire git commit: [SUREFIRE] refactoring
Posted by ti...@apache.org.
[SUREFIRE] refactoring
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/1e547c8c
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/1e547c8c
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/1e547c8c
Branch: refs/heads/master
Commit: 1e547c8c319d8ba38048f3caa5f86e4be5338a48
Parents: 8e37515
Author: Tibor17 <ti...@lycos.com>
Authored: Mon Aug 3 15:40:59 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:55 2015 +0200
----------------------------------------------------------------------
.../TestSetMockReporterFactory.java | 2 ++
.../surefire/booter/MainCliOptionsAware.java | 2 +-
.../booter/SurefireClassLoadersAware.java | 2 +-
.../apache/maven/surefire/booter/Classpath.java | 5 ++-
.../surefire/booter/PropertiesWrapper.java | 5 ---
.../maven/surefire/junitcore/TestSet.java | 33 ++++++++++----------
6 files changed, 22 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1e547c8c/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
index df6c253..2e337e2 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
@@ -24,6 +24,8 @@ import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
import org.apache.maven.surefire.report.RunListener;
/**
+ * Internal tests use only.
+ *
* @author Kristian Rosenvold
*/
public class TestSetMockReporterFactory
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1e547c8c/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
index b3b3c9d..eddebed 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MainCliOptionsAware.java
@@ -29,7 +29,7 @@ import java.util.List;
* @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
* @since 2.19
*/
-public interface MainCliOptionsAware
+interface MainCliOptionsAware
{
void setMainCliOptions( List<CommandLineOption> mainCliOptions );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1e547c8c/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireClassLoadersAware.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireClassLoadersAware.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireClassLoadersAware.java
index d55002e..351bb51 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireClassLoadersAware.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireClassLoadersAware.java
@@ -23,7 +23,7 @@ package org.apache.maven.surefire.booter;
* @author Kristian Rosenvold
* @noinspection UnusedDeclaration
*/
-public interface SurefireClassLoadersAware
+interface SurefireClassLoadersAware
{
void setClassLoaders( ClassLoader testClassLoader );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1e547c8c/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
index ee093c9..a2a3d52 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
@@ -155,11 +155,10 @@ public class Classpath implements Iterable<String>
{
try
{
- List urls = getAsUrlList();
+ List<URL> urls = getAsUrlList();
IsolatedClassLoader classLoader = new IsolatedClassLoader( parent, childDelegation, roleName );
- for ( Object url1 : urls )
+ for ( URL url : urls )
{
- URL url = (URL) url1;
classLoader.addURL( url );
}
if ( parent != null )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1e547c8c/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
index 8fec269..c4a7103 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PropertiesWrapper.java
@@ -65,11 +65,6 @@ public class PropertiesWrapper
return Boolean.valueOf( properties.get( propertyName ) );
}
- public boolean getBooleanObjectProperty( String propertyName )
- {
- return Boolean.valueOf( properties.get( propertyName ) );
- }
-
public int getIntProperty( String propertyName )
{
return Integer.parseInt( properties.get( propertyName ) );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1e547c8c/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java
index aa03b97..d7a6a01 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java
@@ -19,11 +19,10 @@ package org.apache.maven.surefire.junitcore;
* under the License.
*/
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
import org.apache.maven.surefire.report.ReportEntry;
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.report.SimpleReportEntry;
@@ -35,22 +34,22 @@ import org.junit.runner.Description;
*/
public class TestSet
{
- private final Description testSetDescription;
+ private static final InheritableThreadLocal<TestSet> TEST_SET = new InheritableThreadLocal<TestSet>();
- private final AtomicInteger numberOfCompletedChildren = new AtomicInteger( 0 );
+ private final Description testSetDescription;
- // While the two parameters below may seem duplicated, it is not entirely the case,
- // since numberOfTests has the correct value from the start, while testMethods grows as method execution starts.
+ private final Collection<TestMethod> testMethods = new ConcurrentLinkedQueue<TestMethod>();
- private final AtomicInteger numberOfTests = new AtomicInteger( 0 );
+ private final AtomicBoolean played = new AtomicBoolean();
- private final List<TestMethod> testMethods = Collections.synchronizedList( new ArrayList<TestMethod>() );
+ private volatile boolean allScheduled;
- private static final InheritableThreadLocal<TestSet> TEST_SET = new InheritableThreadLocal<TestSet>();
+ private volatile int numberOfCompletedChildren;
- private final AtomicBoolean allScheduled = new AtomicBoolean();
+ // While the two parameters may seem duplicated, it is not entirely the case,
+ // since numberOfTests has the correct value from the start, while testMethods grows as method execution starts.
- private final AtomicBoolean played = new AtomicBoolean();
+ private volatile int numberOfTests;
public TestSet( Description testSetDescription )
{
@@ -124,7 +123,7 @@ public class TestSet
public void incrementTestMethodCount()
{
- numberOfTests.incrementAndGet();
+ numberOfTests++;
}
private void addTestMethod( TestMethod testMethod )
@@ -134,8 +133,8 @@ public class TestSet
public void incrementFinishedTests( RunListener reporterManager, boolean reportImmediately )
{
- numberOfCompletedChildren.incrementAndGet();
- if ( allScheduled.get() && isAllTestsDone() && reportImmediately )
+ numberOfCompletedChildren++;
+ if ( allScheduled && isAllTestsDone() && reportImmediately )
{
replay( reporterManager );
}
@@ -143,7 +142,7 @@ public class TestSet
public void setAllScheduled( RunListener reporterManager )
{
- allScheduled.set( true );
+ allScheduled = true;
if ( isAllTestsDone() )
{
replay( reporterManager );
@@ -152,7 +151,7 @@ public class TestSet
private boolean isAllTestsDone()
{
- return numberOfTests.get() == numberOfCompletedChildren.get();
+ return numberOfTests == numberOfCompletedChildren;
}
public void attachToThread()
[12/17] maven-surefire git commit: [SUREFIRE-580] updated
documentation
Posted by ti...@apache.org.
[SUREFIRE-580] updated documentation
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/605708ca
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/605708ca
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/605708ca
Branch: refs/heads/master
Commit: 605708cabb584078beac02ff4f941081b37840fd
Parents: 3eb6fa7
Author: Tibor17 <ti...@lycos.com>
Authored: Thu Sep 3 16:56:59 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:00 2015 +0200
----------------------------------------------------------------------
.../site/apt/examples/skip-after-failure.apt.vm | 22 +++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/605708ca/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
index 9e7af97..0fc1fc0 100644
--- a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
@@ -31,28 +31,34 @@ Skipping Tests After First Failure
To skip remaining tests after first failure or error has happened
set configuration parameter <<<skipAfterFailureCount>>> to <<<1>>>.
- Prerequisite: use ${project.artifactId} 2.19 or higher, JUnit 4.0
- or higher, or TestNG 5.10 or higher.
-
- Limitations: Although this feature works in forking modes as well, the
- functionality cannot be fully guaranteed (real first failure) in concurrent
- mode due to race conditions.
-
If version of TestNG is lover than 5.10 while the parameter
<<<skipAfterFailureCount>>> is set, the plugin fails with error:
<<<[ERROR] org.apache.maven.surefire.util.SurefireReflectionException:
java.lang.NoClassDefFoundError: org/testng/IInvokedMethodListener>>>
-Skipping after the Nth failure or error
+Skipping Tests After the Nth Failure or Error
To skip remaining tests after the Nth failure or error has happened
set configuration parameter <<<skipAfterFailureCount>>> to N, where
N is number greater than zero.
+Prerequisite
+
+ Use ${project.artifactId} 2.19 or higher, JUnit 4.0 or higher, or
+ TestNG 5.10 or higher.
+
+
Notices
TestNG reports skipped methods however JUnit reports skipped classes.
Preferably use JUnit 4.12 or higher version which fixed thread safety issues.
+
+
+Limitations
+
+ Although this feature works in forking modes as well, the functionality
+ cannot be fully guaranteed (real first failure) in concurrent mode
+ due to race conditions.
\ No newline at end of file
[05/17] maven-surefire git commit: [SUREFIRE] refactoring
Posted by ti...@apache.org.
[SUREFIRE] refactoring
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/d755ecfc
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/d755ecfc
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/d755ecfc
Branch: refs/heads/master
Commit: d755ecfc45fcc68dd4b40953737dada0f2a00fcd
Parents: 1e547c8
Author: Tibor17 <ti...@lycos.com>
Authored: Mon Aug 3 22:48:36 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:56 2015 +0200
----------------------------------------------------------------------
.../surefire/common/junit4/JUnitTestFailureListener.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/d755ecfc/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnitTestFailureListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnitTestFailureListener.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnitTestFailureListener.java
index 473082d..e6fe2de 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnitTestFailureListener.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnitTestFailureListener.java
@@ -20,6 +20,7 @@ package org.apache.maven.surefire.common.junit4;
*/
import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
import java.util.ArrayList;
import java.util.List;
@@ -30,14 +31,13 @@ import java.util.List;
* @author Qingzhou Luo
*/
public class JUnitTestFailureListener
- extends org.junit.runner.notification.RunListener
+ extends RunListener
{
-
- List<Failure> allFailures = new ArrayList<Failure>();
+ private final List<Failure> allFailures = new ArrayList<Failure>();
@Override
public void testFailure( Failure failure )
- throws java.lang.Exception
+ throws Exception
{
allFailures.add( failure );
}
[13/17] maven-surefire git commit: [SUREFIRE-580] updated
documentation
Posted by ti...@apache.org.
[SUREFIRE-580] updated documentation
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/deb3214e
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/deb3214e
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/deb3214e
Branch: refs/heads/master
Commit: deb3214e35d4f7db0048ad38a8c17c7cdc4f8c61
Parents: 605708c
Author: Tibor17 <ti...@lycos.com>
Authored: Thu Sep 3 16:59:09 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:01 2015 +0200
----------------------------------------------------------------------
.../src/site/apt/examples/skip-after-failure.apt.vm | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/deb3214e/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
index 0fc1fc0..31c5726 100644
--- a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
@@ -31,11 +31,6 @@ Skipping Tests After First Failure
To skip remaining tests after first failure or error has happened
set configuration parameter <<<skipAfterFailureCount>>> to <<<1>>>.
- If version of TestNG is lover than 5.10 while the parameter
- <<<skipAfterFailureCount>>> is set, the plugin fails with error:
- <<<[ERROR] org.apache.maven.surefire.util.SurefireReflectionException:
- java.lang.NoClassDefFoundError: org/testng/IInvokedMethodListener>>>
-
Skipping Tests After the Nth Failure or Error
@@ -49,6 +44,11 @@ Prerequisite
Use ${project.artifactId} 2.19 or higher, JUnit 4.0 or higher, or
TestNG 5.10 or higher.
+ If version of TestNG is lover than 5.10 while the parameter
+ <<<skipAfterFailureCount>>> is set, the plugin fails with error:
+ <<<[ERROR] org.apache.maven.surefire.util.SurefireReflectionException:
+ java.lang.NoClassDefFoundError: org/testng/IInvokedMethodListener>>>
+
Notices
[02/17] maven-surefire git commit: [SUREFIRE] added missing interface
MainCliOptionsAware
Posted by ti...@apache.org.
[SUREFIRE] added missing interface MainCliOptionsAware
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/67af00f1
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/67af00f1
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/67af00f1
Branch: refs/heads/master
Commit: 67af00f1cba38c56cb2036d247dd178016ebaf9c
Parents: 668b1b9
Author: Tibor17 <ti...@lycos.com>
Authored: Sat Jul 25 03:28:20 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:54 2015 +0200
----------------------------------------------------------------------
.../surefire/booter/SurefireReflector.java | 31 ++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/67af00f1/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
index 0e53a8f..b271171 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
@@ -24,6 +24,8 @@ import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -41,6 +43,8 @@ import org.apache.maven.surefire.util.ReflectionUtils;
import org.apache.maven.surefire.util.RunOrder;
import org.apache.maven.surefire.util.SurefireReflectionException;
+import static java.util.Collections.checkedList;
+
/**
* Does reflection based invocation of the surefire methods.
* <p/>
@@ -84,7 +88,10 @@ public class SurefireReflector
private final Class<?> mainCliOptions;
+ private final Class<Enum> commandLineOptionsClass;
+
+ @SuppressWarnings( "unchecked" )
public SurefireReflector( ClassLoader surefireClassLoader )
{
this.surefireClassLoader = surefireClassLoader;
@@ -107,6 +114,8 @@ public class SurefireReflector
booterParameters = surefireClassLoader.loadClass( ProviderParameters.class.getName() );
testListResolver = surefireClassLoader.loadClass( TestListResolver.class.getName() );
mainCliOptions = surefireClassLoader.loadClass( MainCliOptionsAware.class.getName() );
+ commandLineOptionsClass =
+ (Class<Enum>) surefireClassLoader.loadClass( CommandLineOption.class.getName() );
}
catch ( ClassNotFoundException e )
{
@@ -272,7 +281,16 @@ public class SurefireReflector
{
if ( mainCliOptions.isAssignableFrom( o.getClass() ) )
{
- ReflectionUtils.invokeSetter( o, "setMainCliOptions", List.class, options );
+ List<Enum> newOptions = checkedList( new ArrayList<Enum>( options.size() ), commandLineOptionsClass );
+ Collection<Integer> ordinals = toOrdinals( options );
+ for ( Enum e : commandLineOptionsClass.getEnumConstants() )
+ {
+ if ( ordinals.contains( e.ordinal() ) )
+ {
+ newOptions.add( e );
+ }
+ }
+ ReflectionUtils.invokeSetter( o, "setMainCliOptions", List.class, newOptions );
}
}
@@ -288,7 +306,6 @@ public class SurefireReflector
ReflectionUtils.invokeSetter( o, "setRunOrderParameters", this.runOrderParameters, param );
}
-
public void setTestSuiteDefinitionAware( Object o, TestRequest testSuiteDefinition2 )
{
if ( testSuiteDefinitionAware.isAssignableFrom( o.getClass() ) )
@@ -365,4 +382,14 @@ public class SurefireReflector
return runResult.isAssignableFrom( o.getClass() );
}
+ private static Collection<Integer> toOrdinals( Collection<? extends Enum> enums )
+ {
+ Collection<Integer> ordinals = new ArrayList<Integer>( enums.size() );
+ for ( Enum e : enums )
+ {
+ ordinals.add( e.ordinal() );
+ }
+ return ordinals;
+ }
+
}
[14/17] maven-surefire git commit: [SUREFIRE-580] more sanity check
Posted by ti...@apache.org.
[SUREFIRE-580] more sanity check
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/1b7fe2d4
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/1b7fe2d4
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/1b7fe2d4
Branch: refs/heads/master
Commit: 1b7fe2d44e618cd7419755c74d75a484e49d761d
Parents: deb3214
Author: Tibor17 <ti...@lycos.com>
Authored: Sat Sep 5 00:16:37 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:02 2015 +0200
----------------------------------------------------------------------
.../org/apache/maven/plugin/surefire/AbstractSurefireMojo.java | 4 ++++
1 file changed, 4 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/1b7fe2d4/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git 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
index e8f1f75..ff2e51e 100644
--- 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
@@ -2352,6 +2352,10 @@ public abstract class AbstractSurefireMojo
private void warnIfRerunClashes()
throws MojoFailureException
{
+ if ( getSkipAfterFailureCount() < 0 )
+ {
+ throw new MojoFailureException( "Parameter rerunFailingTestsCount should not be negative." );
+ }
boolean isRerun = getRerunFailingTestsCount() > 0;
boolean isFailFast = getSkipAfterFailureCount() > 0;
if ( isRerun && isFailFast )
[09/17] maven-surefire git commit: [SUREFIRE-580] Allow "fail fast"
or stop running on first failure
Posted by ti...@apache.org.
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
new file mode 100644
index 0000000..c1a075f
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
@@ -0,0 +1,128 @@
+package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.surefire.booter.Command;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream.TestLessInputStreamBuilder;
+import static org.apache.maven.surefire.booter.Command.NOOP;
+import static org.apache.maven.surefire.booter.Command.SHUTDOWN;
+import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Testing cached and immediate commands in {@link TestLessInputStream}.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class TestLessInputStreamBuilderTest
+{
+ @Rule
+ public final ExpectedException e = ExpectedException.none();
+
+ @Test
+ public void cachableCommandsShouldBeIterableWithStillOpenIterator()
+ {
+ TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
+ TestLessInputStream is = builder.build();
+ Iterator<Command> iterator = builder.getIterableCachable().iterator();
+
+ assertFalse( iterator.hasNext() );
+
+ builder.getCachableCommands().skipSinceNextTest();
+ assertTrue( iterator.hasNext() );
+ assertThat( iterator.next(), is( SKIP_SINCE_NEXT_TEST ) );
+
+ assertFalse( iterator.hasNext() );
+
+ builder.getCachableCommands().noop();
+ assertTrue( iterator.hasNext() );
+ assertThat( iterator.next(), is( NOOP ) );
+
+ builder.removeStream( is );
+ }
+
+ @Test
+ public void immediateCommands()
+ throws IOException
+ {
+ TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
+ TestLessInputStream is = builder.build();
+ assertThat( is.availablePermits(), is( 0 ) );
+ is.noop();
+ assertThat( is.availablePermits(), is( 1 ) );
+ is.beforeNextCommand();
+ assertThat( is.availablePermits(), is( 0 ) );
+ assertThat( is.nextCommand(), is( NOOP ) );
+ assertThat( is.availablePermits(), is( 0 ) );
+ e.expect( NoSuchElementException.class );
+ is.nextCommand();
+ }
+
+ @Test
+ public void combinedCommands()
+ throws IOException
+ {
+ TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
+ TestLessInputStream is = builder.build();
+ assertThat( is.availablePermits(), is( 0 ) );
+ builder.getCachableCommands().skipSinceNextTest();
+ is.noop();
+ assertThat( is.availablePermits(), is( 2 ) );
+ is.beforeNextCommand();
+ assertThat( is.availablePermits(), is( 1 ) );
+ assertThat( is.nextCommand(), is( NOOP ) );
+ assertThat( is.availablePermits(), is( 1 ) );
+ builder.getCachableCommands().skipSinceNextTest();
+ assertThat( is.availablePermits(), is( 1 ) );
+ builder.getImmediateCommands().shutdown();
+ assertThat( is.availablePermits(), is( 2 ) );
+ is.beforeNextCommand();
+ assertThat( is.nextCommand(), is( SHUTDOWN ) );
+ assertThat( is.availablePermits(), is( 1 ) );
+ is.beforeNextCommand();
+ assertThat( is.nextCommand(), is( SKIP_SINCE_NEXT_TEST ) );
+ assertThat( is.availablePermits(), is( 0 ) );
+ builder.getImmediateCommands().noop();
+ assertThat( is.availablePermits(), is( 1 ) );
+ builder.getCachableCommands().shutdown();
+ builder.getCachableCommands().shutdown();
+ assertThat( is.availablePermits(), is( 2 ) );
+ is.beforeNextCommand();
+ assertThat( is.nextCommand(), is( NOOP ) );
+ assertThat( is.availablePermits(), is( 1 ) );
+ is.beforeNextCommand();
+ assertThat( is.nextCommand(), is( SHUTDOWN ) );
+ assertThat( is.availablePermits(), is( 0 ) );
+ e.expect( NoSuchElementException.class );
+ is.nextCommand();
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java
index feca48b..6fc171e 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java
@@ -19,8 +19,6 @@ package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
* under the License.
*/
-import org.apache.maven.surefire.booter.Command;
-import org.apache.maven.surefire.booter.MasterProcessCommand;
import org.junit.Test;
import java.io.IOException;
@@ -45,7 +43,7 @@ public class TestProvidingInputStreamTest
public void closedStreamShouldReturnEndOfStream()
throws IOException
{
- Queue<Command> commands = new ArrayDeque<Command>();
+ Queue<String> commands = new ArrayDeque<String>();
TestProvidingInputStream is = new TestProvidingInputStream( commands );
is.close();
assertThat( is.read(), is( -1 ) );
@@ -55,7 +53,7 @@ public class TestProvidingInputStreamTest
public void emptyStreamShouldWaitUntilClosed()
throws Exception
{
- Queue<Command> commands = new ArrayDeque<Command>();
+ Queue<String> commands = new ArrayDeque<String>();
final TestProvidingInputStream is = new TestProvidingInputStream( commands );
final Thread streamThread = Thread.currentThread();
FutureTask<Thread.State> futureTask = new FutureTask<Thread.State>( new Callable<Thread.State>()
@@ -79,9 +77,9 @@ public class TestProvidingInputStreamTest
public void finishedTestsetShouldNotBlock()
throws IOException
{
- Queue<Command> commands = new ArrayDeque<Command>();
- commands.add( new Command( MasterProcessCommand.TEST_SET_FINISHED ) );
+ Queue<String> commands = new ArrayDeque<String>();
final TestProvidingInputStream is = new TestProvidingInputStream( commands );
+ is.testSetFinished();
new Thread( new Runnable()
{
public void run()
@@ -104,8 +102,8 @@ public class TestProvidingInputStreamTest
public void shouldReadTest()
throws IOException
{
- Queue<Command> commands = new ArrayDeque<Command>();
- commands.add( new Command( MasterProcessCommand.RUN_CLASS, "Test" ) );
+ Queue<String> commands = new ArrayDeque<String>();
+ commands.add( "Test" );
final TestProvidingInputStream is = new TestProvidingInputStream( commands );
new Thread( new Runnable()
{
@@ -136,6 +134,7 @@ public class TestProvidingInputStreamTest
}
catch ( InterruptedException e )
{
+ // do nothing
}
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
index 995e2a1..80cf5ff 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
@@ -26,6 +26,7 @@ import org.apache.maven.plugin.surefire.booterclient.BooterDeserializerProviderC
import org.apache.maven.plugin.surefire.booterclient.BooterDeserializerStartupConfigurationTest;
import org.apache.maven.plugin.surefire.booterclient.ForkConfigurationTest;
import org.apache.maven.plugin.surefire.booterclient.ForkingRunListenerTest;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStreamBuilderTest;
import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvidingInputStreamTest;
import org.apache.maven.plugin.surefire.report.DefaultReporterFactoryTest;
import org.apache.maven.plugin.surefire.report.StatelessXmlReporterTest;
@@ -65,6 +66,7 @@ import org.junit.runners.Suite;
BooterDeserializerStartupConfigurationTest.class,
BooterDeserializerProviderConfigurationTest.class,
TestProvidingInputStreamTest.class,
+ TestLessInputStreamBuilderTest.class
} )
@RunWith( Suite.class )
public class JUnit4SuiteTest
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index 4c06f6b..2e925cf 100644
--- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -104,7 +104,6 @@ public class SurefirePlugin
@Parameter( property = "surefire.useFile", defaultValue = "true" )
private boolean useFile;
-
/**
* Set this to "true" to cause a failure if the none of the tests specified in -Dtest=... are run. Defaults to
* "true".
@@ -279,6 +278,17 @@ public class SurefirePlugin
@Parameter( property = "surefire.excludesFile" )
private File excludesFile;
+ /**
+ * Set to "true" to skip remaining tests after first test failure appeared.
+ * Due to race conditions in parallel/forked execution this may not be fully guaranteed.<br/>
+ * Enable with system property -Dsurefire.skipAfterFailureCount=1 or any number greater than zero.
+ * Defaults to "0".
+ *
+ * @since 2.19
+ */
+ @Parameter( property = "surefire.skipAfterFailureCount", defaultValue = "0" )
+ private int skipAfterFailureCount;
+
protected int getRerunFailingTestsCount()
{
return rerunFailingTestsCount;
@@ -448,6 +458,11 @@ public class SurefirePlugin
this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
}
+ public int getSkipAfterFailureCount()
+ {
+ return skipAfterFailureCount;
+ }
+
public boolean isPrintSummary()
{
return printSummary;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
new file mode 100644
index 0000000..9e7af97
--- /dev/null
+++ b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm
@@ -0,0 +1,58 @@
+ ------
+ Skipping Tests After Failure
+ ------
+ Tibor Digana
+ ------
+ July 2015
+ ------
+
+ ~~ 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.
+
+ ~~ NOTE: For help with the syntax of this file, see:
+ ~~ http://maven.apache.org/doxia/references/apt-format.html
+
+Skipping Tests After First Failure
+
+ To skip remaining tests after first failure or error has happened
+ set configuration parameter <<<skipAfterFailureCount>>> to <<<1>>>.
+
+ Prerequisite: use ${project.artifactId} 2.19 or higher, JUnit 4.0
+ or higher, or TestNG 5.10 or higher.
+
+ Limitations: Although this feature works in forking modes as well, the
+ functionality cannot be fully guaranteed (real first failure) in concurrent
+ mode due to race conditions.
+
+ If version of TestNG is lover than 5.10 while the parameter
+ <<<skipAfterFailureCount>>> is set, the plugin fails with error:
+ <<<[ERROR] org.apache.maven.surefire.util.SurefireReflectionException:
+ java.lang.NoClassDefFoundError: org/testng/IInvokedMethodListener>>>
+
+
+Skipping after the Nth failure or error
+
+ To skip remaining tests after the Nth failure or error has happened
+ set configuration parameter <<<skipAfterFailureCount>>> to N, where
+ N is number greater than zero.
+
+
+Notices
+
+ TestNG reports skipped methods however JUnit reports skipped classes.
+ Preferably use JUnit 4.12 or higher version which fixed thread safety issues.
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-plugin/src/site/site.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/site.xml b/maven-surefire-plugin/src/site/site.xml
index 1320caf..833c0a9 100644
--- a/maven-surefire-plugin/src/site/site.xml
+++ b/maven-surefire-plugin/src/site/site.xml
@@ -42,6 +42,7 @@
<item name="Using JUnit" href="examples/junit.html"/>
<item name="Using POJO Tests" href="examples/pojo-test.html"/>
<item name="Skipping Tests" href="examples/skipping-test.html"/>
+ <item name="Skip After Failure" href="examples/skip-after-failure.html"/>
<item name="Inclusions and Exclusions of Tests" href="examples/inclusion-exclusion.html"/>
<item name="Running a Single Test" href="examples/single-test.html"/>
<item name="Re-run Failing Tests" href="examples/rerun-failing-tests.html"/>
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
index 980f6d9..0433a01 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
@@ -45,7 +45,8 @@ import java.util.Map;
*/
public class BaseProviderFactory
implements DirectoryScannerParametersAware, ReporterConfigurationAware, SurefireClassLoadersAware, TestRequestAware,
- ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware, MainCliOptionsAware
+ ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware, MainCliOptionsAware,
+ FailFastAware
{
private static final int ROOT_CHANNEL = 0;
@@ -69,6 +70,8 @@ public class BaseProviderFactory
private TestArtifactInfo testArtifactInfo;
+ private int skipAfterFailureCount;
+
public BaseProviderFactory( ReporterFactory reporterFactory, boolean insideFork )
{
this.reporterFactory = reporterFactory;
@@ -188,4 +191,19 @@ public class BaseProviderFactory
{
this.mainCliOptions = mainCliOptions == null ? Collections.<CommandLineOption>emptyList() : mainCliOptions;
}
+
+ public int getSkipAfterFailureCount()
+ {
+ return skipAfterFailureCount;
+ }
+
+ public void setSkipAfterFailureCount( int skipAfterFailureCount )
+ {
+ this.skipAfterFailureCount = skipAfterFailureCount;
+ }
+
+ public boolean isInsideFork()
+ {
+ return insideFork;
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
index 992c78c..25bb2d1 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
@@ -19,17 +19,27 @@ package org.apache.maven.surefire.booter;
* under the License.
*/
+import static org.apache.maven.surefire.util.internal.StringUtils.requireNonNull;
+
/**
* Encapsulates data and command sent from master to forked process.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
*/
public final class Command
{
+ public static final Command TEST_SET_FINISHED = new Command( MasterProcessCommand.TEST_SET_FINISHED );
+ public static final Command SKIP_SINCE_NEXT_TEST = new Command( MasterProcessCommand.SKIP_SINCE_NEXT_TEST );
+ public static final Command SHUTDOWN = new Command( MasterProcessCommand.SHUTDOWN );
+ public static final Command NOOP = new Command( MasterProcessCommand.NOOP );
+
private final MasterProcessCommand command;
private final String data;
public Command( MasterProcessCommand command, String data )
{
- this.command = command;
+ this.command = requireNonNull( command );
this.data = data;
}
@@ -47,4 +57,30 @@ public final class Command
{
return data;
}
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ Command arg = (Command) o;
+
+ return command == arg.command && ( data == null ? arg.data == null : data.equals( arg.data ) );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = command.hashCode();
+ result = 31 * result + ( data != null ? data.hashCode() : 0 );
+ return result;
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/FailFastAware.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/FailFastAware.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/FailFastAware.java
new file mode 100644
index 0000000..06e47ba
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/FailFastAware.java
@@ -0,0 +1,31 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * 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.
+ */
+
+/**
+ * See the plugin configuration parameter <em>skipAfterFailureCount</em>.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+interface FailFastAware
+{
+ void setSkipAfterFailureCount( int skipAfterFailureCount );
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java
index 78f29e2..8108609 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java
@@ -48,7 +48,7 @@ public class ForkingReporterFactory
this.originalSystemOut = originalSystemOut;
}
- public synchronized RunListener createReporter()
+ public RunListener createReporter()
{
return new ForkingRunListener( originalSystemOut, testSetChannelId++, isTrimstackTrace );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
index 203651e..e56b94b 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
@@ -29,6 +29,7 @@ import org.apache.maven.surefire.report.ConsoleOutputReceiver;
import org.apache.maven.surefire.report.ReportEntry;
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.report.SafeThrowable;
+import org.apache.maven.surefire.report.SimpleReportEntry;
import org.apache.maven.surefire.report.StackTraceWriter;
import org.apache.maven.surefire.util.internal.StringUtils;
@@ -80,6 +81,8 @@ public class ForkingRunListener
public static final byte BOOTERCODE_NEXT_TEST = (byte) 'N';
+ public static final byte BOOTERCODE_STOP_ON_NEXT_TEST = (byte) 'S';
+
public static final byte BOOTERCODE_ERROR = (byte) 'X';
public static final byte BOOTERCODE_BYE = (byte) 'Z';
@@ -144,15 +147,18 @@ public class ForkingRunListener
encodeAndWriteToTarget( toString( BOOTERCODE_TEST_SKIPPED, report, testSetChannelId ) );
}
+ public void testExecutionSkippedByUser()
+ {
+ encodeAndWriteToTarget( toString( BOOTERCODE_STOP_ON_NEXT_TEST, new SimpleReportEntry(), testSetChannelId ) );
+ }
+
void sendProps()
{
Properties systemProperties = System.getProperties();
if ( systemProperties != null )
{
- Enumeration<?> propertyKeys = systemProperties.propertyNames();
-
- while ( propertyKeys.hasMoreElements() )
+ for ( Enumeration<?> propertyKeys = systemProperties.propertyNames(); propertyKeys.hasMoreElements(); )
{
String key = (String) propertyKeys.nextElement();
String value = systemProperties.getProperty( key );
@@ -202,7 +208,10 @@ public class ForkingRunListener
private void encodeAndWriteToTarget( String string )
{
byte[] encodeBytes = encodeStringForForkCommunication( string );
- target.write( encodeBytes, 0, encodeBytes.length );
+ synchronized ( target ) // See notes about synchronization/thread safety in class javadoc
+ {
+ target.write( encodeBytes, 0, encodeBytes.length );
+ }
}
private String toPropertyString( String key, String value )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
index 0a553f7..3512b5a 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
@@ -40,7 +40,7 @@ public enum MasterProcessCommand
{
RUN_CLASS( 0, String.class ),
TEST_SET_FINISHED( 1, Void.class ),
- STOP_ON_NEXT_TEST( 2, Void.class ),
+ SKIP_SINCE_NEXT_TEST( 2, Void.class ),
SHUTDOWN( 3, Void.class ),
/** To tell a forked process that the master process is still alive. Repeated after 30 seconds. */
NOOP( 4, Void.class );
@@ -65,6 +65,11 @@ public enum MasterProcessCommand
return dataType;
}
+ public boolean hasDataType()
+ {
+ return dataType != Void.class;
+ }
+
@SuppressWarnings( "checkstyle:magicnumber" )
public byte[] encode( String data )
{
@@ -119,7 +124,8 @@ public enum MasterProcessCommand
if ( command.getDataType() == Void.class )
{
// must read entire sequence to get to the next command; cannot be above the loop
- throw new IOException( "Command " + command + " read Void data with length " + dataLength );
+ throw new IOException( format( "Command %s unexpectedly read Void data with length %d.",
+ command, dataLength ) );
}
if ( total != dataLength )
@@ -129,7 +135,7 @@ public enum MasterProcessCommand
throw new EOFException( "stream closed" );
}
- throw new EOFException( format( "%s read %d out of %d bytes",
+ throw new IOException( format( "%s read %d out of %d bytes",
MasterProcessCommand.class, total, dataLength ) );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java
new file mode 100644
index 0000000..89a4f89
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java
@@ -0,0 +1,28 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * 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.
+ */
+
+/**
+ * listener interface
+ */
+public interface MasterProcessListener
+{
+ void update( Command command );
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
new file mode 100644
index 0000000..8c36bd2
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
@@ -0,0 +1,421 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * 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.
+ */
+
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static java.lang.Thread.State.NEW;
+import static java.lang.Thread.State.RUNNABLE;
+import static java.lang.Thread.State.TERMINATED;
+import static java.util.concurrent.locks.LockSupport.park;
+import static java.util.concurrent.locks.LockSupport.unpark;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.decode;
+import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
+import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
+import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
+import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread;
+import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_NEXT_TEST;
+
+/**
+ * Reader of commands coming from plugin(master) process.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public final class MasterProcessReader
+{
+ private static final MasterProcessReader READER = new MasterProcessReader();
+
+ private final Queue<TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener>> listeners
+ = new ConcurrentLinkedQueue<TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener>>();
+
+ private final Thread commandThread = newDaemonThread( new CommandRunnable(), "surefire-forkedjvm-command-thread" );
+
+ private final AtomicReference<Thread.State> state = new AtomicReference<Thread.State>( NEW );
+
+ private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
+
+ private final Node head = new Node();
+
+ private volatile Node tail = head;
+
+ private static class Node
+ {
+ final AtomicReference<Node> successor = new AtomicReference<Node>();
+ volatile String item;
+ }
+
+ public static MasterProcessReader getReader()
+ {
+ final MasterProcessReader reader = READER;
+ if ( reader.state.compareAndSet( NEW, RUNNABLE ) )
+ {
+ reader.commandThread.start();
+ }
+ return reader;
+ }
+
+ /**
+ * @param listener listener called with <em>Any</em> {@link MasterProcessCommand command type}
+ */
+ public void addListener( MasterProcessListener listener )
+ {
+ listeners.add( new TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener>( null, listener ) );
+ }
+
+ public void addListener( MasterProcessCommand cmd, MasterProcessListener listener )
+ {
+ listeners.add( new TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener>( cmd, listener ) );
+ }
+
+ public void removeListener( MasterProcessListener listener )
+ {
+ for ( Iterator<TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener>> it = listeners.iterator();
+ it.hasNext(); )
+ {
+ TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener> listenerWrapper = it.next();
+ if ( listener == listenerWrapper.getP2() )
+ {
+ it.remove();
+ }
+ }
+ }
+
+ Iterable<String> getIterableClasses( PrintStream originalOutStream )
+ {
+ return new ClassesIterable( head, originalOutStream );
+ }
+
+ public void stop()
+ {
+ if ( state.compareAndSet( NEW, TERMINATED ) || state.compareAndSet( RUNNABLE, TERMINATED ) )
+ {
+ makeQueueFull();
+ listeners.clear();
+ commandThread.interrupt();
+ }
+ }
+
+ private static boolean isLastNode( Node current )
+ {
+ return current.successor.get() == current;
+ }
+
+ private boolean isQueueFull()
+ {
+ return isLastNode( tail );
+ }
+
+ private boolean addToQueue( String item )
+ {
+ if ( tail.item == null )
+ {
+ tail.item = item;
+ Node newNode = new Node();
+ tail.successor.set( newNode );
+ tail = newNode;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * After this method returns the queue is closed, new item cannot be added and method
+ * {@link #isQueueFull()} returns true.
+ */
+ @SuppressWarnings( { "all", "checkstyle:needbraces", "checkstyle:emptystatement" } )
+ public void makeQueueFull()
+ {
+ // order between (#compareAndSet, and #get) matters in multithreading
+ for ( Node tail = this.tail;
+ !tail.successor.compareAndSet( null, tail ) && tail.successor.get() != tail;
+ tail = tail.successor.get() );
+ }
+
+ private void insertForQueue( Command cmd )
+ {
+ MasterProcessCommand expectedCommandType = cmd.getCommandType();
+ switch ( expectedCommandType )
+ {
+ case RUN_CLASS:
+ addToQueue( cmd.getData() );
+ break;
+ case TEST_SET_FINISHED:
+ makeQueueFull();
+ break;
+ default:
+ // checkstyle noop
+ break;
+ }
+ }
+
+ private void insertForListeners( Command cmd )
+ {
+ MasterProcessCommand expectedCommandType = cmd.getCommandType();
+ for ( TwoPropertiesWrapper<MasterProcessCommand, MasterProcessListener> listenerWrapper
+ : MasterProcessReader.this.listeners )
+ {
+ MasterProcessCommand commandType = listenerWrapper.getP1();
+ MasterProcessListener listener = listenerWrapper.getP2();
+ if ( commandType == null || commandType == expectedCommandType )
+ {
+ listener.update( cmd );
+ }
+ }
+ }
+
+ private void insert( Command cmd )
+ {
+ insertForQueue( cmd );
+ insertForListeners( cmd );
+ }
+
+ private final class ClassesIterable
+ implements Iterable<String>
+ {
+ private final Node head;
+ private final PrintStream originalOutStream;
+
+ ClassesIterable( Node head, PrintStream originalOutStream )
+ {
+ this.head = head;
+ this.originalOutStream = originalOutStream;
+ }
+
+ public Iterator<String> iterator()
+ {
+ return new ClassesIterator( head, originalOutStream );
+ }
+ }
+
+ private final class ClassesIterator
+ implements Iterator<String>
+ {
+ private final PrintStream originalOutStream;
+
+ private Node current;
+
+ private String clazz;
+
+ private ClassesIterator( Node current, PrintStream originalOutStream )
+ {
+ this.current = current;
+ this.originalOutStream = originalOutStream;
+ }
+
+ public boolean hasNext()
+ {
+ popUnread();
+ return isNotBlank( clazz );
+ }
+
+ public String next()
+ {
+ popUnread();
+ try
+ {
+ if ( isBlank( clazz ) )
+ {
+ throw new NoSuchElementException();
+ }
+ else
+ {
+ return clazz;
+ }
+ }
+ finally
+ {
+ clazz = null;
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ private void popUnread()
+ {
+ if ( state.get() == TERMINATED )
+ {
+ clazz = null;
+ return;
+ }
+
+ if ( isBlank( clazz ) )
+ {
+ do
+ {
+ requestNextTest();
+ if ( isLastNode( current ) )
+ {
+ clazz = null;
+ }
+ else if ( current.item == null )
+ {
+ do
+ {
+ await();
+ /**
+ * {@link java.util.concurrent.locks.LockSupport#park()}
+ * may spuriously (that is, for no reason) return, therefore the loop here.
+ */
+ } while ( current.item == null && !isLastNode( current ) );
+ clazz = current.item;
+ current = current.successor.get();
+ }
+ else
+ {
+ clazz = current.item;
+ current = current.successor.get();
+ }
+ }
+ while ( tryNullWhiteClass() );
+ }
+
+ if ( state.get() == TERMINATED )
+ {
+ clazz = null;
+ }
+ }
+
+ private boolean tryNullWhiteClass()
+ {
+ if ( clazz != null && isBlank( clazz ) )
+ {
+ clazz = null;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private void requestNextTest()
+ {
+ byte[] encoded = encodeStringForForkCommunication( ( (char) BOOTERCODE_NEXT_TEST ) + ",0,want more!\n" );
+ originalOutStream.write( encoded, 0, encoded.length );
+ }
+ }
+
+ private Command read( DataInputStream stdIn )
+ throws IOException
+ {
+ Command command = decode( stdIn );
+ if ( command != null )
+ {
+ insertForQueue( command );
+ }
+ return command;
+ }
+
+ private void await()
+ {
+ final Thread currentThread = Thread.currentThread();
+ try
+ {
+ waiters.add( currentThread );
+ park();
+ }
+ finally
+ {
+ waiters.remove( currentThread );
+ }
+ }
+
+ private void wakeupWaiters()
+ {
+ for ( Thread waiter : waiters )
+ {
+ unpark( waiter );
+ }
+ }
+
+ private final class CommandRunnable
+ implements Runnable
+ {
+ public void run()
+ {
+ DataInputStream stdIn = new DataInputStream( System.in );
+ boolean isTestSetFinished = false;
+ try
+ {
+ while ( MasterProcessReader.this.state.get() == RUNNABLE )
+ {
+ Command command = read( stdIn );
+ if ( command == null )
+ {
+ System.err.println( "[SUREFIRE] std/in stream corrupted: first sequence not recognized" );
+ break;
+ }
+ else
+ {
+ if ( command.getCommandType() == TEST_SET_FINISHED )
+ {
+ isTestSetFinished = true;
+ wakeupWaiters();
+ }
+ else if ( command.getCommandType() == RUN_CLASS )
+ {
+ wakeupWaiters();
+ }
+ insertForListeners( command );
+ }
+ }
+ }
+ catch ( EOFException e )
+ {
+ MasterProcessReader.this.state.set( TERMINATED );
+ }
+ catch ( IOException e )
+ {
+ MasterProcessReader.this.state.set( TERMINATED );
+ if ( !( e.getCause() instanceof InterruptedException ) )
+ {
+ System.err.println( "[SUREFIRE] std/in stream corrupted" );
+ e.printStackTrace();
+ }
+ }
+ finally
+ {
+ // ensure fail-safe iterator as well as safe to finish in for-each loop using ClassesIterator
+ if ( !isTestSetFinished )
+ {
+ insert( new Command( TEST_SET_FINISHED ) );
+ }
+ wakeupWaiters();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
index b271171..cf07331 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
@@ -294,6 +294,11 @@ public class SurefireReflector
}
}
+ public void setSkipAfterFailureCount( Object o, int skipAfterFailureCount )
+ {
+ ReflectionUtils.invokeSetter( o, "setSkipAfterFailureCount", int.class, skipAfterFailureCount );
+ }
+
public void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams )
{
final Object param = createDirectoryScannerParameters( dirScannerParams );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/booter/TwoPropertiesWrapper.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/TwoPropertiesWrapper.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/TwoPropertiesWrapper.java
new file mode 100644
index 0000000..5c6e690
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/TwoPropertiesWrapper.java
@@ -0,0 +1,50 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * 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.
+ */
+
+/**
+ * Internal generic wrapper.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ * @param <P1> first property
+ * @param <P2> second property
+ */
+final class TwoPropertiesWrapper<P1, P2>
+{
+ private final P1 p1;
+ private final P2 p2;
+
+ TwoPropertiesWrapper( P1 p1, P2 p2 )
+ {
+ this.p1 = p1;
+ this.p2 = p2;
+ }
+
+ P1 getP1()
+ {
+ return p1;
+ }
+
+ P2 getP2()
+ {
+ return p2;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
index cb6da9a..708b436 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
@@ -132,4 +132,15 @@ public interface ProviderParameters
TestArtifactInfo getTestArtifactInfo();
List<CommandLineOption> getMainCliOptions();
+
+ /**
+ * Defaults to 0. Configured with parameter <em>skipAfterFailureCount</em> in POM.
+ */
+ int getSkipAfterFailureCount();
+
+ /**
+ * @return {@code true} if test provider appears in forked jvm; Otherwise {@code false} means
+ * in-plugin provider.
+ */
+ boolean isInsideFork();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java
index e46ebcf..b964430 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java
@@ -66,7 +66,6 @@ public interface RunListener
*/
void testAssumptionFailure( ReportEntry report );
-
/**
* Event fired when a test ended with an error (non anticipated problem)
*
@@ -87,4 +86,11 @@ public interface RunListener
* @param report The report entry to log for
*/
void testSkipped( ReportEntry report );
+
+ /**
+ * Event fired skipping an execution of remaining test-set in other fork(s); or does nothing if no forks.
+ * The method is called by {@link org.apache.maven.surefire.providerapi.SurefireProvider}.<p>
+ * (The event is fired after the Nth test failed to signal skipping the rest of test-set.)
+ */
+ void testExecutionSkippedByUser();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java
index 2229815..9455b04 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java
@@ -35,6 +35,11 @@ public class SimpleReportEntry
private final String message;
+ public SimpleReportEntry()
+ {
+ this( null, null );
+ }
+
public SimpleReportEntry( String source, String name )
{
this( source, name, null, null );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
index 00e7bbc..717ab4e 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
@@ -29,7 +29,6 @@ import java.io.IOException;
import static org.apache.maven.surefire.booter.MasterProcessCommand.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
import static org.junit.Assert.assertNotNull;
/**
@@ -98,7 +97,7 @@ public class MasterProcessCommandTest
decoded = command.toDataTypeAsString( encoded );
assertNull( decoded );
break;
- case STOP_ON_NEXT_TEST:
+ case SKIP_SINCE_NEXT_TEST:
assertEquals( Void.class, command.getDataType() );
encoded = command.fromDataType( dummyData );
assertThat( encoded.length, is( 0 ) );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java b/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
index ad26f85..91ff446 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/report/MockReporter.java
@@ -114,6 +114,15 @@ public class MockReporter
testIgnored.incrementAndGet();
}
+ public void testExecutionSkippedByUser()
+ {
+ }
+
+ public void testSkippedByUser( ReportEntry report )
+ {
+ testSkipped( report );
+ }
+
public String getFirstEvent()
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
index be5c4c3..749f0e9 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
@@ -53,4 +53,5 @@ public final class BooterConstants
public static final String FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM = "preferTestsFromInStream";
public static final String RERUN_FAILING_TESTS_COUNT = "rerunFailingTestsCount";
public static final String MAIN_CLI_OPTIONS = "mainCliOptions";
+ public static final String FAIL_FAST_COUNT = "failFastCount";
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
index 5b89ed0..b8f2d0b 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
@@ -86,7 +86,7 @@ public class BooterDeserializer
DirectoryScannerParameters dirScannerParams =
new DirectoryScannerParameters( testClassesDirectory, includes, excludes, specificTests,
- properties.getBooleanObjectProperty( FAILIFNOTESTS ), runOrder );
+ properties.getBooleanProperty( FAILIFNOTESTS ), runOrder );
RunOrderParameters runOrderParameters = new RunOrderParameters( runOrder, runStatisticsFile );
@@ -96,14 +96,16 @@ public class BooterDeserializer
rerunFailingTestsCount );
ReporterConfiguration reporterConfiguration =
- new ReporterConfiguration( reportsDirectory, properties.getBooleanObjectProperty( ISTRIMSTACKTRACE ) );
+ new ReporterConfiguration( reportsDirectory, properties.getBooleanProperty( ISTRIMSTACKTRACE ) );
Collection<String> cli = properties.getStringList( MAIN_CLI_OPTIONS );
+ int failFastCount = properties.getIntProperty( FAIL_FAST_COUNT );
+
return new ProviderConfiguration( dirScannerParams, runOrderParameters,
properties.getBooleanProperty( FAILIFNOTESTS ), reporterConfiguration, testNg,
testSuiteDefinition, properties.getProperties(), typeEncodedTestForFork,
- preferTestsFromInStream, fromStrings( cli ) );
+ preferTestsFromInStream, fromStrings( cli ), failFastCount );
}
public StartupConfiguration getProviderConfiguration()
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
index 518c523..7567cd5 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
@@ -193,7 +193,7 @@ public final class ForkedBooter
private static RunResult invokeProviderInSameClassLoader( Object testSet, Object factory,
ProviderConfiguration providerConfiguration,
boolean insideFork,
- StartupConfiguration startupConfiguration1,
+ StartupConfiguration startupConfig,
boolean restoreStreams )
throws TestSetFailedException, InvocationTargetException
{
@@ -202,11 +202,10 @@ public final class ForkedBooter
// Note that System.out/System.err are also read in the "ReporterConfiguration" instatiation
// in createProvider below. These are the same values as here.
- final SurefireProvider provider =
- createProviderInCurrentClassloader( startupConfiguration1, insideFork, providerConfiguration, factory );
try
{
- return provider.invoke( testSet );
+ return createProviderInCurrentClassloader( startupConfig, insideFork, providerConfiguration, factory )
+ .invoke( testSet );
}
finally
{
@@ -233,6 +232,7 @@ public final class ForkedBooter
bpf.setRunOrderParameters( providerConfiguration.getRunOrderParameters() );
bpf.setDirectoryScannerParameters( providerConfiguration.getDirScannerParams() );
bpf.setMainCliOptions( providerConfiguration.getMainCliOptions() );
+ bpf.setSkipAfterFailureCount( providerConfiguration.getSkipAfterFailureCount() );
return (SurefireProvider) ReflectionUtils.instantiateOneArg( classLoader,
startupConfiguration1.getActualClassName(),
ProviderParameters.class, bpf );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java
deleted file mode 100644
index 89a4f89..0000000
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessListener.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.apache.maven.surefire.booter;
-
-/*
- * 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.
- */
-
-/**
- * listener interface
- */
-public interface MasterProcessListener
-{
- void update( Command command );
-}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
deleted file mode 100644
index 2dde2e1..0000000
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
+++ /dev/null
@@ -1,257 +0,0 @@
-package org.apache.maven.surefire.booter;
-
-/*
- * 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.
- */
-
-import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
-
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Queue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static java.lang.Thread.State.NEW;
-import static java.lang.Thread.State.RUNNABLE;
-import static java.lang.Thread.State.TERMINATED;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.decode;
-import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
-import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
-import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
-import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_NEXT_TEST;
-
-/**
- * Testing singleton {@code MasterProcessReader}.
- *
- * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
- * @since 2.19
- */
-public final class MasterProcessReader
-{
- private static final MasterProcessReader READER = new MasterProcessReader();
-
- private final BlockingQueue<Command> classes = new LinkedBlockingQueue<Command>();
-
- private final Queue<MasterProcessListener> listeners = new ConcurrentLinkedQueue<MasterProcessListener>();
-
- private final Thread commandThread =
- DaemonThreadFactory.newDaemonThread( new CommandRunnable(), "surefire-forkedjvm-command-thread" );
-
- private final AtomicReference<Thread.State> state = new AtomicReference<Thread.State>( NEW );
-
- public static MasterProcessReader getReader()
- {
- if ( READER.state.compareAndSet( NEW, RUNNABLE ) )
- {
- READER.commandThread.start();
- }
- return READER;
- }
-
- private MasterProcessReader()
- {
- commandThread.setDaemon( true );
- }
-
- Iterable<String> getIterableClasses( PrintStream originalOutStream )
- {
- return new ClassesIterable( originalOutStream );
- }
-
- void stop( boolean interruptCurrentThread )
- {
- if ( state.compareAndSet( NEW, TERMINATED ) || state.compareAndSet( RUNNABLE, TERMINATED ) )
- {
- classes.drainTo( new ArrayList<Command>() );
- listeners.clear();
- commandThread.interrupt();
- if ( interruptCurrentThread )
- {
- Thread.currentThread().interrupt();
- }
- }
- }
-
- private final class ClassesIterable
- implements Iterable<String>
- {
- private final ClassesIterator it;
-
- public ClassesIterable( PrintStream originalOutStream )
- {
- it = new ClassesIterator( originalOutStream );
- }
-
- public Iterator<String> iterator()
- {
- return it;
- }
- }
-
- private final class ClassesIterator
- implements Iterator<String>
- {
- private final PrintStream originalOutStream;
-
- private String clazz;
-
- private ClassesIterator( PrintStream originalOutStream )
- {
- this.originalOutStream = originalOutStream;
- }
-
- public boolean hasNext()
- {
- popUnread();
- return isNotBlank( clazz );
- }
-
- public String next()
- {
- popUnread();
- try
- {
- if ( isBlank( clazz ) )
- {
- throw new NoSuchElementException();
- }
- else
- {
- return clazz;
- }
- }
- finally
- {
- clazz = null;
- }
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
-
- private void popUnread()
- {
- if ( state.get() == TERMINATED )
- {
- clazz = null;
- return;
- }
-
- if ( isBlank( clazz ) )
- {
- requestNextTest();
- try
- {
- do
- {
- Command command = MasterProcessReader.this.classes.take();
- clazz = command.getCommandType() == TEST_SET_FINISHED ? null : command.getData();
- }
- while ( tryNullWhiteClass() );
- }
- catch ( InterruptedException e )
- {
- Thread.currentThread().interrupt();
- clazz = null;
- }
- }
-
- if ( state.get() == TERMINATED )
- {
- clazz = null;
- }
- }
-
- private boolean tryNullWhiteClass()
- {
- if ( clazz != null && isBlank( clazz ) )
- {
- clazz = null;
- return true;
- }
- else
- {
- return false;
- }
- }
-
- private void requestNextTest()
- {
- byte[] encoded = encodeStringForForkCommunication( ( (char) BOOTERCODE_NEXT_TEST ) + ",0,want more!\n" );
- originalOutStream.write( encoded, 0, encoded.length );
- }
- }
-
- private final class CommandRunnable
- implements Runnable
- {
- public void run()
- {
- DataInputStream stdIn = new DataInputStream( System.in );
- try
- {
- while ( MasterProcessReader.this.state.get() == RUNNABLE )
- {
- Command command = decode( stdIn );
- if ( command != null )
- {
- // command is null if stream is corrupted, i.e. the first sequence could not be recognized
- insert( command );
- }
- }
- }
- catch ( IOException e )
- {
- MasterProcessReader.this.state.set( TERMINATED );
- }
- finally
- {
- // ensure fail-safe iterator as well as safe to finish in for-each loop using ClassesIterator
- insert( new Command( TEST_SET_FINISHED ) );
- }
- }
-
- @SuppressWarnings( "unchecked" )
- private void insert( Command cmd )
- {
- MasterProcessCommand commandType = cmd.getCommandType();
- if ( commandType == RUN_CLASS || commandType == TEST_SET_FINISHED )
- {
- MasterProcessReader.this.classes.add( cmd );
- }
- else
- {
- for ( MasterProcessListener listener : MasterProcessReader.this.listeners )
- {
- listener.update( cmd );
- }
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
index 61f204d..69c7f2c 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
@@ -66,13 +66,15 @@ public class ProviderConfiguration
private final List<CommandLineOption> mainCliOptions;
+ private int skipAfterFailureCount;
+
@SuppressWarnings( "checkstyle:parameternumber" )
public ProviderConfiguration( DirectoryScannerParameters directoryScannerParameters,
RunOrderParameters runOrderParameters, boolean failIfNoTests,
ReporterConfiguration reporterConfiguration, TestArtifactInfo testArtifact,
TestRequest testSuiteDefinition, Map<String, String> providerProperties,
TypeEncodedValue typeEncodedTestSet, boolean readTestsFromInStream,
- List<CommandLineOption> mainCliOptions )
+ List<CommandLineOption> mainCliOptions, int skipAfterFailureCount )
{
this.runOrderParameters = runOrderParameters;
this.providerProperties = providerProperties;
@@ -84,6 +86,7 @@ public class ProviderConfiguration
this.forkTestSet = typeEncodedTestSet;
this.readTestsFromInStream = readTestsFromInStream;
this.mainCliOptions = mainCliOptions;
+ this.skipAfterFailureCount = skipAfterFailureCount;
}
public ReporterConfiguration getReporterConfiguration()
@@ -152,4 +155,14 @@ public class ProviderConfiguration
{
return mainCliOptions;
}
+
+ public void setSkipAfterFailureCount( int skipAfterFailureCount )
+ {
+ this.skipAfterFailureCount = skipAfterFailureCount;
+ }
+
+ public int getSkipAfterFailureCount()
+ {
+ return skipAfterFailureCount;
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
index c5d93ab..5ad587f 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
@@ -46,8 +46,7 @@ public class ProviderFactory
private final Object reporterManagerFactory;
- private static final Class[] INVOKE_PARAMETERS = new Class[]{ Object.class };
-
+ private static final Class[] INVOKE_PARAMETERS = { Object.class };
public ProviderFactory( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
ClassLoader testsClassLoader, Object reporterManagerFactory )
@@ -61,7 +60,7 @@ public class ProviderFactory
public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader, Object factory,
ProviderConfiguration providerConfiguration, boolean insideFork,
- StartupConfiguration startupConfiguration1, boolean restoreStreams )
+ StartupConfiguration startupConfig, boolean restoreStreams )
throws TestSetFailedException, InvocationTargetException
{
final PrintStream orgSystemOut = System.out;
@@ -69,12 +68,11 @@ public class ProviderFactory
// Note that System.out/System.err are also read in the "ReporterConfiguration" instantiation
// in createProvider below. These are the same values as here.
- ProviderFactory providerFactory =
- new ProviderFactory( startupConfiguration1, providerConfiguration, testsClassLoader, factory );
- final SurefireProvider provider = providerFactory.createProvider( insideFork );
try
{
- return provider.invoke( testSet );
+ return new ProviderFactory( startupConfig, providerConfiguration, testsClassLoader, factory )
+ .createProvider( insideFork )
+ .invoke( testSet );
}
finally
{
@@ -101,6 +99,7 @@ public class ProviderFactory
surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
surefireReflector.setMainCliOptions( o, providerConfiguration.getMainCliOptions() );
+ surefireReflector.setSkipAfterFailureCount( o, providerConfiguration.getSkipAfterFailureCount() );
Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
currentThread.setContextClassLoader( systemClassLoader );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-booter/src/test/java/org/apache/maven/surefire/booter/MasterProcessReaderTest.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/MasterProcessReaderTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/MasterProcessReaderTest.java
index 9440e0d..ae299c1 100644
--- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/MasterProcessReaderTest.java
+++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/MasterProcessReaderTest.java
@@ -30,13 +30,19 @@ import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
import static org.apache.maven.surefire.util.internal.StringUtils.FORK_STREAM_CHARSET_NAME;
import static org.junit.Assert.assertFalse;
@@ -56,6 +62,7 @@ public class MasterProcessReaderTest
{
private final BlockingQueue<Byte> blockingStream = new LinkedBlockingQueue<Byte>();
private InputStream realInputStream;
+ private MasterProcessReader reader;
@Before
public void init()
@@ -63,25 +70,26 @@ public class MasterProcessReaderTest
{
Thread.interrupted();
realInputStream = System.in;
- addThisTestToPipeline( MasterProcessReaderTest.class.getName() );
+ addThisTestToPipeline( getClass().getName() );
System.setIn( new SystemInputStream() );
+ reader = MasterProcessReader.getReader();
}
@After
public void deinit()
{
+ reader.stop();
System.setIn( realInputStream );
}
@Test
public void readJustOneClass() throws Exception
{
- MasterProcessReader reader = MasterProcessReader.getReader();
Iterator<String> it = reader.getIterableClasses( new PrintStream( new ByteArrayOutputStream() ) )
.iterator();
assertTrue( it.hasNext() );
assertThat( it.next(), is( getClass().getName() ) );
- reader.stop( true );
+ reader.stop();
assertFalse( it.hasNext() );
try
{
@@ -98,7 +106,6 @@ public class MasterProcessReaderTest
public void stopBeforeReadInThread()
throws Throwable
{
- final MasterProcessReader reader = MasterProcessReader.getReader();
Runnable runnable = new Runnable()
{
public void run()
@@ -110,7 +117,7 @@ public class MasterProcessReaderTest
};
FutureTask<Object> futureTask = new FutureTask<Object>( runnable, null );
Thread t = new Thread( futureTask );
- reader.stop( false );
+ reader.stop();
t.start();
try
{
@@ -126,7 +133,6 @@ public class MasterProcessReaderTest
public void readTwoClassesInThread()
throws Throwable
{
- final MasterProcessReader reader = MasterProcessReader.getReader();
final CountDownLatch counter = new CountDownLatch( 1 );
Runnable runnable = new Runnable()
{
@@ -152,9 +158,45 @@ public class MasterProcessReaderTest
{
throw e.getCause();
}
- finally
+ }
+
+ @Test
+ public void readTwoClassesInTwoThreads()
+ throws Throwable
+ {
+ final Iterable<String> lazyTestSet =
+ reader.getIterableClasses( new PrintStream( new ByteArrayOutputStream() ) );
+
+ class Provider implements Runnable
+ {
+ public void run()
+ {
+ Iterator<String> it = lazyTestSet.iterator();
+ assertThat( it.next(), is( MasterProcessReaderTest.class.getName() ) );
+ assertThat( it.next(), is( PropertiesWrapperTest.class.getName() ) );
+ assertFalse( it.hasNext() );
+ }
+ }
+
+ ExecutorService es = Executors.newFixedThreadPool( 2 );
+ Future<?> result1 = es.submit( new Provider() );
+ Random rnd = new Random();
+ TimeUnit.MILLISECONDS.sleep( rnd.nextInt( 50 ) );
+ Future<?> result2 = es.submit( new Provider() );
+ TimeUnit.MILLISECONDS.sleep( rnd.nextInt( 50 ) );
+ addThisTestToPipeline( PropertiesWrapperTest.class.getName() );
+ TimeUnit.MILLISECONDS.sleep( rnd.nextInt( 50 ) );
+ addTestSetFinishedToPipeline();
+ for ( Future<?> result : Arrays.asList( result1, result2 ) )
{
- reader.stop( false );
+ try
+ {
+ result.get();
+ }
+ catch ( ExecutionException e )
+ {
+ throw e.getCause();
+ }
}
}
@@ -190,4 +232,13 @@ public class MasterProcessReaderTest
blockingStream.add( buffer.get() );
}
}
+
+ private void addTestSetFinishedToPipeline()
+ throws UnsupportedEncodingException
+ {
+ for ( byte b : MasterProcessCommand.TEST_SET_FINISHED.encode() )
+ {
+ blockingStream.add( b );
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java
index 35dc888..e43a71e 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java
@@ -22,38 +22,36 @@ package org.apache.maven.surefire.common.junit4;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import org.apache.maven.surefire.util.ReflectionUtils;
import org.apache.maven.surefire.util.SurefireReflectionException;
import org.junit.Ignore;
import org.junit.runner.Description;
import org.junit.runner.Request;
+import static org.apache.maven.surefire.util.ReflectionUtils.tryGetMethod;
+import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray;
+
/**
* JUnit4 reflection helper
*
*/
public final class JUnit4Reflector
{
- private static final Class[] PARAMS = new Class[]{ Class.class };
+ private static final Class[] PARAMS = { Class.class };
+
+ private static final Class[] IGNORE_PARAMS = { Ignore.class };
- private static final Class[] IGNORE_PARAMS = new Class[]{ Ignore.class };
+ private static final Class[] PARAMS_WITH_ANNOTATIONS = { String.class, Annotation[].class };
private JUnit4Reflector()
{
throw new IllegalStateException( "not instantiable constructor" );
}
- public static Ignore getAnnotatedIgnore( Description description )
+ public static Ignore getAnnotatedIgnore( Description d )
{
- Method getAnnotation = ReflectionUtils.tryGetMethod( description.getClass(), "getAnnotation", PARAMS );
-
- if ( getAnnotation == null )
- {
- return null;
- }
-
- return (Ignore) ReflectionUtils.invokeMethodWithArray( description, getAnnotation, IGNORE_PARAMS );
+ Method getAnnotation = tryGetMethod( d.getClass(), "getAnnotation", PARAMS );
+ return getAnnotation == null ? null : (Ignore) invokeMethodWithArray( d, getAnnotation, IGNORE_PARAMS );
}
public static String getAnnotatedIgnoreValue( Description description )
@@ -92,20 +90,79 @@ public final class JUnit4Reflector
}
catch ( NoSuchMethodError e )
{
- try
- {
- return (Description) Description.class.getDeclaredMethod( "createSuiteDescription",
- String.class, Annotation[].class )
- .invoke( null, description, new Annotation[0] );
- }
- catch ( InvocationTargetException e1 )
+ Method method = tryGetMethod( Description.class, "createSuiteDescription", PARAMS_WITH_ANNOTATIONS );
+ Object[] parameters = { description, new Annotation[0] };
+ // may throw exception probably with JUnit 5.x
+ return (Description) invokeMethodWithArray( null, method, parameters );
+ }
+ }
+
+ public static Description createDescription( String description, Annotation... annotations )
+ {
+ Method method = tryGetMethod( Description.class, "createSuiteDescription", PARAMS_WITH_ANNOTATIONS );
+ return method == null
+ ? Description.createSuiteDescription( description )
+ : (Description) invokeMethodWithArray( null, method, new Object[] { description, annotations } );
+ }
+
+ public static Ignore createIgnored( String value )
+ {
+ return new IgnoredWithUserError( value );
+ }
+
+ private static class IgnoredWithUserError
+ implements Annotation, Ignore
+ {
+ private final String value;
+
+ public IgnoredWithUserError( String value )
+ {
+ this.value = value;
+ }
+
+ public IgnoredWithUserError()
+ {
+ this( "" );
+ }
+
+ public String value()
+ {
+ return value;
+ }
+
+ public Class<? extends Annotation> annotationType()
+ {
+ return Ignore.class;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return value == null ? 0 : value.hashCode();
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ return obj instanceof Annotation && obj instanceof Ignore && equalValue( ( Ignore ) obj );
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format( "%s(%s)", Ignore.class, value );
+ }
+
+ private boolean equalValue( Ignore ignore )
+ {
+ if ( ignore == null )
{
- throw new SurefireReflectionException( e1.getCause() );
+ return false;
}
- catch ( Exception e1 )
+ else
{
- // probably JUnit 5.x
- throw new SurefireReflectionException( e1 );
+ String val = ignore.value();
+ return val == null ? value == null : val.equals( value );
}
}
}
[16/17] maven-surefire git commit: [SUREFIRE-580] integration tests
Posted by ti...@apache.org.
[SUREFIRE-580] integration tests
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/62c7cd0d
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/62c7cd0d
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/62c7cd0d
Branch: refs/heads/master
Commit: 62c7cd0d6885c073efc48d8fdc3c6c77cf05ae03
Parents: 779e381
Author: Tibor17 <ti...@lycos.com>
Authored: Sun Sep 6 10:50:12 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:04 2015 +0200
----------------------------------------------------------------------
.../maven/surefire/its/AbstractFailFastIT.java | 104 +++++++++++++++++
.../maven/surefire/its/FailFastJUnitIT.java | 68 +++++++++++
.../maven/surefire/its/FailFastTestNgIT.java | 62 ++++++++++
.../surefire/its/fixture/MavenLauncher.java | 9 ++
.../src/test/resources/fail-fast-junit/pom.xml | 112 +++++++++++++++++++
.../src/test/resources/fail-fast-testng/pom.xml | 67 +++++++++++
6 files changed, 422 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/62c7cd0d/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java
new file mode 100644
index 0000000..5b79a4d
--- /dev/null
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java
@@ -0,0 +1,104 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.surefire.its.fixture.MavenLauncher;
+import org.apache.maven.surefire.its.fixture.OutputValidator;
+import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.runners.Parameterized.Parameter;
+
+/**
+ * Base test class for SUREFIRE-580, configuration parameter <em>skipAfterFailureCount</em>.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+@RunWith( Parameterized.class )
+public abstract class AbstractFailFastIT
+ extends SurefireJUnit4IntegrationTestCase
+{
+ @Parameter( 0 )
+ public String description;
+
+ @Parameter( 1 )
+ public String profile;
+
+ @Parameter( 2 )
+ public Map<String, String> properties;
+
+ @Parameter( 3 )
+ public int total;
+
+ @Parameter( 4 )
+ public int failures;
+
+ @Parameter( 5 )
+ public int errors;
+
+ @Parameter( 6 )
+ public int skipped;
+
+ protected abstract String withProvider();
+
+ protected final OutputValidator prepare( String description, String profile, Map<String, String> properties )
+ {
+ MavenLauncher launcher = unpack( "/fail-fast-" + withProvider(), "_" + description )
+ .maven();
+
+ if ( profile != null )
+ {
+ launcher.addGoal( "-P " + profile );
+ }
+
+ if ( failures != 0 || errors != 0 )
+ {
+ launcher.withFailure();
+ }
+
+ return launcher.sysProp( properties ).executeTest();
+ }
+
+ protected final OutputValidator prepare( String description, Map<String, String> properties )
+ {
+ return prepare( description, null, properties );
+ }
+
+ protected static Map<String, String> props( int forkCount, int skipAfterFailureCount )
+ {
+ Map<String, String> props = new HashMap<String, String>( 2 );
+ props.put( "surefire.skipAfterFailureCount", "" + skipAfterFailureCount );
+ props.put( "forkCount", "" + forkCount );
+ return props;
+ }
+
+ @Test
+ public void test()
+ {
+ prepare( description, profile, properties )
+ .assertTestSuiteResults( total, errors, failures, skipped );
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/62c7cd0d/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java
new file mode 100644
index 0000000..3a85d5b
--- /dev/null
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java
@@ -0,0 +1,68 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+
+import static org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Test class for SUREFIRE-580, configuration parameter <em>skipAfterFailureCount</em>.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class FailFastJUnitIT
+ extends AbstractFailFastIT
+{
+
+ @Parameters(name = "{0}")
+ public static Iterable<Object[]> data()
+ {
+ ArrayList<Object[]> args = new ArrayList<Object[]>();
+ // description
+ // profile
+ // forkCount,
+ // fail-fast-count
+ // total
+ // failures
+ // errors
+ // skipped
+ args.add( new Object[] { "junit4-oneFork-ff1", "junit4", props( 1, 1 ), 5, 0, 1, 4 } );
+ args.add( new Object[] { "junit47-oneFork-ff1", "junit47", props( 1, 1 ), 5, 0, 1, 4 } );
+ args.add( new Object[] { "junit4-oneFork-ff2", "junit4", props( 1, 2 ), 5, 0, 2, 3 } );
+ args.add( new Object[] { "junit47-oneFork-ff2", "junit47", props( 1, 2 ), 5, 0, 2, 3 } );
+ args.add( new Object[] { "junit4-twoForks-ff1", "junit4", props( 2, 1 ), 5, 0, 1, 4 } );
+ args.add( new Object[] { "junit47-twoForks-ff1", "junit47",props( 2, 1 ), 5, 0, 1, 4 } );
+ args.add( new Object[] { "junit4-twoForks-ff2", "junit4", props( 2, 2 ), 5, 0, 2, 3 } );
+ args.add( new Object[] { "junit47-twoForks-ff2", "junit47",props( 2, 2 ), 5, 0, 2, 3 } );
+ args.add( new Object[] { "junit4-oneFork-ff3", "junit4", props( 1, 3 ), 5, 0, 2, 0 } );
+ args.add( new Object[] { "junit47-oneFork-ff3", "junit47", props( 1, 3 ), 5, 0, 2, 0 } );
+ args.add( new Object[] { "junit4-twoForks-ff3", "junit4", props( 2, 3 ), 5, 0, 2, 0 } );
+ args.add( new Object[] { "junit47-twoForks-ff3", "junit47",props( 2, 3 ), 5, 0, 2, 0 } );
+ return args;
+ }
+
+ @Override
+ protected String withProvider()
+ {
+ return "junit";
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/62c7cd0d/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java
new file mode 100644
index 0000000..1c2a3bd
--- /dev/null
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java
@@ -0,0 +1,62 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+
+import static org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Test class for SUREFIRE-580, configuration parameter <em>skipAfterFailureCount</em>.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class FailFastTestNgIT
+ extends AbstractFailFastIT
+{
+
+ @Parameters(name = "{0}")
+ public static Iterable<Object[]> data()
+ {
+ ArrayList<Object[]> args = new ArrayList<Object[]>();
+ // description
+ // profile
+ // forkCount,
+ // fail-fast-count
+ // total
+ // failures
+ // errors
+ // skipped
+ args.add( new Object[] { "testng-oneFork-ff1", null, props( 1, 1 ), 5, 1, 0, 4 } );
+ args.add( new Object[] { "testng-oneFork-ff2", null, props( 1, 2 ), 5, 2, 0, 3 } );
+ args.add( new Object[] { "testng-twoForks-ff1", null, props( 2, 1 ), 5, 1, 0, 4 } );
+ args.add( new Object[] { "testng-twoForks-ff2", null, props( 2, 2 ), 5, 2, 0, 3 } );
+ args.add( new Object[] { "testng-oneFork-ff3", null, props( 2, 3 ), 5, 2, 0, 0 } );
+ args.add( new Object[] { "testng-twoForks-ff3", null, props( 2, 3 ), 5, 2, 0, 0 } );
+ return args;
+ }
+
+ @Override
+ protected String withProvider()
+ {
+ return "testng";
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/62c7cd0d/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
index ef5dc33..1198fcb 100755
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
@@ -337,6 +337,15 @@ public class MavenLauncher
return addGoal( "-D" + variable + "=" + value );
}
+ public MavenLauncher sysProp( Map<String, String> properties )
+ {
+ for ( Map.Entry<String, String> property : properties.entrySet() )
+ {
+ sysProp( property.getKey(), property.getValue() );
+ }
+ return this;
+ }
+
public MavenLauncher sysProp( String variable, boolean value )
{
return addGoal( "-D" + variable + "=" + value );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/62c7cd0d/surefire-integration-tests/src/test/resources/fail-fast-junit/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/fail-fast-junit/pom.xml b/surefire-integration-tests/src/test/resources/fail-fast-junit/pom.xml
new file mode 100644
index 0000000..6a6be11
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/fail-fast-junit/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>it-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <groupId>org.apache.maven.plugins.surefire</groupId>
+ <artifactId>jiras-surefire-580-junit</artifactId>
+ <version>1.0</version>
+
+ <properties>
+ <junit>4.0</junit>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <runOrder>alphabetical</runOrder>
+ <reuseForks>true</reuseForks>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>junit4</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit4</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>junit47</id>
+ <properties>
+ <junit>4.7</junit>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/62c7cd0d/surefire-integration-tests/src/test/resources/fail-fast-testng/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/fail-fast-testng/pom.xml b/surefire-integration-tests/src/test/resources/fail-fast-testng/pom.xml
new file mode 100644
index 0000000..4fb8385
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/fail-fast-testng/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>it-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <groupId>org.apache.maven.plugins.surefire</groupId>
+ <artifactId>jiras-surefire-580-testng</artifactId>
+ <version>1.0</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>5.10</version>
+ <classifier>jdk15</classifier>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <runOrder>alphabetical</runOrder>
+ <reuseForks>true</reuseForks>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
[04/17] maven-surefire git commit: [SUREFIRE] MasterProcessReader
Thread should be quite after throwing exception
Posted by ti...@apache.org.
[SUREFIRE] MasterProcessReader Thread should be quite after throwing exception
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/8e37515a
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/8e37515a
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/8e37515a
Branch: refs/heads/master
Commit: 8e37515a06a804a154713daf0b0b53dc319a6e0a
Parents: 67af00f
Author: Tibor17 <ti...@lycos.com>
Authored: Sat Jul 25 03:30:55 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:55 2015 +0200
----------------------------------------------------------------------
.../org/apache/maven/surefire/booter/MasterProcessReader.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/8e37515a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
index 1d86167..2dde2e1 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
@@ -228,10 +228,12 @@ public final class MasterProcessReader
}
catch ( IOException e )
{
+ MasterProcessReader.this.state.set( TERMINATED );
+ }
+ finally
+ {
// ensure fail-safe iterator as well as safe to finish in for-each loop using ClassesIterator
insert( new Command( TEST_SET_FINISHED ) );
- // and let us know what has happened with the stream
- throw new IllegalStateException( e.getLocalizedMessage(), e );
}
}
[15/17] maven-surefire git commit: [SUREFIRE-580] configuration
parameter 'skipAfterFailureCount'
Posted by ti...@apache.org.
[SUREFIRE-580] configuration parameter 'skipAfterFailureCount'
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/779e3811
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/779e3811
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/779e3811
Branch: refs/heads/master
Commit: 779e381102a8f882e58c95ad3e50eadca170cba7
Parents: 1b7fe2d
Author: Tibor17 <ti...@lycos.com>
Authored: Sat Sep 5 01:15:07 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:04 2015 +0200
----------------------------------------------------------------------
.../surefire/booterclient/ForkStarter.java | 12 ++-
surefire-api/pom.xml | 6 ++
.../util/internal/ConcurrencyUtils.java | 64 ++++++++++++
.../java/org/apache/maven/JUnit4SuiteTest.java | 78 ++++++++++++++
.../util/internal/ConcurrencyUtilsTest.java | 104 +++++++++++++++++++
.../maven/surefire/common/junit4/Notifier.java | 35 ++++---
.../maven/surefire/common/junit4/Stoppable.java | 35 +++++++
.../surefire/junit4/JUnit4FailFastListener.java | 13 +--
.../maven/surefire/junit4/JUnit4Provider.java | 11 +-
.../junitcore/JUnit47FailFastListener.java | 5 +-
.../maven/surefire/junitcore/JUnitCore.java | 11 --
.../surefire/junitcore/JUnitCoreProvider.java | 9 +-
.../surefire/junitcore/JUnitCoreWrapper.java | 15 ++-
.../maven/surefire/junitcore/Stoppable.java | 32 ------
.../surefire/testng/utils/FailFastListener.java | 3 +-
.../maven/surefire/testng/utils/Stoppable.java | 4 +-
.../testng/TestNGDirectoryTestSuite.java | 15 +--
.../maven/surefire/testng/TestNGExecutor.java | 43 +++++---
.../maven/surefire/testng/TestNGProvider.java | 10 +-
.../surefire/testng/TestNGXmlTestSuite.java | 8 +-
20 files changed, 397 insertions(+), 116 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 632834f..396e99f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
@@ -67,7 +67,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static org.apache.maven.shared.utils.cli.CommandLineUtils.executeCommandLine;
@@ -79,6 +79,7 @@ import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDae
import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder;
import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.
TestLessInputStream.TestLessInputStreamBuilder;
+import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero;
import static org.apache.maven.surefire.booter.Classpath.join;
import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
import static org.apache.maven.surefire.suite.RunResult.timeout;
@@ -248,7 +249,7 @@ public class ForkStarter
testStreams.add( new TestProvidingInputStream( tests ) );
}
- final AtomicBoolean notifyStreamsToSkipTestsJustNow = new AtomicBoolean();
+ final AtomicInteger notifyStreamsToSkipTestsJustNow = new AtomicInteger();
Collection<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount );
for ( final TestProvidingInputStream testProvidingInputStream : testStreams )
{
@@ -267,7 +268,7 @@ public class ForkStarter
@Override
protected void stopOnNextTest()
{
- if ( notifyStreamsToSkipTestsJustNow.compareAndSet( false, true ) )
+ if ( countDownToZero( notifyStreamsToSkipTestsJustNow ) )
{
notifyStreamsToSkipTests( testStreams );
}
@@ -306,7 +307,8 @@ public class ForkStarter
executorService.setThreadFactory( threadFactory );
try
{
- final AtomicBoolean notifyStreamsToSkipTestsJustNow = new AtomicBoolean();
+ int failFastCount = providerConfiguration.getSkipAfterFailureCount();
+ final AtomicInteger notifyStreamsToSkipTestsJustNow = new AtomicInteger( failFastCount );
final TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
for ( final Object testSet : getSuitesIterator() )
{
@@ -324,7 +326,7 @@ public class ForkStarter
@Override
protected void stopOnNextTest()
{
- if ( notifyStreamsToSkipTestsJustNow.compareAndSet( false, true ) )
+ if ( countDownToZero( notifyStreamsToSkipTestsJustNow ) )
{
builder.getCachableCommands().skipSinceNextTest();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-api/pom.xml b/surefire-api/pom.xml
index 6f66e66..3567b93 100644
--- a/surefire-api/pom.xml
+++ b/surefire-api/pom.xml
@@ -42,6 +42,12 @@
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ <includes>
+ <include>**/JUnit4SuiteTest.java</include>
+ </includes>
+ </configuration>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java
new file mode 100644
index 0000000..6cfc6bf
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ConcurrencyUtils.java
@@ -0,0 +1,64 @@
+package org.apache.maven.surefire.util.internal;
+
+/*
+ * 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.
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Concurrency utilities.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public final class ConcurrencyUtils
+{
+ private ConcurrencyUtils()
+ {
+ throw new IllegalStateException( "not instantiable constructor" );
+ }
+
+ /**
+ * Decreases {@code counter} to zero, or does not change the counter if negative.
+ * This method pretends been atomic. Only one thread can succeed setting the counter to zero.
+ *
+ * @param counter atomic counter
+ * @return {@code true} if this Thread modified concurrent counter from any positive number down to zero.
+ */
+ @SuppressWarnings( "checkstyle:emptyforiteratorpad" )
+ public static boolean countDownToZero( AtomicInteger counter )
+ {
+ for (;;)
+ {
+ int c = counter.get();
+ if ( c > 0 )
+ {
+ int newCounter = c - 1;
+ if ( counter.compareAndSet( c, newCounter ) )
+ {
+ return newCounter == 0;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
new file mode 100644
index 0000000..c2ec153
--- /dev/null
+++ b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
@@ -0,0 +1,78 @@
+package org.apache.maven;
+
+/*
+ * 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.
+ */
+
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.Test;
+import org.apache.maven.plugin.surefire.runorder.ThreadedExecutionSchedulerTest;
+import org.apache.maven.surefire.SpecificTestClassFilterTest;
+import org.apache.maven.surefire.booter.ForkingRunListenerTest;
+import org.apache.maven.surefire.booter.MasterProcessCommandTest;
+import org.apache.maven.surefire.booter.SurefireReflectorTest;
+import org.apache.maven.surefire.report.LegacyPojoStackTraceWriterTest;
+import org.apache.maven.surefire.suite.RunResultTest;
+import org.apache.maven.surefire.testset.ResolvedTestTest;
+import org.apache.maven.surefire.testset.TestListResolverTest;
+import org.apache.maven.surefire.util.DefaultDirectoryScannerTest;
+import org.apache.maven.surefire.util.RunOrderCalculatorTest;
+import org.apache.maven.surefire.util.RunOrderTest;
+import org.apache.maven.surefire.util.ScanResultTest;
+import org.apache.maven.surefire.util.TestsToRunTest;
+import org.apache.maven.surefire.util.UrlUtilsTest;
+import org.apache.maven.surefire.util.internal.ByteBufferTest;
+import org.apache.maven.surefire.util.internal.ConcurrencyUtilsTest;
+import org.apache.maven.surefire.util.internal.StringUtilsTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite.
+ *
+ * @author Tibor Digana (tibor17)
+ * @since 2.19
+ */
+@Suite.SuiteClasses( {
+ ThreadedExecutionSchedulerTest.class,
+ ForkingRunListenerTest.class,
+ MasterProcessCommandTest.class,
+ SurefireReflectorTest.class,
+ LegacyPojoStackTraceWriterTest.class,
+ RunResultTest.class,
+ ResolvedTestTest.class,
+ TestListResolverTest.class,
+ ByteBufferTest.class,
+ ConcurrencyUtilsTest.class,
+ StringUtilsTest.class,
+ DefaultDirectoryScannerTest.class,
+ RunOrderCalculatorTest.class,
+ RunOrderTest.class,
+ ScanResultTest.class,
+ TestsToRunTest.class,
+ UrlUtilsTest.class,
+ SpecificTestClassFilterTest.class
+} )
+@RunWith( Suite.class )
+public class JUnit4SuiteTest
+{
+ public static Test suite()
+ {
+ return new JUnit4TestAdapter( JUnit4SuiteTest.class );
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java
new file mode 100644
index 0000000..516f885
--- /dev/null
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java
@@ -0,0 +1,104 @@
+package org.apache.maven.surefire.util.internal;
+
+/*
+ * 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.
+ */
+
+import org.junit.Test;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * Concurrency utilities.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public class ConcurrencyUtilsTest
+{
+
+ @Test
+ public void countDownShouldBeUnchangedAsZero$NegativeTest()
+ {
+ AtomicInteger atomicCounter = new AtomicInteger( 0 );
+ assertFalse( countDownToZero( atomicCounter ) );
+ assertThat( atomicCounter.get(), is( 0 ) );
+ }
+
+ @Test
+ public void countDownShouldBeUnchangedAsNegative$NegativeTest()
+ {
+ AtomicInteger atomicCounter = new AtomicInteger( -1 );
+ assertFalse( countDownToZero( atomicCounter ) );
+ assertThat( atomicCounter.get(), is( -1 ) );
+ }
+
+ @Test
+ public void countDownShouldBeDecreasedByOneThreadModification()
+ {
+ AtomicInteger atomicCounter = new AtomicInteger( 10 );
+ assertFalse( countDownToZero( atomicCounter ) );
+ assertThat( atomicCounter.get(), is( 9 ) );
+ }
+
+ @Test
+ public void countDownToZeroShouldBeDecreasedByOneThreadModification()
+ {
+ AtomicInteger atomicCounter = new AtomicInteger( 1 );
+ assertTrue( countDownToZero( atomicCounter ) );
+ assertThat( atomicCounter.get(), is( 0 ) );
+ }
+
+ @Test
+ public void countDownShouldBeDecreasedByTwoThreadsModification()
+ throws ExecutionException, InterruptedException
+ {
+ final AtomicInteger atomicCounter = new AtomicInteger( 3 );
+
+ FutureTask<Boolean> task = new FutureTask<Boolean>( new Callable<Boolean>()
+ {
+ public Boolean call()
+ throws Exception
+ {
+ return countDownToZero( atomicCounter );
+ }
+ } );
+ Thread t = new Thread( task );
+ t.start();
+
+ assertFalse( countDownToZero( atomicCounter ) );
+
+ assertFalse( task.get() );
+
+ assertThat( atomicCounter.get(), is( 1 ) );
+
+ assertTrue( countDownToZero( atomicCounter ) );
+
+ assertThat( atomicCounter.get(), is( 0 ) );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
index e9136e1..5748e4b 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java
@@ -25,6 +25,9 @@ import org.junit.runner.notification.RunNotifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero;
/**
* Extends {@link RunNotifier JUnit notifier},
@@ -35,31 +38,29 @@ import java.util.Iterator;
* @since 2.19
*/
public class Notifier
- extends RunNotifier
+ extends RunNotifier implements Stoppable
{
private final Collection<RunListener> listeners = new ArrayList<RunListener>();
- private JUnit4RunListener reporter;
+ private final AtomicInteger skipAfterFailureCount;
- @Override
- public void pleaseStop()
+ private final JUnit4RunListener reporter;
+
+ public Notifier( JUnit4RunListener reporter, int skipAfterFailureCount )
{
- super.pleaseStop();
- reporter.testExecutionSkippedByUser();
+ addListener( reporter );
+ this.reporter = reporter;
+ this.skipAfterFailureCount = new AtomicInteger( skipAfterFailureCount );
}
- /**
- * Adds reporter listener to the bottom of queue and retrieves old reporter if any exists.
- *
- * @param reporter registered listener
- * @return old listener; or null if did not exist
- */
- public JUnit4RunListener setReporter( JUnit4RunListener reporter )
+ public void fireStopEvent()
{
- JUnit4RunListener old = this.reporter;
- this.reporter = reporter;
- addListener( reporter );
- return old;
+ if ( countDownToZero( skipAfterFailureCount ) )
+ {
+ pleaseStop();
+ }
+
+ reporter.testExecutionSkippedByUser();
}
@Override
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java
new file mode 100644
index 0000000..376d631
--- /dev/null
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Stoppable.java
@@ -0,0 +1,35 @@
+package org.apache.maven.surefire.common.junit4;
+
+/*
+ * 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.
+ */
+
+/**
+ * Covers configuration parameter <em>skipAfterFailureCount</em>.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ * @see org.apache.maven.surefire.common.junit4.Notifier
+ */
+public interface Stoppable
+{
+ /**
+ * Fire stop even to plugin process and/or call {@link org.junit.runner.notification.RunNotifier#pleaseStop()}.
+ */
+ void fireStopEvent();
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
index d45b678..84346e7 100644
--- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
+++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4FailFastListener.java
@@ -19,12 +19,13 @@ package org.apache.maven.surefire.junit4;
* under the License.
*/
+import org.apache.maven.surefire.common.junit4.Notifier;
+import org.apache.maven.surefire.common.junit4.Stoppable;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
-import org.junit.runner.notification.RunNotifier;
/**
- * Calling {@link RunNotifier#pleaseStop()} if failure appeared.
+ * Calling {@link Notifier#fireStopEvent()} if failure happens.
*
* @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
* @since 2.19
@@ -32,17 +33,17 @@ import org.junit.runner.notification.RunNotifier;
final class JUnit4FailFastListener
extends RunListener
{
- private final RunNotifier notifier;
+ private final Stoppable stoppable;
- JUnit4FailFastListener( RunNotifier notifier )
+ JUnit4FailFastListener( Notifier stoppable )
{
- this.notifier = notifier;
+ this.stoppable = stoppable;
}
@Override
public void testFailure( Failure failure )
throws Exception
{
- notifier.pleaseStop();
+ stoppable.fireStopEvent();
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
index e8f041d..2276eac 100644
--- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
+++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
@@ -146,8 +146,7 @@ public class JUnit4Provider
startCapture( (ConsoleOutputReceiver) reporter );
- Notifier notifier = new Notifier();
- notifier.setReporter( new JUnit4RunListener( reporter ) );
+ Notifier notifier = new Notifier( new JUnit4RunListener( reporter ), getSkipAfterFailureCount() );
if ( isFailFast() )
{
notifier.addListener( new JUnit4FailFastListener( notifier ) );
@@ -193,6 +192,11 @@ public class JUnit4Provider
return providerParameters.getSkipAfterFailureCount() > 0;
}
+ private int getSkipAfterFailureCount()
+ {
+ return isFailFast() && !isRerunFailingTests() ? providerParameters.getSkipAfterFailureCount() : 0;
+ }
+
private void closeCommandsReader()
{
if ( commandsReader != null )
@@ -227,7 +231,8 @@ public class JUnit4Provider
if ( isFailFast() && e instanceof StoppedByUserException )
{
String reason = e.getClass().getName();
- notifier.fireTestIgnored( createDescription( clazz.getName(), createIgnored( reason ) ) );
+ Description skippedTest = createDescription( clazz.getName(), createIgnored( reason ) );
+ notifier.fireTestIgnored( skippedTest );
}
else
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
index dda6b68..0f6efc9 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnit47FailFastListener.java
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.junitcore;
* under the License.
*/
+import org.apache.maven.surefire.common.junit4.Stoppable;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
@@ -27,7 +28,7 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
- * Calling {@link Stoppable#pleaseStop()} if failure appeared.
+ * Calling {@link Stoppable#fireStopEvent()} if failure happens.
*
* @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
* @since 2.19
@@ -60,6 +61,6 @@ final class JUnit47FailFastListener
public void testFailure( Failure failure )
throws Exception
{
- stoppable.pleaseStop();
+ stoppable.fireStopEvent();
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
index 7f1a03a..9935d9a 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCore.java
@@ -29,15 +29,12 @@ import org.junit.runner.notification.RunListener;
* JUnitCore solves bugs in original junit class {@link org.junit.runner.JUnitCore}.<p>
* The notifier method {@link org.junit.runner.notification.RunNotifier#fireTestRunFinished}
* is called anyway in finally block.
- * This class provides method {@link #pleaseStop()} without any need to retrieve
- * {@link org.junit.runner.notification.RunNotifier} outside.
*
* @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
* @since 2.19
* @see https://github.com/junit-team/junit/issues/1186
*/
class JUnitCore
- implements Stoppable
{
private final Notifier notifier;
@@ -79,12 +76,4 @@ class JUnitCore
protected void afterFinished()
{
}
-
- /**
- * {@inheritDoc}
- */
- public void pleaseStop()
- {
- notifier.pleaseStop();
- }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
index 243cca0..29687ef 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
@@ -145,8 +145,8 @@ public class JUnitCoreProvider
}
}
- Notifier notifier = new Notifier();
- notifier.setReporter( createRunListener( reporterFactory, consoleLogger ) );
+ Notifier notifier =
+ new Notifier( createRunListener( reporterFactory, consoleLogger ), getSkipAfterFailureCount() );
// Add test failure listener
JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener();
@@ -195,6 +195,11 @@ public class JUnitCoreProvider
return providerParameters.getSkipAfterFailureCount() > 0;
}
+ private int getSkipAfterFailureCount()
+ {
+ return isFailFast() && !isRerunFailingTests() ? providerParameters.getSkipAfterFailureCount() : 0;
+ }
+
private void closeCommandsReader()
{
if ( commandsReader != null )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
index e0c9f9e..eb41217 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
@@ -27,6 +27,7 @@ import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.TestsToRun;
import org.junit.Ignore;
import org.junit.runner.Computer;
+import org.junit.runner.Description;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.manipulation.Filter;
@@ -36,7 +37,6 @@ import org.junit.runner.notification.StoppedByUserException;
import java.util.Collection;
import java.util.Collections;
import java.util.Queue;
-import java.util.Random;
import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createDescription;
import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.createIgnored;
@@ -54,8 +54,6 @@ final class JUnitCoreWrapper
private final ConsoleLogger logger;
private final boolean failFast;
- private Object o = new Random().nextInt();
-
JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleLogger logger,
boolean failFast )
{
@@ -86,7 +84,7 @@ final class JUnitCoreWrapper
private JUnitCore createJUnitCore( final Notifier notifier, Collection<RunListener> listeners )
{
- JUnitCore junitCore = new JUnitCore( notifier );
+ JUnitCore junitCore = new JUnitCore();
// custom listeners added last
notifier.addListeners( listeners );
@@ -154,10 +152,10 @@ final class JUnitCoreWrapper
{
private final JUnit47FailFastListener failFastListener;
- JUnitCore( Notifier notifier )
+ JUnitCore()
{
super( notifier );
- failFastListener = failFast ? new JUnit47FailFastListener( this ) : null;
+ failFastListener = failFast ? new JUnit47FailFastListener( notifier ) : null;
if ( failFastListener != null )
{
notifier.addListener( failFastListener );
@@ -188,10 +186,11 @@ final class JUnitCoreWrapper
if ( stoppedTests != null )
{
String reason = e.getClass().getName();
- Ignore reasonForIgnoredTest = createIgnored( reason );
+ Ignore reasonForSkippedTest = createIgnored( reason );
for ( String clazz; ( clazz = stoppedTests.poll() ) != null; )
{
- notifier.fireTestIgnored( createDescription( clazz, reasonForIgnoredTest ) );
+ Description skippedTest = createDescription( clazz, reasonForSkippedTest );
+ notifier.fireTestIgnored( skippedTest );
}
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java
deleted file mode 100644
index 2450e64..0000000
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/Stoppable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.apache.maven.surefire.junitcore;
-
-/*
- * 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.
- */
-
-/**
- * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
- * @since 2.19
- */
-interface Stoppable
-{
- /**
- * Delegates this call to {@link org.junit.runner.notification.RunNotifier#pleaseStop()}.
- */
- void pleaseStop();
-}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
index d3d5c00..91f3461 100644
--- a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/FailFastListener.java
@@ -51,8 +51,7 @@ public class FailFastListener
public void onTestFailure( ITestResult result )
{
- FailFastEventsSingleton.getInstance().setSkipOnNextTest();
- stoppable.pleaseStop();
+ stoppable.fireStopEvent();
}
public void onTestSkipped( ITestResult result )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
index c7be682..dd172d2 100644
--- a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/Stoppable.java
@@ -20,6 +20,8 @@ package org.apache.maven.surefire.testng.utils;
*/
/**
+ * Covers configuration parameter <em>skipAfterFailureCount</em>.
+ *
* @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
* @since 2.19
*/
@@ -28,5 +30,5 @@ public interface Stoppable
/**
* Delegates this call to {@link org.apache.maven.surefire.report.RunListener#testExecutionSkippedByUser()}.
*/
- void pleaseStop();
+ void fireStopEvent();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
index 5297276..a721bbc 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
@@ -79,11 +79,12 @@ public class TestNGDirectoryTestSuite
private final List<CommandLineOption> mainCliOptions;
- private final boolean isFailFast;
+ private final int skipAfterFailureCount;
public TestNGDirectoryTestSuite( String testSourceDirectory, Map<String, String> confOptions, File reportsDirectory,
TestListResolver methodFilter, RunOrderCalculator runOrderCalculator,
- ScanResult scanResult, List<CommandLineOption> mainCliOptions, boolean isFailFast )
+ ScanResult scanResult, List<CommandLineOption> mainCliOptions,
+ int skipAfterFailureCount )
{
this.runOrderCalculator = runOrderCalculator;
this.options = confOptions;
@@ -96,7 +97,7 @@ public class TestNGDirectoryTestSuite
this.junitTestAnnotation = findJUnitTestAnnotation();
this.junitOptions = createJUnitOptions();
this.mainCliOptions = mainCliOptions;
- this.isFailFast = isFailFast;
+ this.skipAfterFailureCount = skipAfterFailureCount;
}
public void execute( TestsToRun testsToRun, ReporterFactory reporterManagerFactory )
@@ -131,7 +132,7 @@ public class TestNGDirectoryTestSuite
final Map<String, String> optionsToUse = isJUnitTest( testClass ) ? junitOptions : options;
TestNGExecutor.run( new Class<?>[]{ testClass }, testSourceDirectory, optionsToUse, reporter, this,
- reportsDirectory, methodFilter, mainCliOptions, isFailFast );
+ reportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
finishTestSuite( reporter, this );
}
@@ -221,14 +222,14 @@ public class TestNGDirectoryTestSuite
Class<?>[] testClasses = testNgTestClasses.toArray( new Class<?>[testNgTestClasses.size()] );
TestNGExecutor.run( testClasses, testSourceDirectory, options, reporterManager, this,
- testNgReportsDirectory, methodFilter, mainCliOptions, isFailFast );
+ testNgReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
if ( !junitTestClasses.isEmpty() )
{
testClasses = junitTestClasses.toArray( new Class[junitTestClasses.size()] );
TestNGExecutor.run( testClasses, testSourceDirectory, junitOptions, reporterManager, this,
- junitReportsDirectory, methodFilter, mainCliOptions, isFailFast );
+ junitReportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
}
finishTestSuite( reporterManager, this );
@@ -298,7 +299,7 @@ public class TestNGDirectoryTestSuite
startTestSuite( reporter, this );
TestNGExecutor.run( new Class<?>[] { testSet.getTestClass() }, testSourceDirectory, options, reporter,
- this, reportsDirectory, methodFilter, mainCliOptions, isFailFast );
+ this, reportsDirectory, methodFilter, mainCliOptions, skipAfterFailureCount );
finishTestSuite( reporter, this );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
index d481bb2..5a91db0 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
@@ -23,6 +23,7 @@ import org.apache.maven.surefire.booter.ProviderParameterNames;
import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.testng.conf.Configurator;
+import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton;
import org.apache.maven.surefire.testng.utils.FailFastListener;
import org.apache.maven.surefire.testng.utils.Stoppable;
import org.apache.maven.surefire.testset.TestListResolver;
@@ -45,8 +46,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.maven.surefire.util.ReflectionUtils.instantiate;
+import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero;
/**
* Contains utility methods for executing TestNG.
@@ -73,7 +76,8 @@ public class TestNGExecutor
public static void run( Class<?>[] testClasses, String testSourceDirectory,
Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
RunListener reportManager, TestNgTestSuite suite, File reportsDirectory,
- TestListResolver methodFilter, List<CommandLineOption> mainCliOptions, boolean isFailFast )
+ TestListResolver methodFilter, List<CommandLineOption> mainCliOptions,
+ int skipAfterFailureCount )
throws TestSetFailedException
{
TestNG testng = new TestNG( true );
@@ -123,7 +127,7 @@ public class TestNGExecutor
testng.setXmlSuites( xmlSuites );
configurator.configure( testng, options );
- postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast );
+ postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, skipAfterFailureCount );
testng.run();
}
@@ -265,13 +269,13 @@ public class TestNGExecutor
public static void run( List<String> suiteFiles, String testSourceDirectory,
Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
RunListener reportManager, TestNgTestSuite suite, File reportsDirectory,
- boolean isFailFast )
+ int skipAfterFailureCount )
throws TestSetFailedException
{
TestNG testng = new TestNG( true );
Configurator configurator = getConfigurator( options.get( "testng.configurator" ) );
configurator.configure( testng, options );
- postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast );
+ postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, skipAfterFailureCount );
testng.setTestSuites( suiteFiles );
testng.run();
}
@@ -297,7 +301,7 @@ public class TestNGExecutor
}
private static void postConfigure( TestNG testNG, String sourcePath, final RunListener reportManager,
- TestNgTestSuite suite, File reportsDirectory, boolean skipAfterFailure )
+ TestNgTestSuite suite, File reportsDirectory, int skipAfterFailureCount )
throws TestSetFailedException
{
// turn off all TestNG output
@@ -306,19 +310,12 @@ public class TestNGExecutor
TestNGReporter reporter = createTestNGReporter( reportManager, suite );
testNG.addListener( (Object) reporter );
- if ( skipAfterFailure )
+ if ( skipAfterFailureCount > 0 )
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
testNG.addListener( instantiate( cl, "org.apache.maven.surefire.testng.utils.FailFastNotifier",
Object.class ) );
- Stoppable stoppable = new Stoppable()
- {
- public void pleaseStop()
- {
- reportManager.testExecutionSkippedByUser();
- }
- };
- testNG.addListener( new FailFastListener( stoppable ) );
+ testNG.addListener( new FailFastListener( createStoppable( reportManager, skipAfterFailureCount ) ) );
}
// FIXME: use classifier to decide if we need to pass along the source dir (only for JDK14)
@@ -330,6 +327,24 @@ public class TestNGExecutor
testNG.setOutputDirectory( reportsDirectory.getAbsolutePath() );
}
+ private static Stoppable createStoppable( final RunListener reportManager, int skipAfterFailureCount )
+ {
+ final AtomicInteger currentFaultCount = new AtomicInteger( skipAfterFailureCount );
+
+ return new Stoppable()
+ {
+ public void fireStopEvent()
+ {
+ if ( countDownToZero( currentFaultCount ) )
+ {
+ FailFastEventsSingleton.getInstance().setSkipOnNextTest();
+ }
+
+ reportManager.testExecutionSkippedByUser();
+ }
+ };
+ }
+
// If we have access to IResultListener, return a ConfigurationAwareTestNGReporter
// But don't cause NoClassDefFoundErrors if it isn't available; just return a regular TestNGReporter instead
private static TestNGReporter createTestNGReporter( RunListener reportManager, TestNgTestSuite suite )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
index 8777ceb..77b5c75 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
@@ -149,6 +149,11 @@ public class TestNGProvider
return providerParameters.getSkipAfterFailureCount() > 0;
}
+ private int getSkipAfterFailureCount()
+ {
+ return isFailFast() ? providerParameters.getSkipAfterFailureCount() : 0;
+ }
+
private void closeCommandsReader()
{
if ( commandsReader != null )
@@ -174,7 +179,8 @@ public class TestNGProvider
{
return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties,
reporterConfiguration.getReportsDirectory(), createMethodFilter(),
- runOrderCalculator, scanResult, mainCliOptions, isFailFast() );
+ runOrderCalculator, scanResult, mainCliOptions,
+ getSkipAfterFailureCount() );
}
private TestNGXmlTestSuite newXmlSuite()
@@ -182,7 +188,7 @@ public class TestNGProvider
return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(),
testRequest.getTestSourceDirectory().toString(),
providerProperties,
- reporterConfiguration.getReportsDirectory(), isFailFast() );
+ reporterConfiguration.getReportsDirectory(), getSkipAfterFailureCount() );
}
@SuppressWarnings( "unchecked" )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/779e3811/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
index bf105fe..ab9ae7f 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
@@ -49,7 +49,7 @@ public class TestNGXmlTestSuite
private final File reportsDirectory;
- private final boolean isFailFast;
+ private final int skipAfterFailureCount;
// Not really used
private Map<File, String> testSets;
@@ -59,13 +59,13 @@ public class TestNGXmlTestSuite
* xml file(s). The XML files are suite definitions files according to TestNG DTD.
*/
public TestNGXmlTestSuite( List<File> suiteFiles, String testSourceDirectory, Map<String, String> confOptions,
- File reportsDirectory, boolean isFailFast )
+ File reportsDirectory, int skipAfterFailureCount )
{
this.suiteFiles = suiteFiles;
this.options = confOptions;
this.testSourceDirectory = testSourceDirectory;
this.reportsDirectory = reportsDirectory;
- this.isFailFast = isFailFast;
+ this.skipAfterFailureCount = skipAfterFailureCount;
}
public void execute( ReporterFactory reporterManagerFactory )
@@ -81,7 +81,7 @@ public class TestNGXmlTestSuite
TestNGDirectoryTestSuite.startTestSuite( reporter, this );
TestNGExecutor.run( suiteFilePaths, testSourceDirectory, options, reporter, this, reportsDirectory,
- isFailFast );
+ skipAfterFailureCount );
TestNGDirectoryTestSuite.finishTestSuite( reporter, this );
}
[11/17] maven-surefire git commit: [SUREFIRE-580] sanity check
Posted by ti...@apache.org.
[SUREFIRE-580] sanity check
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/3eb6fa72
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/3eb6fa72
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/3eb6fa72
Branch: refs/heads/master
Commit: 3eb6fa7259846ec514f943cbf0b16450efde56b0
Parents: 2a944f0
Author: Tibor17 <ti...@lycos.com>
Authored: Thu Sep 3 11:20:29 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:58:00 2015 +0200
----------------------------------------------------------------------
.../plugin/surefire/AbstractSurefireMojo.java | 23 +++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/3eb6fa72/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git 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
index f847604..e8f1f75 100644
--- 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
@@ -826,6 +826,7 @@ public abstract class AbstractSurefireMojo
ensureThreadCountWithPerThread();
warnIfUselessUseSystemClassLoaderParameter();
warnIfDefunctGroupsCombinations();
+ warnIfRerunClashes();
}
return true;
}
@@ -2256,7 +2257,7 @@ public abstract class AbstractSurefireMojo
}
- void ensureWorkingDirectoryExists()
+ private void ensureWorkingDirectoryExists()
throws MojoFailureException
{
if ( getWorkingDirectory() == null )
@@ -2286,7 +2287,7 @@ public abstract class AbstractSurefireMojo
}
}
- void ensureParallelRunningCompatibility()
+ private void ensureParallelRunningCompatibility()
throws MojoFailureException
{
if ( isMavenParallel() && isNotForking() )
@@ -2295,7 +2296,7 @@ public abstract class AbstractSurefireMojo
}
}
- void ensureThreadCountWithPerThread()
+ private void ensureThreadCountWithPerThread()
throws MojoFailureException
{
if ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) && getThreadCount() < 1 )
@@ -2304,7 +2305,7 @@ public abstract class AbstractSurefireMojo
}
}
- void warnIfUselessUseSystemClassLoaderParameter()
+ private void warnIfUselessUseSystemClassLoaderParameter()
{
if ( isUseSystemClassLoader() && isNotForking() )
{
@@ -2322,7 +2323,7 @@ public abstract class AbstractSurefireMojo
return SurefireHelper.commandLineOptions( getSession(), getLog() );
}
- void warnIfDefunctGroupsCombinations()
+ private void warnIfDefunctGroupsCombinations()
throws MojoFailureException, MojoExecutionException
{
if ( isAnyGroupsSelected() )
@@ -2348,6 +2349,18 @@ public abstract class AbstractSurefireMojo
}
}
+ private void warnIfRerunClashes()
+ throws MojoFailureException
+ {
+ boolean isRerun = getRerunFailingTestsCount() > 0;
+ boolean isFailFast = getSkipAfterFailureCount() > 0;
+ if ( isRerun && isFailFast )
+ {
+ throw new MojoFailureException( "Parameters [rerunFailingTestsCount, skipAfterFailureCount] "
+ + "should not be enabled together." );
+ }
+ }
+
final class TestNgProviderInfo
implements ProviderInfo
{
[10/17] maven-surefire git commit: [SUREFIRE-580] Allow "fail fast"
or stop running on first failure
Posted by ti...@apache.org.
[SUREFIRE-580] Allow "fail fast" or stop running on first failure
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/2a944f06
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/2a944f06
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/2a944f06
Branch: refs/heads/master
Commit: 2a944f0687ee849003403e401d69750af856fc47
Parents: 8c34806
Author: Tibor17 <ti...@lycos.com>
Authored: Thu Sep 3 01:33:26 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:59 2015 +0200
----------------------------------------------------------------------
.../plugin/failsafe/IntegrationTestMojo.java | 16 +
.../plugin/surefire/AbstractSurefireMojo.java | 48 +-
.../surefire/SurefireExecutionParameters.java | 2 +
.../plugin/surefire/SurefireProperties.java | 57 +--
.../surefire/booterclient/BooterSerializer.java | 1 +
.../surefire/booterclient/ForkStarter.java | 219 +++++----
.../surefire/booterclient/MockReporter.java | 160 -------
.../lazytestprovider/AbstractCommandStream.java | 122 +++++
.../AbstractForkInputStream.java | 61 +++
.../lazytestprovider/NotifiableTestStream.java | 14 +
.../lazytestprovider/TestLessInputStream.java | 453 +++++++++++++++++++
.../TestProvidingInputStream.java | 169 +++----
.../booterclient/output/ForkClient.java | 7 +
.../surefire/report/TestSetRunListener.java | 4 +
...erDeserializerProviderConfigurationTest.java | 2 +-
...terDeserializerStartupConfigurationTest.java | 2 +-
.../surefire/booterclient/MockReporter.java | 161 +++++++
.../TestLessInputStreamBuilderTest.java | 128 ++++++
.../TestProvidingInputStreamTest.java | 15 +-
.../apache/maven/surefire/JUnit4SuiteTest.java | 2 +
.../maven/plugin/surefire/SurefirePlugin.java | 17 +-
.../site/apt/examples/skip-after-failure.apt.vm | 58 +++
maven-surefire-plugin/src/site/site.xml | 1 +
.../surefire/booter/BaseProviderFactory.java | 20 +-
.../apache/maven/surefire/booter/Command.java | 38 +-
.../maven/surefire/booter/FailFastAware.java | 31 ++
.../surefire/booter/ForkingReporterFactory.java | 2 +-
.../surefire/booter/ForkingRunListener.java | 17 +-
.../surefire/booter/MasterProcessCommand.java | 12 +-
.../surefire/booter/MasterProcessListener.java | 28 ++
.../surefire/booter/MasterProcessReader.java | 421 +++++++++++++++++
.../surefire/booter/SurefireReflector.java | 5 +
.../surefire/booter/TwoPropertiesWrapper.java | 50 ++
.../providerapi/ProviderParameters.java | 11 +
.../maven/surefire/report/RunListener.java | 8 +-
.../surefire/report/SimpleReportEntry.java | 5 +
.../booter/MasterProcessCommandTest.java | 3 +-
.../maven/surefire/report/MockReporter.java | 9 +
.../maven/surefire/booter/BooterConstants.java | 1 +
.../surefire/booter/BooterDeserializer.java | 8 +-
.../maven/surefire/booter/ForkedBooter.java | 8 +-
.../surefire/booter/MasterProcessListener.java | 28 --
.../surefire/booter/MasterProcessReader.java | 257 -----------
.../surefire/booter/ProviderConfiguration.java | 15 +-
.../maven/surefire/booter/ProviderFactory.java | 13 +-
.../booter/MasterProcessReaderTest.java | 67 ++-
.../surefire/common/junit4/JUnit4Reflector.java | 103 ++++-
.../common/junit4/JUnit4RunListener.java | 64 +--
.../maven/surefire/common/junit4/Notifier.java | 106 +++++
.../maven/surefire/junit4/MockReporter.java | 11 +-
.../common/junit4/JUnit4Reflector40Test.java | 28 ++
.../maven/surefire/junit/JUnitTestSetTest.java | 9 +
.../surefire/junit4/JUnit4FailFastListener.java | 48 ++
.../maven/surefire/junit4/JUnit4Provider.java | 193 +++++---
.../junitcore/ConcurrentRunListener.java | 19 +-
.../surefire/junitcore/FilteringRequest.java | 54 +++
.../junitcore/JUnit47FailFastListener.java | 65 +++
.../maven/surefire/junitcore/JUnitCore.java | 90 ++++
.../surefire/junitcore/JUnitCoreProvider.java | 125 +++--
.../surefire/junitcore/JUnitCoreWrapper.java | 159 +++++--
.../maven/surefire/junitcore/Stoppable.java | 32 ++
.../junitcore/JUnit4Reflector481Test.java | 52 +++
.../surefire/junitcore/Surefire746Test.java | 4 +-
.../surefire-testng-utils/pom.xml | 2 +-
.../testng/utils/FailFastEventsSingleton.java | 53 +++
.../surefire/testng/utils/FailFastListener.java | 77 ++++
.../surefire/testng/utils/FailFastNotifier.java | 50 ++
.../maven/surefire/testng/utils/Stoppable.java | 32 ++
.../testng/TestNGDirectoryTestSuite.java | 13 +-
.../maven/surefire/testng/TestNGExecutor.java | 34 +-
.../maven/surefire/testng/TestNGProvider.java | 114 +++--
.../surefire/testng/TestNGXmlTestSuite.java | 12 +-
72 files changed, 3337 insertions(+), 988 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index 2c2339a..eb315ce 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -301,6 +301,17 @@ public class IntegrationTestMojo
@Parameter( property = "failsafe.excludesFile" )
private File excludesFile;
+ /**
+ * Set to "true" to skip remaining tests after first test failure appeared.
+ * Due to race conditions in parallel/forked execution this may not be fully guaranteed.<br/>
+ * Enable with system property -Dfailsafe.skipAfterFailureCount=1 or any number greater than zero.
+ * Defaults to "0".
+ *
+ * @since 2.19
+ */
+ @Parameter( property = "failsafe.skipAfterFailureCount", defaultValue = "0" )
+ private int skipAfterFailureCount;
+
protected int getRerunFailingTestsCount()
{
return rerunFailingTestsCount;
@@ -594,6 +605,11 @@ public class IntegrationTestMojo
this.failIfNoSpecifiedTests = failIfNoSpecifiedTests;
}
+ public int getSkipAfterFailureCount()
+ {
+ return skipAfterFailureCount;
+ }
+
@Override
public List<String> getIncludes()
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git 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
index 4af79f2..f847604 100644
--- 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
@@ -683,6 +683,29 @@ public abstract class AbstractSurefireMojo
protected abstract int getRerunFailingTestsCount();
+ public abstract List<String> getIncludes();
+
+ public abstract File getIncludesFile();
+
+ public abstract void setIncludes( List<String> includes );
+
+ public abstract File getExcludesFile();
+
+ public abstract File[] getSuiteXmlFiles();
+
+ public abstract void setSuiteXmlFiles( File[] suiteXmlFiles );
+
+ public abstract String getRunOrder();
+
+ public abstract void setRunOrder( String runOrder );
+
+ protected abstract void handleSummary( RunResult summary, Exception firstForkException )
+ throws MojoExecutionException, MojoFailureException;
+
+ protected abstract String[] getDefaultIncludes();
+
+ protected abstract boolean isSkipExecution();
+
private SurefireDependencyResolver dependencyResolver;
private TestListResolver specificTests;
@@ -807,8 +830,6 @@ public abstract class AbstractSurefireMojo
return true;
}
- protected abstract boolean isSkipExecution();
-
private void executeAfterPreconditionsChecked( DefaultScanResult scanResult )
throws MojoExecutionException, MojoFailureException
{
@@ -1031,9 +1052,6 @@ public abstract class AbstractSurefireMojo
}
}
- protected abstract void handleSummary( RunResult summary, Exception firstForkException )
- throws MojoExecutionException, MojoFailureException;
-
protected void logReportsDirectory()
{
logDebugOrCliShowErrors(
@@ -1448,7 +1466,7 @@ public abstract class AbstractSurefireMojo
reporterConfiguration,
testNg, // Not really used in provider. Limited to de/serializer.
testSuiteDefinition, providerProperties, null,
- false, cli );
+ false, cli, getSkipAfterFailureCount() );
}
private static Map<String, String> toStringProperties( Properties properties )
@@ -2032,8 +2050,6 @@ public abstract class AbstractSurefireMojo
: new ClassLoaderConfiguration( false, false );
}
- protected abstract String[] getDefaultIncludes();
-
/**
* Generate the test classpath.
*
@@ -2591,19 +2607,11 @@ public abstract class AbstractSurefireMojo
}
}
- public abstract List<String> getIncludes();
-
- public abstract File getIncludesFile();
-
- public abstract void setIncludes( List<String> includes );
-
public List<String> getExcludes()
{
return excludes;
}
- public abstract File getExcludesFile();
-
public void setExcludes( List<String> excludes )
{
this.excludes = excludes;
@@ -2805,10 +2813,6 @@ public abstract class AbstractSurefireMojo
this.excludedGroups = excludedGroups;
}
- public abstract File[] getSuiteXmlFiles();
-
- public abstract void setSuiteXmlFiles( File[] suiteXmlFiles );
-
public String getJunitArtifactName()
{
return junitArtifactName;
@@ -3046,10 +3050,6 @@ public abstract class AbstractSurefireMojo
return parallelMavenExecution != null && parallelMavenExecution;
}
- public abstract String getRunOrder();
-
- public abstract void setRunOrder( String runOrder );
-
public String[] getDependenciesToScan()
{
return dependenciesToScan;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
index 65c4062..6bd09ff 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
@@ -118,4 +118,6 @@ public interface SurefireExecutionParameters
Boolean getFailIfNoSpecifiedTests();
void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests );
+
+ int getSkipAfterFailureCount();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireProperties.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireProperties.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireProperties.java
index 472c51a..d41d4d7 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireProperties.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireProperties.java
@@ -127,7 +127,6 @@ public class SurefireProperties
return result;
}
-
public void copyToSystemProperties()
{
@@ -197,34 +196,33 @@ public class SurefireProperties
public void addList( List<?> items, String propertyPrefix )
{
- if ( items == null || items.isEmpty() )
- {
- return;
- }
- int i = 0;
- for ( Object item : items )
+ if ( items != null && !items.isEmpty() )
{
- if ( item == null )
- {
- throw new NullPointerException( propertyPrefix + i + " has null value" );
- }
-
- String[] stringArray = StringUtils.split( item.toString(), "," );
-
- for ( String aStringArray : stringArray )
+ int i = 0;
+ for ( Object item : items )
{
- setProperty( propertyPrefix + i, aStringArray );
- i++;
+ if ( item == null )
+ {
+ throw new NullPointerException( propertyPrefix + i + " has null value" );
+ }
+
+ String[] stringArray = StringUtils.split( item.toString(), "," );
+
+ for ( String aStringArray : stringArray )
+ {
+ setProperty( propertyPrefix + i, aStringArray );
+ i++;
+ }
}
}
}
public void setClasspath( String prefix, Classpath classpath )
{
- List classpathElements = classpath.getClassPath();
+ List<String> classpathElements = classpath.getClassPath();
for ( int i = 0; i < classpathElements.size(); ++i )
{
- String element = (String) classpathElements.get( i );
+ String element = classpathElements.get( i );
setProperty( prefix + i, element );
}
}
@@ -232,38 +230,26 @@ public class SurefireProperties
private static SurefireProperties loadProperties( InputStream inStream )
throws IOException
{
- Properties p = new Properties();
-
try
{
+ Properties p = new Properties();
p.load( inStream );
+ return new SurefireProperties( p );
}
finally
{
close( inStream );
}
-
- return new SurefireProperties( p );
}
public static SurefireProperties loadProperties( File file )
throws IOException
{
- if ( file != null )
- {
- return loadProperties( new FileInputStream( file ) );
- }
-
- return new SurefireProperties();
+ return file == null ? new SurefireProperties() : loadProperties( new FileInputStream( file ) );
}
private static void close( InputStream inputStream )
{
- if ( inputStream == null )
- {
- return;
- }
-
try
{
inputStream.close();
@@ -280,8 +266,5 @@ public class SurefireProperties
{
super.setProperty( key, value );
}
-
}
-
-
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
index 0164ba9..139e14b 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
@@ -133,6 +133,7 @@ class BooterSerializer
properties.setProperty( USEMANIFESTONLYJAR, String.valueOf( classLoaderConfig.isUseManifestOnlyJar() ) );
properties.setProperty( FAILIFNOTESTS, String.valueOf( booterConfiguration.isFailIfNoTests() ) );
properties.setProperty( PROVIDER_CONFIGURATION, providerConfiguration.getProviderClassName() );
+ properties.setProperty( FAIL_FAST_COUNT, String.valueOf( booterConfiguration.getSkipAfterFailureCount() ) );
List<CommandLineOption> mainCliOptions = booterConfiguration.getMainCliOptions();
if ( mainCliOptions != null )
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 4b2e184..632834f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
@@ -20,22 +20,21 @@ package org.apache.maven.plugin.surefire.booterclient;
*/
import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
import org.apache.maven.plugin.surefire.CommonReflector;
import org.apache.maven.plugin.surefire.StartupReportConfiguration;
import org.apache.maven.plugin.surefire.SurefireProperties;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.AbstractForkInputStream;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.NotifiableTestStream;
import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream;
import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvidingInputStream;
import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
import org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
import org.apache.maven.shared.utils.cli.CommandLineException;
import org.apache.maven.shared.utils.cli.CommandLineTimeOutException;
-import org.apache.maven.shared.utils.cli.CommandLineUtils;
-import org.apache.maven.shared.utils.cli.ShutdownHookUtils;
import org.apache.maven.surefire.booter.Classpath;
import org.apache.maven.surefire.booter.ClasspathConfiguration;
-import org.apache.maven.surefire.booter.Command;
import org.apache.maven.surefire.booter.KeyValueSource;
import org.apache.maven.surefire.booter.PropertiesWrapper;
import org.apache.maven.surefire.booter.ProviderConfiguration;
@@ -43,14 +42,11 @@ import org.apache.maven.surefire.booter.ProviderFactory;
import org.apache.maven.surefire.booter.StartupConfiguration;
import org.apache.maven.surefire.booter.SurefireBooterForkException;
import org.apache.maven.surefire.booter.SurefireExecutionException;
-import org.apache.maven.surefire.booter.SystemPropertyManager;
import org.apache.maven.surefire.providerapi.SurefireProvider;
import org.apache.maven.surefire.report.StackTraceWriter;
import org.apache.maven.surefire.suite.RunResult;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.util.DefaultScanResult;
-import org.apache.maven.surefire.util.internal.DaemonThreadFactory;
-import org.apache.maven.surefire.util.internal.StringUtils;
import java.io.File;
import java.io.IOException;
@@ -59,6 +55,7 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
+import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
@@ -70,10 +67,23 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+import static org.apache.maven.shared.utils.cli.CommandLineUtils.executeCommandLine;
+import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.addShutDownHook;
+import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.removeShutdownHook;
+import static org.apache.maven.surefire.util.internal.StringUtils.FORK_STREAM_CHARSET_NAME;
+import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread;
+import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder;
+import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.
+ TestLessInputStream.TestLessInputStreamBuilder;
import static org.apache.maven.surefire.booter.Classpath.join;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
+import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
+import static org.apache.maven.surefire.suite.RunResult.timeout;
+import static org.apache.maven.surefire.suite.RunResult.failure;
+import static org.apache.maven.surefire.suite.RunResult.SUCCESS;
import static java.lang.StrictMath.min;
/**
@@ -92,7 +102,7 @@ import static java.lang.StrictMath.min;
*/
public class ForkStarter
{
- private final ThreadFactory threadFactory = DaemonThreadFactory.newDaemonThreadFactory();
+ private final ThreadFactory threadFactory = newDaemonThreadFactory();
/**
* Closes an InputStream
@@ -180,9 +190,19 @@ public class ForkStarter
{
DefaultReporterFactory forkedReporterFactory = new DefaultReporterFactory( startupReportConfiguration );
defaultReporterFactories.add( forkedReporterFactory );
- final ForkClient forkClient =
- new ForkClient( forkedReporterFactory, startupReportConfiguration.getTestVmSystemProperties() );
- return fork( null, new PropertiesWrapper( providerProperties ), forkClient, effectiveSystemProperties, null );
+ PropertiesWrapper props = new PropertiesWrapper( providerProperties );
+ ForkClient forkClient =
+ new ForkClient( forkedReporterFactory, startupReportConfiguration.getTestVmSystemProperties() );
+ TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
+ TestLessInputStream stream = builder.build();
+ try
+ {
+ return fork( null, props, forkClient, effectiveSystemProperties, stream, false );
+ }
+ finally
+ {
+ builder.removeStream( stream );
+ }
}
private RunResult run( SurefireProperties effectiveSystemProperties )
@@ -209,41 +229,57 @@ public class ForkStarter
private RunResult runSuitesForkOnceMultiple( final SurefireProperties effectiveSystemProperties, int forkCount )
throws SurefireBooterForkException
{
- ArrayList<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount );
ThreadPoolExecutor executorService = new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>( forkCount ) );
executorService.setThreadFactory( threadFactory );
try
{
- final Queue<Command> commands = new ConcurrentLinkedQueue<Command>();
+ final Queue<String> tests = new ConcurrentLinkedQueue<String>();
+
for ( Class<?> clazz : getSuitesIterator() )
{
- commands.add( new Command( RUN_CLASS, clazz.getName() ) );
+ tests.add( clazz.getName() );
+ }
+
+ final Queue<TestProvidingInputStream> testStreams = new ConcurrentLinkedQueue<TestProvidingInputStream>();
+
+ for ( int forkNum = 0, total = min( forkCount, tests.size() ); forkNum < total; forkNum++ )
+ {
+ testStreams.add( new TestProvidingInputStream( tests ) );
}
- Collection<TestProvidingInputStream> testStreams = new ArrayList<TestProvidingInputStream>();
- for ( int forkNum = 0, total = min( forkCount, commands.size() ); forkNum < total; forkNum++ )
+
+ final AtomicBoolean notifyStreamsToSkipTestsJustNow = new AtomicBoolean();
+ Collection<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount );
+ for ( final TestProvidingInputStream testProvidingInputStream : testStreams )
{
- final TestProvidingInputStream testProvidingInputStream = new TestProvidingInputStream( commands );
- testStreams.add( testProvidingInputStream );
Callable<RunResult> pf = new Callable<RunResult>()
{
public RunResult call()
throws Exception
{
- DefaultReporterFactory forkedReporterFactory =
- new DefaultReporterFactory( startupReportConfiguration );
- defaultReporterFactories.add( forkedReporterFactory );
- ForkClient forkClient = new ForkClient( forkedReporterFactory,
- startupReportConfiguration.getTestVmSystemProperties(),
- testProvidingInputStream );
+ DefaultReporterFactory reporter = new DefaultReporterFactory( startupReportConfiguration );
+ defaultReporterFactories.add( reporter );
+
+ Properties vmProps = startupReportConfiguration.getTestVmSystemProperties();
+
+ ForkClient forkClient = new ForkClient( reporter, vmProps, testProvidingInputStream )
+ {
+ @Override
+ protected void stopOnNextTest()
+ {
+ if ( notifyStreamsToSkipTestsJustNow.compareAndSet( false, true ) )
+ {
+ notifyStreamsToSkipTests( testStreams );
+ }
+ }
+ };
return fork( null, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
- forkClient, effectiveSystemProperties, testProvidingInputStream );
+ forkClient, effectiveSystemProperties, testProvidingInputStream, true );
}
};
results.add( executorService.submit( pf ) );
}
- dispatchTestSetFinished( testStreams );
return awaitResultsDone( results, executorService );
}
finally
@@ -252,6 +288,14 @@ public class ForkStarter
}
}
+ private static void notifyStreamsToSkipTests( Collection<? extends NotifiableTestStream> notifiableTestStreams )
+ {
+ for ( NotifiableTestStream notifiableTestStream : notifiableTestStreams )
+ {
+ notifiableTestStream.skipSinceNextTest();
+ }
+ }
+
@SuppressWarnings( "checkstyle:magicnumber" )
private RunResult runSuitesForkPerTestSet( final SurefireProperties effectiveSystemProperties, int forkCount )
throws SurefireBooterForkException
@@ -262,6 +306,8 @@ public class ForkStarter
executorService.setThreadFactory( threadFactory );
try
{
+ final AtomicBoolean notifyStreamsToSkipTestsJustNow = new AtomicBoolean();
+ final TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
for ( final Object testSet : getSuitesIterator() )
{
Callable<RunResult> pf = new Callable<RunResult>()
@@ -272,10 +318,29 @@ public class ForkStarter
DefaultReporterFactory forkedReporterFactory =
new DefaultReporterFactory( startupReportConfiguration );
defaultReporterFactories.add( forkedReporterFactory );
- ForkClient forkClient = new ForkClient( forkedReporterFactory,
- startupReportConfiguration.getTestVmSystemProperties() );
- return fork( testSet, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
- forkClient, effectiveSystemProperties, null );
+ Properties vmProps = startupReportConfiguration.getTestVmSystemProperties();
+ ForkClient forkClient = new ForkClient( forkedReporterFactory, vmProps )
+ {
+ @Override
+ protected void stopOnNextTest()
+ {
+ if ( notifyStreamsToSkipTestsJustNow.compareAndSet( false, true ) )
+ {
+ builder.getCachableCommands().skipSinceNextTest();
+ }
+ }
+ };
+ TestLessInputStream stream = builder.build();
+ try
+ {
+ return fork( testSet,
+ new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
+ forkClient, effectiveSystemProperties, stream, false );
+ }
+ finally
+ {
+ builder.removeStream( stream );
+ }
}
};
results.add( executorService.submit( pf ) );
@@ -314,20 +379,14 @@ public class ForkStarter
}
catch ( ExecutionException e )
{
- throw new SurefireBooterForkException( "ExecutionException", e );
+ Throwable realException = e.getCause();
+ String error = realException == null ? "" : realException.getLocalizedMessage();
+ throw new SurefireBooterForkException( "ExecutionException " + error, realException );
}
}
return globalResult;
}
- private static void dispatchTestSetFinished( Iterable<TestProvidingInputStream> testStreams )
- {
- for ( TestProvidingInputStream testStream : testStreams )
- {
- testStream.testSetFinished();
- }
- }
-
@SuppressWarnings( "checkstyle:magicnumber" )
private void closeExecutor( ExecutorService executorService )
throws SurefireBooterForkException
@@ -347,14 +406,14 @@ public class ForkStarter
private RunResult fork( Object testSet, KeyValueSource providerProperties, ForkClient forkClient,
SurefireProperties effectiveSystemProperties,
- TestProvidingInputStream testProvidingInputStream )
+ AbstractForkInputStream testProvidingInputStream, boolean readTestsFromInStream )
throws SurefireBooterForkException
{
int forkNumber = ForkNumberBucket.drawNumber();
try
{
return fork( testSet, providerProperties, forkClient, effectiveSystemProperties, forkNumber,
- testProvidingInputStream );
+ testProvidingInputStream, readTestsFromInStream );
}
finally
{
@@ -364,28 +423,30 @@ public class ForkStarter
private RunResult fork( Object testSet, KeyValueSource providerProperties, ForkClient forkClient,
SurefireProperties effectiveSystemProperties, int forkNumber,
- TestProvidingInputStream testProvidingInputStream )
+ AbstractForkInputStream testProvidingInputStream, boolean readTestsFromInStream )
throws SurefireBooterForkException
{
- File surefireProperties;
- File systPropsFile = null;
+ final File surefireProperties;
+ final File systPropsFile;
try
{
BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration );
- surefireProperties =
- booterSerializer.serialize( providerProperties, providerConfiguration, startupConfiguration, testSet,
- null != testProvidingInputStream );
+ surefireProperties = booterSerializer.serialize( providerProperties, providerConfiguration,
+ startupConfiguration, testSet, readTestsFromInStream );
if ( effectiveSystemProperties != null )
{
SurefireProperties filteredProperties =
- AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder( effectiveSystemProperties,
- forkNumber );
- systPropsFile =
- SystemPropertyManager.writePropertiesFile( filteredProperties, forkConfiguration.getTempDirectory(),
- "surefire_" + systemPropertiesFileCounter++,
- forkConfiguration.isDebug() );
+ createCopyAndReplaceForkNumPlaceholder( effectiveSystemProperties, forkNumber );
+
+ systPropsFile = writePropertiesFile( filteredProperties, forkConfiguration.getTempDirectory(),
+ "surefire_" + systemPropertiesFileCounter++,
+ forkConfiguration.isDebug() );
+ }
+ else
+ {
+ systPropsFile = null;
}
}
catch ( IOException e )
@@ -407,23 +468,14 @@ public class ForkStarter
log.debug( bootClasspath.getLogMessage( "boot" ) );
log.debug( bootClasspath.getCompactLogMessage( "boot(compact)" ) );
}
+
OutputStreamFlushableCommandline cli =
forkConfiguration.createCommandLine( bootClasspath.getClassPath(), startupConfiguration, forkNumber );
- final InputStreamCloser inputStreamCloser;
- final Thread inputStreamCloserHook;
- if ( testProvidingInputStream != null )
- {
- testProvidingInputStream.setFlushReceiverProvider( cli );
- inputStreamCloser = new InputStreamCloser( testProvidingInputStream );
- inputStreamCloserHook = DaemonThreadFactory.newDaemonThread( inputStreamCloser, "input-stream-closer" );
- ShutdownHookUtils.addShutDownHook( inputStreamCloserHook );
- }
- else
- {
- inputStreamCloser = null;
- inputStreamCloserHook = null;
- }
+ InputStreamCloser inputStreamCloser = new InputStreamCloser( testProvidingInputStream );
+ Thread inputStreamCloserHook = newDaemonThread( inputStreamCloser, "input-stream-closer" );
+ testProvidingInputStream.setFlushReceiverProvider( cli );
+ addShutDownHook( inputStreamCloserHook );
cli.createArg().setFile( surefireProperties );
@@ -444,11 +496,12 @@ public class ForkStarter
try
{
final int timeout = forkedProcessTimeoutInSeconds > 0 ? forkedProcessTimeoutInSeconds : 0;
- final int result =
- CommandLineUtils.executeCommandLine( cli, testProvidingInputStream, threadedStreamConsumer,
- threadedStreamConsumer, timeout, inputStreamCloser,
- Charset.forName( StringUtils.FORK_STREAM_CHARSET_NAME ) );
- if ( result != RunResult.SUCCESS )
+
+ final int result = executeCommandLine( cli, testProvidingInputStream, threadedStreamConsumer,
+ threadedStreamConsumer, timeout, inputStreamCloser,
+ Charset.forName( FORK_STREAM_CHARSET_NAME ) );
+
+ if ( result != SUCCESS )
{
throw new SurefireBooterForkException( "Error occurred in starting fork, check output in log" );
}
@@ -456,27 +509,24 @@ public class ForkStarter
}
catch ( CommandLineTimeOutException e )
{
- runResult = RunResult.timeout(
- forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult() );
+ runResult = timeout( forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult() );
}
catch ( CommandLineException e )
{
- runResult =
- RunResult.failure( forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult(), e );
+ runResult = failure( forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult(), e );
throw new SurefireBooterForkException( "Error while executing forked tests.", e.getCause() );
}
finally
{
threadedStreamConsumer.close();
- if ( inputStreamCloser != null )
- {
- inputStreamCloser.run();
- ShutdownHookUtils.removeShutdownHook( inputStreamCloserHook );
- }
+ inputStreamCloser.run();
+ removeShutdownHook( inputStreamCloserHook );
+
if ( runResult == null )
{
runResult = forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult();
}
+
if ( !runResult.isTimeout() )
{
StackTraceWriter errorInFork = forkClient.getErrorInFork();
@@ -512,9 +562,8 @@ public class ForkStarter
CommonReflector commonReflector = new CommonReflector( unifiedClassLoader );
Object reporterFactory = commonReflector.createReportingReporterFactory( startupReportConfiguration );
- final ProviderFactory providerFactory =
- new ProviderFactory( startupConfiguration, providerConfiguration, unifiedClassLoader,
- reporterFactory );
+ ProviderFactory providerFactory =
+ new ProviderFactory( startupConfiguration, providerConfiguration, unifiedClassLoader, reporterFactory );
SurefireProvider surefireProvider = providerFactory.createProvider( false );
return surefireProvider.getSuites();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
deleted file mode 100644
index b80f80f..0000000
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package org.apache.maven.plugin.surefire.booterclient;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.maven.surefire.report.ConsoleLogger;
-import org.apache.maven.surefire.report.ConsoleOutputReceiver;
-import org.apache.maven.surefire.report.ReportEntry;
-import org.apache.maven.surefire.report.RunListener;
-
-/**
- * Internal use only
- */
-public class MockReporter
- implements RunListener, ConsoleLogger, ConsoleOutputReceiver
-{
- private final List<String> events = new ArrayList<String>();
-
- private final List<Object> data = new ArrayList<Object>();
-
- public static final String SET_STARTING = "SET_STARTED";
-
- public static final String SET_COMPLETED = "SET_COMPLETED";
-
- public static final String TEST_STARTING = "TEST_STARTED";
-
- public static final String TEST_SUCCEEDED = "TEST_COMPLETED";
-
- public static final String TEST_FAILED = "TEST_FAILED";
-
- public static final String TEST_ERROR = "TEST_ERROR";
-
- public static final String TEST_SKIPPED = "TEST_SKIPPED";
-
- public static final String TEST_ASSUMPTION_FAIL = "TEST_ASSUMPTION_SKIPPED";
-
- public static final String CONSOLE_OUTPUT = "CONSOLE_OUTPUT";
-
- public static final String STDOUT = "STDOUT";
-
- public static final String STDERR = "STDERR";
-
- private final AtomicInteger testSucceeded = new AtomicInteger();
-
- private final AtomicInteger testIgnored = new AtomicInteger();
-
- private final AtomicInteger testFailed = new AtomicInteger();
-
- public MockReporter()
- {
- }
-
- public void testSetStarting( ReportEntry report )
- {
- events.add( SET_STARTING );
- data.add( report );
- }
-
- public void testSetCompleted( ReportEntry report )
- {
- events.add( SET_COMPLETED );
- data.add( report );
- }
-
- public void testStarting( ReportEntry report )
- {
- events.add( TEST_STARTING );
- data.add( report );
- }
-
- public void testSucceeded( ReportEntry report )
- {
- events.add( TEST_SUCCEEDED );
- testSucceeded.incrementAndGet();
- data.add( report );
- }
-
- public void testError( ReportEntry report )
- {
- events.add( TEST_ERROR );
- data.add( report );
- testFailed.incrementAndGet();
- }
-
- public void testFailed( ReportEntry report )
- {
- events.add( TEST_FAILED );
- data.add( report );
- testFailed.incrementAndGet();
- }
-
-
- public void testSkipped( ReportEntry report )
- {
- events.add( TEST_SKIPPED );
- data.add( report );
- testIgnored.incrementAndGet();
- }
-
-
- public List<String> getEvents()
- {
- return events;
- }
-
- public List getData()
- {
- return data;
- }
-
- public String getFirstEvent()
- {
- return events.get( 0 );
- }
-
- public ReportEntry getFirstData()
- {
- return (ReportEntry) data.get( 0 );
- }
-
-
- public void testAssumptionFailure( ReportEntry report )
- {
- events.add( TEST_ASSUMPTION_FAIL );
- data.add( report );
- testIgnored.incrementAndGet();
-
- }
-
- public void info( String message )
- {
- events.add( CONSOLE_OUTPUT );
- data.add( message );
- }
-
- public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
- {
- events.add( stdout ? STDOUT : STDERR );
- data.add( new String( buf, off, len ) );
- }
-}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractCommandStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractCommandStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractCommandStream.java
new file mode 100644
index 0000000..4d6331c
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractCommandStream.java
@@ -0,0 +1,122 @@
+package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.MasterProcessCommand;
+
+import java.io.IOException;
+
+/**
+ * Reader stream sends commands to forked jvm std-{@link java.io.InputStream input-stream}.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ * @see org.apache.maven.surefire.booter.Command
+ */
+public abstract class AbstractCommandStream
+ extends AbstractForkInputStream
+{
+ private byte[] currentBuffer;
+ private int currentPos;
+ private volatile MasterProcessCommand lastCommand;
+
+ protected abstract boolean isClosed();
+
+ /**
+ * Unnecessarily opposite to {@link #isClosed()} however may respect
+ * {@link #getLastCommand() last command} and {@link #isClosed()}.
+ */
+ protected abstract boolean canContinue();
+
+ /**
+ * Possibly waiting for next command (see {@link #nextCommand()}) unless the stream is atomically
+ * closed (see {@link #isClosed()} returns {@code true}) before this method has returned.
+ */
+ protected void beforeNextCommand()
+ throws IOException
+ {
+ }
+
+ protected abstract Command nextCommand();
+
+ /**
+ * Returns quietly and immediately.
+ */
+ protected final void invalidateInternalBuffer()
+ {
+ currentBuffer = null;
+ currentPos = 0;
+ }
+
+ protected final MasterProcessCommand getLastCommand()
+ {
+ return lastCommand;
+ }
+
+ /**
+ * Used by single thread in StreamFeeder class.
+ *
+ * @return {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @SuppressWarnings( "checkstyle:magicnumber" )
+ @Override
+ public int read()
+ throws IOException
+ {
+ if ( isClosed() )
+ {
+ return -1;
+ }
+
+ byte[] buffer = currentBuffer;
+ if ( buffer == null )
+ {
+ tryFlush();
+
+ if ( !canContinue() )
+ {
+ close();
+ return -1;
+ }
+
+ beforeNextCommand();
+
+ if ( isClosed() )
+ {
+ return -1;
+ }
+
+ Command cmd = nextCommand();
+ lastCommand = cmd.getCommandType();
+ buffer = lastCommand.hasDataType() ? lastCommand.encode( cmd.getData() ) : lastCommand.encode();
+ }
+
+ int b = buffer[currentPos++] & 0xff;
+ if ( currentPos == buffer.length )
+ {
+ buffer = null;
+ currentPos = 0;
+ }
+ currentBuffer = buffer;
+ return b;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractForkInputStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractForkInputStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractForkInputStream.java
new file mode 100644
index 0000000..281c05d
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/AbstractForkInputStream.java
@@ -0,0 +1,61 @@
+package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.apache.maven.surefire.util.internal.StringUtils.requireNonNull;
+
+/**
+ * Reader stream sends bytes to forked jvm std-{@link InputStream input-stream}.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public abstract class AbstractForkInputStream
+ extends InputStream
+ implements NotifiableTestStream
+{
+ private volatile FlushReceiverProvider flushReceiverProvider;
+
+ /**
+ * @param flushReceiverProvider the provider for a flush receiver.
+ */
+ public void setFlushReceiverProvider( FlushReceiverProvider flushReceiverProvider )
+ {
+ this.flushReceiverProvider = requireNonNull( flushReceiverProvider );
+ }
+
+ protected boolean tryFlush()
+ throws IOException
+ {
+ if ( flushReceiverProvider != null )
+ {
+ FlushReceiver flushReceiver = flushReceiverProvider.getFlushReceiver();
+ if ( flushReceiver != null )
+ {
+ flushReceiver.flush();
+ return true;
+ }
+ }
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
index 47aa642..d47645b 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
@@ -28,5 +28,19 @@ package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
*/
public interface NotifiableTestStream
{
+ /**
+ * Notifies {@link TestProvidingInputStream} in order to dispatch a new test back to the forked
+ * jvm (particular fork which hits this call); or do nothing in {@link TestLessInputStream}.
+ */
void provideNewTest();
+
+ /**
+ * Sends an event to a fork jvm in order to skip tests.
+ * Returns immediately without blocking.
+ */
+ void skipSinceNextTest();
+
+ void shutdown();
+
+ void noop();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
new file mode 100644
index 0000000..b608620
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
@@ -0,0 +1,453 @@
+package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.surefire.booter.Command;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import static org.apache.maven.surefire.booter.Command.NOOP;
+import static org.apache.maven.surefire.booter.Command.SHUTDOWN;
+import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
+
+/**
+ * Dispatches commands without tests.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public final class TestLessInputStream
+ extends AbstractCommandStream
+{
+ private final Semaphore barrier = new Semaphore( 0 );
+
+ private final AtomicBoolean closed = new AtomicBoolean();
+
+ private final Queue<Command> immediateCommands = new ConcurrentLinkedQueue<Command>();
+
+ private final TestLessInputStreamBuilder builder;
+
+ private Iterator<Command> cachableCommands;
+
+ private TestLessInputStream( TestLessInputStreamBuilder builder )
+ {
+ this.builder = builder;
+ }
+
+ public void provideNewTest()
+ {
+ }
+
+ public void skipSinceNextTest()
+ {
+ if ( canContinue() )
+ {
+ immediateCommands.add( SKIP_SINCE_NEXT_TEST );
+ barrier.release();
+ }
+ }
+
+ public void shutdown()
+ {
+ if ( canContinue() )
+ {
+ immediateCommands.add( SHUTDOWN );
+ barrier.release();
+ }
+ }
+
+ public void noop()
+ {
+ if ( canContinue() )
+ {
+ immediateCommands.add( NOOP );
+ barrier.release();
+ }
+ }
+
+ @Override
+ protected boolean isClosed()
+ {
+ return closed.get();
+ }
+
+ @Override
+ protected boolean canContinue()
+ {
+ return !isClosed();
+ }
+
+ @Override
+ protected Command nextCommand()
+ {
+ Command cmd = immediateCommands.poll();
+ if ( cmd == null )
+ {
+ if ( cachableCommands == null )
+ {
+ cachableCommands = builder.getIterableCachable().iterator();
+ }
+
+ cmd = cachableCommands.next();
+ }
+ return cmd;
+ }
+
+ @Override
+ protected void beforeNextCommand()
+ throws IOException
+ {
+ awaitNextCommand();
+ }
+
+ @Override
+ public void close()
+ {
+ if ( closed.compareAndSet( false, true ) )
+ {
+ invalidateInternalBuffer();
+ barrier.drainPermits();
+ barrier.release();
+ }
+ }
+
+ /**
+ * For testing purposes only.
+ *
+ * @return permits used internally by {@link #beforeNextCommand()}
+ */
+ int availablePermits()
+ {
+ return barrier.availablePermits();
+ }
+
+ private void awaitNextCommand()
+ throws IOException
+ {
+ try
+ {
+ barrier.acquire();
+ }
+ catch ( InterruptedException e )
+ {
+ // help GC to free this object because StreamFeeder Thread cannot read it anyway after IOE
+ invalidateInternalBuffer();
+ throw new IOException( e.getLocalizedMessage() );
+ }
+ }
+
+ /**
+ * todo
+ */
+ public static final class TestLessInputStreamBuilder
+ {
+ ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
+ private final Queue<TestLessInputStream> aliveStreams = new ConcurrentLinkedQueue<TestLessInputStream>();
+ private final ImmediateCommands immediateCommands = new ImmediateCommands();
+ private final CachableCommands cachableCommands = new CachableCommands();
+ private final Node head = new Node( null );
+ private final Iterable<Command> iterableCachable;
+
+ public TestLessInputStreamBuilder()
+ {
+ iterableCachable = new Iterable<Command>()
+ {
+ public Iterator<Command> iterator()
+ {
+ return new CIt();
+ }
+ };
+ }
+
+ public TestLessInputStream build()
+ {
+ Lock lock = rwLock.writeLock();
+ lock.lock();
+ try
+ {
+ TestLessInputStream is = new TestLessInputStream( this );
+ aliveStreams.offer( is );
+ return is;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ public void removeStream( TestLessInputStream is )
+ {
+ Lock lock = rwLock.writeLock();
+ lock.lock();
+ try
+ {
+ aliveStreams.remove( is );
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ public NotifiableTestStream getImmediateCommands()
+ {
+ return immediateCommands;
+ }
+
+ public NotifiableTestStream getCachableCommands()
+ {
+ return cachableCommands;
+ }
+
+ /**
+ * The iterator is not thread safe.
+ */
+ Iterable<Command> getIterableCachable()
+ {
+ return iterableCachable;
+ }
+
+ @SuppressWarnings( "checkstyle:innerassignment" )
+ private void addTailNode( Command command )
+ {
+ Node newTail = new Node( command );
+ Node currentTail = head;
+ do
+ {
+ for ( Node successor; ( successor = currentTail.next.get() ) != null; )
+ {
+ currentTail = successor;
+ }
+ } while ( !currentTail.next.compareAndSet( null, newTail ) );
+ }
+
+ @SuppressWarnings( "checkstyle:innerassignment" )
+ private boolean addTailNodeIfAbsent( Command command )
+ {
+ Node newTail = new Node( command );
+ Node currentTail = head;
+ do
+ {
+ for ( Node successor; ( successor = currentTail.next.get() ) != null; )
+ {
+ currentTail = successor;
+ if ( command.equals( currentTail.command ) )
+ {
+ return false;
+ }
+ }
+ } while ( !currentTail.next.compareAndSet( null, newTail ) );
+ return true;
+ }
+
+ private static Node nextCachedNode( Node current )
+ {
+ return current.next.get();
+ }
+
+ private final class CIt
+ implements Iterator<Command>
+ {
+ private Node node = TestLessInputStreamBuilder.this.head;
+
+ public boolean hasNext()
+ {
+ return examineNext( false ) != null;
+ }
+
+ public Command next()
+ {
+ Command command = examineNext( true );
+ if ( command == null )
+ {
+ throw new NoSuchElementException();
+ }
+ return command;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ private Command examineNext( boolean store )
+ {
+ Node next = nextCachedNode( node );
+ if ( store && next != null )
+ {
+ node = next;
+ }
+ return next == null ? null : next.command;
+ }
+ }
+
+ /**
+ * Event is called just now for all alive streams and command is not persisted.
+ */
+ private final class ImmediateCommands
+ implements NotifiableTestStream
+ {
+ public void provideNewTest()
+ {
+ }
+
+ public void skipSinceNextTest()
+ {
+ Lock lock = rwLock.readLock();
+ lock.lock();
+ try
+ {
+ for ( TestLessInputStream aliveStream : TestLessInputStreamBuilder.this.aliveStreams )
+ {
+ aliveStream.skipSinceNextTest();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ public void shutdown()
+ {
+ Lock lock = rwLock.readLock();
+ lock.lock();
+ try
+ {
+ for ( TestLessInputStream aliveStream : TestLessInputStreamBuilder.this.aliveStreams )
+ {
+ aliveStream.shutdown();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ public void noop()
+ {
+ Lock lock = rwLock.readLock();
+ lock.lock();
+ try
+ {
+ for ( TestLessInputStream aliveStream : TestLessInputStreamBuilder.this.aliveStreams )
+ {
+ aliveStream.noop();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Event is persisted.
+ */
+ private final class CachableCommands
+ implements NotifiableTestStream
+ {
+ public void provideNewTest()
+ {
+ }
+
+ public void skipSinceNextTest()
+ {
+ Lock lock = rwLock.readLock();
+ lock.lock();
+ try
+ {
+ if ( TestLessInputStreamBuilder.this.addTailNodeIfAbsent( SKIP_SINCE_NEXT_TEST ) )
+ {
+ release();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ public void shutdown()
+ {
+ Lock lock = rwLock.readLock();
+ lock.lock();
+ try
+ {
+ if ( TestLessInputStreamBuilder.this.addTailNodeIfAbsent( SHUTDOWN ) )
+ {
+ release();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ public void noop()
+ {
+ Lock lock = rwLock.readLock();
+ lock.lock();
+ try
+ {
+ if ( TestLessInputStreamBuilder.this.addTailNodeIfAbsent( NOOP ) )
+ {
+ release();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ private void release()
+ {
+ for ( TestLessInputStream aliveStream : TestLessInputStreamBuilder.this.aliveStreams )
+ {
+ aliveStream.barrier.release();
+ }
+ }
+ }
+
+ private static class Node
+ {
+ private final AtomicReference<Node> next = new AtomicReference<Node>();
+ private final Command command;
+
+ Node( Command command )
+ {
+ this.command = command;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
index 97bf24d..dcc2997 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
@@ -20,144 +20,136 @@ package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
*/
import org.apache.maven.surefire.booter.Command;
-import org.apache.maven.surefire.booter.MasterProcessCommand;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED;
-import static org.apache.maven.surefire.util.internal.StringUtils.requireNonNull;
+import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
+import static org.apache.maven.surefire.booter.Command.SHUTDOWN;
+import static org.apache.maven.surefire.booter.Command.NOOP;
/**
- * An {@link InputStream} that, when read, provides test class names out of a queue.
+ * An {@link java.io.InputStream} that, when read, provides test class names out of a queue.
* <p/>
* The Stream provides only one test at a time, but only after {@link #provideNewTest()} has been invoked.
* <p/>
* After providing each test class name, followed by a newline character, a flush is performed on the
* {@link FlushReceiver} provided by the {@link FlushReceiverProvider} that can be set using
* {@link #setFlushReceiverProvider(FlushReceiverProvider)}.
+ * <p/>
+ * The instance is used only in reusable forks in {@link org.apache.maven.plugin.surefire.booterclient.ForkStarter}
+ * by one Thread.
*
* @author Andreas Gudian
+ * @author Tibor Digana (tibor17)
*/
-public class TestProvidingInputStream
- extends InputStream
- implements NotifiableTestStream
+public final class TestProvidingInputStream
+ extends AbstractCommandStream
{
- private final Semaphore semaphore = new Semaphore( 0 );
+ private final Semaphore barrier = new Semaphore( 0 );
- private final Queue<Command> commands;
+ private final Queue<Command> commands = new ConcurrentLinkedQueue<Command>();
private final AtomicBoolean closed = new AtomicBoolean();
- private byte[] currentBuffer;
-
- private int currentPos;
-
- private MasterProcessCommand lastCommand;
-
- private volatile FlushReceiverProvider flushReceiverProvider;
+ private final Queue<String> testClassNames;
/**
* C'tor
*
- * @param commands source of the tests to be read from this stream
+ * @param testClassNames source of the tests to be read from this stream
*/
- public TestProvidingInputStream( Queue<Command> commands )
+ public TestProvidingInputStream( Queue<String> testClassNames )
{
- this.commands = commands;
+ this.testClassNames = testClassNames;
}
/**
- * @param flushReceiverProvider the provider for a flush receiver.
+ * For testing purposes.
*/
- public void setFlushReceiverProvider( FlushReceiverProvider flushReceiverProvider )
+ void testSetFinished()
{
- this.flushReceiverProvider = requireNonNull( flushReceiverProvider );
+ if ( canContinue() )
+ {
+ commands.add( Command.TEST_SET_FINISHED );
+ barrier.release();
+ }
}
- public void testSetFinished()
+ public void skipSinceNextTest()
{
- commands.add( new Command( TEST_SET_FINISHED ) );
+ if ( canContinue() )
+ {
+ commands.add( SKIP_SINCE_NEXT_TEST );
+ barrier.release();
+ }
}
- /**
- * Used by single thread in StreamFeeder.
- *
- * @return {@inheritDoc}
- * @throws IOException {@inheritDoc}
- */
- @SuppressWarnings( "checkstyle:magicnumber" )
- @Override
- public int read()
- throws IOException
+ public void shutdown()
{
- byte[] buffer = currentBuffer;
- if ( buffer == null )
+ if ( canContinue() )
{
- if ( flushReceiverProvider != null )
- {
- FlushReceiver flushReceiver = flushReceiverProvider.getFlushReceiver();
- if ( flushReceiver != null )
- {
- flushReceiver.flush();
- }
- }
-
- if ( lastCommand == TEST_SET_FINISHED || closed.get() )
- {
- close();
- return -1;
- }
-
- awaitNextTest();
-
- if ( closed.get() )
- {
- return -1;
- }
-
- Command command = commands.poll();
- lastCommand = command.getCommandType();
- String test = command.getData();
- buffer = lastCommand == TEST_SET_FINISHED ? lastCommand.encode() : lastCommand.encode( test );
+ commands.add( SHUTDOWN );
+ barrier.release();
}
+ }
- int b = buffer[currentPos++] & 0xff;
- if ( currentPos == buffer.length )
+ public void noop()
+ {
+ if ( canContinue() )
{
- buffer = null;
- currentPos = 0;
+ commands.add( NOOP );
+ barrier.release();
}
- currentBuffer = buffer;
- return b;
}
- private void awaitNextTest()
- throws IOException
+ @Override
+ protected Command nextCommand()
{
- try
+ Command cmd = commands.poll();
+ if ( cmd == null )
{
- semaphore.acquire();
+ String cmdData = testClassNames.poll();
+ return cmdData == null ? Command.TEST_SET_FINISHED : new Command( RUN_CLASS, cmdData );
}
- catch ( InterruptedException e )
+ else
{
- // help GC to free this object because StreamFeeder Thread cannot read it after IOE
- currentBuffer = null;
- throw new IOException( e.getLocalizedMessage() );
+ return cmd;
}
}
+ @Override
+ protected void beforeNextCommand()
+ throws IOException
+ {
+ awaitNextTest();
+ }
+
+ @Override
+ protected boolean isClosed()
+ {
+ return closed.get();
+ }
+
+ @Override
+ protected boolean canContinue()
+ {
+ return getLastCommand() != TEST_SET_FINISHED && !isClosed();
+ }
+
/**
* Signal that a new test is to be provided.
*/
public void provideNewTest()
{
- if ( !closed.get() )
+ if ( canContinue() )
{
- semaphore.release();
+ barrier.release();
}
}
@@ -166,9 +158,24 @@ public class TestProvidingInputStream
{
if ( closed.compareAndSet( false, true ) )
{
- currentBuffer = null;
- semaphore.drainPermits();
- semaphore.release();
+ invalidateInternalBuffer();
+ barrier.drainPermits();
+ barrier.release();
+ }
+ }
+
+ private void awaitNextTest()
+ throws IOException
+ {
+ try
+ {
+ barrier.acquire();
+ }
+ catch ( InterruptedException e )
+ {
+ // help GC to free this object because StreamFeeder Thread cannot read it anyway after IOE
+ invalidateInternalBuffer();
+ throw new IOException( e.getLocalizedMessage() );
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
index 1778051..6cbc9bc 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
@@ -75,6 +75,10 @@ public class ForkClient
this.notifiableTestStream = notifiableTestStream;
}
+ protected void stopOnNextTest()
+ {
+ }
+
public DefaultReporterFactory getDefaultReporterFactory()
{
return defaultReporterFactory;
@@ -162,6 +166,9 @@ public class ForkClient
case ForkingRunListener.BOOTERCODE_BYE:
saidGoodBye = true;
break;
+ case ForkingRunListener.BOOTERCODE_STOP_ON_NEXT_TEST:
+ stopOnNextTest();
+ break;
default:
System.out.println( s );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
index b7bcadb..497a316 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
@@ -217,6 +217,10 @@ public class TestSetRunListener
clearCapture();
}
+ public void testExecutionSkippedByUser()
+ {
+ }
+
public void testAssumptionFailure( ReportEntry report )
{
testSkipped( report );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
index 113e2de..9c8cc07 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
@@ -237,7 +237,7 @@ public class BooterDeserializerProviderConfigurationTest
RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null );
return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration,
new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap<String, String>(), aTestTyped,
- readTestsFromInStream, cli );
+ readTestsFromInStream, cli, 0 );
}
private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
index 89c1f3e..6f232fa 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
@@ -144,7 +144,7 @@ public class BooterDeserializerStartupConfigurationTest
RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null );
return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration,
new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap<String, String>(),
- BooterDeserializerProviderConfigurationTest.aTestTyped, true, cli );
+ BooterDeserializerProviderConfigurationTest.aTestTyped, true, cli, 0 );
}
private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
new file mode 100644
index 0000000..3f2d221
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java
@@ -0,0 +1,161 @@
+package org.apache.maven.plugin.surefire.booterclient;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.ConsoleOutputReceiver;
+import org.apache.maven.surefire.report.ReportEntry;
+import org.apache.maven.surefire.report.RunListener;
+
+/**
+ * Internal tests use only.
+ */
+public class MockReporter
+ implements RunListener, ConsoleLogger, ConsoleOutputReceiver
+{
+ private final List<String> events = new ArrayList<String>();
+
+ private final List<Object> data = new ArrayList<Object>();
+
+ public static final String SET_STARTING = "SET_STARTED";
+
+ public static final String SET_COMPLETED = "SET_COMPLETED";
+
+ public static final String TEST_STARTING = "TEST_STARTED";
+
+ public static final String TEST_SUCCEEDED = "TEST_COMPLETED";
+
+ public static final String TEST_FAILED = "TEST_FAILED";
+
+ public static final String TEST_ERROR = "TEST_ERROR";
+
+ public static final String TEST_SKIPPED = "TEST_SKIPPED";
+
+ public static final String TEST_ASSUMPTION_FAIL = "TEST_ASSUMPTION_SKIPPED";
+
+ public static final String CONSOLE_OUTPUT = "CONSOLE_OUTPUT";
+
+ public static final String STDOUT = "STDOUT";
+
+ public static final String STDERR = "STDERR";
+
+ private final AtomicInteger testSucceeded = new AtomicInteger();
+
+ private final AtomicInteger testIgnored = new AtomicInteger();
+
+ private final AtomicInteger testFailed = new AtomicInteger();
+
+ public void testSetStarting( ReportEntry report )
+ {
+ events.add( SET_STARTING );
+ data.add( report );
+ }
+
+ public void testSetCompleted( ReportEntry report )
+ {
+ events.add( SET_COMPLETED );
+ data.add( report );
+ }
+
+ public void testStarting( ReportEntry report )
+ {
+ events.add( TEST_STARTING );
+ data.add( report );
+ }
+
+ public void testSucceeded( ReportEntry report )
+ {
+ events.add( TEST_SUCCEEDED );
+ testSucceeded.incrementAndGet();
+ data.add( report );
+ }
+
+ public void testError( ReportEntry report )
+ {
+ events.add( TEST_ERROR );
+ data.add( report );
+ testFailed.incrementAndGet();
+ }
+
+ public void testFailed( ReportEntry report )
+ {
+ events.add( TEST_FAILED );
+ data.add( report );
+ testFailed.incrementAndGet();
+ }
+
+ public void testSkipped( ReportEntry report )
+ {
+ events.add( TEST_SKIPPED );
+ data.add( report );
+ testIgnored.incrementAndGet();
+ }
+
+ public void testExecutionSkippedByUser()
+ {
+ }
+
+ public void testSkippedByUser( ReportEntry report )
+ {
+ testSkipped( report );
+ }
+
+ public List<String> getEvents()
+ {
+ return events;
+ }
+
+ public List getData()
+ {
+ return data;
+ }
+
+ public String getFirstEvent()
+ {
+ return events.get( 0 );
+ }
+
+ public ReportEntry getFirstData()
+ {
+ return (ReportEntry) data.get( 0 );
+ }
+
+ public void testAssumptionFailure( ReportEntry report )
+ {
+ events.add( TEST_ASSUMPTION_FAIL );
+ data.add( report );
+ testIgnored.incrementAndGet();
+ }
+
+ public void info( String message )
+ {
+ events.add( CONSOLE_OUTPUT );
+ data.add( message );
+ }
+
+ public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
+ {
+ events.add( stdout ? STDOUT : STDERR );
+ data.add( new String( buf, off, len ) );
+ }
+}
[06/17] maven-surefire git commit: [SUREFIRE] refactoring
Posted by ti...@apache.org.
[SUREFIRE] refactoring
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/8c34806b
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/8c34806b
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/8c34806b
Branch: refs/heads/master
Commit: 8c34806bd7d2a2e384823a6febe1f4131a9c5ee5
Parents: d755ecf
Author: Tibor17 <ti...@lycos.com>
Authored: Wed Aug 5 00:00:28 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Sep 6 22:57:57 2015 +0200
----------------------------------------------------------------------
.../common/junit4/JUnit4ProviderUtilTest.java | 2 --
.../common/junit4/JUnit4Reflector40Test.java | 4 +--
.../common/junit4/JUnit4RunListenerTest.java | 5 +--
.../surefire/junit4/JUnit4TestCheckerTest.java | 38 +++++++-------------
4 files changed, 16 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/8c34806b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
index 6a6e2e7..b05a562 100644
--- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
+++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
@@ -21,12 +21,10 @@ package org.apache.maven.surefire.common.junit4;
import junit.framework.TestCase;
import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.apache.maven.surefire.util.TestsToRun;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/8c34806b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
index 979adb8..28b5fed 100644
--- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
+++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java
@@ -19,7 +19,6 @@ package org.apache.maven.surefire.common.junit4;
*/
import junit.framework.TestCase;
-import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.Description;
@@ -30,12 +29,11 @@ import org.junit.runner.Description;
public class JUnit4Reflector40Test
extends TestCase
{
- @Test
public void testGetAnnotatedIgnore()
{
Description desc = Description.createTestDescription( IgnoreWithDescription.class, "testSomething2" );
Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( desc );
- Assert.assertNull( annotatedIgnore );
+ assertNull( annotatedIgnore );
}
private static final String reason = "Ignorance is bliss";
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/8c34806b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java
index c4765e9..deda538 100644
--- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java
+++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java
@@ -20,6 +20,8 @@ package org.apache.maven.surefire.common.junit4;
*/
import java.util.concurrent.CountDownLatch;
+
+import junit.framework.TestCase;
import org.apache.maven.surefire.junit4.MockReporter;
import junit.framework.Assert;
@@ -36,8 +38,8 @@ import org.junit.runner.notification.RunNotifier;
* @author Kristian Rosenvold
*/
public class JUnit4RunListenerTest
+ extends TestCase
{
- @Test
public void testTestStarted()
throws Exception
{
@@ -48,7 +50,6 @@ public class JUnit4RunListenerTest
junitTestRunner.run( runNotifier );
}
- @Test
public void testParallelInvocations()
throws Exception
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/8c34806b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java
index 3f2ed2b..a9f1b80 100644
--- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java
+++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java
@@ -33,91 +33,77 @@ import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Suite;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
/**
* @author Kristian Rosenvold
*/
public class JUnit4TestCheckerTest
+ extends TestCase
{
private final JUnit4TestChecker jUnit4TestChecker = new JUnit4TestChecker( this.getClass().getClassLoader() );
- @Test
- public void validJunit4Annotated()
+ public void testValidJunit4Annotated()
throws TestSetFailedException
{
assertTrue( jUnit4TestChecker.accept( JUnit4TestCheckerTest.class ) );
}
- @Test
- public void validJunit4itsAJunit3Test()
+ public void testValidJunit4itsAJunit3Test()
throws TestSetFailedException
{
assertTrue( jUnit4TestChecker.accept( AlsoValid.class ) );
}
- @Test
- public void validJunitSubclassWithoutOwnTestmethods()
+ public void testValidJunitSubclassWithoutOwnTestmethods()
throws TestSetFailedException
{
assertTrue( jUnit4TestChecker.accept( SubClassWithoutOwnTestMethods.class ) );
}
- @Test
- public void validSuite()
+ public void testValidSuite()
throws TestSetFailedException
{
assertTrue( jUnit4TestChecker.accept( SuiteValid1.class ) );
}
- @Test
- public void validCustomSuite()
+ public void testValidCustomSuite()
throws TestSetFailedException
{
assertTrue( jUnit4TestChecker.accept( SuiteValid2.class ) );
}
- @Test
- public void validCustomRunner()
+ public void testValidCustomRunner()
throws TestSetFailedException
{
assertTrue( jUnit4TestChecker.accept( SuiteValidCustomRunner.class ) );
}
- @Test
- public void invalidTest()
+ public void testInvalidTest()
throws TestSetFailedException
{
assertFalse( jUnit4TestChecker.accept( NotValidTest.class ) );
}
- @Test
- public void dontAcceptAbstractClasses()
+ public void testDontAcceptAbstractClasses()
{
assertFalse( jUnit4TestChecker.accept( BaseClassWithTest.class ) );
}
- @Test
- public void suiteOnlyTest()
+ public void testSuiteOnlyTest()
{
assertTrue( jUnit4TestChecker.accept( SuiteOnlyTest.class ) );
}
- @Test
- public void customSuiteOnlyTest()
+ public void testCustomSuiteOnlyTest()
{
assertTrue( jUnit4TestChecker.accept( CustomSuiteOnlyTest.class ) );
}
- @Test
- public void innerClassNotAutomaticallyTc()
+ public void testInnerClassNotAutomaticallyTc()
{
assertTrue( jUnit4TestChecker.accept( NestedTC.class ) );
assertFalse( jUnit4TestChecker.accept( NestedTC.Inner.class ) );
}
- @Test
public void testCannotLoadRunWithAnnotation()
throws Exception
{