Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ArgumentHandler.java
40948 views
/*1* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package nsk.monitoring.share;2425import nsk.share.log.Log;26import nsk.share.TestBug;27import nsk.share.ArgumentParser;28import java.lang.management.*;2930/**31* Parser for JSR-174 test's arguments.32* <p>33* <code>ArgumentHandler</code> handles specific command line arguments34* related to way of execution of a test in addition to general arguments35* recognized by {@link ArgumentParser <code>ArgumentParser</code>}.36* <p>37* Following is the list of specific options for <code>ArgumentHandler</code>:38* <ul>39* <li><code>-testMode="<i>value</i>"</code>, where <i>value</i> may take40* one of the following values: <code>directly</code> -- to call methods in41* the MBean directly within the same JVM, <code>server</code> -- to call42* methods through MBeanServer, <code>proxy</code> -- to call methods43* through MBean proxy (not yet implemented).44* <li><code>-MBeanServer="<i>value</i>"</code>, where <i>value</i> may take45* one of the following values: <code>default</code> -- to execute test for46* default JMX implementation of MBeanServer or <code>custom</code> -- for47* implementation provided by NSK J2SE SQE Team.48* <li><code>-loadableClassCount=<i>value</i></code>, where <i>value</i> defines49* amount of loadable classes. Default values is <code>100</code>.50* <li><code>-loadersCount=<i>value</i></code>, where <i>value</i> defines51* amount of class loaders. Default values is <code>100</code>.52* <li><code>-singleClassloaderClass</code> specifies whether class loaders are53* instances of the same class.54* <li><code>-memory="<i>value</i>"</code>, where <i>value</i> may take55* one of the following values: <code>heap</code> -- to test heap memory,56* <code>nonheap</code> to test nonheap memory, <code>mixed</code> -- to57* test both heap and nonheap memory.58* <li><code>-invocationType="<i>value</i>"</code>, where <i>value</i> may take59* one of the following values: <code>java</code> -- to start java threads,60* <code>native</code> -- to start native threads, <code>mixed</code> -- to61* both java and native threads.62* <li><code>-monitoring="<i>value</i>"</code>, where <i>value</i> may take63* one of the following values: <code>polling</code> -- to start polling64* mechanism of monitoring, <code>notification</code> -- to start65* notification mechanism of monitoring.66* <li><code>-threshold="<i>value</i>"</code>, where <i>value</i> may take67* one of the following values: <code>usage</code> -- to test usage68* thresholds, <code>collection</code> -- to test collection usage69* thresholds.70* <li><code>-depth=<i>value</i></code>, where <i>value</i> defines71* depth of recursion. Default values is <code>1</code>.72* <li><code>-threadCount=<i>value</i></code>, where <i>value</i> defines73* number of threads to start. Default values is <code>1</code>.74* <li><code>-timeout=<i>value</i></code>, where <i>value</i> defines75* number of minutes to run the test.76* </ul>77* <p>78* See also list of basic options recognized by <code>ArgumentParser</code>.79* <p>80* See also comments to <code>ArgumentParser</code> how to work with81* command line arguments and options.82*83* @see ArgumentParser84*/85public class ArgumentHandler extends ArgumentParser {86static final String TEST_MODE = "testMode";87static final String DIRECTLY_MODE = "directly";88static final String SERVER_MODE = "server";89static final String PROXY_MODE = "proxy";9091static final String SERVER_TYPE = "MBeanServer";92static final String DEFAULT_TYPE = "default";93static final String CUSTOM_TYPE = "custom";9495static final String LOADABLE_CLASSES_COUNT = "loadableClassCount";96static final String LOADERS_COUNT = "loadersCount";97static final String SINGLE_CLASSLOADER_CLASS = "singleClassloaderClass";9899static final String MEMORY_TYPE = "memory";100static final String MT_HEAP = "heap";101static final String MT_NONHEAP = "nonheap";102static final String MT_MIXED = "mixed";103104static final String INVOCATION_TYPE = "invocationType";105static final String JAVA_TYPE = "java";106static final String NATIVE_TYPE = "native";107static final String MIXED_TYPE = "mixed";108109static final String MONITORING = "monitoring";110static final String MON_POLLING = "polling";111static final String MON_NOTIF = "notification";112113static final String THRESHOLD = "threshold";114static final String TH_USAGE = "usage";115static final String TH_COLLECTION = "collection";116117static final String THREAD_DEPTH = "depth";118static final String THREAD_COUNT = "threadCount";119static final String TIMEOUT = "timeout";120121static final String SCENARIO_TYPE = "scenarioType";122123static final String ITERATIONS = "iterations";124125/**126* Keep a copy of raw command-line arguments and parse them;127* but throw an exception on parsing error.128*129* @param args Array of the raw command-line arguments.130*131* @throws BadOption If unknown option or illegal132* option value found133*134* @see ArgumentParser135*/136public ArgumentHandler(String args[]) {137super(args);138}139140/**141* Returns the test mode.142* <p>143* To access the metrics directly, <code>testMode</code> option should144* be defined in command line <code>-testMode="directly"</code>.145* To access the metrics via MBeanServer, <code>"server"</code> should be146* assigned to <code>-testMode="directly"</code>.147* <p>148* If <code>testMode</code> is not defined by command line, a test is149* executed in <code>directly</code> mode.150*151* @return name of test mode.152*153*/154public String getTestMode() {155return options.getProperty(TEST_MODE, DIRECTLY_MODE);156}157158/**159* Returns a type of MBean server if any.160* Two kinds of MBean servers are allowed: default and custom servers.161* Default server is an implementation of {@link162* javax.management.MBeanServer <tt>javax.management.MBeanServer</tt>}163* interface provided by JMX. Custom server is an implementation provided164* by NSK J2SE SQE Team. Server type is defined by <tt>MBeanServer</tt>165* key in command line <code>-MBeanServer="default"</code> or166* <code>-MBeanServer="custom"</code>167*168* @return <i>MBeanServer</i> server type.169*170*/171public String getServerType() {172return options.getProperty(SERVER_TYPE, DEFAULT_TYPE);173}174175/**176* Returns <i>true</i> if default implementation is used.177*178* @return <i>true</i> if default implementation is used.179*180* @see #getServerType()181*/182public boolean isDefaultServer() {183return getServerType().equals(DEFAULT_TYPE);184}185186/**187* Returns amount of class loaders.188*189* @return <i>loadersCount</i> as an integer value190*/191public int getLoadersCount() {192String val = options.getProperty(LOADERS_COUNT, "100");193int number;194try {195number = Integer.parseInt(val);196} catch (NumberFormatException e) {197throw new TestBug("Not integer value of \"" + LOADERS_COUNT198+ "\" argument: " + val);199}200return number;201}202203/**204* Returns <i>true</i> if class loaders, which perform class loading, are205* instances of the same class. If <code>-singleClassloaderClass</code> key206* is not set in command line options, then <i>false</i> is returned.207*208* @return if class loaders are instances of the same class.209*210*/211public boolean singleClassloaderClass() {212return options.getProperty(SINGLE_CLASSLOADER_CLASS) != null;213}214215/**216* Returns amount of loadable classes. If <code>-loadableClassesCount</code>217* key is not set with command line, <code>100</code> is returned.218*219* @return <i>loadableClassesCount</i> as an integer value220*221* @throws TestBug <i>loadableClassesCount</i> is non-numeric value.222*223*/224public int getLoadableClassesCount() {225String val = options.getProperty(LOADABLE_CLASSES_COUNT, "1");226int number;227try {228number = Integer.parseInt(val);229} catch (NumberFormatException e) {230throw new TestBug("Not integer value of \"" + LOADABLE_CLASSES_COUNT231+ "\" argument: " + val);232}233return number;234}235236/**237* Returns invocation type.238*239* @return <i>invocationType</i> value240*241*/242public String getInvocationType() {243return options.getProperty(INVOCATION_TYPE, JAVA_TYPE);244}245246/**247* Returns tested memory type.248*249* @return <i>memory</i> value250*251*/252public String getTestedMemory() {253return options.getProperty(MEMORY_TYPE, MT_HEAP);254}255256/**257* Returns timeout.258*259* @return <i>timeout</i> value260*261*/262public int getTimeout() {263String value = options.getProperty(TIMEOUT, "30");264265try {266return Integer.parseInt(value);267} catch (NumberFormatException e) {268throw new TestBug("Not integer value of \"" + TIMEOUT269+ "\" argument: " + value);270}271}272273/**274* Returns recursion depth.275*276* @return <i>depth</i> value277*278*/279public int getThreadDepth() {280String value = options.getProperty(THREAD_DEPTH, "1");281282try {283return Integer.parseInt(value);284} catch (NumberFormatException e) {285throw new TestBug("Not integer value of \"" + THREAD_DEPTH286+ "\" argument: " + value);287}288}289290/**291* Returns number of threads.292*293* @return <i>threadCount</i> value294*295*/296public int getThreadCount() {297String value = options.getProperty(THREAD_COUNT, "1");298299try {300return Integer.parseInt(value);301} catch (NumberFormatException e) {302throw new TestBug("Not integer value of \"" + THREAD_COUNT303+ "\" argument: " + value);304}305}306307/**308* Returns type of monitoring.309*310* @return <i>monitoring</i> value311*312*/313public String getMonitoring() {314return options.getProperty(MONITORING, MON_NOTIF);315}316317/**318* Returns type of threshold.319*320* @return <i>threshold</i> value321*322*/323public String getThreshold() {324return options.getProperty(THRESHOLD, TH_USAGE);325}326327/**328* Returns thread type to create.329*/330public String getScenarioType() {331return options.getProperty(SCENARIO_TYPE, "running");332}333334public int getIterations() {335return Integer.parseInt(options.getProperty(ITERATIONS, "3"));336}337338/**339* Checks if an option is allowed and has proper value.340* This method is invoked by <code>parseArguments()</code>341*342* @param option option name343* @param value string representation of value344* (could be an empty string too)345* null if this option has no value346* @return <i>true</i> if option is allowed and has proper value347* <i>false</i> if otion is not admissible348*349* @throws <i>BadOption</i> if option has an illegal value350*351* @see nsk.share.ArgumentParser#parseArguments352*/353protected boolean checkOption(String option, String value) {354355// defines directly, server or proxytest mode356if (option.equals(TEST_MODE)) {357if ( (!value.equals(DIRECTLY_MODE)) &&358(!value.equals(SERVER_MODE)) &&359(!value.equals(PROXY_MODE))360) {361throw new BadOption(option + ": must be one of: "362+ "\"" + DIRECTLY_MODE + "\", "363+ "\"" + SERVER_MODE + "\", "364+ "\"" + PROXY_MODE + "\"");365}366return true;367}368369// defines invocation type for stack filling370if (option.equals(INVOCATION_TYPE)) {371if ( (!value.equals(JAVA_TYPE)) &&372(!value.equals(NATIVE_TYPE)) &&373(!value.equals(MIXED_TYPE))374) {375throw new BadOption(option + ": must be one of: "376+ "\"" + JAVA_TYPE + "\", "377+ "\"" + NATIVE_TYPE + "\", "378+ "\"" + MIXED_TYPE + "\"");379}380return true;381}382383// defines default or custom MBean server384if (option.equals(SERVER_TYPE)) {385if ((!value.equals(DEFAULT_TYPE))386&& (!value.equals(CUSTOM_TYPE))) {387throw new BadOption(option + ": must be one of: \""388+ DEFAULT_TYPE + "\", \""389+ CUSTOM_TYPE + "\"");390}391392return true;393}394395// defines loadable classes and loaders counts396if (option.equals(LOADABLE_CLASSES_COUNT) ||397option.equals(LOADERS_COUNT) ||398option.equals(THREAD_DEPTH) || option.equals(THREAD_COUNT)) {399try {400int number = Integer.parseInt(value);401if (number < 0) {402throw new BadOption(option + ": value must be a positive "403+ "integer");404}405} catch (NumberFormatException e) {406throw new BadOption(option + ": value must be an integer");407}408return true;409}410411// defines timeout412if (option.equals(TIMEOUT)) {413try {414int number = Integer.parseInt(value);415416if (number < 0)417throw new BadOption(option + ": value must be a positive "418+ "integer");419} catch (NumberFormatException e) {420throw new BadOption(option + ": value must be an integer");421}422return true;423}424425// defines if classloader class is single426if (option.equals(SINGLE_CLASSLOADER_CLASS)) {427if (!(value == null || value.length() <= 0)) {428throw new BadOption(option + ": no value must be specified");429}430return true;431}432433// defines memory types434if (option.equals(MEMORY_TYPE)) {435if ( (!value.equals(MT_HEAP)) &&436(!value.equals(MT_NONHEAP)) &&437(!value.equals(MT_MIXED))438)439throw new BadOption(option + ": must be one of: "440+ "\"" + MT_HEAP + "\", "441+ "\"" + MT_NONHEAP + "\", "442+ "\"" + MT_MIXED + "\"");443return true;444}445446// defines type of monitoring447if (option.equals(MONITORING)) {448if ( (!value.equals(MON_POLLING)) &&449(!value.equals(MON_NOTIF))450)451throw new BadOption(option + ": must be one of: "452+ "\"" + MON_POLLING + "\", "453+ "\"" + MON_NOTIF + "\"");454return true;455}456457// defines threshold458if (option.equals(THRESHOLD)) {459if ( (!value.equals(TH_USAGE)) &&460(!value.equals(TH_COLLECTION))461)462throw new BadOption(option + ": must be one of: "463+ "\"" + TH_USAGE + "\", "464+ "\"" + TH_COLLECTION + "\"");465return true;466}467468if (option.equals(SCENARIO_TYPE)) {469return true;470}471if (option.equals(ITERATIONS)) {472try {473int number = Integer.parseInt(value);474475if (number < 0)476throw new BadOption(option + ": value must be a positive "477+ "integer");478return true;479} catch (NumberFormatException e) {480throw new BadOption(option + ": value must be an integer");481}482483}484return super.checkOption(option, value);485}486487/**488* Check if the values of all options are consistent.489* This method is invoked by <code>parseArguments()</code>490*491* @throws <i>BadOption</i> if options have inconsistent values492*493* @see nsk.share.ArgumentParser#parseArguments494*/495protected void checkOptions() {496super.checkOptions();497}498499public void dump(Log log) {500log.info("Test mode: " + getTestMode());501log.info("Server type: " + getServerType());502log.info("loadableClassesCount: " + getLoadableClassesCount());503log.info("loadersCount: " + getLoadersCount());504log.info("singleClassloaderClass: " + singleClassloaderClass());505}506} // ArgumentHandler507508509