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>

Reply via email to