47bc94b60e
Reviewed-by: kvn, ihse, sspitsyn
508 lines
18 KiB
Java
508 lines
18 KiB
Java
/*
|
|
* Copyright (c) 2003, 2018, 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 nsk.monitoring.share;
|
|
|
|
import nsk.share.log.Log;
|
|
import nsk.share.TestBug;
|
|
import nsk.share.ArgumentParser;
|
|
import java.lang.management.*;
|
|
|
|
/**
|
|
* Parser for JSR-174 test's arguments.
|
|
* <p>
|
|
* <code>ArgumentHandler</code> handles specific command line arguments
|
|
* related to way of execution of a test in addition to general arguments
|
|
* recognized by {@link ArgumentParser <code>ArgumentParser</code>}.
|
|
* <p>
|
|
* Following is the list of specific options for <code>ArgumentHandler</code>:
|
|
* <ul>
|
|
* <li><code>-testMode="<i>value</i>"</code>, where <i>value</i> may take
|
|
* one of the following values: <code>directly</code> -- to call methods in
|
|
* the MBean directly within the same JVM, <code>server</code> -- to call
|
|
* methods through MBeanServer, <code>proxy</code> -- to call methods
|
|
* through MBean proxy (not yet implemented).
|
|
* <li><code>-MBeanServer="<i>value</i>"</code>, where <i>value</i> may take
|
|
* one of the following values: <code>default</code> -- to execute test for
|
|
* default JMX implementation of MBeanServer or <code>custom</code> -- for
|
|
* implementation provided by NSK J2SE SQE Team.
|
|
* <li><code>-loadableClassCount=<i>value</i></code>, where <i>value</i> defines
|
|
* amount of loadable classes. Default values is <code>100</code>.
|
|
* <li><code>-loadersCount=<i>value</i></code>, where <i>value</i> defines
|
|
* amount of class loaders. Default values is <code>100</code>.
|
|
* <li><code>-singleClassloaderClass</code> specifies whether class loaders are
|
|
* instances of the same class.
|
|
* <li><code>-memory="<i>value</i>"</code>, where <i>value</i> may take
|
|
* one of the following values: <code>heap</code> -- to test heap memory,
|
|
* <code>nonheap</code> to test nonheap memory, <code>mixed</code> -- to
|
|
* test both heap and nonheap memory.
|
|
* <li><code>-invocationType="<i>value</i>"</code>, where <i>value</i> may take
|
|
* one of the following values: <code>java</code> -- to start java threads,
|
|
* <code>native</code> -- to start native threads, <code>mixed</code> -- to
|
|
* both java and native threads.
|
|
* <li><code>-monitoring="<i>value</i>"</code>, where <i>value</i> may take
|
|
* one of the following values: <code>polling</code> -- to start polling
|
|
* mechanism of monitoring, <code>notification</code> -- to start
|
|
* notification mechanism of monitoring.
|
|
* <li><code>-threshold="<i>value</i>"</code>, where <i>value</i> may take
|
|
* one of the following values: <code>usage</code> -- to test usage
|
|
* thresholds, <code>collection</code> -- to test collection usage
|
|
* thresholds.
|
|
* <li><code>-depth=<i>value</i></code>, where <i>value</i> defines
|
|
* depth of recursion. Default values is <code>1</code>.
|
|
* <li><code>-threadCount=<i>value</i></code>, where <i>value</i> defines
|
|
* number of threads to start. Default values is <code>1</code>.
|
|
* <li><code>-timeout=<i>value</i></code>, where <i>value</i> defines
|
|
* number of minutes to run the test.
|
|
* </ul>
|
|
* <p>
|
|
* See also list of basic options recognized by <code>ArgumentParser</code>.
|
|
* <p>
|
|
* See also comments to <code>ArgumentParser</code> how to work with
|
|
* command line arguments and options.
|
|
*
|
|
* @see ArgumentParser
|
|
*/
|
|
public class ArgumentHandler extends ArgumentParser {
|
|
static final String TEST_MODE = "testMode";
|
|
static final String DIRECTLY_MODE = "directly";
|
|
static final String SERVER_MODE = "server";
|
|
static final String PROXY_MODE = "proxy";
|
|
|
|
static final String SERVER_TYPE = "MBeanServer";
|
|
static final String DEFAULT_TYPE = "default";
|
|
static final String CUSTOM_TYPE = "custom";
|
|
|
|
static final String LOADABLE_CLASSES_COUNT = "loadableClassCount";
|
|
static final String LOADERS_COUNT = "loadersCount";
|
|
static final String SINGLE_CLASSLOADER_CLASS = "singleClassloaderClass";
|
|
|
|
static final String MEMORY_TYPE = "memory";
|
|
static final String MT_HEAP = "heap";
|
|
static final String MT_NONHEAP = "nonheap";
|
|
static final String MT_MIXED = "mixed";
|
|
|
|
static final String INVOCATION_TYPE = "invocationType";
|
|
static final String JAVA_TYPE = "java";
|
|
static final String NATIVE_TYPE = "native";
|
|
static final String MIXED_TYPE = "mixed";
|
|
|
|
static final String MONITORING = "monitoring";
|
|
static final String MON_POLLING = "polling";
|
|
static final String MON_NOTIF = "notification";
|
|
|
|
static final String THRESHOLD = "threshold";
|
|
static final String TH_USAGE = "usage";
|
|
static final String TH_COLLECTION = "collection";
|
|
|
|
static final String THREAD_DEPTH = "depth";
|
|
static final String THREAD_COUNT = "threadCount";
|
|
static final String TIMEOUT = "timeout";
|
|
|
|
static final String SCENARIO_TYPE = "scenarioType";
|
|
|
|
static final String ITERATIONS = "iterations";
|
|
|
|
/**
|
|
* Keep a copy of raw command-line arguments and parse them;
|
|
* but throw an exception on parsing error.
|
|
*
|
|
* @param args Array of the raw command-line arguments.
|
|
*
|
|
* @throws BadOption If unknown option or illegal
|
|
* option value found
|
|
*
|
|
* @see ArgumentParser
|
|
*/
|
|
public ArgumentHandler(String args[]) {
|
|
super(args);
|
|
}
|
|
|
|
/**
|
|
* Returns the test mode.
|
|
* <p>
|
|
* To access the metrics directly, <code>testMode</code> option should
|
|
* be defined in command line <code>-testMode="directly"</code>.
|
|
* To access the metrics via MBeanServer, <code>"server"</code> should be
|
|
* assigned to <code>-testMode="directly"</code>.
|
|
* <p>
|
|
* If <code>testMode</code> is not defined by command line, a test is
|
|
* executed in <code>directly</code> mode.
|
|
*
|
|
* @return name of test mode.
|
|
*
|
|
*/
|
|
public String getTestMode() {
|
|
return options.getProperty(TEST_MODE, DIRECTLY_MODE);
|
|
}
|
|
|
|
/**
|
|
* Returns a type of MBean server if any.
|
|
* Two kinds of MBean servers are allowed: default and custom servers.
|
|
* Default server is an implementation of {@link
|
|
* javax.management.MBeanServer <tt>javax.management.MBeanServer</tt>}
|
|
* interface provided by JMX. Custom server is an implementation provided
|
|
* by NSK J2SE SQE Team. Server type is defined by <tt>MBeanServer</tt>
|
|
* key in command line <code>-MBeanServer="default"</code> or
|
|
* <code>-MBeanServer="custom"</code>
|
|
*
|
|
* @return <i>MBeanServer</i> server type.
|
|
*
|
|
*/
|
|
public String getServerType() {
|
|
return options.getProperty(SERVER_TYPE, DEFAULT_TYPE);
|
|
}
|
|
|
|
/**
|
|
* Returns <i>true</i> if default implementation is used.
|
|
*
|
|
* @return <i>true</i> if default implementation is used.
|
|
*
|
|
* @see #getServerType()
|
|
*/
|
|
public boolean isDefaultServer() {
|
|
return getServerType().equals(DEFAULT_TYPE);
|
|
}
|
|
|
|
/**
|
|
* Returns amount of class loaders.
|
|
*
|
|
* @return <i>loadersCount</i> as an integer value
|
|
*/
|
|
public int getLoadersCount() {
|
|
String val = options.getProperty(LOADERS_COUNT, "100");
|
|
int number;
|
|
try {
|
|
number = Integer.parseInt(val);
|
|
} catch (NumberFormatException e) {
|
|
throw new TestBug("Not integer value of \"" + LOADERS_COUNT
|
|
+ "\" argument: " + val);
|
|
}
|
|
return number;
|
|
}
|
|
|
|
/**
|
|
* Returns <i>true</i> if class loaders, which perform class loading, are
|
|
* instances of the same class. If <code>-singleClassloaderClass</code> key
|
|
* is not set in command line options, then <i>false</i> is returned.
|
|
*
|
|
* @return if class loaders are instances of the same class.
|
|
*
|
|
*/
|
|
public boolean singleClassloaderClass() {
|
|
return options.getProperty(SINGLE_CLASSLOADER_CLASS) != null;
|
|
}
|
|
|
|
/**
|
|
* Returns amount of loadable classes. If <code>-loadableClassesCount</code>
|
|
* key is not set with command line, <code>100</code> is returned.
|
|
*
|
|
* @return <i>loadableClassesCount</i> as an integer value
|
|
*
|
|
* @throws TestBug <i>loadableClassesCount</i> is non-numeric value.
|
|
*
|
|
*/
|
|
public int getLoadableClassesCount() {
|
|
String val = options.getProperty(LOADABLE_CLASSES_COUNT, "1");
|
|
int number;
|
|
try {
|
|
number = Integer.parseInt(val);
|
|
} catch (NumberFormatException e) {
|
|
throw new TestBug("Not integer value of \"" + LOADABLE_CLASSES_COUNT
|
|
+ "\" argument: " + val);
|
|
}
|
|
return number;
|
|
}
|
|
|
|
/**
|
|
* Returns invocation type.
|
|
*
|
|
* @return <i>invocationType</i> value
|
|
*
|
|
*/
|
|
public String getInvocationType() {
|
|
return options.getProperty(INVOCATION_TYPE, JAVA_TYPE);
|
|
}
|
|
|
|
/**
|
|
* Returns tested memory type.
|
|
*
|
|
* @return <i>memory</i> value
|
|
*
|
|
*/
|
|
public String getTestedMemory() {
|
|
return options.getProperty(MEMORY_TYPE, MT_HEAP);
|
|
}
|
|
|
|
/**
|
|
* Returns timeout.
|
|
*
|
|
* @return <i>timeout</i> value
|
|
*
|
|
*/
|
|
public int getTimeout() {
|
|
String value = options.getProperty(TIMEOUT, "30");
|
|
|
|
try {
|
|
return Integer.parseInt(value);
|
|
} catch (NumberFormatException e) {
|
|
throw new TestBug("Not integer value of \"" + TIMEOUT
|
|
+ "\" argument: " + value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns recursion depth.
|
|
*
|
|
* @return <i>depth</i> value
|
|
*
|
|
*/
|
|
public int getThreadDepth() {
|
|
String value = options.getProperty(THREAD_DEPTH, "1");
|
|
|
|
try {
|
|
return Integer.parseInt(value);
|
|
} catch (NumberFormatException e) {
|
|
throw new TestBug("Not integer value of \"" + THREAD_DEPTH
|
|
+ "\" argument: " + value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns number of threads.
|
|
*
|
|
* @return <i>threadCount</i> value
|
|
*
|
|
*/
|
|
public int getThreadCount() {
|
|
String value = options.getProperty(THREAD_COUNT, "1");
|
|
|
|
try {
|
|
return Integer.parseInt(value);
|
|
} catch (NumberFormatException e) {
|
|
throw new TestBug("Not integer value of \"" + THREAD_COUNT
|
|
+ "\" argument: " + value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns type of monitoring.
|
|
*
|
|
* @return <i>monitoring</i> value
|
|
*
|
|
*/
|
|
public String getMonitoring() {
|
|
return options.getProperty(MONITORING, MON_NOTIF);
|
|
}
|
|
|
|
/**
|
|
* Returns type of threshold.
|
|
*
|
|
* @return <i>threshold</i> value
|
|
*
|
|
*/
|
|
public String getThreshold() {
|
|
return options.getProperty(THRESHOLD, TH_USAGE);
|
|
}
|
|
|
|
/**
|
|
* Returns thread type to create.
|
|
*/
|
|
public String getScenarioType() {
|
|
return options.getProperty(SCENARIO_TYPE, "running");
|
|
}
|
|
|
|
public int getIterations() {
|
|
return Integer.parseInt(options.getProperty(ITERATIONS, "3"));
|
|
}
|
|
|
|
/**
|
|
* Checks if an option is allowed and has proper value.
|
|
* This method is invoked by <code>parseArguments()</code>
|
|
*
|
|
* @param option option name
|
|
* @param value string representation of value
|
|
* (could be an empty string too)
|
|
* null if this option has no value
|
|
* @return <i>true</i> if option is allowed and has proper value
|
|
* <i>false</i> if otion is not admissible
|
|
*
|
|
* @throws <i>BadOption</i> if option has an illegal value
|
|
*
|
|
* @see nsk.share.ArgumentParser#parseArguments
|
|
*/
|
|
protected boolean checkOption(String option, String value) {
|
|
|
|
// defines directly, server or proxytest mode
|
|
if (option.equals(TEST_MODE)) {
|
|
if ( (!value.equals(DIRECTLY_MODE)) &&
|
|
(!value.equals(SERVER_MODE)) &&
|
|
(!value.equals(PROXY_MODE))
|
|
) {
|
|
throw new BadOption(option + ": must be one of: "
|
|
+ "\"" + DIRECTLY_MODE + "\", "
|
|
+ "\"" + SERVER_MODE + "\", "
|
|
+ "\"" + PROXY_MODE + "\"");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// defines invocation type for stack filling
|
|
if (option.equals(INVOCATION_TYPE)) {
|
|
if ( (!value.equals(JAVA_TYPE)) &&
|
|
(!value.equals(NATIVE_TYPE)) &&
|
|
(!value.equals(MIXED_TYPE))
|
|
) {
|
|
throw new BadOption(option + ": must be one of: "
|
|
+ "\"" + JAVA_TYPE + "\", "
|
|
+ "\"" + NATIVE_TYPE + "\", "
|
|
+ "\"" + MIXED_TYPE + "\"");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// defines default or custom MBean server
|
|
if (option.equals(SERVER_TYPE)) {
|
|
if ((!value.equals(DEFAULT_TYPE))
|
|
&& (!value.equals(CUSTOM_TYPE))) {
|
|
throw new BadOption(option + ": must be one of: \""
|
|
+ DEFAULT_TYPE + "\", \""
|
|
+ CUSTOM_TYPE + "\"");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// defines loadable classes and loaders counts
|
|
if (option.equals(LOADABLE_CLASSES_COUNT) ||
|
|
option.equals(LOADERS_COUNT) ||
|
|
option.equals(THREAD_DEPTH) || option.equals(THREAD_COUNT)) {
|
|
try {
|
|
int number = Integer.parseInt(value);
|
|
if (number < 0) {
|
|
throw new BadOption(option + ": value must be a positive "
|
|
+ "integer");
|
|
}
|
|
} catch (NumberFormatException e) {
|
|
throw new BadOption(option + ": value must be an integer");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// defines timeout
|
|
if (option.equals(TIMEOUT)) {
|
|
try {
|
|
int number = Integer.parseInt(value);
|
|
|
|
if (number < 0)
|
|
throw new BadOption(option + ": value must be a positive "
|
|
+ "integer");
|
|
} catch (NumberFormatException e) {
|
|
throw new BadOption(option + ": value must be an integer");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// defines if classloader class is single
|
|
if (option.equals(SINGLE_CLASSLOADER_CLASS)) {
|
|
if (!(value == null || value.length() <= 0)) {
|
|
throw new BadOption(option + ": no value must be specified");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// defines memory types
|
|
if (option.equals(MEMORY_TYPE)) {
|
|
if ( (!value.equals(MT_HEAP)) &&
|
|
(!value.equals(MT_NONHEAP)) &&
|
|
(!value.equals(MT_MIXED))
|
|
)
|
|
throw new BadOption(option + ": must be one of: "
|
|
+ "\"" + MT_HEAP + "\", "
|
|
+ "\"" + MT_NONHEAP + "\", "
|
|
+ "\"" + MT_MIXED + "\"");
|
|
return true;
|
|
}
|
|
|
|
// defines type of monitoring
|
|
if (option.equals(MONITORING)) {
|
|
if ( (!value.equals(MON_POLLING)) &&
|
|
(!value.equals(MON_NOTIF))
|
|
)
|
|
throw new BadOption(option + ": must be one of: "
|
|
+ "\"" + MON_POLLING + "\", "
|
|
+ "\"" + MON_NOTIF + "\"");
|
|
return true;
|
|
}
|
|
|
|
// defines threshold
|
|
if (option.equals(THRESHOLD)) {
|
|
if ( (!value.equals(TH_USAGE)) &&
|
|
(!value.equals(TH_COLLECTION))
|
|
)
|
|
throw new BadOption(option + ": must be one of: "
|
|
+ "\"" + TH_USAGE + "\", "
|
|
+ "\"" + TH_COLLECTION + "\"");
|
|
return true;
|
|
}
|
|
|
|
if (option.equals(SCENARIO_TYPE)) {
|
|
return true;
|
|
}
|
|
if (option.equals(ITERATIONS)) {
|
|
try {
|
|
int number = Integer.parseInt(value);
|
|
|
|
if (number < 0)
|
|
throw new BadOption(option + ": value must be a positive "
|
|
+ "integer");
|
|
return true;
|
|
} catch (NumberFormatException e) {
|
|
throw new BadOption(option + ": value must be an integer");
|
|
}
|
|
|
|
}
|
|
return super.checkOption(option, value);
|
|
}
|
|
|
|
/**
|
|
* Check if the values of all options are consistent.
|
|
* This method is invoked by <code>parseArguments()</code>
|
|
*
|
|
* @throws <i>BadOption</i> if options have inconsistent values
|
|
*
|
|
* @see nsk.share.ArgumentParser#parseArguments
|
|
*/
|
|
protected void checkOptions() {
|
|
super.checkOptions();
|
|
}
|
|
|
|
public void dump(Log log) {
|
|
log.info("Test mode: " + getTestMode());
|
|
log.info("Server type: " + getServerType());
|
|
log.info("loadableClassesCount: " + getLoadableClassesCount());
|
|
log.info("loadersCount: " + getLoadersCount());
|
|
log.info("singleClassloaderClass: " + singleClassloaderClass());
|
|
}
|
|
} // ArgumentHandler
|