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 2019/12/02 03:01:06 UTC
[maven-surefire] branch cli updated: substitutes the old call
executeCommandLineAsCallable() - (process call with all stream handlers)
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch cli
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
The following commit(s) were added to refs/heads/cli by this push:
new 71b8fd3 substitutes the old call executeCommandLineAsCallable() - (process call with all stream handlers)
71b8fd3 is described below
commit 71b8fd300a1bfd792bc970c2acfda9ee496a8282
Author: tibordigana <ti...@apache.org>
AuthorDate: Sun Dec 1 02:39:52 2019 +0100
substitutes the old call executeCommandLineAsCallable() - (process call with all stream handlers)
---
.../plugin/surefire/booterclient/ForkStarter.java | 53 +++++++++++---
surefire-extensions-api/pom.xml | 7 +-
.../extensions/util/CommandlineExecutor.java | 11 ++-
.../extensions/util/CommandlineStreams.java | 3 +-
.../util/FlushableWritableByteChannel.java | 3 +-
.../extensions/util/LineConsumerThread.java | 25 +++++--
.../surefire/extensions/util/StreamFeeder.java | 85 ++++++++++++++++++++++
7 files changed, 163 insertions(+), 24 deletions(-)
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 e3a76da..4b5e4fd 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
@@ -33,7 +33,10 @@ import org.apache.maven.plugin.surefire.booterclient.output.NativeStdErrStreamCo
import org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
-import org.apache.maven.surefire.shared.utils.cli.CommandLineCallable;
+import org.apache.maven.surefire.extensions.util.CommandlineExecutor;
+import org.apache.maven.surefire.extensions.util.CommandlineStreams;
+import org.apache.maven.surefire.extensions.util.LineConsumerThread;
+import org.apache.maven.surefire.extensions.util.StreamFeeder;
import org.apache.maven.surefire.shared.utils.cli.CommandLineException;
import org.apache.maven.surefire.booter.AbstractPathConfiguration;
import org.apache.maven.surefire.booter.KeyValueSource;
@@ -61,6 +64,7 @@ import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@@ -75,7 +79,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.StrictMath.min;
import static java.lang.System.currentTimeMillis;
import static java.lang.Thread.currentThread;
-import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.util.Collections.addAll;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.Executors.newScheduledThreadPool;
@@ -88,7 +91,6 @@ import static org.apache.maven.plugin.surefire.booterclient.ForkNumberBucket.dra
import static org.apache.maven.plugin.surefire.booterclient.ForkNumberBucket.returnNumber;
import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream
.TestLessInputStreamBuilder;
-import static org.apache.maven.surefire.shared.utils.cli.CommandLineUtils.executeCommandLineAsCallable;
import static org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils.addShutDownHook;
import static org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils.removeShutdownHook;
import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
@@ -217,6 +219,11 @@ public class ForkStarter
removeShutdownHook( inputStreamCloserHook );
}
}
+
+ void addCloseable( Closeable closeable )
+ {
+ testProvidingInputStream.add( closeable );
+ }
}
public ForkStarter( ProviderConfiguration providerConfiguration, StartupConfiguration startupConfiguration,
@@ -603,30 +610,54 @@ public class ForkStarter
Integer result = null;
RunResult runResult = null;
SurefireBooterForkException booterForkException = null;
+ StreamFeeder in = null;
+ LineConsumerThread out = null;
+ LineConsumerThread err = null;
try
{
NativeStdErrStreamConsumer stdErrConsumer =
new NativeStdErrStreamConsumer( forkClient.getDefaultReporterFactory() );
-
- CommandLineCallable future =
- executeCommandLineAsCallable( cli, testProvidingInputStream, threadedStreamConsumer,
- stdErrConsumer, 0, closer, ISO_8859_1 );
-
currentForkClients.add( forkClient );
- result = future.call();
+ // default impl of the extension - solves everything including the encoder/decoder, Process starter,
+ // adaptation of the streams to pipes and sockets
+ // non-default impl may use another classes and not the LineConsumerThread, StreamFeeder - freedom
+ // BEGIN: beginning of the call of the extension
+ CountDownLatch endOfStreamsCountdown = new CountDownLatch( 2 );
+ CommandlineExecutor exec = new CommandlineExecutor( cli, closer, endOfStreamsCountdown );
+ CommandlineStreams streams = exec.execute();
+ in = new StreamFeeder( "std-in-fork-" + forkNumber, streams.getStdInChannel(), testProvidingInputStream );
+ closer.addCloseable( in );
+ in.start();
+ out = new LineConsumerThread( "std-out-fork-" + forkNumber, streams.getStdOutChannel(),
+ threadedStreamConsumer, endOfStreamsCountdown );
+ closer.addCloseable( out );
+ out.start();
+ err = new LineConsumerThread( "std-err-fork-" + forkNumber, streams.getStdErrChannel(),
+ stdErrConsumer, endOfStreamsCountdown );
+ closer.addCloseable( err );
+ err.start();
+ result = exec.awaitExit();
+ // END: end of the call of the extension
if ( forkClient.hadTimeout() )
{
runResult = timeout( forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult() );
}
- else if ( result == null || result != SUCCESS )
+ else if ( result != SUCCESS )
{
booterForkException =
new SurefireBooterForkException( "Error occurred in starting fork, check output in log" );
}
}
- catch ( CommandLineException e )
+ catch ( InterruptedException e )
+ {
+ // maybe implement it in the Future.cancel() of the extension or similar
+ in.disable();
+ out.disable();
+ err.disable();
+ }
+ catch ( CommandLineException | IOException e )
{
runResult = failure( forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult(), e );
String cliErr = e.getLocalizedMessage();
diff --git a/surefire-extensions-api/pom.xml b/surefire-extensions-api/pom.xml
index a9d940b..5a79731 100644
--- a/surefire-extensions-api/pom.xml
+++ b/surefire-extensions-api/pom.xml
@@ -43,6 +43,11 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
@@ -92,4 +97,4 @@
</plugins>
</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineExecutor.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineExecutor.java
index 9415bfe..55f62e3 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineExecutor.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineExecutor.java
@@ -50,9 +50,12 @@ import static org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils.remov
* int exitCode = exec.awaitExit();
* // process exitCode
* }
- * catch ( InterruptedException | IOException | CommandLineException e )
+ * catch ( InterruptedException e )
+ * {
+ * lineConsumerThread.disable();
+ * }
+ * catch ( IOException | CommandLineException e )
* {
- * // lineConsumerThread.disable();
* // handle the exceptions
* }
* } </pre>
@@ -68,6 +71,10 @@ public class CommandlineExecutor implements Closeable
public CommandlineExecutor( Commandline cli,
Closeable closeAfterProcessTermination, CountDownLatch endOfStreamsCountdown )
{
+ // now the surefire-extension-api is dependent on CLI without casting generic type T to unrelated object
+ // and the user would not use maven-surefire-common nothing but the only surefire-extension-api
+ // because maven-surefire-common is used for MOJO plugin and not the user's extensions. The user does not need
+ // to see all MOJO impl. Only the surefire-api, surefire-logger-api and surefire-extension-api.
this.cli = cli;
this.closeAfterProcessTermination = closeAfterProcessTermination;
this.endOfStreamsCountdown = endOfStreamsCountdown;
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineStreams.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineStreams.java
index e60b2c6..43ec328 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineStreams.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/CommandlineStreams.java
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.extensions.util;
* under the License.
*/
+import javax.annotation.Nonnull;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
@@ -39,7 +40,7 @@ public final class CommandlineStreams implements Closeable
private final WritableByteChannel stdInChannel;
private volatile boolean closed;
- public CommandlineStreams( Process process )
+ public CommandlineStreams( @Nonnull Process process )
{
InputStream stdOutStream = process.getInputStream();
stdOutChannel = newChannel( stdOutStream );
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/FlushableWritableByteChannel.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/FlushableWritableByteChannel.java
index b769407..e4112f2 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/FlushableWritableByteChannel.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/FlushableWritableByteChannel.java
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.extensions.util;
* under the License.
*/
+import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
@@ -34,7 +35,7 @@ final class FlushableWritableByteChannel implements WritableByteChannel
private final OutputStream os;
private final WritableByteChannel channel;
- private FlushableWritableByteChannel( OutputStream os )
+ private FlushableWritableByteChannel( @Nonnull OutputStream os )
{
this.os = os;
this.channel = newChannel( os );
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/LineConsumerThread.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/LineConsumerThread.java
index 771cdc5..f0f39f3 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/LineConsumerThread.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/LineConsumerThread.java
@@ -21,6 +21,9 @@ package org.apache.maven.surefire.extensions.util;
import org.apache.maven.surefire.shared.utils.cli.StreamConsumer;
+import javax.annotation.Nonnull;
+import java.io.Closeable;
+import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.util.Scanner;
@@ -29,23 +32,23 @@ import java.util.concurrent.CountDownLatch;
/**
*
*/
-public final class LineConsumerThread extends Thread
+public final class LineConsumerThread extends Thread implements Closeable
{
private final Scanner scanner;
private final StreamConsumer consumer;
private final CountDownLatch endOfStreamsCountdown;
private volatile boolean disabled;
- public LineConsumerThread( String threadName,
- ReadableByteChannel channel, StreamConsumer consumer,
- CountDownLatch endOfStreamsCountdown )
+ public LineConsumerThread( @Nonnull String threadName,
+ @Nonnull ReadableByteChannel channel, @Nonnull StreamConsumer consumer,
+ @Nonnull CountDownLatch endOfStreamsCountdown )
{
- this( threadName, channel, consumer, Charset.defaultCharset(), endOfStreamsCountdown );
+ this( threadName, channel, consumer, endOfStreamsCountdown, Charset.defaultCharset() );
}
- public LineConsumerThread( String threadName,
- ReadableByteChannel channel, StreamConsumer consumer, Charset encoding,
- CountDownLatch endOfStreamsCountdown )
+ public LineConsumerThread( @Nonnull String threadName,
+ @Nonnull ReadableByteChannel channel, @Nonnull StreamConsumer consumer,
+ @Nonnull CountDownLatch endOfStreamsCountdown, @Nonnull Charset encoding )
{
setName( threadName );
setDaemon( true );
@@ -91,4 +94,10 @@ public final class LineConsumerThread extends Thread
{
disabled = true;
}
+
+ @Override
+ public void close() throws IOException
+ {
+ scanner.close();
+ }
}
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
new file mode 100644
index 0000000..255104b
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/util/StreamFeeder.java
@@ -0,0 +1,85 @@
+package org.apache.maven.surefire.extensions.util;
+
+/*
+ * 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 javax.annotation.Nonnull;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.WritableByteChannel;
+
+/**
+ *
+ */
+public class StreamFeeder extends Thread implements Closeable
+{
+ private final WritableByteChannel channel;
+ private final InputStream is;
+
+ private volatile boolean disabled;
+ private volatile boolean closed;
+ private volatile Throwable exception;
+
+ public StreamFeeder( @Nonnull String threadName, @Nonnull WritableByteChannel channel, @Nonnull InputStream is )
+ {
+ setName( threadName );
+ setDaemon( true );
+ this.channel = channel;
+ this.is = is;
+ }
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ for ( int data = is.read(); !closed && data != -1; data = is.read() )
+ {
+ if ( !disabled )
+ {
+ // todo use CommandReader interface instead of InputStream. Then we would write ByteBuffer.
+ channel.write( ByteBuffer.wrap( new byte[] {(byte) data} ) );
+ }
+ }
+ }
+ catch ( IOException | NonWritableChannelException e )
+ {
+ exception = e.getCause() == null ? e : e.getCause();
+ }
+ }
+
+ public void disable()
+ {
+ disabled = true;
+ }
+
+ public Throwable getException()
+ {
+ return exception;
+ }
+
+ @Override
+ public void close()
+ {
+ closed = true;
+ }
+}