[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-17 Thread jaikiran
Github user jaikiran closed the pull request at:

https://github.com/apache/ant/pull/60


---

-
To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org
For additional commands, e-mail: dev-h...@ant.apache.org



[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172044906
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172044717
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,295 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Task task;
+
+private SysOutErrContentStore sysOutStore;
+private SysOutErrContentStore sysErrStore;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStore == null) {
+this.sysOutStore = new SysOutErrContentStore(true);
+}
+try {
+this.sysOutStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStore == null) {
+this.sysErrStore = new SysOutErrContentStore(false);
+}
+try {
+this.sysErrStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+/**
+ * @return Returns true if there's any stdout data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysOut() {
+return this.sysOutStore != null && this.sysOutStore.hasData();
+}
+
+/**
+ * @return Returns true if there's any stderr data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysErr() {
+return this.sysErrStore != null && this.sysErrStore.hasData();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stdout data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysOut()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysOutReader() throws IOException {
+return this.sysOutStore.getReader();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stderr data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysErr()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysErrReader() throws IOException {
+return this.sysErrStore.getReader();
+}
+
+/**
+ * Writes out any stdout data that was generated during the
+ * test execution. If there was no such data then this method just 
returns.
+ *
+ * @param writer The {@link Writer} to use. Cannot be null.
+ * @throws IOException If any I/O problem occurs during writing the 
data
+ */
+void writeSysOut(final Writer writer) throws IOException {
+Objects.requireNonNull(writer, "Writer cannot be null");
+this.writeFrom(this.sysOutStore, writer);
+}
+
+/**
+ * Writes out any stderr data that was generated during the
+ * test execution. If there was no such data then this 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172044665
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,295 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Task task;
+
+private SysOutErrContentStore sysOutStore;
+private SysOutErrContentStore sysErrStore;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStore == null) {
+this.sysOutStore = new SysOutErrContentStore(true);
+}
+try {
+this.sysOutStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStore == null) {
+this.sysErrStore = new SysOutErrContentStore(false);
+}
+try {
+this.sysErrStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+/**
+ * @return Returns true if there's any stdout data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysOut() {
+return this.sysOutStore != null && this.sysOutStore.hasData();
+}
+
+/**
+ * @return Returns true if there's any stderr data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysErr() {
+return this.sysErrStore != null && this.sysErrStore.hasData();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stdout data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysOut()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysOutReader() throws IOException {
+return this.sysOutStore.getReader();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stderr data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysErr()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysErrReader() throws IOException {
+return this.sysErrStore.getReader();
+}
+
+/**
+ * Writes out any stdout data that was generated during the
+ * test execution. If there was no such data then this method just 
returns.
+ *
+ * @param writer The {@link Writer} to use. Cannot be null.
+ * @throws IOException If any I/O problem occurs during writing the 
data
+ */
+void writeSysOut(final Writer writer) throws IOException {
+Objects.requireNonNull(writer, "Writer cannot be null");
+this.writeFrom(this.sysOutStore, writer);
+}
+
+/**
+ * Writes out any stderr data that was generated during the
+ * test execution. If there was no such data then this 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172044509
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,295 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Task task;
+
+private SysOutErrContentStore sysOutStore;
+private SysOutErrContentStore sysErrStore;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStore == null) {
+this.sysOutStore = new SysOutErrContentStore(true);
+}
+try {
+this.sysOutStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStore == null) {
+this.sysErrStore = new SysOutErrContentStore(false);
+}
+try {
+this.sysErrStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+/**
+ * @return Returns true if there's any stdout data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysOut() {
+return this.sysOutStore != null && this.sysOutStore.hasData();
+}
+
+/**
+ * @return Returns true if there's any stderr data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysErr() {
+return this.sysErrStore != null && this.sysErrStore.hasData();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stdout data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysOut()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysOutReader() throws IOException {
+return this.sysOutStore.getReader();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stderr data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysErr()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysErrReader() throws IOException {
+return this.sysErrStore.getReader();
+}
+
+/**
+ * Writes out any stdout data that was generated during the
+ * test execution. If there was no such data then this method just 
returns.
+ *
+ * @param writer The {@link Writer} to use. Cannot be null.
+ * @throws IOException If any I/O problem occurs during writing the 
data
+ */
+void writeSysOut(final Writer writer) throws IOException {
+Objects.requireNonNull(writer, "Writer cannot be null");
+this.writeFrom(this.sysOutStore, writer);
+}
+
+/**
+ * Writes out any stderr data that was generated during the
+ * test execution. If there was no such data then this 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172043964
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172043835
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,295 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Task task;
+
+private SysOutErrContentStore sysOutStore;
+private SysOutErrContentStore sysErrStore;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStore == null) {
+this.sysOutStore = new SysOutErrContentStore(true);
+}
+try {
+this.sysOutStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStore == null) {
+this.sysErrStore = new SysOutErrContentStore(false);
+}
+try {
+this.sysErrStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+/**
+ * @return Returns true if there's any stdout data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysOut() {
+return this.sysOutStore != null && this.sysOutStore.hasData();
+}
+
+/**
+ * @return Returns true if there's any stderr data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysErr() {
+return this.sysErrStore != null && this.sysErrStore.hasData();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stdout data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysOut()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysOutReader() throws IOException {
+return this.sysOutStore.getReader();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stderr data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysErr()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysErrReader() throws IOException {
+return this.sysErrStore.getReader();
+}
+
+/**
+ * Writes out any stdout data that was generated during the
+ * test execution. If there was no such data then this method just 
returns.
+ *
+ * @param writer The {@link Writer} to use. Cannot be null.
+ * @throws IOException If any I/O problem occurs during writing the 
data
+ */
+void writeSysOut(final Writer writer) throws IOException {
+Objects.requireNonNull(writer, "Writer cannot be null");
+this.writeFrom(this.sysOutStore, writer);
+}
+
+/**
+ * Writes out any stderr data that was generated during the
+ * test execution. If there was no such data then this 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-03-04 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r172043778
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,295 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Task task;
+
+private SysOutErrContentStore sysOutStore;
+private SysOutErrContentStore sysErrStore;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStore == null) {
+this.sysOutStore = new SysOutErrContentStore(true);
+}
+try {
+this.sysOutStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStore == null) {
+this.sysErrStore = new SysOutErrContentStore(false);
+}
+try {
+this.sysErrStore.store(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+/**
+ * @return Returns true if there's any stdout data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysOut() {
+return this.sysOutStore != null && this.sysOutStore.hasData();
+}
+
+/**
+ * @return Returns true if there's any stderr data, that was generated 
during the
+ * tests, is available for use. Else returns false.
+ */
+boolean hasSysErr() {
+return this.sysErrStore != null && this.sysErrStore.hasData();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stdout data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysOut()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysOutReader() throws IOException {
+return this.sysOutStore.getReader();
+}
+
+/**
+ * @return Returns a {@link Reader} for reading any stderr data that 
was generated
+ * during the test execution. It is expected that the {@link 
#hasSysErr()} be first
+ * called to see if any such data is available and only if there is, 
then this method
+ * be called
+ * @throws IOException If there's any I/O problem while creating the 
{@link Reader}
+ */
+Reader getSysErrReader() throws IOException {
+return this.sysErrStore.getReader();
+}
+
+/**
+ * Writes out any stdout data that was generated during the
+ * test execution. If there was no such data then this method just 
returns.
+ *
+ * @param writer The {@link Writer} to use. Cannot be null.
+ * @throws IOException If any I/O problem occurs during writing the 
data
+ */
+void writeSysOut(final Writer writer) throws IOException {
+Objects.requireNonNull(writer, "Writer cannot be null");
+this.writeFrom(this.sysOutStore, writer);
+}
+
+/**
+ * Writes out any stderr data that was generated during the
+ * test execution. If there was no such data then this 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-21 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169626791
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-21 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169625878
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-21 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169624865
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-21 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169624837
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-21 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169624475
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-20 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169248698
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-20 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169248048
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-20 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169247383
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-20 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169245116
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-20 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r169243988
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java
 ---
@@ -0,0 +1,508 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.KeepAliveOutputStream;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestExecutionListener;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Ant {@link Task} responsible for launching the JUnit platform for 
running tests.
+ * This requires a minimum of JUnit 5, since that's the version in which 
the JUnit platform launcher
+ * APIs were introduced.
+ * 
+ * This task in itself doesn't run the JUnit tests, instead the sole 
responsibility of
+ * this task is to setup the JUnit platform launcher, build requests, 
launch those requests and then parse the
+ * result of the execution to present in a way that's been configured on 
this Ant task.
+ * 
+ * 
+ * Furthermore, this task allows users control over which classes to 
select for passing on to the JUnit 5
+ * platform for test execution. It however, is solely the JUnit 5 
platform, backed by test engines that
+ * decide and execute the tests.
+ *
+ * @see https://junit.org/junit5/;>JUnit 5 documentation for 
more details
+ * on how JUnit manages the platform and the test engines.
+ */
+public class JUnitLauncherTask extends Task {
+
+private Path classPath;
+private boolean haltOnFailure;
+private String failureProperty;
+private final List tests = new ArrayList<>();
+private final List listeners = new ArrayList<>();
+
+public JUnitLauncherTask() {
+}
+
+@Override
+public void execute() throws BuildException {
+final ClassLoader previousClassLoader = 
Thread.currentThread().getContextClassLoader();
+try {
+final ClassLoader executionCL = 
createClassLoaderForTestExecution();
+Thread.currentThread().setContextClassLoader(executionCL);
+final Launcher launcher = LauncherFactory.create();
+final List requests = buildTestRequests();
+for (final TestRequest testRequest : requests) {
+try {
+final TestDefinition test = testRequest.getOwner();
+final LauncherDiscoveryRequest request = 
testRequest.getDiscoveryRequest().build();
+final List 
testExecutionListeners = new ArrayList<>();
+// a listener that we always put at the front of list 
of listeners
+// for this request.
+final Listener firstListener = new Listener();
+// we always enroll the summary generating listener, 
to the request, so that we
+// get to use some of the details of the summary for 
our further decision making
+testExecutionListeners.add(firstListener);
+
testExecutionListeners.addAll(getListeners(testRequest, executionCL));
+final PrintStream originalSysOut = System.out;
+final PrintStream originalSysErr = System.err;
+try {
+firstListener.switchedSysOutHandle = 
trySwitchSysOut(testRequest);
+firstListener.switchedSysErrHandle = 
trySwitchSysErr(testRequest);
+launcher.execute(request, 
testExecutionListeners.toArray(new 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-18 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r168983237
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,139 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Path sysOutFilePath;
+protected Path sysErrFilePath;
+protected Task task;
+
+private OutputStream sysOutStream;
+private OutputStream sysErrStream;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStream == null) {
+try {
+this.sysOutFilePath = Files.createTempFile(null, "sysout");
+this.sysOutFilePath.toFile().deleteOnExit();
+this.sysOutStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysOutStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStream == null) {
+try {
+this.sysErrFilePath = Files.createTempFile(null, "syserr");
+this.sysErrFilePath.toFile().deleteOnExit();
+this.sysErrStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysErrStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+protected void writeSysOut(final Writer writer) throws IOException {
+this.writeFrom(this.sysOutFilePath, writer);
+}
+
+protected void writeSysErr(final Writer writer) throws IOException {
+this.writeFrom(this.sysErrFilePath, writer);
+}
+
+static Optional traverseAndFindTestClass(final 
TestPlan testPlan, final TestIdentifier testIdentifier) {
+if (isTestClass(testIdentifier).isPresent()) {
+return Optional.of(testIdentifier);
+}
+final Optional parent = 
testPlan.getParent(testIdentifier);
+return parent.isPresent() ? traverseAndFindTestClass(testPlan, 
parent.get()) : Optional.empty();
+}
+
+static Optional isTestClass(final TestIdentifier 
testIdentifier) {
+if (testIdentifier == null) {
+return Optional.empty();
+}
+final Optional source = testIdentifier.getSource();
+if (!source.isPresent()) {
+return Optional.empty();
+}
+final TestSource testSource = source.get();
+if (testSource instanceof ClassSource) {
+return Optional.of((ClassSource) testSource);
+}
+return Optional.empty();
+}
+
+private void writeFrom(final Path path, final Writer writer) throws 
IOException {
+final byte[] content = new byte[1024];
+int numBytes;
+try (final InputStream is = Files.newInputStream(path)) {
+while ((numBytes = is.read(content)) != -1) {
+writer.write(new String(content, 0, numBytes));
+}
+}
+}
+
+@Override
+public void close() throws IOException {
+if (this.sysOutStream != null) {
+try {
+this.sysOutStream.close();
+} catch (Exception e) {
+// ignore
+}

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-18 Thread jaikiran
Github user jaikiran commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r168983118
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,139 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Path sysOutFilePath;
+protected Path sysErrFilePath;
+protected Task task;
+
+private OutputStream sysOutStream;
+private OutputStream sysErrStream;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStream == null) {
+try {
+this.sysOutFilePath = Files.createTempFile(null, "sysout");
+this.sysOutFilePath.toFile().deleteOnExit();
+this.sysOutStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysOutStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStream == null) {
+try {
+this.sysErrFilePath = Files.createTempFile(null, "syserr");
+this.sysErrFilePath.toFile().deleteOnExit();
+this.sysErrStream = 
Files.newOutputStream(this.sysOutFilePath);
--- End diff --

Indeed :) Fixed.


---

-
To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org
For additional commands, e-mail: dev-h...@ant.apache.org



[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-18 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r168964381
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,139 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Path sysOutFilePath;
+protected Path sysErrFilePath;
+protected Task task;
+
+private OutputStream sysOutStream;
+private OutputStream sysErrStream;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStream == null) {
+try {
+this.sysOutFilePath = Files.createTempFile(null, "sysout");
+this.sysOutFilePath.toFile().deleteOnExit();
+this.sysOutStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysOutStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStream == null) {
+try {
+this.sysErrFilePath = Files.createTempFile(null, "syserr");
+this.sysErrFilePath.toFile().deleteOnExit();
+this.sysErrStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysErrStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+protected void writeSysOut(final Writer writer) throws IOException {
+this.writeFrom(this.sysOutFilePath, writer);
+}
+
+protected void writeSysErr(final Writer writer) throws IOException {
+this.writeFrom(this.sysErrFilePath, writer);
+}
+
+static Optional traverseAndFindTestClass(final 
TestPlan testPlan, final TestIdentifier testIdentifier) {
+if (isTestClass(testIdentifier).isPresent()) {
+return Optional.of(testIdentifier);
+}
+final Optional parent = 
testPlan.getParent(testIdentifier);
+return parent.isPresent() ? traverseAndFindTestClass(testPlan, 
parent.get()) : Optional.empty();
+}
+
+static Optional isTestClass(final TestIdentifier 
testIdentifier) {
+if (testIdentifier == null) {
+return Optional.empty();
+}
+final Optional source = testIdentifier.getSource();
+if (!source.isPresent()) {
+return Optional.empty();
+}
+final TestSource testSource = source.get();
+if (testSource instanceof ClassSource) {
+return Optional.of((ClassSource) testSource);
+}
+return Optional.empty();
+}
+
+private void writeFrom(final Path path, final Writer writer) throws 
IOException {
+final byte[] content = new byte[1024];
+int numBytes;
+try (final InputStream is = Files.newInputStream(path)) {
+while ((numBytes = is.read(content)) != -1) {
+writer.write(new String(content, 0, numBytes));
+}
+}
+}
+
+@Override
+public void close() throws IOException {
+if (this.sysOutStream != null) {
+try {
+this.sysOutStream.close();
+} catch (Exception e) {
+// ignore
+}
+ 

[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-18 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r168964295
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,139 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Path sysOutFilePath;
+protected Path sysErrFilePath;
+protected Task task;
+
+private OutputStream sysOutStream;
+private OutputStream sysErrStream;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStream == null) {
+try {
+this.sysOutFilePath = Files.createTempFile(null, "sysout");
+this.sysOutFilePath.toFile().deleteOnExit();
+this.sysOutStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysOutStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStream == null) {
+try {
+this.sysErrFilePath = Files.createTempFile(null, "syserr");
+this.sysErrFilePath.toFile().deleteOnExit();
+this.sysErrStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysErrStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void setExecutingTask(final Task task) {
+this.task = task;
+}
+
+protected void writeSysOut(final Writer writer) throws IOException {
+this.writeFrom(this.sysOutFilePath, writer);
+}
+
+protected void writeSysErr(final Writer writer) throws IOException {
+this.writeFrom(this.sysErrFilePath, writer);
+}
+
+static Optional traverseAndFindTestClass(final 
TestPlan testPlan, final TestIdentifier testIdentifier) {
+if (isTestClass(testIdentifier).isPresent()) {
+return Optional.of(testIdentifier);
+}
+final Optional parent = 
testPlan.getParent(testIdentifier);
+return parent.isPresent() ? traverseAndFindTestClass(testPlan, 
parent.get()) : Optional.empty();
+}
+
+static Optional isTestClass(final TestIdentifier 
testIdentifier) {
+if (testIdentifier == null) {
+return Optional.empty();
+}
+final Optional source = testIdentifier.getSource();
+if (!source.isPresent()) {
+return Optional.empty();
+}
+final TestSource testSource = source.get();
+if (testSource instanceof ClassSource) {
+return Optional.of((ClassSource) testSource);
+}
+return Optional.empty();
+}
+
+private void writeFrom(final Path path, final Writer writer) throws 
IOException {
+final byte[] content = new byte[1024];
+int numBytes;
+try (final InputStream is = Files.newInputStream(path)) {
+while ((numBytes = is.read(content)) != -1) {
+writer.write(new String(content, 0, numBytes));
+}
--- End diff --

I don't think this is going to work reliably. The `read` may have split a 
multi-byte sequence at the end of `content` and then creating a string from it 
is going to break. Is there any reason you want to use a stream when reading 
the temporary file rather than a reader?


---


[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-18 Thread bodewig
Github user bodewig commented on a diff in the pull request:

https://github.com/apache/ant/pull/60#discussion_r168963955
  
--- Diff: 
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/AbstractJUnitResultFormatter.java
 ---
@@ -0,0 +1,139 @@
+package org.apache.tools.ant.taskdefs.optional.junitlauncher;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+/**
+ * Contains some common behaviour that's used by our internal {@link 
TestResultFormatter}s
+ */
+abstract class AbstractJUnitResultFormatter implements TestResultFormatter 
{
+
+protected static String NEW_LINE = 
System.getProperty("line.separator");
+protected Path sysOutFilePath;
+protected Path sysErrFilePath;
+protected Task task;
+
+private OutputStream sysOutStream;
+private OutputStream sysErrStream;
+
+@Override
+public void sysOutAvailable(final byte[] data) {
+if (this.sysOutStream == null) {
+try {
+this.sysOutFilePath = Files.createTempFile(null, "sysout");
+this.sysOutFilePath.toFile().deleteOnExit();
+this.sysOutStream = 
Files.newOutputStream(this.sysOutFilePath);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+try {
+this.sysOutStream.write(data);
+} catch (IOException e) {
+handleException(e);
+return;
+}
+}
+
+@Override
+public void sysErrAvailable(final byte[] data) {
+if (this.sysErrStream == null) {
+try {
+this.sysErrFilePath = Files.createTempFile(null, "syserr");
+this.sysErrFilePath.toFile().deleteOnExit();
+this.sysErrStream = 
Files.newOutputStream(this.sysOutFilePath);
--- End diff --

copy-paste error, you want that to be `sysErrFilePath` :-)


---

-
To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org
For additional commands, e-mail: dev-h...@ant.apache.org



[GitHub] ant pull request #60: JUnit 5 support - A new junitlauncher task

2018-02-15 Thread jaikiran
GitHub user jaikiran opened a pull request:

https://github.com/apache/ant/pull/60

JUnit 5 support - A new junitlauncher task

This is the initial working version of a new `junitlauncher` task that 
support using JUnit 5 framework for testing, within Ant build files. The commit 
in this PR is the initial set of goals that I had in mind for the first release 
of this task.

The manual for this task can be (temporarily) found at 
https://builds.apache.org/job/Ant-Build-Jaikiran/ws/manual/Tasks/junitlauncher.html

You can merge this pull request into a Git repository by running:

$ git pull https://github.com/jaikiran/ant junit5

Alternatively you can review and apply these changes as the patch at:

https://github.com/apache/ant/pull/60.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

This closes #60


commit 991bddff07b4fed1db2dc7f6b83f47557e62213b
Author: Jaikiran Pai 
Date:   2017-12-13T13:37:41Z

JUnit 5 support - A new junitlauncher task




---

-
To unsubscribe, e-mail: dev-unsubscr...@ant.apache.org
For additional commands, e-mail: dev-h...@ant.apache.org