/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.test.framework;

import static jdk.nashorn.internal.test.framework.TestConfig.TEST_FAILED_LIST_FILE;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_ENABLE_STRICT_MODE;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_EXCLUDES_FILE;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_EXCLUDE_LIST;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_FRAMEWORK;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_ROOTS;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.nashorn.internal.test.framework.TestFinder.TestFactory;

/**
 * Parallel test runner runs tests in multiple threads - but avoids any dependency
 * on third-party test framework library such as TestNG.
 */
@SuppressWarnings("javadoc")
public class ParallelTestRunner {

    // ParallelTestRunner-specific
    private static final String    TEST_JS_THREADS     = "test.js.threads";
    private static final String    TEST_JS_REPORT_FILE = "test.js.report.file";
    // test262 does a lot of eval's and the JVM hates multithreaded class definition, so lower thread count is usually faster.
    private static final int       THREADS = Integer.getInteger(TEST_JS_THREADS, Runtime.getRuntime().availableProcessors() > 4 ? 4 : 2);

    private final List<ScriptRunnable> tests    = new ArrayList<>();
    private final Set<String>      orphans  = new TreeSet<>();
    private final ExecutorService  executor = Executors.newFixedThreadPool(THREADS);

    // Ctrl-C handling
    private final CountDownLatch   finishedLatch = new CountDownLatch(1);
    private final Thread           shutdownHook  = new Thread() {
                                                       @Override
                                                       public void run() {
                                                           if (!executor.isTerminated()) {
                                                               executor.shutdownNow();
                                                               try {
                                                                   executor.awaitTermination(25, TimeUnit.SECONDS);
                                                                   finishedLatch.await(5, TimeUnit.SECONDS);
                                                               } catch (final InterruptedException e) {
                                                                   // empty
                                                               }
                                                           }
                                                       }
                                                   };

    public ParallelTestRunner() throws Exception {
        suite();
    }

    private static PrintStream outputStream() {
        final String reportFile = System.getProperty(TEST_JS_REPORT_FILE, "");
        PrintStream output = System.out;

        if (!reportFile.isEmpty()) {
            try {
                output = new PrintStream(new OutputStreamDelegator(System.out, new FileOutputStream(reportFile)));
            } catch (final IOException e) {
                System.err.println(e);
            }
        }

        return output;
    }

    public static final class ScriptRunnable extends AbstractScriptRunnable implements Callable<ScriptRunnable.Result> {
        private final Result                result   = new Result();

        public class Result {
            private boolean  passed = true;
            public String    expected;
            public String    out;
            public String    err;
            public Throwable exception;

            public ScriptRunnable getTest() {
                return ScriptRunnable.this;
            }

            public boolean passed() {
                return passed;
            }

            @Override
            public String toString() {
                return getTest().toString();
            }
        }

        public ScriptRunnable(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> scriptArguments) {
            super(framework, testFile, engineOptions, testOptions, scriptArguments);
        }

        @Override
        protected void log(final String msg) {
            System.err.println(msg);
        }

        @Override
        protected void fail(final String message) {
            throw new TestFailedError(message);
        }

        @Override
        protected void compile() throws IOException {
            final ByteArrayOutputStream out = new ByteArrayOutputStream();
            final ByteArrayOutputStream err = new ByteArrayOutputStream();
            final List<String> args = getCompilerArgs();
            int errors;
            try {
                errors = evaluateScript(out, err, args.toArray(new String[args.size()]));
            } catch (final AssertionError e) {
                final PrintWriter writer = new PrintWriter(err);
                e.printStackTrace(writer);
                writer.flush();
                errors = 1;
            }
            if (errors != 0 || checkCompilerMsg) {
                result.err = err.toString();
                if (expectCompileFailure || checkCompilerMsg) {
                    final PrintStream outputDest = new PrintStream(new FileOutputStream(getErrorFileName()));
                    TestHelper.dumpFile(outputDest, new StringReader(new String(err.toByteArray())));
                    outputDest.println("--");
                }
                if (errors != 0 && !expectCompileFailure) {
                    fail(String.format("%d errors compiling %s", errors, testFile));
                }
                if (checkCompilerMsg) {
                    compare(getErrorFileName(), expectedFileName, true);
                }
            }
            if (expectCompileFailure && errors == 0) {
                fail(String.format("No errors encountered compiling negative test %s", testFile));
            }
        }

        @Override
        protected void execute() {
            final List<String> args = getRuntimeArgs();
            final ByteArrayOutputStream out = new ByteArrayOutputStream();
            final ByteArrayOutputStream err = new ByteArrayOutputStream();

            try {
                final int errors = evaluateScript(out, err, args.toArray(new String[args.size()]));

                if (errors != 0 || err.size() > 0) {
                    if (expectRunFailure) {
                        return;
                    }
                    if (!ignoreStdError) {

                        try (OutputStream outputFile = new FileOutputStream(getOutputFileName()); OutputStream errorFile = new FileOutputStream(getErrorFileName())) {
                            outputFile.write(out.toByteArray());
                            errorFile.write(err.toByteArray());
                        }

                        result.out = out.toString();
                        result.err = err.toString();
                        fail(err.toString());
                    }
                }

                if (compare) {
                    final File expectedFile = new File(expectedFileName);
                    try {
                        BufferedReader expected;
                        if (expectedFile.exists()) {
                            expected = new BufferedReader(new FileReader(expectedFile));
                        } else {
                            expected = new BufferedReader(new StringReader(""));
                        }
                        compare(new BufferedReader(new StringReader(out.toString())), expected, false);
                    } catch (final Throwable ex) {
                        if (expectedFile.exists()) {
                            copyExpectedFile();
                        }
                        try (OutputStream outputFile = new FileOutputStream(getOutputFileName()); OutputStream errorFile = new FileOutputStream(getErrorFileName())) {
                            outputFile.write(out.toByteArray());
                            errorFile.write(err.toByteArray());
                        }
                        ex.printStackTrace();
                        throw ex;
                    }
                }
            } catch (final IOException e) {
                if (!expectRunFailure) {
                    fail("Failure running test " + testFile + ": " + e.getMessage());
                } // else success
            }
        }

        private void compare(final String fileName, final String expected, final boolean compareCompilerMsg) throws IOException {
            final File expectedFile = new File(expected);

            BufferedReader expectedReader;
            if (expectedFile.exists()) {
                expectedReader = new BufferedReader(new InputStreamReader(new FileInputStream(expectedFileName)));
            } else {
                expectedReader = new BufferedReader(new StringReader(""));
            }

            final BufferedReader actual = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));

            compare(actual, expectedReader, compareCompilerMsg);
        }

        private void copyExpectedFile() {
            if (!new File(expectedFileName).exists()) {
                return;
            }
            // copy expected file overwriting existing file and preserving last
            // modified time of source
            try {
                Files.copy(FileSystems.getDefault().getPath(expectedFileName), FileSystems.getDefault().getPath(getCopyExpectedFileName()), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
            } catch (final IOException ex) {
                fail("failed to copy expected " + expectedFileName + " to " + getCopyExpectedFileName() + ": " + ex.getMessage());
            }
        }

        @Override
        public Result call() {
            try {
                runTest();
            } catch (final Throwable ex) {
                result.exception = ex;
                result.passed = false;
                ex.printStackTrace();
            }
            return result;
        }

        private String getOutputFileName() {
            buildDir.mkdirs();
            return outputFileName;
        }

        private String getErrorFileName() {
            buildDir.mkdirs();
            return errorFileName;
        }

        private String getCopyExpectedFileName() {
            buildDir.mkdirs();
            return copyExpectedFileName;
        }
    }

    private void suite() throws Exception {
        Locale.setDefault(new Locale(""));
        System.setOut(outputStream());

        final TestFactory<ScriptRunnable> testFactory = new TestFactory<ScriptRunnable>() {
            @Override
            public ScriptRunnable createTest(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> arguments) {
                return new ScriptRunnable(framework, testFile, engineOptions, testOptions, arguments);
            }

            @Override
            public void log(final String msg) {
                System.err.println(msg);
            }
        };

        TestFinder.findAllTests(tests, orphans, testFactory);

        Collections.sort(tests, new Comparator<ScriptRunnable>() {
            @Override
            public int compare(final ScriptRunnable o1, final ScriptRunnable o2) {
                return o1.testFile.compareTo(o2.testFile);
            }
        });
    }

    @SuppressWarnings("resource")
    public boolean run() throws IOException {
        final int testCount = tests.size();
        int passCount = 0;
        int doneCount = 0;
        System.out.printf("Found %d tests.\n", testCount);
        final long startTime = System.nanoTime();

        Runtime.getRuntime().addShutdownHook(shutdownHook);

        final List<Future<ScriptRunnable.Result>> futures = new ArrayList<>();
        for (final ScriptRunnable test : tests) {
            futures.add(executor.submit(test));
        }

        executor.shutdown();
        try {
            executor.awaitTermination(60, TimeUnit.MINUTES);
        } catch (final InterruptedException ex) {
            // empty
        }

        final List<ScriptRunnable.Result> results = new ArrayList<>();
        for (final Future<ScriptRunnable.Result> future : futures) {
            if (future.isDone()) {
                try {
                    final ScriptRunnable.Result result = future.get();
                    results.add(result);
                    doneCount++;
                    if (result.passed()) {
                        passCount++;
                    }
                } catch (CancellationException | ExecutionException ex) {
                    ex.printStackTrace();
                } catch (final InterruptedException ex) {
                    assert false : "should not reach here";
                }
            }
        }

        Collections.sort(results, new Comparator<ScriptRunnable.Result>() {
            @Override
            public int compare(final ScriptRunnable.Result o1, final ScriptRunnable.Result o2) {
                return o1.getTest().testFile.compareTo(o2.getTest().testFile);
            }
        });

        boolean hasFailed = false;
        final String failedList = System.getProperty(TEST_FAILED_LIST_FILE);
        final boolean hasFailedList = failedList != null;
        final boolean hadPreviouslyFailingTests = hasFailedList && new File(failedList).length() > 0;
        final FileWriter failedFileWriter = hasFailedList ? new FileWriter(failedList) : null;
        try {
            final PrintWriter failedListWriter = failedFileWriter == null ? null : new PrintWriter(failedFileWriter);
            for (final ScriptRunnable.Result result : results) {
                if (!result.passed()) {
                    if (hasFailed == false) {
                        hasFailed = true;
                        System.out.println();
                        System.out.println("FAILED TESTS");
                    }

                    System.out.println(result.getTest());
                    if(failedFileWriter != null) {
                        failedListWriter.println(result.getTest().testFile.getPath());
                    }
                    if (result.exception != null) {
                        final String exceptionString = result.exception instanceof TestFailedError ? result.exception.getMessage() : result.exception.toString();
                        System.out.print(exceptionString.endsWith("\n") ? exceptionString : exceptionString + "\n");
                        System.out.print(result.out != null ? result.out : "");
                    }
                }
            }
        } finally {
            if(failedFileWriter != null) {
                failedFileWriter.close();
            }
        }
        final double timeElapsed = (System.nanoTime() - startTime) / 1e9; // [s]
        System.out.printf("Tests run: %d/%d tests, passed: %d (%.2f%%), failed: %d. Time elapsed: %.0fmin %.0fs.\n", doneCount, testCount, passCount, 100d * passCount / doneCount, doneCount - passCount, timeElapsed / 60, timeElapsed % 60);
        System.out.flush();

        finishedLatch.countDown();

        if (hasFailed) {
            throw new AssertionError("TEST FAILED");
        }

        if(hasFailedList) {
            new File(failedList).delete();
        }

        if(hadPreviouslyFailingTests) {
            System.out.println();
            System.out.println("Good job on getting all your previously failing tests pass!");
            System.out.println("NOW re-running all tests to make sure you haven't caused any NEW test failures.");
            System.out.println();
        }

        return hadPreviouslyFailingTests;
    }

    public static void main(final String[] args) throws Exception {
        parseArgs(args);

        while (new ParallelTestRunner().run()) {
            //empty
        }
    }

    private static void parseArgs(final String[] args) {
        if (args.length > 0) {
            String roots = "";
            String reportFile = "";
            for (int i = 0; i < args.length; i++) {
                if (args[i].equals("--roots") && i != args.length - 1) {
                    roots += args[++i] + " ";
                } else if (args[i].equals("--report-file") && i != args.length - 1) {
                    reportFile = args[++i];
                } else if (args[i].equals("--test262")) {
                    try {
                        setTest262Properties();
                    } catch (final IOException ex) {
                        System.err.println(ex);
                    }
                }
            }
            if (!roots.isEmpty()) {
                System.setProperty(TEST_JS_ROOTS, roots.trim());
            }
            if (!reportFile.isEmpty()) {
                System.setProperty(TEST_JS_REPORT_FILE, reportFile);
            }
        }
    }

    private static void setTest262Properties() throws IOException {
        System.setProperty(TEST_JS_ROOTS, "test/test262/test/suite/");
        System.setProperty(TEST_JS_FRAMEWORK, "test/script/test262.js test/test262/test/harness/framework.js test/test262/test/harness/sta.js");
        System.setProperty(TEST_JS_EXCLUDES_FILE, "test/test262/test/config/excludelist.xml");
        System.setProperty(TEST_JS_ENABLE_STRICT_MODE, "true");

        final Properties projectProperties = new Properties();
        projectProperties.load(new FileInputStream("project.properties"));
        String excludeList = projectProperties.getProperty("test262-test-sys-prop.test.js.exclude.list", "");
        final Pattern pattern = Pattern.compile("\\$\\{([^}]+)}");
        for (;;) {
            final Matcher matcher = pattern.matcher(excludeList);
            if (!matcher.find()) {
                break;
            }
            final String propertyValue = projectProperties.getProperty(matcher.group(1), "");
            excludeList = excludeList.substring(0, matcher.start()) + propertyValue + excludeList.substring(matcher.end());
        }
        System.setProperty(TEST_JS_EXCLUDE_LIST, excludeList);
    }

    public static final class OutputStreamDelegator extends OutputStream {
        private final OutputStream[] streams;

        public OutputStreamDelegator(final OutputStream... streams) {
            this.streams = streams;
        }

        @Override
        public void write(final int b) throws IOException {
            for (final OutputStream stream : streams) {
                stream.write(b);
            }
        }

        @Override
        public void flush() throws IOException {
            for (final OutputStream stream : streams) {
                stream.flush();
            }
        }
    }
}

final class TestFailedError extends Error {
    private static final long serialVersionUID = 1L;

    public TestFailedError(final String message) {
        super(message);
    }

    public TestFailedError(final String message, final Throwable cause) {
        super(message, cause);
    }

    public TestFailedError(final Throwable cause) {
        super(cause);
    }
}
