/*
 * Copyright (c) 2008, 2025, 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.
 *
 * 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.
 */

import java.io.OutputStream;
import java.io.InputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.Set;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.Files;
import java.nio.file.FileVisitResult;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Arrays;
import java.util.spi.ToolProvider;
import java.util.stream.Collectors;

import static java.nio.file.StandardCopyOption.*;
import static java.nio.file.StandardOpenOption.*;

/**
 * This class provides some common utilities for the launcher tests.
 */
public class TestHelper {
    // commonly used jtreg constants
    static final File TEST_CLASSES_DIR;
    static final File TEST_SOURCES_DIR;

    static final String NL = System.getProperty("line.separator");
    static final String JAVAHOME = System.getProperty("java.home");
    static final String JAVA_BIN;
    static final String JAVA_LIB;
    static final String javaCmd;
    static final String javawCmd;
    static final String javacCmd;
    static final String jarCmd;
    static final boolean haveServerVM;
    static final boolean haveClientVM;

    static final ToolProvider compiler = ToolProvider.findFirst("javac").orElse(null);

    static final boolean debug = Boolean.getBoolean("TestHelper.Debug");
    static final boolean isWindows =
            System.getProperty("os.name", "unknown").startsWith("Windows");
    static final boolean isMacOSX =
            System.getProperty("os.name", "unknown").contains("OS X");
    static final boolean is64Bit =
            System.getProperty("sun.arch.data.model").equals("64");
    static final boolean is32Bit =
            System.getProperty("sun.arch.data.model").equals("32");
    static final boolean isLinux =
            System.getProperty("os.name", "unknown").startsWith("Linux");
    static final boolean isAIX =
            System.getProperty("os.name", "unknown").startsWith("AIX");
    static final String LIBJVM = isWindows
                        ? "jvm.dll"
                        : "libjvm" + (isMacOSX ? ".dylib" : ".so");

    // make a note of the golden default locale
    static final Locale DefaultLocale = Locale.getDefault();

    static final String JAVA_FILE_EXT   = ".java";
    static final String CLASS_FILE_EXT  = ".class";
    static final String JAR_FILE_EXT    = ".jar";
    static final String EXE_FILE_EXT    = ".exe";
    static final String MAC_DSYM_EXT    = ".dsym";
    static final String NIX_DBGINFO_EXT = ".debuginfo";
    static final String JLDEBUG_KEY     = "_JAVA_LAUNCHER_DEBUG";
    static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC";
    static final String TEST_PREFIX     = "###TestError###: ";

    static int testExitValue = 0;

    static {
        String tmp = System.getProperty("test.classes", null);
        if (tmp == null) {
            throw new Error("property test.classes not defined ??");
        }
        TEST_CLASSES_DIR = new File(tmp).getAbsoluteFile();

        tmp = System.getProperty("test.src", null);
        if (tmp == null) {
            throw new Error("property test.src not defined ??");
        }
        TEST_SOURCES_DIR = new File(tmp).getAbsoluteFile();

        if (is64Bit && is32Bit) {
            throw new RuntimeException("arch model cannot be both 32 and 64 bit");
        }
        if (!is64Bit && !is32Bit) {
            throw new RuntimeException("arch model is not 32 or 64 bit ?");
        }

        File binDir = new File(JAVAHOME, "bin");
        JAVA_BIN = binDir.getAbsolutePath();
        File libDir = new File(JAVAHOME, "lib");
        JAVA_LIB = libDir.getAbsolutePath();

        File javaCmdFile = (isWindows)
                ? new File(binDir, "java.exe")
                : new File(binDir, "java");
        javaCmd = javaCmdFile.getAbsolutePath();
        if (!javaCmdFile.canExecute()) {
            throw new RuntimeException("java <" + TestHelper.javaCmd +
                    "> must exist and should be executable");
        }

        File javacCmdFile = (isWindows)
                ? new File(binDir, "javac.exe")
                : new File(binDir, "javac");
        javacCmd = javacCmdFile.getAbsolutePath();

        File jarCmdFile = (isWindows)
                ? new File(binDir, "jar.exe")
                : new File(binDir, "jar");
        jarCmd = jarCmdFile.getAbsolutePath();
        if (!jarCmdFile.canExecute()) {
            throw new RuntimeException("java <" + TestHelper.jarCmd +
                    "> must exist and should be executable");
        }

        if (isWindows) {
            File javawCmdFile = new File(binDir, "javaw.exe");
            javawCmd = javawCmdFile.getAbsolutePath();
            if (!javawCmdFile.canExecute()) {
                throw new RuntimeException("java <" + javawCmd +
                        "> must exist and should be executable");
            }
        } else {
            javawCmd = null;
        }

        if (!javacCmdFile.canExecute()) {
            throw new RuntimeException("java <" + javacCmd +
                    "> must exist and should be executable");
        }

        haveClientVM = haveVmVariant("client");
        haveServerVM = haveVmVariant("server");
    }
    private static boolean haveVmVariant(String type) {
        if (isWindows) {
            File vmDir = new File(JAVA_BIN, type);
            File jvmFile = new File(vmDir, LIBJVM);
            return jvmFile.exists();
        } else {
            File vmDir = new File(JAVA_LIB, type);
            File jvmFile = new File(vmDir, LIBJVM);
            return jvmFile.exists();
        }
    }
    void run(String[] args) throws Exception {
        int passed = 0, failed = 0;
        final Pattern p = (args != null && args.length > 0)
                ? Pattern.compile(args[0])
                : null;
        for (Method m : this.getClass().getDeclaredMethods()) {
            boolean selected = (p == null)
                    ? m.isAnnotationPresent(Test.class)
                    : p.matcher(m.getName()).matches();
            if (selected) {
                try {
                    m.invoke(this, (Object[]) null);
                    System.out.println(m.getName() + ": OK");
                    passed++;
                    System.out.printf("Passed: %d, Failed: %d, ExitValue: %d%n",
                                      passed, failed, testExitValue);
                } catch (Throwable ex) {
                    System.out.printf("Test %s failed: %s %n", m, ex);
                    System.out.println("----begin detailed exceptions----");
                    ex.printStackTrace(System.out);
                    for (Throwable t : ex.getSuppressed()) {
                        t.printStackTrace(System.out);
                    }
                    System.out.println("----end detailed exceptions----");
                    failed++;
                }
            }
        }
        System.out.printf("Total: Passed: %d, Failed %d%n", passed, failed);
        if (failed > 0) {
            throw new RuntimeException("Tests failed: " + failed);
        }
        if (passed == 0 && failed == 0) {
            throw new AssertionError("No test(s) selected: passed = " +
                    passed + ", failed = " + failed + " ??????????");
        }
    }

    /*
     * usually the jre/lib/arch-name is the same as os.arch, except for x86.
     */
    static String getJreArch() {
        String arch = System.getProperty("os.arch");
        return arch.equals("x86") ? "i386" : arch;
    }
    static String getArch() {
        return System.getProperty("os.arch");
    }
    static File getClassFile(File javaFile) {
        String s = javaFile.getAbsolutePath().replace(JAVA_FILE_EXT, CLASS_FILE_EXT);
        return new File(s);
    }

    static File getJavaFile(File classFile) {
        String s = classFile.getAbsolutePath().replace(CLASS_FILE_EXT, JAVA_FILE_EXT);
        return new File(s);
    }

    static String baseName(File f) {
        String s = f.getName();
        return s.substring(0, s.indexOf("."));
    }

    /*
     * A convenience method to create a jar with jar file name and defs
     */
    static void createJar(File jarName, String... mainDefs)
            throws FileNotFoundException{
        createJar(null, jarName, new File("Foo"), mainDefs);
    }

    /*
     * A convenience method to create a java file, compile and jar it up, using
     * the sole class file name in the jar, as the Main-Class attribute value.
     */
    static void createJar(File jarName, File mainClass, String... mainDefs)
            throws FileNotFoundException {
            createJar(null, jarName, mainClass, mainDefs);
    }

    /*
     * A convenience method to compile java files.
     */
    static void compile(String... compilerArgs) {
        if (compiler.run(System.out, System.err, compilerArgs) != 0) {
            String sarg = "";
            for (String x : compilerArgs) {
                sarg.concat(x + " ");
            }
            throw new Error("compilation failed: " + sarg);
        }
    }

    /*
     * A generic jar file creator to create a java file, compile it
     * and jar it up, a specific Main-Class entry name in the
     * manifest can be specified or a null to use the sole class file name
     * as the Main-Class attribute value.
     */
    static void createJar(String mEntry, File jarName, File mainClass,
            String... mainDefs) throws FileNotFoundException {
        String source =
                Arrays.stream(mainDefs != null ? mainDefs : new String[0])
                      .collect(Collectors.joining(NL,
                                                  "public class Foo {" + NL,
                                                  "}" + NL));
        createJarForSource(mEntry, jarName, mainClass, source);
    }

    static void createJarForSource(String mEntry, File jarName, File mainClass,
            String source) throws FileNotFoundException {
        if (jarName.exists()) {
            jarName.delete();
        }
        try (PrintStream ps = new PrintStream(new FileOutputStream(mainClass + ".java"))) {
            ps.println(source);
        }

        String compileArgs[] = {
            mainClass + ".java"
        };
        if (compiler.run(System.out, System.err, compileArgs) != 0) {
            throw new RuntimeException("compilation failed " + mainClass + ".java");
        }
        if (mEntry == null) {
            mEntry = mainClass.getName();
        }
        String jarArgs[] = {
            (debug) ? "cvfe" : "cfe",
            jarName.getAbsolutePath(),
            mEntry,
            mainClass.getName() + ".class"
        };
        createJar(jarArgs);
    }

   static void createJar(String... args) {
        List<String> cmdList = new ArrayList<>();
        cmdList.add(jarCmd);
        cmdList.addAll(Arrays.asList(args));
        doExec(cmdList.toArray(new String[cmdList.size()]));
   }

   static void copyStream(InputStream in, OutputStream out) throws IOException {
        byte[] buf = new byte[8192];
        int n = in.read(buf);
        while (n > 0) {
            out.write(buf, 0, n);
            n = in.read(buf);
        }
    }

   static void copyFile(File src, File dst) throws IOException {
        Path parent = dst.toPath().getParent();
        if (parent != null) {
            Files.createDirectories(parent);
        }
        Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING);
    }

    /**
     * Attempt to create a file at the given location. If an IOException
     * occurs then back off for a moment and try again. When a number of
     * attempts fail, give up and throw an exception.
     */
    void createAFile(File aFile, List<String> lines) throws IOException {
        createAFile(aFile, lines, true);
    }

    void createAFile(File aFile, List<String> lines, boolean endWithNewline) throws IOException {
        IOException cause = null;
        for (int attempts = 0; attempts < 10; attempts++) {
            try {
                if (endWithNewline) {
                    Files.write(aFile.getAbsoluteFile().toPath(),
                        lines, Charset.defaultCharset(),
                        CREATE, TRUNCATE_EXISTING, WRITE);
                } else {
                    Files.write(aFile.getAbsoluteFile().toPath(),
                        String.join(System.lineSeparator(), lines).getBytes(Charset.defaultCharset()),
                        CREATE, TRUNCATE_EXISTING, WRITE);
                }
                if (cause != null) {
                    /*
                     * report attempts and errors that were encountered
                     * for diagnostic purposes
                     */
                    System.err.println("Created batch file " +
                                        aFile + " in " + (attempts + 1) +
                                        " attempts");
                    System.err.println("Errors encountered: " + cause);
                    cause.printStackTrace();
                }
                return;
            } catch (IOException ioe) {
                if (cause != null) {
                    // chain the exceptions so they all get reported for diagnostics
                    cause.addSuppressed(ioe);
                } else {
                    cause = ioe;
                }
            }

            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
                if (cause != null) {
                    // cause should alway be non-null here
                    ie.addSuppressed(cause);
                }
                throw new RuntimeException("Interrupted while creating batch file", ie);
            }
        }
        throw new RuntimeException("Unable to create batch file", cause);
    }

    static void createFile(File outFile, List<String> content) throws IOException {
        Files.write(outFile.getAbsoluteFile().toPath(), content,
                Charset.defaultCharset(), CREATE_NEW);
    }

    static void recursiveDelete(File target) throws IOException {
        if (!target.exists()) {
            return;
        }
        Files.walkFileTree(target.toPath(), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
                try {
                    Files.deleteIfExists(dir);
                } catch (IOException ex) {
                    System.out.println("Error: could not delete: " + dir.toString());
                    System.out.println(ex.getMessage());
                    return FileVisitResult.TERMINATE;
                }
                return FileVisitResult.CONTINUE;
            }
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                try {
                    Files.deleteIfExists(file);
                } catch (IOException ex) {
                    System.out.println("Error: could not delete: " + file.toString());
                    System.out.println(ex.getMessage());
                    return FileVisitResult.TERMINATE;
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    static TestResult doExec(String...cmds) {
        return doExec(null, null, cmds);
    }

    static TestResult doExec(Map<String, String> envToSet, String...cmds) {
        return doExec(envToSet, null, cmds);
    }
    /*
     * A method which executes a java cmd and returns the results in a container
     */
    static TestResult doExec(Map<String, String> envToSet,
                             Set<String> envToRemove, String...cmds) {
        String cmdStr = "";
        for (String x : cmds) {
            cmdStr = cmdStr.concat(x + " ");
        }
        ProcessBuilder pb = new ProcessBuilder(cmds);
        Map<String, String> env = pb.environment();
        if (envToRemove != null) {
            for (String key : envToRemove) {
                env.remove(key);
            }
        }
        if (envToSet != null) {
            env.putAll(envToSet);
        }
        BufferedReader rdr = null;
        try {
            List<String> outputList = new ArrayList<>();
            pb.redirectErrorStream(true);
            Process p = pb.start();
            rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String in = rdr.readLine();
            while (in != null) {
                outputList.add(in);
                in = rdr.readLine();
            }
            p.waitFor();
            p.destroy();

            return new TestHelper.TestResult(cmdStr, p.exitValue(), outputList,
                    env, new Throwable("current stack of the test"));
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
    }

    static FileFilter createFilter(final String extension) {
        return new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                String name = pathname.getName();
                if (name.endsWith(extension)) {
                    return true;
                }
                return false;
            }
        };
    }

    static boolean isEnglishLocale() {
        return Locale.getDefault().getLanguage().equals("en");
    }

    /**
     * Helper method to initialize a simple module that just prints the passed in arguments
     */
    static void createEchoArgumentsModule(File modulesDir) throws IOException {
        if (modulesDir.exists()) {
            recursiveDelete(modulesDir);
        }

        modulesDir.mkdirs();

        File srcDir = new File(modulesDir, "src");
        File modsDir = new File(modulesDir, "mods");
        File testDir = new File(srcDir, "test");
        File launcherTestDir = new File(testDir, "launcher");
        srcDir.mkdir();
        modsDir.mkdir();
        testDir.mkdir();
        launcherTestDir.mkdir();

        String[] moduleInfoCode = { "module test {}" };
        createFile(new File(testDir, "module-info.java"), Arrays.asList(moduleInfoCode));

        String[] moduleCode = {
            "package launcher;",
            "import java.util.Arrays;",
            "public class Main {",
            "public static void main(String[] args) {",
            "System.out.println(Arrays.toString(args));",
            "}",
            "}"
        };
        createFile(new File(launcherTestDir, "Main.java"), Arrays.asList(moduleCode));
    }

    static class ToolFilter implements FileFilter {
        final List<String> exclude = new ArrayList<>();
        protected ToolFilter(String... exclude) {
            for (String x : exclude) {
                String str = x + ((isWindows) ? EXE_FILE_EXT : "");
                this.exclude.add(str.toLowerCase());
            }
        }

        @Override
        public boolean accept(File pathname) {
            if (!pathname.isFile() || !pathname.canExecute()) {
                return false;
            }
            String name = pathname.getName().toLowerCase();
            if (isWindows) {
                if (!name.endsWith(EXE_FILE_EXT)) {
                    return false;
                }
            } else if (isMacOSX) {
                if (name.endsWith(MAC_DSYM_EXT)) {
                    return false;
                }
            } else {
                if (name.endsWith(NIX_DBGINFO_EXT)) {
                    return false;
                }
            }
            for (String x : exclude) {
                if (name.endsWith(x)) {
                    return false;
                }
            }
            return true;
        }
    }

    /*
     * A class to encapsulate the test results and stuff, with some ease
     * of use methods to check the test results.
     */
    static class TestResult {
        PrintWriter status;
        StringWriter sw;
        int exitValue;
        List<String> testOutput;
        Map<String, String> env;
        Throwable t;
        boolean testStatus;

        public TestResult(String str, int rv, List<String> oList,
                Map<String, String> env, Throwable t) {
            sw = new StringWriter();
            status = new PrintWriter(sw);
            status.println("Executed command: " + str + "\n");
            exitValue = rv;
            testOutput = oList;
            this.env = env;
            this.t = t;
            testStatus = true;
        }

        void appendError(String x) {
            testStatus = false;
            testExitValue++;
            status.println(TEST_PREFIX + x);
        }

        void indentStatus(String x) {
            status.println("  " + x);
        }

        void checkNegative() {
            if (exitValue == 0) {
                appendError("test must not return 0 exit value");
            }
        }

        void checkPositive() {
            if (exitValue != 0) {
                appendError("test did not return 0 exit value");
            }
        }

        boolean isOK() {
            return exitValue == 0;
        }

        boolean isZeroOutput() {
            if (!testOutput.isEmpty()) {
                appendError("No message from cmd please");
                return false;
            }
            return true;
        }

        boolean isNotZeroOutput() {
            if (testOutput.isEmpty()) {
                appendError("Missing message");
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            status.println("++++Begin Test Info++++");
            status.println("Test Status: " + (testStatus ? "PASS" : "FAIL"));
            status.println("++++Test Environment++++");
            for (String x : env.keySet()) {
                indentStatus(x + "=" + env.get(x));
            }
            status.println("++++Test Output++++");
            for (String x : testOutput) {
                indentStatus(x);
            }
            status.println("++++Test Stack Trace++++");
            status.println(t.toString());
            for (StackTraceElement e : t.getStackTrace()) {
                indentStatus(e.toString());
            }
            status.println("++++End of Test Info++++");
            status.flush();
            String out = sw.toString();
            status.close();
            return out;
        }

        boolean contains(String str) {
            for (String x : testOutput) {
                if (x.contains(str)) {
                    return true;
                }
            }
            appendError("string <" + str + "> not found");
            return false;
        }

        boolean notContains(String str) {
            for (String x : testOutput) {
                if (x.contains(str)) {
                    appendError("string <" + str + "> found");
                    return false;
                }
            }
            return true;
        }

        boolean matches(String regexToMatch) {
            for (String x : testOutput) {
                if (x.matches(regexToMatch)) {
                    return true;
                }
            }
            appendError("regex <" + regexToMatch + "> not matched");
            return false;
        }

        boolean notMatches(String regexToMatch) {
            for (String x : testOutput) {
                if (!x.matches(regexToMatch)) {
                    return true;
                }
            }
            appendError("regex <" + regexToMatch + "> matched");
            return false;
        }
    }
    /**
    * Indicates that the annotated method is a test method.
    */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Test {}
}
