8072931: JEP-JDK-8059557: Test task: test framework development
Test set for JEP 245 Validate JVM Command-Line Flag Arguments Reviewed-by: ctornqvi, dholmes, gziemski
This commit is contained in:
parent
ed2bb8c9fc
commit
4875379a42
hotspot/test
TEST.groups
runtime/CommandLine/OptionsValidation
@ -420,6 +420,7 @@ hotspot_runtime = \
|
||||
-runtime/SharedArchiveFile/DefaultUseWithClient.java \
|
||||
-runtime/Thread/CancellableThreadTest.java \
|
||||
-runtime/7158988/FieldMonitor.java \
|
||||
-runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
|
||||
sanity/ \
|
||||
testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
|
||||
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Verify jcmd error message for out-of-range value and for
|
||||
* value which is not allowed by constraint. Also check that
|
||||
* jcmd does not print an error message to the target process output.
|
||||
* @library /testlibrary
|
||||
* @modules java.base/sun.misc
|
||||
* java.management
|
||||
* jdk.management
|
||||
* @run main TestJcmdOutput
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.DynamicVMOption;
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.ProcessTools;
|
||||
import jdk.test.lib.dcmd.PidJcmdExecutor;
|
||||
|
||||
public class TestJcmdOutput {
|
||||
|
||||
/* Message printed by jcmd for value which is out-of-range */
|
||||
static final String JCMD_OUT_OF_RANGE_MESSAGE = "error: must have value in range";
|
||||
/* Message printed by jcmd for value which is not allowed by constraint */
|
||||
static final String JCMD_CONSTRAINT_MESSAGE = "value violates its flag's constraint";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OutputAnalyzer output;
|
||||
|
||||
System.out.println("Verify jcmd error message and that jcmd does not write errors to the target process output");
|
||||
output = new OutputAnalyzer((ProcessTools.createJavaProcessBuilder(
|
||||
"-Dtest.jdk=" + System.getProperty("test.jdk"),
|
||||
"-XX:MinHeapFreeRatio=20", "-XX:MaxHeapFreeRatio=80", runJcmd.class.getName())).start());
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
/* Verify that jcmd not print error message to the target process output */
|
||||
output.shouldNotContain(JCMD_OUT_OF_RANGE_MESSAGE);
|
||||
output.shouldNotContain(JCMD_CONSTRAINT_MESSAGE);
|
||||
}
|
||||
|
||||
public static class runJcmd {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int minHeapFreeRatio = new Integer((new DynamicVMOption("MinHeapFreeRatio")).getValue());
|
||||
int maxHeapFreeRatio = new Integer((new DynamicVMOption("MaxHeapFreeRatio")).getValue());
|
||||
PidJcmdExecutor executor = new PidJcmdExecutor();
|
||||
|
||||
Asserts.assertGT(minHeapFreeRatio, 0, "MinHeapFreeRatio must be greater than 0");
|
||||
Asserts.assertLT(maxHeapFreeRatio, 100, "MaxHeapFreeRatio must be less than 100");
|
||||
|
||||
/* Check out-of-range values */
|
||||
executor.execute("VM.set_flag MinHeapFreeRatio -1", true).shouldContain(JCMD_OUT_OF_RANGE_MESSAGE);
|
||||
executor.execute("VM.set_flag MaxHeapFreeRatio 101", true).shouldContain(JCMD_OUT_OF_RANGE_MESSAGE);
|
||||
|
||||
/* Check values which not allowed by constraint */
|
||||
executor.execute(
|
||||
String.format("VM.set_flag MinHeapFreeRatio %d", maxHeapFreeRatio + 1), true)
|
||||
.shouldContain(JCMD_CONSTRAINT_MESSAGE);
|
||||
executor.execute(
|
||||
String.format("VM.set_flag MaxHeapFreeRatio %d", minHeapFreeRatio - 1), true)
|
||||
.shouldContain(JCMD_CONSTRAINT_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test VM Options with ranges
|
||||
* @library /testlibrary /runtime/CommandLine/OptionsValidation/common
|
||||
* @modules java.base/sun.misc
|
||||
* java.management
|
||||
* jdk.attach
|
||||
* jdk.management/sun.tools.attach
|
||||
* @run main/othervm/timeout=600 TestOptionsWithRanges
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.test.lib.Asserts;
|
||||
import optionsvalidation.JVMOption;
|
||||
import optionsvalidation.JVMOptionsUtils;
|
||||
|
||||
public class TestOptionsWithRanges {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int failedTests;
|
||||
Map<String, JVMOption> allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap();
|
||||
List<JVMOption> allOptions;
|
||||
|
||||
/*
|
||||
* Remove CICompilerCount from testing because currently it can hang system
|
||||
*/
|
||||
allOptionsAsMap.remove("CICompilerCount");
|
||||
|
||||
allOptions = new ArrayList<>(allOptionsAsMap.values());
|
||||
|
||||
Asserts.assertGT(allOptions.size(), 0, "Options with ranges not found!");
|
||||
|
||||
System.out.println("Parsed " + allOptions.size() + " options with ranges. Start test!");
|
||||
|
||||
failedTests = JVMOptionsUtils.runCommandLineTests(allOptions);
|
||||
|
||||
Asserts.assertEQ(failedTests, 0,
|
||||
String.format("%d tests failed! %s", failedTests, JVMOptionsUtils.getMessageWithFailures()));
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test writeable VM Options with ranges.
|
||||
* @library /testlibrary /runtime/CommandLine/OptionsValidation/common
|
||||
* @modules java.base/sun.misc
|
||||
* java.management
|
||||
* jdk.attach
|
||||
* jdk.management/sun.tools.attach
|
||||
* @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestOptionsWithRangesDynamic
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import jdk.test.lib.Asserts;
|
||||
import optionsvalidation.JVMOption;
|
||||
import optionsvalidation.JVMOptionsUtils;
|
||||
|
||||
public class TestOptionsWithRangesDynamic {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int failedTests;
|
||||
List<JVMOption> allWriteableOptions;
|
||||
|
||||
/* Get only writeable options */
|
||||
allWriteableOptions = JVMOptionsUtils.getOptionsWithRange(origin -> (origin.contains("manageable") || origin.contains("rw")));
|
||||
|
||||
Asserts.assertGT(allWriteableOptions.size(), 0, "Options with ranges not found!");
|
||||
|
||||
System.out.println("Test " + allWriteableOptions.size() + " writeable options with ranges. Start test!");
|
||||
|
||||
failedTests = JVMOptionsUtils.runDynamicTests(allWriteableOptions);
|
||||
|
||||
failedTests += JVMOptionsUtils.runJcmdTests(allWriteableOptions);
|
||||
|
||||
failedTests += JVMOptionsUtils.runAttachTests(allWriteableOptions);
|
||||
|
||||
Asserts.assertEQ(failedTests, 0,
|
||||
String.format("%d tests failed! %s", failedTests, JVMOptionsUtils.getMessageWithFailures()));
|
||||
}
|
||||
}
|
202
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/DoubleJVMOption.java
Normal file
202
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/DoubleJVMOption.java
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DoubleJVMOption extends JVMOption {
|
||||
|
||||
/**
|
||||
* Additional double values to test
|
||||
*/
|
||||
private static final double ADDITIONAL_TEST_DOUBLE_NEGATIVE = -1.5;
|
||||
private static final double ADDITIONAL_TEST_DOUBLE_ZERO = 0.0;
|
||||
private static final double ADDITIONAL_TEST_DOUBLE_POSITIVE = 1.75;
|
||||
|
||||
/**
|
||||
* Mininum option value
|
||||
*/
|
||||
private double min;
|
||||
/**
|
||||
* Maximum option value
|
||||
*/
|
||||
private double max;
|
||||
|
||||
/**
|
||||
* Initialize double option with passed name
|
||||
*
|
||||
* @param name name of the option
|
||||
*/
|
||||
DoubleJVMOption(String name) {
|
||||
this.name = name;
|
||||
min = Double.MIN_VALUE;
|
||||
max = Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize double option with passed name, min and max values
|
||||
*
|
||||
* @param name name of the option
|
||||
* @param min minimum value of the option
|
||||
* @param max maximum value of the option
|
||||
*/
|
||||
public DoubleJVMOption(String name, double min, double max) {
|
||||
this(name);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new minimum option value
|
||||
*
|
||||
* @param min new minimum value
|
||||
*/
|
||||
@Override
|
||||
void setMin(String min) {
|
||||
this.min = new Double(min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string with minimum value of the option
|
||||
*
|
||||
* @return string with minimum value of the option
|
||||
*/
|
||||
@Override
|
||||
String getMin() {
|
||||
return formatValue(min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new maximum option value
|
||||
*
|
||||
* @param max new maximum value
|
||||
*/
|
||||
@Override
|
||||
void setMax(String max) {
|
||||
this.max = new Double(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string with maximum value of the option
|
||||
*
|
||||
* @return string with maximum value of the option
|
||||
*/
|
||||
@Override
|
||||
String getMax() {
|
||||
return formatValue(max);
|
||||
}
|
||||
|
||||
private String formatValue(double value) {
|
||||
return String.format("%f", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected List<String> getValidValues() {
|
||||
List<String> validValues = new ArrayList<>();
|
||||
|
||||
validValues.add(formatValue(min));
|
||||
validValues.add(formatValue(max));
|
||||
|
||||
if ((Double.compare(min, ADDITIONAL_TEST_DOUBLE_NEGATIVE) < 0)
|
||||
&& (Double.compare(max, ADDITIONAL_TEST_DOUBLE_NEGATIVE) > 0)) {
|
||||
validValues.add(formatValue(ADDITIONAL_TEST_DOUBLE_NEGATIVE));
|
||||
}
|
||||
|
||||
if ((Double.compare(min, ADDITIONAL_TEST_DOUBLE_ZERO) < 0)
|
||||
&& (Double.compare(max, ADDITIONAL_TEST_DOUBLE_ZERO) > 0)) {
|
||||
validValues.add(formatValue(ADDITIONAL_TEST_DOUBLE_ZERO));
|
||||
}
|
||||
|
||||
if ((Double.compare(min, ADDITIONAL_TEST_DOUBLE_POSITIVE) < 0)
|
||||
&& (Double.compare(max, ADDITIONAL_TEST_DOUBLE_POSITIVE) > 0)) {
|
||||
validValues.add(formatValue(ADDITIONAL_TEST_DOUBLE_POSITIVE));
|
||||
}
|
||||
|
||||
return validValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected List<String> getInvalidValues() {
|
||||
List<String> invalidValues = new ArrayList<>();
|
||||
|
||||
if (withRange) {
|
||||
/* Return invalid values only for options which have defined range in VM */
|
||||
if (Double.compare(min, Double.MIN_VALUE) != 0) {
|
||||
if ((Double.compare(min, 0.0) > 0)
|
||||
&& (Double.isNaN(min * 0.999) == false)) {
|
||||
invalidValues.add(formatValue(min * 0.999));
|
||||
} else if ((Double.compare(min, 0.0) < 0)
|
||||
&& (Double.isNaN(min * 1.001) == false)) {
|
||||
invalidValues.add(formatValue(min * 1.001));
|
||||
}
|
||||
}
|
||||
|
||||
if (Double.compare(max, Double.MAX_VALUE) != 0) {
|
||||
if ((Double.compare(max, 0.0) > 0)
|
||||
&& (Double.isNaN(max * 1.001) == false)) {
|
||||
invalidValues.add(formatValue(max * 1.001));
|
||||
} else if ((Double.compare(max, 0.0) < 0)
|
||||
&& (Double.isNaN(max * 0.999) == false)) {
|
||||
invalidValues.add(formatValue(max * 0.999));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return invalidValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected String getErrorMessageCommandLine(String value) {
|
||||
String errorMsg;
|
||||
|
||||
if (withRange) {
|
||||
/* Option have defined range in VM */
|
||||
errorMsg = "is outside the allowed range";
|
||||
} else {
|
||||
errorMsg = "";
|
||||
}
|
||||
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
309
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/IntJVMOption.java
Normal file
309
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/IntJVMOption.java
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
public class IntJVMOption extends JVMOption {
|
||||
|
||||
private static final BigInteger MIN_LONG;
|
||||
private static final BigInteger MAX_LONG;
|
||||
private static final BigInteger MAX_UNSIGNED_LONG;
|
||||
private static final BigInteger MAX_UNSIGNED_LONG_64;
|
||||
private static final BigInteger MINUS_ONE = new BigInteger("-1");
|
||||
private static final BigInteger TWO = new BigInteger("2");
|
||||
private static final BigInteger MIN_4_BYTE_INT = new BigInteger("-2147483648");
|
||||
private static final BigInteger MAX_4_BYTE_INT = new BigInteger("2147483647");
|
||||
private static final BigInteger MAX_4_BYTE_INT_PLUS_ONE = new BigInteger("2147483648");
|
||||
private static final BigInteger MAX_4_BYTE_UNSIGNED_INT = new BigInteger("4294967295");
|
||||
private static final BigInteger MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE = new BigInteger("4294967296");
|
||||
|
||||
/**
|
||||
* Mininum option value
|
||||
*/
|
||||
private BigInteger min;
|
||||
|
||||
/**
|
||||
* Maximum option value
|
||||
*/
|
||||
private BigInteger max;
|
||||
|
||||
/**
|
||||
* Option type: intx, uintx, size_t or uint64_t
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Is this value signed or unsigned
|
||||
*/
|
||||
private boolean unsigned;
|
||||
|
||||
/**
|
||||
* Is this 32 bit type
|
||||
*/
|
||||
private boolean is32Bit = false;
|
||||
|
||||
/**
|
||||
* Is this value 64 bit unsigned
|
||||
*/
|
||||
private boolean uint64 = false;
|
||||
|
||||
static {
|
||||
if (Platform.is32bit()) {
|
||||
MIN_LONG = new BigInteger(String.valueOf(Integer.MIN_VALUE));
|
||||
MAX_LONG = new BigInteger(String.valueOf(Integer.MAX_VALUE));
|
||||
MAX_UNSIGNED_LONG = MAX_LONG.multiply(TWO).add(BigInteger.ONE);
|
||||
} else {
|
||||
MIN_LONG = new BigInteger(String.valueOf(Long.MIN_VALUE));
|
||||
MAX_LONG = new BigInteger(String.valueOf(Long.MAX_VALUE));
|
||||
MAX_UNSIGNED_LONG = MAX_LONG.multiply(TWO).add(BigInteger.ONE);
|
||||
}
|
||||
|
||||
MAX_UNSIGNED_LONG_64 = (new BigInteger(String.valueOf(Long.MAX_VALUE)))
|
||||
.multiply(TWO).add(BigInteger.ONE);
|
||||
}
|
||||
|
||||
private IntJVMOption() {
|
||||
type = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize new integer option with given type. Type can be: INTX -
|
||||
* integer signed option UINTX - unsigned integer option UINT64_T - unsigned
|
||||
* 64 bit integer option
|
||||
*
|
||||
* @param name name of the option
|
||||
* @param type type of the option
|
||||
*/
|
||||
IntJVMOption(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
|
||||
switch (type) {
|
||||
case "uint64_t":
|
||||
unsigned = true;
|
||||
uint64 = true;
|
||||
max = MAX_UNSIGNED_LONG_64;
|
||||
break;
|
||||
case "uintx":
|
||||
case "size_t":
|
||||
unsigned = true;
|
||||
max = MAX_UNSIGNED_LONG;
|
||||
break;
|
||||
case "uint":
|
||||
unsigned = true;
|
||||
is32Bit = true;
|
||||
max = MAX_4_BYTE_UNSIGNED_INT;
|
||||
break;
|
||||
case "int":
|
||||
min = MIN_4_BYTE_INT;
|
||||
max = MAX_4_BYTE_INT;
|
||||
is32Bit = true;
|
||||
break;
|
||||
default:
|
||||
min = MIN_LONG;
|
||||
max = MAX_LONG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unsigned) {
|
||||
min = BigInteger.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize integer option with passed name, min and max values. Min and
|
||||
* max are string because they can be very big, bigger than long.
|
||||
*
|
||||
* @param name name of the option
|
||||
* @param min minimum value of the option
|
||||
* @param max maximum value of the option
|
||||
*/
|
||||
public IntJVMOption(String name, String min, String max) {
|
||||
this();
|
||||
this.name = name;
|
||||
this.min = new BigInteger(min);
|
||||
this.max = new BigInteger(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new minimum option value
|
||||
*
|
||||
* @param min new minimum value
|
||||
*/
|
||||
@Override
|
||||
void setMin(String min) {
|
||||
this.min = new BigInteger(min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string with minimum value of the option
|
||||
*
|
||||
* @return string with minimum value of the option
|
||||
*/
|
||||
@Override
|
||||
String getMin() {
|
||||
return min.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new maximum option value
|
||||
*
|
||||
* @param max new maximum value
|
||||
*/
|
||||
@Override
|
||||
void setMax(String max) {
|
||||
this.max = new BigInteger(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string with maximum value of the option
|
||||
*
|
||||
* @return string with maximum value of the option
|
||||
*/
|
||||
@Override
|
||||
String getMax() {
|
||||
return max.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected List<String> getValidValues() {
|
||||
List<String> validValues = new ArrayList<>();
|
||||
|
||||
validValues.add(min.toString());
|
||||
validValues.add(max.toString());
|
||||
|
||||
if ((min.compareTo(MINUS_ONE) == -1) && (max.compareTo(MINUS_ONE) == 1)) {
|
||||
/*
|
||||
* Add -1 as valid value if min is less than -1 and max is greater than -1
|
||||
*/
|
||||
validValues.add("-1");
|
||||
}
|
||||
|
||||
if ((min.compareTo(BigInteger.ZERO) == -1) && (max.compareTo(BigInteger.ZERO) == 1)) {
|
||||
/*
|
||||
* Add 0 as valid value if min is less than 0 and max is greater than 0
|
||||
*/
|
||||
validValues.add("0");
|
||||
}
|
||||
if ((min.compareTo(BigInteger.ONE) == -1) && (max.compareTo(BigInteger.ONE) == 1)) {
|
||||
/*
|
||||
* Add 1 as valid value if min is less than 1 and max is greater than 1
|
||||
*/
|
||||
validValues.add("1");
|
||||
}
|
||||
|
||||
if (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1) {
|
||||
/*
|
||||
* Check for overflow when flag is assigned to the
|
||||
* 4 byte int variable
|
||||
*/
|
||||
validValues.add(MAX_4_BYTE_INT_PLUS_ONE.toString());
|
||||
}
|
||||
|
||||
if (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1) {
|
||||
/*
|
||||
* Check for overflow when flag is assigned to the
|
||||
* 4 byte unsigned int variable
|
||||
*/
|
||||
validValues.add(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE.toString());
|
||||
}
|
||||
|
||||
return validValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected List<String> getInvalidValues() {
|
||||
List<String> invalidValues = new ArrayList<>();
|
||||
|
||||
if (withRange) {
|
||||
/* Return invalid values only for options which have defined range in VM */
|
||||
if ((is32Bit && min.compareTo(MIN_4_BYTE_INT) != 0)
|
||||
|| (!is32Bit && min.compareTo(MIN_LONG) != 0)) {
|
||||
invalidValues.add(min.subtract(BigInteger.ONE).toString());
|
||||
}
|
||||
|
||||
if (!unsigned
|
||||
&& ((is32Bit && (max.compareTo(MAX_4_BYTE_INT) != 0))
|
||||
|| (!is32Bit && (max.compareTo(MAX_LONG) != 0)))) {
|
||||
invalidValues.add(max.add(BigInteger.ONE).toString());
|
||||
}
|
||||
|
||||
if (unsigned
|
||||
&& ((is32Bit && (max.compareTo(MAX_4_BYTE_UNSIGNED_INT) != 0))
|
||||
|| (!is32Bit && !uint64 && (max.compareTo(MAX_UNSIGNED_LONG) != 0))
|
||||
|| (uint64 && (max.compareTo(MAX_UNSIGNED_LONG_64) != 0)))) {
|
||||
invalidValues.add(max.add(BigInteger.ONE).toString());
|
||||
}
|
||||
}
|
||||
|
||||
return invalidValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
protected String getErrorMessageCommandLine(String value) {
|
||||
String errorMsg;
|
||||
|
||||
if (withRange) {
|
||||
/* Option have defined range in VM */
|
||||
if (unsigned && ((new BigInteger(value)).compareTo(BigInteger.ZERO) < 0)) {
|
||||
/*
|
||||
* Special case for unsigned options with lower range equal to 0. If
|
||||
* passed value is negative then error will be caught earlier for
|
||||
* such options. Thus use different error message.
|
||||
*/
|
||||
errorMsg = String.format("Improperly specified VM option '%s=%s'", name, value);
|
||||
} else {
|
||||
errorMsg = String.format("%s %s=%s is outside the allowed range [ %s ... %s ]",
|
||||
type, name, value, min.toString(), max.toString());
|
||||
}
|
||||
} else {
|
||||
errorMsg = "";
|
||||
}
|
||||
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
477
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
Normal file
477
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.List;
|
||||
import jdk.test.lib.DynamicVMOption;
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.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.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;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
withRange = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 value = optionValue.substring(optionValue.lastIndexOf("=") + 1);
|
||||
String fullOptionString = prependString.toString() + optionValue;
|
||||
List<String> runJava = new ArrayList<>();
|
||||
OutputAnalyzer out;
|
||||
|
||||
if (VMType != null) {
|
||||
runJava.add(VMType);
|
||||
}
|
||||
runJava.addAll(prepend);
|
||||
runJava.add(optionValue);
|
||||
runJava.add(JVMOptionsUtils.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 */
|
||||
failedMessage(name, fullOptionString, valid, "JVM output reports a fatal error. JVM exited with code " + exitCode + "!");
|
||||
printOutputContent(out);
|
||||
result = false;
|
||||
} else if (valid == true) {
|
||||
if ((exitCode != 0) && (exitCode != 1)) {
|
||||
failedMessage(name, fullOptionString, valid, "JVM exited with unexpected error code = " + exitCode);
|
||||
printOutputContent(out);
|
||||
result = false;
|
||||
} else if ((exitCode == 1) && (out.getOutput().isEmpty() == true)) {
|
||||
failedMessage(name, fullOptionString, valid, "JVM exited with error(exitcode == 1)"
|
||||
+ ", but with empty stdout and stderr. Description of error is needed!");
|
||||
result = false;
|
||||
} else if (out.getOutput().contains("is outside the allowed range")) {
|
||||
failedMessage(name, fullOptionString, valid, "JVM output contains \"is outside the allowed range\"");
|
||||
printOutputContent(out);
|
||||
result = false;
|
||||
}
|
||||
} else {
|
||||
// valid == false
|
||||
if (exitCode == 0) {
|
||||
failedMessage(name, fullOptionString, valid, "JVM successfully exit");
|
||||
result = false;
|
||||
} else if (exitCode != 1) {
|
||||
failedMessage(name, fullOptionString, valid, "JVM exited with code "
|
||||
+ exitCode + " which not equal to 1");
|
||||
result = false;
|
||||
} else if (!out.getOutput().contains(getErrorMessageCommandLine(value))) {
|
||||
failedMessage(name, fullOptionString, valid, "JVM output does not contain "
|
||||
+ "expected output \"" + getErrorMessageCommandLine(value) + "\"");
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
450
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java
Normal file
450
hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java
Normal file
@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.function.Predicate;
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.ProcessTools;
|
||||
|
||||
public class JVMOptionsUtils {
|
||||
|
||||
/* Java option which print options with ranges */
|
||||
private static final String PRINT_FLAGS_RANGES = "-XX:+PrintFlagsRanges";
|
||||
|
||||
/* StringBuilder to accumulate failed message */
|
||||
private static final StringBuilder finalFailedMessage = new StringBuilder();
|
||||
|
||||
/* Used to start the JVM with the same type as current */
|
||||
static String VMType;
|
||||
|
||||
static {
|
||||
if (Platform.isServer()) {
|
||||
VMType = "-server";
|
||||
} else if (Platform.isClient()) {
|
||||
VMType = "-client";
|
||||
} else if (Platform.isMinimal()) {
|
||||
VMType = "-minimal";
|
||||
} else if (Platform.isGraal()) {
|
||||
VMType = "-graal";
|
||||
} else {
|
||||
VMType = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add dependency for option depending on it's name. E.g. enable G1 GC for
|
||||
* G1 options or add prepend options to not hit constraints.
|
||||
*
|
||||
* @param option option
|
||||
*/
|
||||
private static void addNameDependency(JVMOption option) {
|
||||
String name = option.getName();
|
||||
|
||||
if (name.startsWith("G1")) {
|
||||
option.addPrepend("-XX:+UseG1GC");
|
||||
}
|
||||
|
||||
if (name.startsWith("CMS")) {
|
||||
option.addPrepend("-XX:+UseConcMarkSweepGC");
|
||||
}
|
||||
|
||||
switch (name) {
|
||||
case "MinHeapFreeRatio":
|
||||
option.addPrepend("-XX:MaxHeapFreeRatio=100");
|
||||
break;
|
||||
case "MaxHeapFreeRatio":
|
||||
option.addPrepend("-XX:MinHeapFreeRatio=0");
|
||||
break;
|
||||
case "MinMetaspaceFreeRatio":
|
||||
option.addPrepend("-XX:MaxMetaspaceFreeRatio=100");
|
||||
break;
|
||||
case "MaxMetaspaceFreeRatio":
|
||||
option.addPrepend("-XX:MinMetaspaceFreeRatio=0");
|
||||
break;
|
||||
case "CMSOldPLABMin":
|
||||
option.addPrepend("-XX:CMSOldPLABMax=" + option.getMax());
|
||||
break;
|
||||
case "CMSOldPLABMax":
|
||||
option.addPrepend("-XX:CMSOldPLABMin=" + option.getMin());
|
||||
break;
|
||||
case "CMSPrecleanNumerator":
|
||||
option.addPrepend("-XX:CMSPrecleanDenominator=" + option.getMax());
|
||||
break;
|
||||
case "CMSPrecleanDenominator":
|
||||
option.addPrepend("-XX:CMSPrecleanNumerator=" + ((new Integer(option.getMin())) - 1));
|
||||
break;
|
||||
case "InitialTenuringThreshold":
|
||||
option.addPrepend("-XX:MaxTenuringThreshold=" + option.getMax());
|
||||
break;
|
||||
default:
|
||||
/* Do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add dependency for option depending on it's type. E.g. run the JVM in
|
||||
* compilation mode for compiler options.
|
||||
*
|
||||
* @param option option
|
||||
* @param type type of the option
|
||||
*/
|
||||
private static void addTypeDependency(JVMOption option, String type) {
|
||||
if (type.contains("C1") || type.contains("C2")) {
|
||||
/* Run in compiler mode for compiler flags */
|
||||
option.addPrepend("-Xcomp");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JVM Options. Get input from "inputReader". Parse using
|
||||
* "-XX:+PrintFlagsRanges" output format.
|
||||
*
|
||||
* @param inputReader input data for parsing
|
||||
* @param withRanges true if needed options with defined ranges inside JVM
|
||||
* @param acceptOrigin predicate for option origins. Origins can be
|
||||
* "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
|
||||
* to true.
|
||||
* @return map from option name to the JVMOption object
|
||||
* @throws IOException if an error occurred while reading the data
|
||||
*/
|
||||
private static Map<String, JVMOption> getJVMOptions(Reader inputReader,
|
||||
boolean withRanges, Predicate<String> acceptOrigin) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(inputReader);
|
||||
String type;
|
||||
String line;
|
||||
String token;
|
||||
String name;
|
||||
StringTokenizer st;
|
||||
JVMOption option;
|
||||
Map<String, JVMOption> allOptions = new LinkedHashMap<>();
|
||||
|
||||
// Skip first line
|
||||
line = reader.readLine();
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
/*
|
||||
* Parse option from following line:
|
||||
* <type> <name> [ <min, optional> ... <max, optional> ] {<origin>}
|
||||
*/
|
||||
st = new StringTokenizer(line);
|
||||
|
||||
type = st.nextToken();
|
||||
|
||||
name = st.nextToken();
|
||||
|
||||
option = JVMOption.createVMOption(type, name);
|
||||
|
||||
/* Skip '[' */
|
||||
token = st.nextToken();
|
||||
|
||||
/* Read min range or "..." if range is absent */
|
||||
token = st.nextToken();
|
||||
|
||||
if (token.equals("...") == false) {
|
||||
if (!withRanges) {
|
||||
/*
|
||||
* Option have range, but asked for options without
|
||||
* ranges => skip it
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Mark this option as option which range is defined in VM */
|
||||
option.optionWithRange();
|
||||
|
||||
option.setMin(token);
|
||||
|
||||
/* Read "..." and skip it */
|
||||
token = st.nextToken();
|
||||
|
||||
/* Get max value */
|
||||
token = st.nextToken();
|
||||
option.setMax(token);
|
||||
} else if (withRanges) {
|
||||
/*
|
||||
* Option not have range, but asked for options with
|
||||
* ranges => skip it
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip ']' */
|
||||
token = st.nextToken();
|
||||
|
||||
/* Read origin of the option */
|
||||
token = st.nextToken();
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
token += st.nextToken();
|
||||
};
|
||||
token = token.substring(1, token.indexOf("}"));
|
||||
|
||||
if (acceptOrigin.test(token)) {
|
||||
addTypeDependency(option, token);
|
||||
addNameDependency(option);
|
||||
|
||||
allOptions.put(name, option);
|
||||
}
|
||||
}
|
||||
|
||||
return allOptions;
|
||||
}
|
||||
|
||||
static void failedMessage(String optionName, String value, boolean valid, String message) {
|
||||
String temp;
|
||||
|
||||
if (valid) {
|
||||
temp = "valid";
|
||||
} else {
|
||||
temp = "invalid";
|
||||
}
|
||||
|
||||
failedMessage(String.format("Error processing option %s with %s value '%s'! %s",
|
||||
optionName, temp, value, message));
|
||||
}
|
||||
|
||||
static void failedMessage(String message) {
|
||||
System.err.println("TEST FAILED: " + message);
|
||||
finalFailedMessage.append(String.format("(%s)%n", message));
|
||||
}
|
||||
|
||||
static void printOutputContent(OutputAnalyzer output) {
|
||||
System.err.println(String.format("stdout content[%s]", output.getStdout()));
|
||||
System.err.println(String.format("stderr content[%s]%n", output.getStderr()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string with accumulated failure messages
|
||||
*
|
||||
* @return string with accumulated failure messages
|
||||
*/
|
||||
public static String getMessageWithFailures() {
|
||||
return finalFailedMessage.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run command line tests for options passed in the list
|
||||
*
|
||||
* @param options list of options to test
|
||||
* @return number of failed tests
|
||||
* @throws Exception if java process can not be started
|
||||
*/
|
||||
public static int runCommandLineTests(List<? extends JVMOption> options) throws Exception {
|
||||
int failed = 0;
|
||||
|
||||
for (JVMOption option : options) {
|
||||
failed += option.testCommandLine();
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test passed options using DynamicVMOption isValidValue and isInvalidValue
|
||||
* methods. Only tests writeable options.
|
||||
*
|
||||
* @param options list of options to test
|
||||
* @return number of failed tests
|
||||
*/
|
||||
public static int runDynamicTests(List<? extends JVMOption> options) {
|
||||
int failed = 0;
|
||||
|
||||
for (JVMOption option : options) {
|
||||
failed += option.testDynamic();
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test passed options using Jcmd. Only tests writeable options.
|
||||
*
|
||||
* @param options list of options to test
|
||||
* @return number of failed tests
|
||||
*/
|
||||
public static int runJcmdTests(List<? extends JVMOption> options) {
|
||||
int failed = 0;
|
||||
|
||||
for (JVMOption option : options) {
|
||||
failed += option.testJcmd();
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test passed option using attach method. Only tests writeable options.
|
||||
*
|
||||
* @param options list of options to test
|
||||
* @return number of failed tests
|
||||
* @throws Exception if an error occurred while attaching to the target JVM
|
||||
*/
|
||||
public static int runAttachTests(List<? extends JVMOption> options) throws Exception {
|
||||
int failed = 0;
|
||||
|
||||
for (JVMOption option : options) {
|
||||
failed += option.testAttach();
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM options as map. Can return options with defined ranges or options
|
||||
* without range depending on "withRanges" argument. "acceptOrigin"
|
||||
* predicate can be used to filter option origin.
|
||||
*
|
||||
* @param withRanges true if needed options with defined ranges inside JVM
|
||||
* @param acceptOrigin predicate for option origins. Origins can be
|
||||
* "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
|
||||
* to true.
|
||||
* @param additionalArgs additional arguments to the Java process which ran
|
||||
* with "-XX:+PrintFlagsRanges"
|
||||
* @return map from option name to the JVMOption object
|
||||
* @throws Exception if a new process can not be created or an error
|
||||
* occurred while reading the data
|
||||
*/
|
||||
public static Map<String, JVMOption> getOptionsAsMap(boolean withRanges, Predicate<String> acceptOrigin,
|
||||
String... additionalArgs) throws Exception {
|
||||
Map<String, JVMOption> result;
|
||||
Process p;
|
||||
List<String> runJava = new ArrayList<>();
|
||||
|
||||
if (additionalArgs.length > 0) {
|
||||
runJava.addAll(Arrays.asList(additionalArgs));
|
||||
}
|
||||
|
||||
if (VMType != null) {
|
||||
runJava.add(VMType);
|
||||
}
|
||||
runJava.add(PRINT_FLAGS_RANGES);
|
||||
runJava.add("-version");
|
||||
|
||||
p = ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start();
|
||||
|
||||
result = getJVMOptions(new InputStreamReader(p.getInputStream()), withRanges, acceptOrigin);
|
||||
|
||||
p.waitFor();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM options as list. Can return options with defined ranges or
|
||||
* options without range depending on "withRanges" argument. "acceptOrigin"
|
||||
* predicate can be used to filter option origin.
|
||||
*
|
||||
* @param withRanges true if needed options with defined ranges inside JVM
|
||||
* @param acceptOrigin predicate for option origins. Origins can be
|
||||
* "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
|
||||
* to true.
|
||||
* @param additionalArgs additional arguments to the Java process which ran
|
||||
* with "-XX:+PrintFlagsRanges"
|
||||
* @return List of options
|
||||
* @throws Exception if a new process can not be created or an error
|
||||
* occurred while reading the data
|
||||
*/
|
||||
public static List<JVMOption> getOptions(boolean withRanges, Predicate<String> acceptOrigin,
|
||||
String... additionalArgs) throws Exception {
|
||||
return new ArrayList<>(getOptionsAsMap(withRanges, acceptOrigin, additionalArgs).values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM options with ranges as list. "acceptOrigin" predicate can be used
|
||||
* to filter option origin.
|
||||
*
|
||||
* @param acceptOrigin predicate for option origins. Origins can be
|
||||
* "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
|
||||
* to true.
|
||||
* @param additionalArgs additional arguments to the Java process which ran
|
||||
* with "-XX:+PrintFlagsRanges"
|
||||
* @return List of options
|
||||
* @throws Exception if a new process can not be created or an error
|
||||
* occurred while reading the data
|
||||
*/
|
||||
public static List<JVMOption> getOptionsWithRange(Predicate<String> acceptOrigin, String... additionalArgs) throws Exception {
|
||||
return getOptions(true, acceptOrigin, additionalArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM options with ranges as list.
|
||||
*
|
||||
* @param additionalArgs additional arguments to the Java process which ran
|
||||
* with "-XX:+PrintFlagsRanges"
|
||||
* @return list of options
|
||||
* @throws Exception if a new process can not be created or an error
|
||||
* occurred while reading the data
|
||||
*/
|
||||
public static List<JVMOption> getOptionsWithRange(String... additionalArgs) throws Exception {
|
||||
return getOptionsWithRange(origin -> true, additionalArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM options with range as map. "acceptOrigin" predicate can be used
|
||||
* to filter option origin.
|
||||
*
|
||||
* @param acceptOrigin predicate for option origins. Origins can be
|
||||
* "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
|
||||
* to true.
|
||||
* @param additionalArgs additional arguments to the Java process which ran
|
||||
* with "-XX:+PrintFlagsRanges"
|
||||
* @return Map from option name to the JVMOption object
|
||||
* @throws Exception if a new process can not be created or an error
|
||||
* occurred while reading the data
|
||||
*/
|
||||
public static Map<String, JVMOption> getOptionsWithRangeAsMap(Predicate<String> acceptOrigin, String... additionalArgs) throws Exception {
|
||||
return getOptionsAsMap(true, acceptOrigin, additionalArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JVM options with range as map
|
||||
*
|
||||
* @param additionalArgs additional arguments to the Java process which ran
|
||||
* with "-XX:+PrintFlagsRanges"
|
||||
* @return map from option name to the JVMOption object
|
||||
* @throws Exception if a new process can not be created or an error
|
||||
* occurred while reading the data
|
||||
*/
|
||||
public static Map<String, JVMOption> getOptionsWithRangeAsMap(String... additionalArgs) throws Exception {
|
||||
return getOptionsWithRangeAsMap(origin -> true, additionalArgs);
|
||||
}
|
||||
|
||||
/* Simple method to test that java start-up. Used for testing options. */
|
||||
public static void main(String[] args) {
|
||||
System.out.print("Java start-up!");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user