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 2020/01/12 03:50:06 UTC

[maven-surefire] branch maven2surefire-jvm-communication updated: used reader of Command-s instead of InputStream

This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch maven2surefire-jvm-communication
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git


The following commit(s) were added to refs/heads/maven2surefire-jvm-communication by this push:
     new 3baa67f  used reader of Command-s instead of InputStream
3baa67f is described below

commit 3baa67f20bf960f537632c53b3f3b7c99469f7e1
Author: tibordigana <ti...@apache.org>
AuthorDate: Sun Jan 12 04:49:58 2020 +0100

    used reader of Command-s instead of InputStream
---
 .../AbstractClasspathForkConfiguration.java        |  3 +-
 .../surefire/booterclient/BooterSerializer.java    |  2 +-
 .../booterclient/ClasspathForkConfiguration.java   |  3 +-
 .../booterclient/JarManifestForkConfiguration.java |  3 +-
 .../ModularClasspathForkConfiguration.java         |  3 +-
 .../output/NativeStdErrStreamConsumer.java         |  2 +-
 .../extensions/NetworkingProcessExecutor.java      | 16 ++++-----
 .../surefire/extensions/PipeProcessExecutor.java   | 17 +++++----
 .../plugin/surefire/extensions/StdErrAdapter.java  | 42 ----------------------
 .../surefire/extensions/SurefireForkChannel.java   | 17 +++++++--
 .../AbstractSurefireMojoJava7PlusTest.java         |  6 ++++
 .../plugin/surefire/AbstractSurefireMojoTest.java  |  6 ++++
 .../booterclient/ForkConfigurationTest.java        |  4 ++-
 .../surefire/booterclient/ForkStarterTest.java     | 12 ++++---
 .../plugin/surefire/booterclient/MainClass.java    | 14 +++-----
 .../TestLessInputStreamBuilderTest.java            | 20 +++++++----
 .../TestProvidingInputStreamTest.java              | 40 ++++++++++-----------
 .../maven/surefire/extensions/CommandReader.java   |  4 ++-
 .../surefire/extensions/ExecutableCommandline.java | 14 ++++----
 .../surefire/extensions/StdErrStreamLine.java      |  5 +--
 .../surefire/extensions/util/StreamFeeder.java     | 20 +++++++----
 .../extensions/util/CommandlineExecutorTest.java   | 29 ++++++++++++---
 22 files changed, 152 insertions(+), 130 deletions(-)

diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java
index 08a8373..f8e08ea 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java
@@ -54,7 +54,8 @@ abstract class AbstractClasspathForkConfiguration
                                         @Nonnull ForkNodeFactory forkNodeFactory )
     {
         super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
-                environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log, forkNodeFactory );
+            environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log,
+            forkNodeFactory );
     }
 
     @Override
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 b166cc2..9a04326 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
@@ -107,7 +107,7 @@ class BooterSerializer
         throws IOException
     {
         SurefireProperties properties = new SurefireProperties( sourceProperties );
-        properties.setProperty( FORK_NODE_CONNECTION_STRING, forkNodeConnectionString );
+        properties.setNullableProperty( FORK_NODE_CONNECTION_STRING, forkNodeConnectionString );
         properties.setProperty( PLUGIN_PID, pid );
 
         AbstractPathConfiguration cp = startupConfiguration.getClasspathConfiguration();
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java
index 94b7ee3..9c906c4 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java
@@ -53,7 +53,8 @@ public final class ClasspathForkConfiguration
                                        @Nonnull ForkNodeFactory forkNodeFactory )
     {
         super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
-                environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log, forkNodeFactory );
+            environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log,
+            forkNodeFactory );
     }
 
     @Override
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java
index 281118b..382bec6 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java
@@ -75,7 +75,8 @@ public final class JarManifestForkConfiguration
                                          @Nonnull ForkNodeFactory forkNodeFactory )
     {
         super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
-                environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log, forkNodeFactory );
+            environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log,
+            forkNodeFactory );
     }
 
     @Override
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java
index 67a977c..d659a6c 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java
@@ -72,7 +72,8 @@ public class ModularClasspathForkConfiguration
                                               @Nonnull ForkNodeFactory forkNodeFactory )
     {
         super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
-                environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log, forkNodeFactory );
+            environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log,
+            forkNodeFactory );
     }
 
     @Override
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
index 6082096..8e4f6f0 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
@@ -40,7 +40,7 @@ public final class NativeStdErrStreamConsumer
     }
 
     @Override
-    public void handleLine( String line )
+    public void consumeLine( String line )
     {
         InPluginProcessDumpSingleton.getSingleton()
                 .dumpStreamText( line, defaultReporterFactory.getReportsDirectory() );
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/NetworkingProcessExecutor.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/NetworkingProcessExecutor.java
index 71b75cc..eecb5ca 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/NetworkingProcessExecutor.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/NetworkingProcessExecutor.java
@@ -61,12 +61,12 @@ final class NetworkingProcessExecutor implements ExecutableCommandline
 
     @Nonnull
     @Override
-    public <T> Callable<Integer> executeCommandLineAsCallable( @Nonnull T cli,
-                                                               @Nonnull final CommandReader commands,
-                                                               @Nonnull final EventHandler events,
-                                                               StdOutStreamLine stdOut,
-                                                               StdErrStreamLine stdErr,
-                                                               @Nonnull Runnable runAfterProcessTermination )
+    public Callable<Integer> executeCommandLineAsCallable( @Nonnull Commandline cli,
+                                                           @Nonnull final CommandReader commands,
+                                                           @Nonnull final EventHandler events,
+                                                           StdOutStreamLine stdOut,
+                                                           StdErrStreamLine stdErr,
+                                                           @Nonnull Runnable runAfterProcessTermination )
             throws Exception
     {
         server.accept( null, new CompletionHandler<AsynchronousSocketChannel, Object>()
@@ -154,8 +154,8 @@ final class NetworkingProcessExecutor implements ExecutableCommandline
             }
         } );
 
-        return CommandLineUtils.executeCommandLineAsCallable( (Commandline) cli, null,
-                new StdOutAdapter( stdOut ), new StdErrAdapter( stdErr ), 0, runAfterProcessTermination, US_ASCII );
+        return CommandLineUtils.executeCommandLineAsCallable( cli, null,
+                new StdOutAdapter( stdOut ), stdErr, 0, runAfterProcessTermination, US_ASCII );
     }
 
     private static InputStream toInputStream( final AsynchronousSocketChannel client )
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/PipeProcessExecutor.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/PipeProcessExecutor.java
index f6e942b..ad3bcfc 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/PipeProcessExecutor.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/PipeProcessExecutor.java
@@ -59,17 +59,16 @@ final class PipeProcessExecutor
 {
     @Override
     @Nonnull
-    public <T> Callable<Integer> executeCommandLineAsCallable( @Nonnull T cli,
-                                                               @Nonnull CommandReader commands,
-                                                               @Nonnull EventHandler events,
-                                                               StdOutStreamLine stdOut,
-                                                               StdErrStreamLine stdErr,
-                                                               @Nonnull Runnable runAfterProcessTermination )
+    public Callable<Integer> executeCommandLineAsCallable( @Nonnull Commandline cli,
+                                                           @Nonnull CommandReader commands,
+                                                           @Nonnull EventHandler events,
+                                                           StdOutStreamLine stdOut,
+                                                           StdErrStreamLine stdErr,
+                                                           @Nonnull Runnable runAfterProcessTermination )
             throws Exception
     {
-        return CommandLineUtils.executeCommandLineAsCallable( (Commandline) cli, new CommandReaderAdapter( commands ),
-                new EventHandlerAdapter( events ), new StdErrAdapter( stdErr ),
-                0, runAfterProcessTermination, US_ASCII );
+        return CommandLineUtils.executeCommandLineAsCallable( cli, new CommandReaderAdapter( commands ),
+                new EventHandlerAdapter( events ), stdErr, 0, runAfterProcessTermination, US_ASCII );
     }
 
     private static class EventHandlerAdapter implements StreamConsumer
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/StdErrAdapter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/StdErrAdapter.java
deleted file mode 100644
index 52d352a..0000000
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/StdErrAdapter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.apache.maven.plugin.surefire.extensions;
-
-/*
- * 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.extensions.StdErrStreamLine;
-import org.apache.maven.surefire.shared.utils.cli.StreamConsumer;
-
-/**
- *
- */
-final class StdErrAdapter implements StreamConsumer
-{
-    private final StdErrStreamLine stdErr;
-
-    StdErrAdapter( StdErrStreamLine stdErr )
-    {
-        this.stdErr = stdErr;
-    }
-
-    @Override
-    public void consumeLine( String line )
-    {
-        stdErr.handleLine( line );
-    }
-}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireForkChannel.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireForkChannel.java
index fb8f789..2238898 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireForkChannel.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireForkChannel.java
@@ -25,6 +25,7 @@ import org.apache.maven.surefire.extensions.ForkChannel;
 import javax.annotation.Nonnull;
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.net.SocketOption;
 import java.nio.channels.AsynchronousServerSocketChannel;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -49,13 +50,23 @@ final class SurefireForkChannel implements ForkChannel
     {
         executorService = Executors.newCachedThreadPool( newDaemonThreadFactory() );
         server = open( withThreadPool( executorService ) );
-        server.setOption( SO_REUSEADDR, true );
-        server.setOption( TCP_NODELAY, true );
-        server.setOption( SO_KEEPALIVE, true );
+        setTrueOptions( SO_REUSEADDR, TCP_NODELAY, SO_KEEPALIVE );
         server.bind( new InetSocketAddress( 0 ) );
         serverPort = ( (InetSocketAddress) server.getLocalAddress() ).getPort();
     }
 
+    @SafeVarargs
+    private final void setTrueOptions( SocketOption<Boolean>... options ) throws IOException
+    {
+        for ( SocketOption<Boolean> option : options )
+        {
+            if ( server.supportedOptions().contains( option ) )
+            {
+                server.setOption( option, true );
+            }
+        }
+    }
+
     @Override
     public String getForkNodeConnectionString()
     {
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java
index bc722e3..da9791a 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java
@@ -633,6 +633,12 @@ public class AbstractSurefireMojoJava7PlusTest
         }
 
         @Override
+        protected ForkNodeFactory getForkNode()
+        {
+            return null;
+        }
+
+        @Override
         protected Artifact getMojoArtifact()
         {
             return null;
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java
index 03cb190..dde8600 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java
@@ -2122,6 +2122,12 @@ public class AbstractSurefireMojoTest
         }
 
         @Override
+        protected ForkNodeFactory getForkNode()
+        {
+            return null;
+        }
+
+        @Override
         protected Artifact getMojoArtifact()
         {
             return new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-plugin", createFromVersion( "1" ),
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
index 16564a3..8d806ca 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
@@ -45,7 +45,9 @@ import static java.util.Collections.singletonList;
 import static org.apache.maven.surefire.booter.Classpath.emptyClasspath;
 import static org.apache.maven.surefire.booter.ProcessCheckerType.ALL;
 import static org.fest.util.Files.temporaryFolder;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 
 /**
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
index e0874f0..a7ab4d7 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkStarterTest.java
@@ -21,12 +21,13 @@ package org.apache.maven.plugin.surefire.booterclient;
 
 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.AbstractCommandReader;
 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.TestLessInputStream.TestLessInputStreamBuilder;
 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvidingInputStream;
 import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
+import org.apache.maven.plugin.surefire.extensions.LegacyForkNodeFactory;
 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
 import org.apache.maven.surefire.booter.AbstractPathConfiguration;
@@ -37,6 +38,7 @@ import org.apache.maven.surefire.booter.ProviderConfiguration;
 import org.apache.maven.surefire.booter.Shutdown;
 import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
+import org.apache.maven.surefire.extensions.ForkNodeFactory;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.shared.compress.archivers.zip.Zip64Mode;
 import org.apache.maven.surefire.shared.compress.archivers.zip.ZipArchiveEntry;
@@ -170,12 +172,12 @@ public class ForkStarterTest
         e.expectMessage( containsString( "VM crash or System.exit called?" ) );
 
         Class<?>[] types = {Object.class, PropertiesWrapper.class, ForkClient.class, SurefireProperties.class,
-            int.class, AbstractForkInputStream.class, boolean.class};
+            int.class, AbstractCommandReader.class, ForkNodeFactory.class, boolean.class};
         TestProvidingInputStream testProvidingInputStream = new TestProvidingInputStream( new ArrayDeque<String>() );
         invokeMethod( forkStarter, "fork", types, null,
             new PropertiesWrapper( Collections.<String, String>emptyMap() ),
             new ForkClient( reporterFactory, null, logger, new AtomicBoolean(), 1 ),
-            new SurefireProperties(), 1, testProvidingInputStream, true );
+            new SurefireProperties(), 1, testProvidingInputStream, new LegacyForkNodeFactory(), true );
         testProvidingInputStream.close();
     }
 
@@ -224,12 +226,12 @@ public class ForkStarterTest
         DefaultReporterFactory reporterFactory = new DefaultReporterFactory( startupReportConfiguration, logger, 1 );
 
         Class<?>[] types = {Object.class, PropertiesWrapper.class, ForkClient.class, SurefireProperties.class,
-            int.class, AbstractForkInputStream.class, boolean.class};
+            int.class, AbstractCommandReader.class, ForkNodeFactory.class, boolean.class};
         TestLessInputStream testLessInputStream = new TestLessInputStreamBuilder().build();
         invokeMethod( forkStarter, "fork", types, null,
             new PropertiesWrapper( Collections.<String, String>emptyMap() ),
             new ForkClient( reporterFactory, testLessInputStream, logger, new AtomicBoolean(), 1 ),
-            new SurefireProperties(), 1, testLessInputStream, true );
+            new SurefireProperties(), 1, testLessInputStream, new LegacyForkNodeFactory(), true );
         testLessInputStream.close();
     }
 
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MainClass.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MainClass.java
index d90a128..f546d66 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MainClass.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MainClass.java
@@ -34,15 +34,11 @@ public class MainClass
         }
         else
         {
-            System.out.println( ":maven:surefire:std:out:bye" );
-            if ( System.in.read() == 0
-                && System.in.read() == 0
-                && System.in.read() == 0
-                && System.in.read() == 5
-                && System.in.read() == 0
-                && System.in.read() == 0
-                && System.in.read() == 0
-                && System.in.read() == 0 )
+            System.out.println( ":maven:surefire:std:out:bye\n" );
+            String byeAck = ":maven-surefire-std-out:bye-ack:";
+            byte[] cmd = new byte[byeAck.length()];
+            int len = System.in.read( cmd );
+            if ( len != -1 && new String( cmd, 0, len ).equals( byeAck ) )
             {
                 System.exit( 0 );
             }
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
index 39789ac..d14014a 100644
--- 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
@@ -32,8 +32,8 @@ import java.io.InputStream;
 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.plugin.surefire.booterclient.lazytestprovider
+    .TestLessInputStream.TestLessInputStreamBuilder;
 import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
 import static org.apache.maven.surefire.booter.MasterProcessCommand.SHUTDOWN;
 import static org.apache.maven.surefire.booter.Shutdown.EXIT;
@@ -88,7 +88,7 @@ public class TestLessInputStreamBuilderTest
         assertThat( is.availablePermits(), is( 1 ) );
         is.beforeNextCommand();
         assertThat( is.availablePermits(), is( 0 ) );
-        assertThat( is.nextCommand(), is( NOOP ) );
+        assertThat( is.nextCommand(), is( Command.NOOP ) );
         assertThat( is.availablePermits(), is( 0 ) );
         e.expect( NoSuchElementException.class );
         is.nextCommand();
@@ -106,7 +106,7 @@ public class TestLessInputStreamBuilderTest
         assertThat( is.availablePermits(), is( 2 ) );
         is.beforeNextCommand();
         assertThat( is.availablePermits(), is( 1 ) );
-        assertThat( is.nextCommand(), is( NOOP ) );
+        assertThat( is.nextCommand(), is( Command.NOOP ) );
         assertThat( is.availablePermits(), is( 1 ) );
         builder.getCachableCommands().skipSinceNextTest();
         assertThat( is.availablePermits(), is( 1 ) );
@@ -124,7 +124,7 @@ public class TestLessInputStreamBuilderTest
         builder.getCachableCommands().shutdown( EXIT );
         assertThat( is.availablePermits(), is( 2 ) );
         is.beforeNextCommand();
-        assertThat( is.nextCommand(), is( NOOP ) );
+        assertThat( is.nextCommand(), is( Command.NOOP ) );
         assertThat( is.availablePermits(), is( 1 ) );
         is.beforeNextCommand();
         assertThat( is.nextCommand().getCommandType(), is( SHUTDOWN ) );
@@ -151,7 +151,15 @@ public class TestLessInputStreamBuilderTest
                 {
                     idx = 0;
                     Command cmd = pluginIs.readNextCommand();
-                    buffer = cmd == null ? null : cmd.getCommandType().encode();
+                    if ( cmd == null )
+                    {
+                        buffer = null;
+                    }
+                    else
+                    {
+                        MasterProcessCommand cmdType = cmd.getCommandType();
+                        buffer = cmdType.hasDataType() ? cmdType.encode( cmd.getData() ) : cmdType.encode();
+                    }
                 }
 
                 if ( buffer != null )
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 f863be1..66b4218 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
@@ -40,6 +40,7 @@ import static org.apache.maven.surefire.booter.MasterProcessCommand.NOOP;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -50,6 +51,7 @@ import static org.junit.Assert.assertTrue;
  */
 public class TestProvidingInputStreamTest
 {
+    private static final int WAIT_LOOPS = 100;
     @Test
     public void closedStreamShouldReturnNullAsEndOfStream()
         throws IOException
@@ -101,15 +103,16 @@ public class TestProvidingInputStreamTest
             }
         } ).start();
 
-        StringBuilder stream = new StringBuilder();
-        for ( int i = 0; i < 82; i++ )
-        {
-            Command cmd = is.readNextCommand();
-            assertThat( cmd.getData(), is( nullValue() ) );
-            stream.append( new String( cmd.getCommandType().encode(), US_ASCII ) );
-        }
-        assertThat( stream.toString(),
-                is( ":maven-surefire-std-out:testset-finished::maven-surefire-std-out:testset-finished:" ) );
+        Command cmd = is.readNextCommand();
+        assertThat( cmd.getData(), is( nullValue() ) );
+        String stream = new String( cmd.getCommandType().encode(), US_ASCII );
+
+        cmd = is.readNextCommand();
+        assertThat( cmd.getData(), is( nullValue() ) );
+        stream += new String( cmd.getCommandType().encode(), US_ASCII );
+
+        assertThat( stream,
+            is( ":maven-surefire-std-out:testset-finished::maven-surefire-std-out:testset-finished:" ) );
 
         boolean emptyStream = isInputStreamEmpty( is );
 
@@ -134,15 +137,8 @@ public class TestProvidingInputStreamTest
             }
         } ).start();
 
-        StringBuilder stream = new StringBuilder();
-        for ( int i = 0; i < 43; i++ )
-        {
-            Command cmd = is.readNextCommand();
-            assertThat( cmd.getData(), is( nullValue() ) );
-            stream.append( new String( is.readNextCommand().getCommandType().encode(), US_ASCII ) );
-        }
-        assertThat( stream.toString(),
-                is( ":maven-surefire-std-out:run-testclass:Test:" ) );
+        Command cmd = is.readNextCommand();
+        assertThat( cmd.getData(), is( "Test" ) );
 
         is.close();
     }
@@ -223,7 +219,10 @@ public class TestProvidingInputStreamTest
                 {
                     Throwable cause = e.getCause();
                     Throwable err = cause == null ? e : cause;
-                    System.err.println( err.toString() );
+                    if ( !( err instanceof InterruptedException ) )
+                    {
+                        System.err.println( err.toString() );
+                    }
                 }
             }
         } );
@@ -234,7 +233,8 @@ public class TestProvidingInputStreamTest
         {
             sleep( 100L );
             state = t.getState();
-        } while ( state == State.NEW && loops++ < 200 );
+        }
+        while ( state == State.NEW && loops++ < WAIT_LOOPS );
         t.interrupt();
         return state == State.WAITING || state == State.TIMED_WAITING;
     }
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/CommandReader.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/CommandReader.java
index 8dd9d96..08fe5ed 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/CommandReader.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/CommandReader.java
@@ -21,6 +21,7 @@ package org.apache.maven.surefire.extensions;
 
 import org.apache.maven.surefire.booter.Command;
 
+import java.io.Closeable;
 import java.io.IOException;
 
 /**
@@ -29,7 +30,7 @@ import java.io.IOException;
  * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
  * @since 3.0.0-M4
  */
-public interface CommandReader
+public interface CommandReader extends Closeable
 {
 
     /**
@@ -38,6 +39,7 @@ public interface CommandReader
      * @return the command, or null if closed
      */
     Command readNextCommand() throws IOException;
+    @Override
     void close();
     boolean isClosed();
     void tryFlush() throws IOException;
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ExecutableCommandline.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ExecutableCommandline.java
index b373002..ed7a8ec 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ExecutableCommandline.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ExecutableCommandline.java
@@ -19,6 +19,8 @@ package org.apache.maven.surefire.extensions;
  * under the License.
  */
 
+import org.apache.maven.surefire.shared.utils.cli.Commandline;
+
 import javax.annotation.Nonnull;
 import java.util.concurrent.Callable;
 
@@ -28,11 +30,11 @@ import java.util.concurrent.Callable;
 public interface ExecutableCommandline
 {
     @Nonnull
-    <T> Callable<Integer> executeCommandLineAsCallable( @Nonnull T cli,
-                                                        @Nonnull CommandReader commands,
-                                                        @Nonnull EventHandler events,
-                                                        StdOutStreamLine stdOut,
-                                                        StdErrStreamLine stdErr,
-                                                        @Nonnull Runnable runAfterProcessTermination )
+    Callable<Integer> executeCommandLineAsCallable( @Nonnull Commandline cli,
+                                                    @Nonnull CommandReader commands,
+                                                    @Nonnull EventHandler events,
+                                                    StdOutStreamLine stdOut,
+                                                    StdErrStreamLine stdErr,
+                                                    @Nonnull Runnable runAfterProcessTermination )
             throws Exception;
 }
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StdErrStreamLine.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StdErrStreamLine.java
index be444ae..f0ae082 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StdErrStreamLine.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StdErrStreamLine.java
@@ -19,10 +19,11 @@ package org.apache.maven.surefire.extensions;
  * under the License.
  */
 
+import org.apache.maven.surefire.shared.utils.cli.StreamConsumer;
+
 /**
  * The line handler of forked process standard-error.
  */
-public interface StdErrStreamLine
+public interface StdErrStreamLine extends StreamConsumer
 {
-    void handleLine( String line );
 }
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/StreamFeeder.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/StreamFeeder.java
index ca8eb8e..9305d07 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/StreamFeeder.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/StreamFeeder.java
@@ -19,10 +19,13 @@ package org.apache.maven.surefire.extensions.util;
  * under the License.
  */
 
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.MasterProcessCommand;
+import org.apache.maven.surefire.extensions.CommandReader;
+
 import javax.annotation.Nonnull;
 import java.io.Closeable;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.NonWritableChannelException;
@@ -34,30 +37,33 @@ import java.nio.channels.WritableByteChannel;
 public class StreamFeeder extends Thread implements Closeable
 {
     private final WritableByteChannel channel;
-    private final InputStream is;
+    private final CommandReader commandReader;
 
     private volatile boolean disabled;
     private volatile Throwable exception;
 
-    public StreamFeeder( @Nonnull String threadName, @Nonnull WritableByteChannel channel, @Nonnull InputStream is )
+    public StreamFeeder( @Nonnull String threadName, @Nonnull WritableByteChannel channel,
+                         @Nonnull CommandReader commandReader )
     {
         setName( threadName );
         setDaemon( true );
         this.channel = channel;
-        this.is = is;
+        this.commandReader = commandReader;
     }
 
     @Override
+    @SuppressWarnings( "checkstyle:innerassignment" )
     public void run()
     {
         try ( WritableByteChannel c = channel )
         {
-            for ( int data = is.read(); data != -1; data = is.read()  )
+            for ( Command cmd; ( cmd = commandReader.readNextCommand() ) != null; )
             {
                 if ( !disabled )
                 {
-                    // todo use CommandReader interface instead of InputStream. Then we would write ByteBuffer.
-                    c.write( ByteBuffer.wrap( new byte[] {(byte) data} ) );
+                    MasterProcessCommand cmdType = cmd.getCommandType();
+                    byte[] data = cmdType.hasDataType() ? cmdType.encode( cmd.getData() ) : cmdType.encode();
+                    c.write( ByteBuffer.wrap( data ) );
                 }
             }
         }
diff --git a/surefire-extensions-api/src/test/java/org/apache/maven/surefire/extensions/util/CommandlineExecutorTest.java b/surefire-extensions-api/src/test/java/org/apache/maven/surefire/extensions/util/CommandlineExecutorTest.java
index fd99059..fc919d2 100644
--- a/surefire-extensions-api/src/test/java/org/apache/maven/surefire/extensions/util/CommandlineExecutorTest.java
+++ b/surefire-extensions-api/src/test/java/org/apache/maven/surefire/extensions/util/CommandlineExecutorTest.java
@@ -19,6 +19,8 @@ package org.apache.maven.surefire.extensions.util;
  * under the License.
  */
 
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.extensions.CommandReader;
 import org.apache.maven.surefire.shared.utils.cli.Commandline;
 import org.apache.maven.surefire.shared.utils.cli.StreamConsumer;
 import org.junit.After;
@@ -26,7 +28,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.Closeable;
-import java.io.InputStream;
 import java.nio.file.Paths;
 
 import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
@@ -90,15 +91,33 @@ public class CommandlineExecutorTest
         exec = new CommandlineExecutor( cli, countdownCloseable );
         streams = exec.execute();
         StreamConsumer consumer = mock( StreamConsumer.class );
-        InputStream is = new InputStream()
+        CommandReader commandReader = new CommandReader()
         {
             @Override
-            public int read()
+            public Command readNextCommand()
             {
-                return -1;
+                return null;
+            }
+
+            @Override
+            public void close()
+            {
+
+            }
+
+            @Override
+            public boolean isClosed()
+            {
+                return false;
+            }
+
+            @Override
+            public void tryFlush()
+            {
+
             }
         };
-        StreamFeeder in = new StreamFeeder( "std-in-fork-1", streams.getStdInChannel(), is );
+        StreamFeeder in = new StreamFeeder( "std-in-fork-1", streams.getStdInChannel(), commandReader );
         in.start();
         out = new LineConsumerThread( "std-out-fork-1", streams.getStdOutChannel(), consumer, countdownCloseable );
         out.start();