/*
 * Copyright (c) 2013, 2024, 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.File;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Arrays;
import java.util.List;

import static jdk.test.lib.Asserts.*;
import jdk.test.lib.Utils;
import jdk.test.lib.JDKToolLauncher;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.thread.ProcessThread;

/**
 * The base class for tests of jstatd.
 *
 * The test sequence for TestJstatdDefaults for example is:
 * <pre>
 * {@code
 * // start jstatd process
 * jstatd -J-XX:+UsePerfData
 *
 * // run jps and verify its output
 * jps -J-XX:+UsePerfData hostname
 *
 * // run jstat and verify its output
 * jstat -J-XX:+UsePerfData -gcutil pid@hostname 250 5
 *
 * // stop jstatd process and verify that no unexpected exceptions have been thrown
 * }
 * </pre>
 */
public final class JstatdTest {

    /**
     * jstat gcutil option: takes JSTAT_GCUTIL_SAMPLES samples at
     * JSTAT_GCUTIL_INTERVAL_MS millisecond intervals
     */
    private static final int JSTAT_GCUTIL_SAMPLES = 5;
    private static final int JSTAT_GCUTIL_INTERVAL_MS = 250;
    private static final String JPS_OUTPUT_REGEX = "^\\d+\\s*.*";

    private static final int MAX_JSTATD_TRIES = 10;

    private boolean useDefaultPort = true;
    private boolean useDefaultRmiPort = true;
    private String port;
    private String rmiPort;
    private String serverName;
    private Long jstatdPid;
    private boolean withExternalRegistry = false;
    private boolean useShortCommandSyntax = false;

    private volatile static boolean portInUse;

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    public void setUseDefaultPort(boolean useDefaultPort) {
        this.useDefaultPort = useDefaultPort;
    }

    public void setUseDefaultRmiPort(boolean useDefaultRmiPort) {
        this.useDefaultRmiPort = useDefaultRmiPort;
    }

    public void setWithExternalRegistry(boolean withExternalRegistry) {
        this.withExternalRegistry = withExternalRegistry;
    }

    private Long waitOnTool(ProcessThread thread) throws Throwable {
        long pid = thread.getPid();
        if (portInUse) {
            System.out.println("Port already in use. Trying to restart with a new one...");
            return null;
        }
        System.out.println(thread.getName() + " pid: " + pid);
        return pid;
    }

    private void log(String caption, String... cmd) {
        System.out.println(Utils.NEW_LINE + caption + ":");
        System.out.println(Arrays.toString(cmd).replace(",", ""));
    }

    private String getDestination() throws UnknownHostException {
        String option = Utils.getHostname();
        if (port != null) {
            option += ":" + port;
        }
        if (serverName != null) {
            option += "/" + serverName;
        }
        return option;
    }

    /**
     * Depending on test settings command line can look like:
     *
     * jps -J-XX:+UsePerfData hostname
     * jps -J-XX:+UsePerfData hostname:port
     * jps -J-XX:+UsePerfData hostname/serverName
     * jps -J-XX:+UsePerfData hostname:port/serverName
     */
    private OutputAnalyzer runJps() throws Exception {
        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jps");
        launcher.addVMArg("-XX:+UsePerfData");
        launcher.addToolArg(getDestination());

        String[] cmd = launcher.getCommand();
        log("Start jps", cmd);

        ProcessBuilder processBuilder = new ProcessBuilder(cmd);
        OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
        System.out.println(output.getOutput());

        return output;
    }

    /**
     * Verifies output form jps contains pids and programs' name information.
     * The function will discard any lines that come before the first line with pid.
     * This can happen if the JVM outputs a warning message for some reason
     * before running jps.
     *
     * The output can look like:
     * 35536 Jstatd
     * 35417 Main
     * 31103 org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar
     */
    private void verifyJpsOutput(OutputAnalyzer output) throws Exception {
        output.shouldHaveExitValue(0);
        assertFalse(output.getOutput().isEmpty(), "Output should not be empty");

        boolean foundFirstLineWithPid = false;
        List<String> lines = output.asLinesWithoutVMWarnings();
        for (String line : lines) {
            if (!foundFirstLineWithPid) {
                foundFirstLineWithPid = line.matches(JPS_OUTPUT_REGEX);
                continue;
            }
            assertTrue(line.matches(JPS_OUTPUT_REGEX),
                    "Output does not match the pattern" + Utils.NEW_LINE + line);
        }
        assertTrue(foundFirstLineWithPid, "Invalid output");
    }

    /**
     * Depending on test settings command line can look like:
     *
     * jstat -J-XX:+UsePerfData -gcutil pid@hostname 250 5
     * jstat -J-XX:+UsePerfData -gcutil pid@hostname:port 250 5
     * jstat -J-XX:+UsePerfData -gcutil pid@hostname/serverName 250 5
     * jstat -J-XX:+UsePerfData -gcutil pid@hostname:port/serverName 250 5
     */
    private OutputAnalyzer runJstat() throws Exception {
        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstat");
        launcher.addVMArg("-XX:+UsePerfData");
        launcher.addToolArg("-gcutil");
        launcher.addToolArg(jstatdPid + "@" + getDestination());
        launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_INTERVAL_MS));
        launcher.addToolArg(Integer.toString(JSTAT_GCUTIL_SAMPLES));

        String[] cmd = launcher.getCommand();
        log("Start jstat", cmd);

        ProcessBuilder processBuilder = new ProcessBuilder(cmd);
        OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
        System.out.println(output.getOutput());

        return output;
    }

    private void verifyJstatOutput(OutputAnalyzer output)
            throws Exception {
        output.shouldHaveExitValue(0);
        assertFalse(output.getOutput().isEmpty(), "Output should not be empty");

        JstatGCUtilParser gcUtilParser = new JstatGCUtilParser(
                output.getOutput());
        gcUtilParser.parse(JSTAT_GCUTIL_SAMPLES);
    }

    private void runToolsAndVerify() throws Exception {
        OutputAnalyzer output = runJps();
        verifyJpsOutput(output);

        output = runJstat();
        verifyJstatOutput(output);
    }

    private Registry startRegistry()
            throws InterruptedException, RemoteException {
        Registry registry = null;
        try {
            System.out.println("Start rmiregistry on port " + port);
            registry = LocateRegistry
                    .createRegistry(Integer.parseInt(port));
        } catch (RemoteException e) {
            if (e.getMessage().contains("Port already in use")) {
                System.out.println("Port already in use. Trying to restart with a new one...");
                Thread.sleep(100);
                return null;
            } else {
                throw e;
            }
        }
        return registry;
    }

    private void cleanUpThread(ProcessThread thread) throws Throwable {
        if (thread != null) {
            thread.stopProcess();
            thread.joinAndThrow();
        }
    }

    /**
     * Depending on test settings command line can look like:
     *
     * jstatd -J-XX:+UsePerfData
     * jstatd -J-XX:+UsePerfData -p port
     * jstatd -J-XX:+UsePerfData -p port -r rmiport
     * jstatd -J-XX:+UsePerfData -n serverName
     * jstatd -J-XX:+UsePerfData -p port -n serverName
     */
    private String[] getJstatdCmd() throws Exception {
        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstatd");
        launcher.addVMArgs(Utils.getTestJavaOpts());
        launcher.addVMArg("-XX:+UsePerfData");
        String testSrc = System.getProperty("test.src");
        if (port != null) {
            addToolArg(launcher,"-p", port);
        }
        if (rmiPort != null) {
            addToolArg(launcher,"-r", rmiPort);
        }
        if (serverName != null) {
            addToolArg(launcher,"-n", serverName);
        }
        if (withExternalRegistry) {
            launcher.addToolArg("-nr");
        }
        String[] cmd = launcher.getCommand();
        log("Start jstatd", cmd);
        return cmd;
    }

    private void addToolArg(JDKToolLauncher launcher, String name, String value) {
        if (useShortCommandSyntax) {
            launcher.addToolArg(name + value);
        } else {
            launcher.addToolArg(name);
            launcher.addToolArg(value);
        }
    }

    private ProcessThread tryToSetupJstatdProcess() throws Throwable {
        portInUse = false;
        ProcessThread jstatdThread = new ProcessThread("Jstatd-Thread",
                JstatdTest::isJstatdReady, getJstatdCmd());
        try {
            jstatdThread.start();
            // Make sure jstatd is up and running
            jstatdPid = waitOnTool(jstatdThread);
            if (jstatdPid == null) {
                // The port is already in use. Cancel and try with new one.
                jstatdThread.stopProcess();
                jstatdThread.join();
                return null;
            }
        } catch (Throwable t) {
            // Something went wrong in the product - clean up!
            cleanUpThread(jstatdThread);
            throw t;
        }

        return jstatdThread;
    }

    private static boolean isJstatdReady(String line) {
        if (line.contains("Port already in use") || line.contains("Could not bind")) {
            portInUse = true;
            return true;
        }
        return line.startsWith("jstatd started (bound to ");
    }

    public void doTest() throws Throwable {
        runTest(false);
        runTest(true);
    }

    private void runTest(boolean useShortSyntax) throws Throwable {
        useShortCommandSyntax = useShortSyntax;
        if (useDefaultPort) {
            verifyNoRmiRegistryOnDefaultPort();
        }

        ProcessThread jstatdThread = null;
        int tries = 0;
        try {
            while (jstatdThread == null && ++tries <= MAX_JSTATD_TRIES) {
                if (!useDefaultPort) {
                    port = String.valueOf(Utils.getFreePort());
                }

                if (!useDefaultRmiPort) {
                    rmiPort = String.valueOf(Utils.getFreePort());
                }

                if (withExternalRegistry) {
                    Registry registry = startRegistry();
                    if (registry == null) {
                        // The port is already in use. Cancel and try with a new one.
                        continue;
                    }
                }
                jstatdThread = tryToSetupJstatdProcess();
            }
            if (jstatdThread == null) {
                throw new RuntimeException("Cannot start jstatd.");
            }
            runToolsAndVerify();
        } finally {
            cleanUpThread(jstatdThread);
        }

        // Verify output from jstatd
        OutputAnalyzer output = jstatdThread.getOutput();
        List<String> stdout = output.asLinesWithoutVMWarnings();
        output.reportDiagnosticSummary();
        assertEquals(stdout.size(), 2, "Output should contain two lines"); // includes deprecation warning
        assertTrue(stdout.get(0).startsWith("jstatd started"), "List should start with 'jstatd started'");
        assertNotEquals(output.getExitValue(), 0,
                "jstatd process exited with unexpected exit code");
    }

    private void verifyNoRmiRegistryOnDefaultPort() throws Exception {
        try {
            Registry registry = LocateRegistry.getRegistry();
            registry.list();
            throw new Exception("There is already RMI registry on the default port: " + registry);
        } catch (RemoteException e) {
            // No RMI registry on default port is detected
        }
    }

}
