Repository: maven-surefire Updated Branches: refs/heads/master 67c06d587 -> ead22a3d3
[SUREFIRE-1410] Add FAQ and improve Warning message when native stream in forked JVM is corrupted Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/ead22a3d Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/ead22a3d Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/ead22a3d Branch: refs/heads/master Commit: ead22a3d399a5fd608ebae90a079644ab786eae8 Parents: 67c06d5 Author: Tibor17 <[email protected]> Authored: Sat Sep 9 11:46:17 2017 +0200 Committer: Tibor17 <[email protected]> Committed: Sat Sep 9 11:46:17 2017 +0200 ---------------------------------------------------------------------- .../surefire/booterclient/ForkStarter.java | 15 ++++--- .../booterclient/output/ForkClient.java | 44 +++++++++++++++----- .../booterclient/ForkingRunListenerTest.java | 14 ++++--- maven-surefire-plugin/src/site/fml/faq.fml | 19 +++++++++ 4 files changed, 70 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/ead22a3d/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 2d82855..3efbd57 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 @@ -69,6 +69,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import static java.lang.StrictMath.min; @@ -269,7 +270,8 @@ public class ForkStarter TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder(); PropertiesWrapper props = new PropertiesWrapper( providerProperties ); TestLessInputStream stream = builder.build(); - ForkClient forkClient = new ForkClient( forkedReporterFactory, stream, log ); + ForkClient forkClient = new ForkClient( forkedReporterFactory, stream, log, forkConfiguration.isDebug(), + new AtomicBoolean() ); Thread shutdown = createImmediateShutdownHookThread( builder, providerConfiguration.getShutdown() ); ScheduledFuture<?> ping = triggerPingTimerForShutdown( builder ); try @@ -334,7 +336,8 @@ public class ForkStarter addShutDownHook( shutdown ); int failFastCount = providerConfiguration.getSkipAfterFailureCount(); final AtomicInteger notifyStreamsToSkipTestsJustNow = new AtomicInteger( failFastCount ); - Collection<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount ); + final Collection<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount ); + final AtomicBoolean printedErrorStream = new AtomicBoolean(); for ( final TestProvidingInputStream testProvidingInputStream : testStreams ) { Callable<RunResult> pf = new Callable<RunResult>() @@ -345,7 +348,8 @@ public class ForkStarter { DefaultReporterFactory reporter = new DefaultReporterFactory( startupReportConfiguration, log ); defaultReporterFactories.add( reporter ); - ForkClient forkClient = new ForkClient( reporter, testProvidingInputStream, log ) + ForkClient forkClient = new ForkClient( reporter, testProvidingInputStream, log, + forkConfiguration.isDebug(), printedErrorStream ) { @Override protected void stopOnNextTest() @@ -397,6 +401,7 @@ public class ForkStarter addShutDownHook( shutdown ); int failFastCount = providerConfiguration.getSkipAfterFailureCount(); final AtomicInteger notifyStreamsToSkipTestsJustNow = new AtomicInteger( failFastCount ); + final AtomicBoolean printedErrorStream = new AtomicBoolean(); for ( final Object testSet : getSuitesIterator() ) { Callable<RunResult> pf = new Callable<RunResult>() @@ -408,8 +413,8 @@ public class ForkStarter DefaultReporterFactory forkedReporterFactory = new DefaultReporterFactory( startupReportConfiguration, log ); defaultReporterFactories.add( forkedReporterFactory ); - ForkClient forkClient = - new ForkClient( forkedReporterFactory, builder.getImmediateCommands(), log ) + ForkClient forkClient = new ForkClient( forkedReporterFactory, builder.getImmediateCommands(), + log, forkConfiguration.isDebug(), printedErrorStream ) { @Override protected void stopOnNextTest() http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/ead22a3d/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 17da4df..bebc949 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 @@ -42,6 +42,7 @@ import java.util.StringTokenizer; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import static java.lang.Integer.decode; @@ -101,23 +102,35 @@ public class ForkClient private final ConsoleLogger log; + private final boolean debug; + + /** + * prevents from printing same warning + */ + private final AtomicBoolean printedErrorStream; + + /** + * Used by single Thread started by {@link ThreadedStreamConsumer} and therefore does not need to be volatile. + */ private RunListener testSetReporter; + /** + * Written by one Thread and read by another: Main Thread and ForkStarter's Thread. + */ private volatile boolean saidGoodBye; private volatile StackTraceWriter errorInFork; private volatile int forkNumber; - // prevents from printing same warning - private boolean printedErrorStream; - - public ForkClient( DefaultReporterFactory defaultReporterFactory, - NotifiableTestStream notifiableTestStream, ConsoleLogger log ) + public ForkClient( DefaultReporterFactory defaultReporterFactory, NotifiableTestStream notifiableTestStream, + ConsoleLogger log, boolean debug, AtomicBoolean printedErrorStream ) { this.defaultReporterFactory = defaultReporterFactory; this.notifiableTestStream = notifiableTestStream; this.log = log; + this.debug = debug; + this.printedErrorStream = printedErrorStream; } protected void stopOnNextTest() @@ -304,18 +317,27 @@ public class ForkClient { if ( event == null || !event.contains( PRINTABLE_JVM_NATIVE_STREAM ) ) { - final String msg = "Corrupted stdin stream in forked JVM " + forkNumber + "."; - final InPluginProcessDumpSingleton util = InPluginProcessDumpSingleton.getSingleton(); - final File dump = + String msg = "Corrupted STDOUT by directly writing to native stream in forked JVM " + forkNumber + "."; + + InPluginProcessDumpSingleton util = InPluginProcessDumpSingleton.getSingleton(); + File dump = e == null ? util.dumpText( msg + " Stream '" + event + "'.", defaultReporterFactory, forkNumber ) : util.dumpException( e, msg + " Stream '" + event + "'.", defaultReporterFactory, forkNumber ); - if ( !printedErrorStream ) + if ( printedErrorStream.compareAndSet( false, true ) ) { - printedErrorStream = true; - log.warning( msg + " See the dump file " + dump.getAbsolutePath() ); + log.warning( msg + " See FAQ web page and the dump file " + dump.getAbsolutePath() ); } + + if ( debug && event != null ) + { + log.debug( event ); + } + } + else if ( debug ) + { + log.debug( event ); } else { http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/ead22a3d/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java index 12b2087..f7406de 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java @@ -222,7 +222,8 @@ public class ForkingRunListenerTest TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory(); NullConsoleLogger log = new NullConsoleLogger(); - ForkClient forkStreamClient = new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log ); + ForkClient forkStreamClient = + new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, false, null ); forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) ); @@ -246,7 +247,8 @@ public class ForkingRunListenerTest TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory(); NullConsoleLogger log = new NullConsoleLogger(); - ForkClient forkStreamClient = new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log ); + ForkClient forkStreamClient = + new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, false, null ); forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) ); @@ -275,7 +277,7 @@ public class ForkingRunListenerTest NotifiableTestStream notifiableTestStream = new MockNotifiableTestStream(); NullConsoleLogger log = new NullConsoleLogger(); - ForkClient forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log ); + ForkClient forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log, false, null ); forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) ); MockReporter reporter = (MockReporter) forkStreamClient.getReporter(); @@ -283,7 +285,7 @@ public class ForkingRunListenerTest Assert.assertEquals( expected, reporter.getFirstData() ); Assert.assertEquals( 1, reporter.getEvents().size() ); - forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log ); + forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log, false, null ); forkStreamClient.consumeMultiLineContent( anotherContent.toString( "UTF-8" ) ); MockReporter reporter2 = (MockReporter) forkStreamClient.getReporter(); Assert.assertEquals( MockReporter.TEST_SKIPPED, reporter2.getFirstEvent() ); @@ -352,8 +354,8 @@ public class ForkingRunListenerTest { TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory(); NullConsoleLogger log = new NullConsoleLogger(); - final ForkClient forkStreamClient = new ForkClient( providerReporterFactory, - new MockNotifiableTestStream(), log ); + final ForkClient forkStreamClient = + new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, false, null ); forkStreamClient.consumeMultiLineContent( content.toString( ) ); reporter = (MockReporter) forkStreamClient.getReporter(); } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/ead22a3d/maven-surefire-plugin/src/site/fml/faq.fml ---------------------------------------------------------------------- diff --git a/maven-surefire-plugin/src/site/fml/faq.fml b/maven-surefire-plugin/src/site/fml/faq.fml index bc39ddc..b73dde6 100644 --- a/maven-surefire-plugin/src/site/fml/faq.fml +++ b/maven-surefire-plugin/src/site/fml/faq.fml @@ -137,5 +137,24 @@ under the License. </p> </answer> </faq> + <faq id="corruptedstream"> + <question>Corrupted STDOUT by directly writing to native stream in forked JVM</question> + <answer> + <p> + If your tests use native library which prints to STDOUT this warning message appears because the library + corrupted the channel used by the plugin in order to transmit events with test status back to Maven process. + It would be even worse if you override the Java stream by <em>System.setOut</em> because the stream is also + supposed to be corrupted but the Maven will never see the tests finished and build may hang. + <br/> + This warning message appears if you use <em>FileDescriptor.out</em> or JVM prints GC summary. + <br/> + In that case the warning is printed + <em>"Corrupted STDOUT by directly writing to native stream in forked JVM"</em>, and a dump file can be found + in Reports directory. + <br/> + If debug level is enabled then messages of corrupted stream appear in the console. + </p> + </answer> + </faq> </part> </faqs>
