/*
 * Copyright (c) 2015, 2016, 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.
 */
package optionsvalidation;

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AttachOperationFailedException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jdk.test.lib.DynamicVMOption;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.dcmd.CommandExecutor;
import jdk.test.lib.dcmd.JMXExecutor;
import sun.tools.attach.HotSpotVirtualMachine;

import static optionsvalidation.JVMOptionsUtils.failedMessage;
import static optionsvalidation.JVMOptionsUtils.GCType;
import static optionsvalidation.JVMOptionsUtils.printOutputContent;
import static optionsvalidation.JVMOptionsUtils.VMType;

public abstract class JVMOption {

    /**
     * Executor for JCMD
     */
    private final static CommandExecutor executor = new JMXExecutor();

    /**
     * Name of the tested parameter
     */
    protected String name;

    /**
     * Range is defined for option inside VM
     */
    protected boolean withRange;

    /**
     * Test valid min range value and additional small values
     */
    protected boolean testMinRange;

    /**
     * Test valid max range value and additional big values
     */
    protected boolean testMaxRange;

    private Set<Integer> allowedExitCodes;

    /**
     * Prepend string which added before testing option to the command line
     */
    private final List<String> prepend;
    private final StringBuilder prependString;

    protected JVMOption() {
        this.prepend = new ArrayList<>();
        prependString = new StringBuilder();
        allowedExitCodes = new HashSet<>();
        allowedExitCodes.add(0);
        allowedExitCodes.add(1);
        withRange = false;
        testMinRange = true;
        testMaxRange = true;
    }

    /**
     * Create JVM Option with given type and name.
     *
     * @param type type: "intx", "size_t", "uintx", "uint64_t" or "double"
     * @param name name of the option
     * @return created JVMOption
     */
    static JVMOption createVMOption(String type, String name) {
        JVMOption parameter;

        switch (type) {
            case "int":
            case "intx":
            case "size_t":
            case "uint":
            case "uintx":
            case "uint64_t":
                parameter = new IntJVMOption(name, type);
                break;
            case "double":
                parameter = new DoubleJVMOption(name);
                break;
            default:
                throw new Error("Expected only \"int\", \"intx\", \"size_t\", "
                        + "\"uint\", \"uintx\", \"uint64_t\", or \"double\" "
                        + "option types! Got " + type + " type!");
        }

        return parameter;
    }

    /**
     * Add passed options to the prepend options of the option. Prepend options
     * will be added before testing option to the command line.
     *
     * @param options array of prepend options
     */
    public final void addPrepend(String... options) {
        String toAdd;

        for (String option : options) {
            if (option.startsWith("-")) {
                toAdd = option;
            } else {
                /* Add "-" before parameter name */
                toAdd = "-" + option;

            }
            prepend.add(toAdd);
            prependString.append(toAdd).append(" ");
        }
    }

    /**
     * Get name of the option
     *
     * @return name of the option
     */
    final String getName() {
        return name;
    }

    /**
     * Mark this option as option which range is defined inside VM
     */
    final void optionWithRange() {
        withRange = true;
    }

    /**
     * Exclude testing of min range value for this option
     */
    public final void excludeTestMinRange() {
        testMinRange = false;
    }

    /**
     * Exclude testing of max range value for this option
     */
    public final void excludeTestMaxRange() {
        testMaxRange = false;
    }

    public final void setAllowedExitCodes(Integer... allowedExitCodes) {
        this.allowedExitCodes.addAll(Arrays.asList(allowedExitCodes));
    }

    /**
     * Set new minimum option value
     *
     * @param min new minimum value
     */
    abstract void setMin(String min);

    /**
     * Get string with minimum value of the option
     *
     * @return string with minimum value of the option
     */
    abstract String getMin();

    /**
     * Set new maximum option value
     *
     * @param max new maximum value
     */
    abstract void setMax(String min);

    /**
     * Get string with maximum value of the option
     *
     * @return string with maximum value of the option
     */
    abstract String getMax();

    /**
     * Return list of strings with valid option values which used for testing
     * using jcmd, attach and etc.
     *
     * @return list of strings which contain valid values for option
     */
    protected abstract List<String> getValidValues();

    /**
     * Return list of strings with invalid option values which used for testing
     * using jcmd, attach and etc.
     *
     * @return list of strings which contain invalid values for option
     */
    protected abstract List<String> getInvalidValues();

    /**
     * Return expected error message for option with value "value" when it used
     * on command line with passed value
     *
     * @param value option value
     * @return expected error message
     */
    protected abstract String getErrorMessageCommandLine(String value);

    /**
     * Testing writeable option using DynamicVMOption isValidValue and
     * isInvalidValue methods
     *
     * @return number of failed tests
     */
    public int testDynamic() {
        DynamicVMOption option = new DynamicVMOption(name);
        int failedTests = 0;
        String origValue;

        if (option.isWriteable()) {

            System.out.println("Testing " + name + " option dynamically by DynamicVMOption");

            origValue = option.getValue();

            for (String value : getValidValues()) {
                if (!option.isValidValue(value)) {
                    failedMessage(String.format("Option %s: Valid value \"%s\" is invalid", name, value));
                    failedTests++;
                }
            }

            for (String value : getInvalidValues()) {
                if (option.isValidValue(value)) {
                    failedMessage(String.format("Option %s: Invalid value \"%s\" is valid", name, value));
                    failedTests++;
                }
            }

            option.setValue(origValue);
        }

        return failedTests;
    }

    /**
     * Testing writeable option using Jcmd
     *
     * @return number of failed tests
     */
    public int testJcmd() {
        DynamicVMOption option = new DynamicVMOption(name);
        int failedTests = 0;
        OutputAnalyzer out;
        String origValue;

        if (option.isWriteable()) {

            System.out.println("Testing " + name + " option dynamically by jcmd");

            origValue = option.getValue();

            for (String value : getValidValues()) {
                out = executor.execute(String.format("VM.set_flag %s %s", name, value), true);

                if (out.getOutput().contains(name + " error")) {
                    failedMessage(String.format("Option %s: Can not change "
                            + "option to valid value \"%s\" via jcmd", name, value));
                    printOutputContent(out);
                    failedTests++;
                }
            }

            for (String value : getInvalidValues()) {
                out = executor.execute(String.format("VM.set_flag %s %s", name, value), true);

                if (!out.getOutput().contains(name + " error")) {
                    failedMessage(String.format("Option %s: Error not reported for "
                            + "option when it chagned to invalid value \"%s\" via jcmd", name, value));
                    printOutputContent(out);
                    failedTests++;
                }
            }

            option.setValue(origValue);
        }

        return failedTests;
    }

    private boolean setFlagAttach(HotSpotVirtualMachine vm, String flagName, String flagValue) throws Exception {
        boolean result;

        try {
            vm.setFlag(flagName, flagValue);
            result = true;
        } catch (AttachOperationFailedException e) {
            result = false;
        }

        return result;
    }

    /**
     * Testing writeable option using attach method
     *
     * @return number of failed tests
     * @throws Exception if an error occurred while attaching to the target JVM
     */
    public int testAttach() throws Exception {
        DynamicVMOption option = new DynamicVMOption(name);
        int failedTests = 0;
        String origValue;

        if (option.isWriteable()) {

            System.out.println("Testing " + name + " option dynamically via attach");

            origValue = option.getValue();

            HotSpotVirtualMachine vm = (HotSpotVirtualMachine) VirtualMachine.attach(String.valueOf(ProcessTools.getProcessId()));

            for (String value : getValidValues()) {
                if (!setFlagAttach(vm, name, value)) {
                    failedMessage(String.format("Option %s: Can not change option to valid value \"%s\" via attach", name, value));
                    failedTests++;
                }
            }

            for (String value : getInvalidValues()) {
                if (setFlagAttach(vm, name, value)) {
                    failedMessage(String.format("Option %s: Option changed to invalid value \"%s\" via attach", name, value));
                    failedTests++;
                }
            }

            vm.detach();

            option.setValue(origValue);
        }

        return failedTests;
    }

    /**
     * Run java with passed parameter and check the result depending on the
     * 'valid' parameter
     *
     * @param param tested parameter passed to the JVM
     * @param valid indicates whether the JVM should fail or not
     * @return true - if test passed
     * @throws Exception if java process can not be started
     */
    private boolean runJavaWithParam(String optionValue, boolean valid) throws Exception {
        int exitCode;
        boolean result = true;
        String errorMessage = null;
        List<String> runJava = new ArrayList<>();
        OutputAnalyzer out;

        if (VMType != null) {
            runJava.add(VMType);
        }

        if (GCType != null) {
            runJava.add(GCType);
        }

        runJava.addAll(prepend);
        runJava.add(optionValue);
        runJava.add(JVMStartup.class.getName());

        out = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start());

        exitCode = out.getExitValue();

        if (out.getOutput().contains("A fatal error has been detected by the Java Runtime Environment")) {
            /* Always consider "fatal error" in output as fail */
            errorMessage = "JVM output reports a fatal error. JVM exited with code " + exitCode + "!";
        } else if (valid == true) {
            if (!allowedExitCodes.contains(exitCode)) {
                errorMessage = "JVM exited with unexpected error code = " + exitCode;
            } else if ((exitCode != 0) && (out.getOutput().isEmpty() == true)) {
                errorMessage = "JVM exited with error(exitcode == " + exitCode + "), but with empty stdout and stderr. " +
                       "Description of error is needed!";
            } else if (out.getOutput().contains("is outside the allowed range")) {
                errorMessage = "JVM output contains \"is outside the allowed range\"";
            }
        } else {
            // valid == false
            String value = optionValue.substring(optionValue.lastIndexOf("=") + 1);
            String errorMessageCommandLineValue = getErrorMessageCommandLine(value);
            if (exitCode == 0) {
                errorMessage = "JVM successfully exit";
            } else if (exitCode != 1) {
                errorMessage = "JVM exited with code " + exitCode + " which not equal to 1";
            } else if (!out.getOutput().contains(errorMessageCommandLineValue)) {
                errorMessage = "JVM output does not contain expected output \"" + errorMessageCommandLineValue + "\"";
            }
        }

        if (errorMessage != null) {
            String fullOptionString = String.format("%s %s %s %s",
                    VMType == null ? "" : VMType, GCType == null ? "" : GCType, prependString.toString(), optionValue).trim().replaceAll("  +", " ");
            failedMessage(name, fullOptionString, valid, errorMessage);
            printOutputContent(out);
            result = false;
        }

        System.out.println("");

        return result;
    }

    /**
     * Construct option string with passed value
     *
     * @param value parameter value
     * @return string containing option with passed value
     */
    private String constructOption(String value) {
        return "-XX:" + name + "=" + value;
    }

    /**
     * Return list of strings which contain options with valid values which can
     * be used for testing on command line
     *
     * @return list of strings which contain options with valid values
     */
    private List<String> getValidCommandLineOptions() {
        List<String> validParameters = new ArrayList<>();

        for (String value : getValidValues()) {
            validParameters.add(constructOption(value));
        }

        return validParameters;
    }

    /**
     * Return list of strings which contain options with invalid values which
     * can be used for testing on command line
     *
     * @return list of strings which contain options with invalid values
     */
    private List<String> getInvalidCommandLineOptions() {
        List<String> invalidParameters = new ArrayList<>();

        for (String value : getInvalidValues()) {
            invalidParameters.add(constructOption(value));
        }

        return invalidParameters;
    }

    /**
     * Perform test of the parameter. Call java with valid option values and
     * with invalid option values.
     *
     * @return number of failed tests
     * @throws Exception if java process can not be started
     */
    public int testCommandLine() throws Exception {
        ProcessBuilder pb;
        int failed = 0;
        List<String> optionValuesList;

        optionValuesList = getValidCommandLineOptions();

        if (optionValuesList.isEmpty() != true) {
            System.out.println("Testing valid " + name + " values.");
            for (String optionValid : optionValuesList) {
                if (runJavaWithParam(optionValid, true) == false) {
                    failed++;
                }
            }
        }

        optionValuesList = getInvalidCommandLineOptions();

        if (optionValuesList.isEmpty() != true) {
            System.out.println("Testing invalid " + name + " values.");

            for (String optionInvalid : optionValuesList) {
                if (runJavaWithParam(optionInvalid, false) == false) {
                    failed++;
                }
            }
        }

        /* return number of failed tests for this option */
        return failed;
    }

}
