/*
 *  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
 *
 *      https://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.
 *
 */

package org.apache.tools.ant.taskdefs.optional.junitlauncher;


import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.MagicNames;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.LaunchDefinition;
import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.ListenerDefinition;
import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.NamedTest;
import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.SingleTestClass;
import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestClasses;
import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.KeepAliveOutputStream;
import org.junit.platform.engine.Filter;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.launcher.EngineFilter;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.TagFilter;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
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.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.NumberFormat;
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;

/**
 * Responsible for doing the real work involved in launching the JUnit platform
 * and passing it the relevant tests that need to be executed by the JUnit platform.
 * <p>
 * This class relies on a {@link LaunchDefinition} for setting up the launch of the
 * JUnit platform.
 * <p>
 * The {@code LauncherSupport} isn't concerned with whether or not
 * it's being executed in the same JVM as the build in which the {@code junitlauncher}
 * was triggered or if it's running as part of a forked JVM. Instead it just relies
 * on the {@code LaunchDefinition} to do whatever decisions need to be done before and
 * after launching the tests.
 * <p>
 * This class is not thread-safe and isn't expected to be used for launching from
 * multiple different threads simultaneously.
 * <p>This class is an internal implementation detail of the Ant project and although
 * it's a public class, it isn't meant to be used outside of this project. This class
 * can be changed, across releases, without any backward compatible guarantees and hence
 * shouldn't be used or relied upon outside of this project.
 */
public class LauncherSupport {

    private final LaunchDefinition launchDefinition;
    private final TestExecutionContext testExecutionContext;

    private boolean testsFailed;

    /**
     * Create a {@link LauncherSupport} for the passed {@link LaunchDefinition}
     *
     * @param definition           The launch definition which will be used for launching the tests
     * @param testExecutionContext The {@link TestExecutionContext} to use for the tests
     */
    public LauncherSupport(final LaunchDefinition definition, final TestExecutionContext testExecutionContext) {
        if (definition == null) {
            throw new IllegalArgumentException("Launch definition cannot be null");
        }
        if (testExecutionContext == null) {
            throw new IllegalArgumentException("Test execution context cannot be null");
        }
        this.launchDefinition = definition;
        this.testExecutionContext = testExecutionContext;
    }

    /**
     * Launches the tests defined in the {@link LaunchDefinition}
     *
     * @throws BuildException If any tests failed and the launch definition was configured to throw
     *                        an exception, or if any other exception occurred before or after launching
     *                        the tests
     */
    public void launch() throws BuildException {
        final ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(this.launchDefinition.getClassLoader());
            final Launcher launcher = LauncherFactory.create();
            final List<TestRequest> requests = buildTestRequests();
            for (final TestRequest testRequest : requests) {
                try {
                    final TestDefinition test = testRequest.getOwner();
                    final LauncherDiscoveryRequest request = testRequest.getDiscoveryRequest().build();
                    final List<TestExecutionListener> testExecutionListeners = new ArrayList<>();
                    // a listener that we always put at the front of list of listeners
                    // for this request.
                    final Listener firstListener = new Listener(System.out);
                    // 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, this.launchDefinition.getClassLoader()));
                    final PrintStream originalSysOut = System.out;
                    final PrintStream originalSysErr = System.err;
                    try {
                        firstListener.switchedSysOutHandle = trySwitchSysOutErr(testRequest, StreamType.SYS_OUT, originalSysErr);
                        firstListener.switchedSysErrHandle = trySwitchSysOutErr(testRequest, StreamType.SYS_ERR, originalSysErr);
                        launcher.execute(request, testExecutionListeners.toArray(new TestExecutionListener[testExecutionListeners.size()]));
                    } finally {
                        // switch back sysout/syserr to the original
                        try {
                            System.setOut(originalSysOut);
                        } catch (Exception e) {
                            // ignore
                        }
                        try {
                            System.setErr(originalSysErr);
                        } catch (Exception e) {
                            // ignore
                        }
                        // close the streams that we had used to redirect System.out/System.err
                        try {
                            firstListener.switchedSysOutHandle.ifPresent((h) -> {
                                try {
                                    h.close();
                                } catch (Exception e) {
                                    // ignore
                                }
                            });
                        } catch (Exception e) {
                            // ignore
                        }
                        try {
                            firstListener.switchedSysErrHandle.ifPresent((h) -> {
                                try {
                                    h.close();
                                } catch (Exception e) {
                                    // ignore
                                }
                            });
                        } catch (Exception e) {
                            // ignore
                        }
                    }
                    handleTestExecutionCompletion(test, firstListener.getSummary());
                } finally {
                    try {
                        testRequest.close();
                    } catch (Exception e) {
                        // log and move on
                        log("Failed to cleanly close test request", e, Project.MSG_DEBUG);
                    }
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(previousClassLoader);
        }
    }

    /**
     * Returns true if there were any test failures, when this {@link LauncherSupport} was used
     * to {@link #launch()} tests. False otherwise.
     *
     * @return
     */
    boolean hasTestFailures() {
        return this.testsFailed;
    }

    private List<TestRequest> buildTestRequests() {
        final List<TestDefinition> tests = this.launchDefinition.getTests();
        if (tests.isEmpty()) {
            return Collections.emptyList();
        }
        final List<TestRequest> requests = new ArrayList<>();
        for (final TestDefinition test : tests) {
            final List<TestRequest> testRequests;
            if (test instanceof SingleTestClass || test instanceof TestClasses) {
                testRequests = createTestRequests(test);
            } else {
                throw new BuildException("Unexpected test definition type " + test.getClass().getName());
            }
            if (testRequests == null || testRequests.isEmpty()) {
                continue;
            }
            requests.addAll(testRequests);
        }
        return requests;
    }

    private List<TestExecutionListener> getListeners(final TestRequest testRequest, final ClassLoader classLoader) {
        final TestDefinition test = testRequest.getOwner();
        final List<ListenerDefinition> applicableListenerElements = test.getListeners().isEmpty()
                ? this.launchDefinition.getListeners() : test.getListeners();
        final List<TestExecutionListener> listeners = new ArrayList<>();
        final Optional<Project> project = this.testExecutionContext.getProject();
        for (final ListenerDefinition applicableListener : applicableListenerElements) {
            if (project.isPresent() && !applicableListener.shouldUse(project.get())) {
                log("Excluding listener " + applicableListener.getClassName() + " since it's not applicable" +
                        " in the context of project", null, Project.MSG_DEBUG);
                continue;
            }
            final TestExecutionListener listener = requireTestExecutionListener(applicableListener, classLoader);
            if (listener instanceof TestResultFormatter) {
                // setup/configure the result formatter
                setupResultFormatter(testRequest, applicableListener, (TestResultFormatter) listener);
            }
            listeners.add(listener);
        }
        return listeners;
    }

    private void setupResultFormatter(final TestRequest testRequest, final ListenerDefinition formatterDefinition,
                                      final TestResultFormatter resultFormatter) {

        testRequest.closeUponCompletion(resultFormatter);
        // set the execution context
        resultFormatter.setContext(this.testExecutionContext);
        resultFormatter.setUseLegacyReportingName(formatterDefinition.isUseLegacyReportingName());
        // set the destination output stream for writing out the formatted result
        final java.nio.file.Path resultOutputFile = getListenerOutputFile(testRequest, formatterDefinition);
        try {
            final OutputStream resultOutputStream = Files.newOutputStream(resultOutputFile);
            // enroll the output stream to be closed when the execution of the TestRequest completes
            testRequest.closeUponCompletion(resultOutputStream);
            resultFormatter.setDestination(new KeepAliveOutputStream(resultOutputStream));
        } catch (IOException e) {
            throw new BuildException(e);
        }
        // check if system.out/system.err content needs to be passed on to the listener
        if (formatterDefinition.shouldSendSysOut()) {
            testRequest.addSysOutInterest(resultFormatter);
        }
        if (formatterDefinition.shouldSendSysErr()) {
            testRequest.addSysErrInterest(resultFormatter);
        }
    }

    private Path getListenerOutputFile(final TestRequest testRequest, final ListenerDefinition listener) {
        final TestDefinition test = testRequest.getOwner();
        final String filename;
        if (listener.getResultFile() != null) {
            filename = listener.getResultFile();
        } else {
            // compute a file name
            final StringBuilder sb = new StringBuilder("TEST-");
            sb.append(testRequest.getName() == null ? "unknown" : testRequest.getName());
            sb.append(".");
            final String suffix;
            if ("org.apache.tools.ant.taskdefs.optional.junitlauncher.LegacyXmlResultFormatter".equals(listener.getClassName())) {
                suffix = "xml";
            } else {
                suffix = "txt";
            }
            sb.append(suffix);
            filename = sb.toString();
        }
        if (listener.getOutputDir() != null) {
            // use the output dir defined on the listener
            return Paths.get(listener.getOutputDir(), filename);
        }
        // check on the enclosing test definition, in context of which this listener is being run
        if (test.getOutputDir() != null) {
            return Paths.get(test.getOutputDir(), filename);
        }
        // neither listener nor the test define a output dir, so use basedir of the project
        final TestExecutionContext testExecutionContext = this.testExecutionContext;
        final String baseDir = testExecutionContext.getProperties().getProperty(MagicNames.PROJECT_BASEDIR);
        return Paths.get(baseDir, filename);
    }

    private TestExecutionListener requireTestExecutionListener(final ListenerDefinition listener, final ClassLoader classLoader) {
        final String className = listener.getClassName();
        if (className == null || className.trim().isEmpty()) {
            throw new BuildException("classname attribute value is missing on listener element");
        }
        final Class<?> klass;
        try {
            klass = Class.forName(className, false, classLoader);
        } catch (ClassNotFoundException e) {
            throw new BuildException("Failed to load listener class " + className, e);
        }
        if (!TestExecutionListener.class.isAssignableFrom(klass)) {
            throw new BuildException("Listener class " + className + " is not of type " + TestExecutionListener.class.getName());
        }
        try {
            return (TestExecutionListener) klass.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new BuildException("Failed to create an instance of listener " + className, e);
        }
    }

    private void handleTestExecutionCompletion(final TestDefinition test, final TestExecutionSummary summary) {
        final boolean hasTestFailures = summary.getTotalFailureCount() != 0;
        if (hasTestFailures) {
            // keep track of the test failure(s) for the entire launched instance
            this.testsFailed = true;
        }
        try {
            if (hasTestFailures && test.getFailureProperty() != null) {
                // if there are test failures and the test is configured to set a property in case
                // of failure, then set the property to true
                final TestExecutionContext testExecutionContext = this.testExecutionContext;
                if (testExecutionContext.getProject().isPresent()) {
                    final Project project = testExecutionContext.getProject().get();
                    project.setNewProperty(test.getFailureProperty(), "true");
                }
            }
        } finally {
            if (hasTestFailures && test.isHaltOnFailure()) {
                // if the test is configured to halt on test failures, throw a build error
                final String errorMessage;
                if (test instanceof NamedTest) {
                    errorMessage = "Test " + ((NamedTest) test).getName() + " has " + summary.getTestsFailedCount() + " failure(s)";
                } else {
                    errorMessage = "Some test(s) have failure(s)";
                }
                throw new BuildException(errorMessage);
            }
        }
    }

    private Optional<SwitchedStreamHandle> trySwitchSysOutErr(final TestRequest testRequest, final StreamType streamType,
                                                              final PrintStream originalSysErr) {
        switch (streamType) {
            case SYS_OUT: {
                if (!testRequest.interestedInSysOut()) {
                    return Optional.empty();
                }
                break;
            }
            case SYS_ERR: {
                if (!testRequest.interestedInSysErr()) {
                    return Optional.empty();
                }
                break;
            }
            default: {
                // unknown, but no need to error out, just be lenient
                // and return back
                return Optional.empty();
            }
        }
        final PipedOutputStream pipedOutputStream = new PipedOutputStream();
        final PipedInputStream pipedInputStream;
        try {
            pipedInputStream = new PipedInputStream(pipedOutputStream);
        } catch (IOException ioe) {
            // log and return
            return Optional.empty();
        }
        final PrintStream printStream = new PrintStream(pipedOutputStream, true);
        final SysOutErrStreamReader streamer;
        switch (streamType) {
            case SYS_OUT: {
                System.setOut(new PrintStream(printStream));
                streamer = new SysOutErrStreamReader(this, pipedInputStream,
                        StreamType.SYS_OUT, testRequest.getSysOutInterests(), originalSysErr);
                final Thread sysOutStreamer = new Thread(streamer);
                sysOutStreamer.setDaemon(true);
                sysOutStreamer.setName("junitlauncher-sysout-stream-reader");
                sysOutStreamer.setUncaughtExceptionHandler((t, e) -> {
                    // skip the logging redirection infrastructure of junitlauncher task (which is what has
                    // failed here) and instead directly write out the error to the original System.err
                    originalSysErr.println("Failed in sysout streaming");
                    e.printStackTrace(originalSysErr);
                });
                sysOutStreamer.start();
                break;
            }
            case SYS_ERR: {
                System.setErr(new PrintStream(printStream));
                streamer = new SysOutErrStreamReader(this, pipedInputStream,
                        StreamType.SYS_ERR, testRequest.getSysErrInterests(), originalSysErr);
                final Thread sysErrStreamer = new Thread(streamer);
                sysErrStreamer.setDaemon(true);
                sysErrStreamer.setName("junitlauncher-syserr-stream-reader");
                sysErrStreamer.setUncaughtExceptionHandler((t, e) -> {
                    // skip the logging redirection infrastructure of junitlauncher task (which is what has
                    // failed here) and instead directly write out the error to the original System.err
                    originalSysErr.println("Failed in syserr streaming");
                    e.printStackTrace(originalSysErr);
                });
                sysErrStreamer.start();
                break;
            }
            default: {
                return Optional.empty();
            }
        }
        return Optional.of(new SwitchedStreamHandle(pipedOutputStream, streamer));
    }

    private void log(final String message, final Throwable t, final int level) {
        final TestExecutionContext testExecutionContext = this.testExecutionContext;
        if (testExecutionContext.getProject().isPresent()) {
            testExecutionContext.getProject().get().log(message, t, level);
            return;
        }
        if (t == null) {
            System.out.println(message);
        } else {
            System.err.println(message);
            t.printStackTrace();
        }
    }


    private List<TestRequest> createTestRequests(final TestDefinition test) {
        // create TestRequest(s) and add necessary selectors, filters to it

        if (test instanceof SingleTestClass) {
            final SingleTestClass singleTestClass = (SingleTestClass) test;
            final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request();
            final TestRequest request = new TestRequest(test, requestBuilder);
            request.setName(singleTestClass.getName());
            final String[] methods = singleTestClass.getMethods();
            if (methods == null) {
                requestBuilder.selectors(DiscoverySelectors.selectClass(singleTestClass.getName()));
            } else {
                // add specific methods
                for (final String method : methods) {
                    requestBuilder.selectors(DiscoverySelectors.selectMethod(singleTestClass.getName(), method));
                }
            }
            addFilters(request);
            return Collections.singletonList(request);
        }

        if (test instanceof TestClasses) {
            final List<String> testClasses = ((TestClasses) test).getTestClassNames();
            if (testClasses.isEmpty()) {
                return Collections.emptyList();
            }
            final List<TestRequest> requests = new ArrayList<>();
            for (final String testClass : testClasses) {
                final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request();
                final TestRequest request = new TestRequest(test, requestBuilder);
                request.setName(testClass);
                requestBuilder.selectors(DiscoverySelectors.selectClass(testClass));
                addFilters(request);

                requests.add(request);
            }
            return requests;
        }
        return Collections.emptyList();
    }

    /**
     * Add necessary {@link Filter JUnit filters} to the {@code testRequest}
     *
     * @param testRequest The test request
     */
    private void addFilters(final TestRequest testRequest) {
        final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest();
        // add any engine filters
        final String[] enginesToInclude = testRequest.getOwner().getIncludeEngines();
        if (enginesToInclude != null && enginesToInclude.length > 0) {
            requestBuilder.filters(EngineFilter.includeEngines(enginesToInclude));
        }
        final String[] enginesToExclude = testRequest.getOwner().getExcludeEngines();
        if (enginesToExclude != null && enginesToExclude.length > 0) {
            requestBuilder.filters(EngineFilter.excludeEngines(enginesToExclude));
        }
        // add any tag filters
        if (this.launchDefinition.getIncludeTags().size() > 0) {
            requestBuilder.filters(TagFilter.includeTags(this.launchDefinition.getIncludeTags()));
        }
        if (this.launchDefinition.getExcludeTags().size() > 0) {
            requestBuilder.filters(TagFilter.excludeTags(this.launchDefinition.getExcludeTags()));
        }
    }

    private enum StreamType {
        SYS_OUT,
        SYS_ERR
    }

    // Implementation note: Logging from this class is prohibited since it can lead
    // to deadlocks (see bz-64733 for details)
    private static final class SysOutErrStreamReader implements Runnable {
        private static final byte[] EMPTY = new byte[0];

        private final LauncherSupport launchManager;
        private final PrintStream originalSysErr;
        private final InputStream sourceStream;
        private final StreamType streamType;
        private final Collection<TestResultFormatter> resultFormatters;
        private volatile SysOutErrContentDeliverer contentDeliverer;

        SysOutErrStreamReader(final LauncherSupport launchManager, final InputStream source,
                              final StreamType streamType, final Collection<TestResultFormatter> resultFormatters,
                              final PrintStream originalSysErr) {
            this.launchManager = launchManager;
            this.sourceStream = source;
            this.streamType = streamType;
            this.resultFormatters = resultFormatters;
            this.originalSysErr = originalSysErr;
        }

        @Override
        public void run() {
            final SysOutErrContentDeliverer streamContentDeliver = new SysOutErrContentDeliverer(this.streamType, this.resultFormatters);
            final Thread deliveryThread = new Thread(streamContentDeliver);
            deliveryThread.setName("junitlauncher-" + (this.streamType == StreamType.SYS_OUT ? "sysout" : "syserr") + "-stream-deliverer");
            deliveryThread.setDaemon(true);
            deliveryThread.start();
            this.contentDeliverer = streamContentDeliver;
            int numRead = -1;
            final byte[] data = new byte[1024];
            try {
                while ((numRead = this.sourceStream.read(data)) != -1) {
                    final byte[] copy = Arrays.copyOf(data, numRead);
                    streamContentDeliver.availableData.offer(copy);
                }
            } catch (IOException e) {
                // let the UncaughtExceptionHandler of this thread deal with this exception
                throw new UncheckedIOException(e);
            } finally {
                streamContentDeliver.stop = true;
                // just "wakeup" the delivery thread, to take into account
                // those race conditions, where that other thread didn't yet
                // notice that it was asked to stop and has now gone into a
                // X amount of wait, waiting for any new data
                streamContentDeliver.availableData.offer(EMPTY);
            }
        }
    }

    private static final class SysOutErrContentDeliverer implements Runnable {
        private volatile boolean stop;
        private final Collection<TestResultFormatter> resultFormatters;
        private final StreamType streamType;
        private final BlockingQueue<byte[]> availableData = new LinkedBlockingQueue<>();
        private final CountDownLatch completionLatch = new CountDownLatch(1);

        SysOutErrContentDeliverer(final StreamType streamType, final Collection<TestResultFormatter> resultFormatters) {
            this.streamType = streamType;
            this.resultFormatters = resultFormatters;
        }

        @Override
        public void run() {
            try {
                while (!this.stop) {
                    final byte[] streamData;
                    try {
                        streamData = this.availableData.poll(2, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                    if (streamData != null) {
                        deliver(streamData);
                    }
                }
                // drain it
                final List<byte[]> remaining = new ArrayList<>();
                this.availableData.drainTo(remaining);
                if (!remaining.isEmpty()) {
                    for (final byte[] data : remaining) {
                        deliver(data);
                    }
                }
            } finally {
                this.completionLatch.countDown();
            }
        }

        private void deliver(final byte[] data) {
            if (data == null || data.length == 0) {
                return;
            }
            for (final TestResultFormatter resultFormatter : this.resultFormatters) {
                // send it to the formatter
                switch (streamType) {
                    case SYS_OUT: {
                        resultFormatter.sysOutAvailable(data);
                        break;
                    }
                    case SYS_ERR: {
                        resultFormatter.sysErrAvailable(data);
                        break;
                    }
                }
            }
        }
    }

    private final class SwitchedStreamHandle implements AutoCloseable {
        private final PipedOutputStream outputStream;
        private final SysOutErrStreamReader streamReader;

        SwitchedStreamHandle(final PipedOutputStream outputStream, final SysOutErrStreamReader streamReader) {
            this.streamReader = streamReader;
            this.outputStream = outputStream;
        }

        @Override
        public void close() throws Exception {
            outputStream.close();
            streamReader.sourceStream.close();
        }
    }

    private final class Listener extends SummaryGeneratingListener {
        private final PrintStream originalSysOut;

        private Optional<SwitchedStreamHandle> switchedSysOutHandle;
        private Optional<SwitchedStreamHandle> switchedSysErrHandle;

        private Listener(final PrintStream originalSysOut) {
            this.originalSysOut = originalSysOut;
        }

        @Override
        public void executionStarted(final TestIdentifier testIdentifier) {
            super.executionStarted(testIdentifier);
            AbstractJUnitResultFormatter.isTestClass(testIdentifier).ifPresent(testClass -> {
                this.originalSysOut.println("Running " + testClass.getClassName());
            });
        }


        private static final double ONE_SECOND = 1000.0;
        // We use this only in the testPlanExecutionFinished method, which
        // as per the JUnit5 platform semantics won't be called concurrently
        // by multiple threads (https://github.com/junit-team/junit5/issues/2539#issuecomment-766325555).
        // So it's safe to use this without any additional thread safety access controls.
        private NumberFormat timeFormatter = NumberFormat.getInstance();

        @Override
        public void testPlanExecutionFinished(final TestPlan testPlan) {
            super.testPlanExecutionFinished(testPlan);
            if (!testPlan.containsTests()) {
                // we print the summary only if any tests are present
                return;
            }
            if (launchDefinition.isPrintSummary()) {
                final TestExecutionSummary summary = this.getSummary();
                // Keep the summary as close to as the old junit task summary
                // tests run, failed, skipped, duration
                final StringBuilder sb = new StringBuilder("Tests run: ");
                sb.append(summary.getTestsStartedCount());
                sb.append(", Failures: ");
                sb.append(summary.getTestsFailedCount());
                sb.append(", Aborted: ");
                sb.append(summary.getTestsAbortedCount());
                sb.append(", Skipped: ");
                sb.append(summary.getTestsSkippedCount());
                sb.append(", Time elapsed: ");
                final long elapsedMs = summary.getTimeFinished() - summary.getTimeStarted();
                sb.append(timeFormatter.format(elapsedMs / ONE_SECOND));
                sb.append(" sec");
                this.originalSysOut.println(sb.toString());
            }
            // now that the test plan execution is finished, close the switched sysout/syserr output streams
            // and wait for the sysout and syserr content delivery, to result formatters, to finish
            if (this.switchedSysOutHandle.isPresent()) {
                final SwitchedStreamHandle sysOut = this.switchedSysOutHandle.get();
                try {
                    closeAndWait(sysOut);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return;
                }
            }
            if (this.switchedSysErrHandle.isPresent()) {
                final SwitchedStreamHandle sysErr = this.switchedSysErrHandle.get();
                try {
                    closeAndWait(sysErr);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }

        private void closeAndWait(final SwitchedStreamHandle handle) throws InterruptedException {
            FileUtils.close(handle.outputStream);
            if (handle.streamReader.contentDeliverer == null) {
                return;
            }
            // wait for a few seconds
            handle.streamReader.contentDeliverer.completionLatch.await(2, TimeUnit.SECONDS);
        }
    }

}
