Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/gc/ArgumentHandler.java
41161 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.share.gc;2425import nsk.share.*;2627/**28* Parser for GC tests' arguments.29* <p>30* <code>ArgumentHandler</code> handles specific command line arguments31* related to way of execution of a test in addition to general arguments32* recognized by {@link ArgumentParser <code>ArgumentParser</code>}.33* <p>34* Following is the list of specific options for <code>ArgumentHandler</code>:35* <ul>36* <li><code>-iterations="<i>value</i>"</code>, where <i>value</i> must either37* be "infinity", or an integer number, greater than 0. This parameter38* specifies the number of iterations to run the testcase. If the value is39* "infinity", then the test will be run for at least <code>gcTimeout</code>40* minutes. Otherwise, the testcase will be repeated for41* <code>iterations</code> times.42* <li><code>-gcTimeout="<i>value</i>"</code>, where <i>value</i> must be an43* integer number, greater than 0. If <i>infinity</i> is set to44* <code>iterations</code>, then the test consider <code>gcTimeout</code>45* argument to run the test for at least specified number of minutes.46* <li><code>-threads="<i>value</i>"</code>, where <i>value</i> must be an47* integer number, greater than 0. A user may specify the number of threads48* to start in the test with that paramenter. However, a test may ignore49* this value, if it does know the number of threads to start. It50* depends on a test: read its README file.51* <li><code>-memoryEater="<i>value</i>"</code>, where <i>value</i> must be52* either "single", or "multi" string. This argument specifies if a single53* thread should be used to eat the whole heap or not. If "multi" string is54* assigned to <code>-memoryEater</code>, then a number of threads will be55* started to eat the heap. The number is equal to number of available56* processors plus 1.57* <li><code>-largeClassesPath="<i>value</i>"</code>, where <i>value</i> is a58* directory to load large classes from.59* <li><code>-fieldsLimitation="<i>value</i>"</code>, where <i>value</i> must60* be either "over", or "under" string. This argument specifies what classes61* should be loaded from <code>largeClassesPath</code> directory. If62* <i>over</i> is set, then the classes that have number of fileds over63* JVM limitation should be loaded, otherwise -- classes that have number64* of fileds under limitation.65* </ul>66* @see ArgumentParser67*/68public class ArgumentHandler extends ArgumentParser {6970// Define all possible arguments71private final static String ITERATIONS = "iterations";72private final static String AGGREGATION_DEPTH = "aggregationDepth";73private final static String GC_TIMEOUT = "gcTimeout";74private final static String THREADS = "threads";75private final static String MEM_EATER = "memoryEater";76private final static String LARGE_CLASSES_PATH = "largeClassesPath";77private final static String FIELDS_LIMITATION = "fieldsLimitation";7879// An acceptible value for ITERATIONS80private final static String INFINITY = "infinity";8182// Acceptible values for MEM_EATER83private final static String ME_SINGLE = "single";84private final static String ME_MULTI = "multi";8586// Acceptible values for FIELDS_LIMITATION87private final static String FL_OVER = "over";88private final static String FL_UNDER = "under";8990/**91* Keep a copy of raw command-line arguments and parse them;92* but throw an exception on parsing error.93*94* @param args Array of the raw command-line arguments.95*96* @throws BadOption If unknown option or illegal option value found97*98* @see ArgumentParser99*/100public ArgumentHandler(String args[]) {101super(args);102}103104/**105* Returns number of iterations.106* <p>107* If <code>-iterations="<i>infinity</i>"</code>, the method returns -1.108* If the argument is not set, the method returns 1. Otherwise, the109* specified number is returned.110*111* @return number of iterations.112*113*/114public int getIterations() {115String value = options.getProperty(ITERATIONS, "1");116117if (INFINITY.equals(value))118return -1;119120try {121return Integer.parseInt(value);122} catch (NumberFormatException e) {123throw new TestBug("Not an integer value of \"" + ITERATIONS124+ "\" argument: " + value);125}126}127128129/**130* Returns the depth of object aggregation.131* <p>132* If the argument is not set, the method returns 0. Otherwise, the133* specified number is returned.134*135* @return number of aggregation depth.136*137*/138public int getAggregationDepth() {139String value = options.getProperty(AGGREGATION_DEPTH, "0");140141try {142return Integer.parseInt(value);143} catch (NumberFormatException e) {144throw new TestBug("Not an integer value of \"" + AGGREGATION_DEPTH145+ "\" argument: " + value);146}147}148149150/**151* Returns number of minutes to run the test.152* <p>153* @return number of minutes to run the test.154*155*/156public int getGCTimeout() {157String value = options.getProperty(GC_TIMEOUT);158159try {160return Integer.parseInt(value);161} catch (NumberFormatException e) {162throw new TestBug("\"" + GC_TIMEOUT + "\" argument is not defined "163+ "or is not integer: " + value);164}165}166167/**168* Returns a directory to load large classes from.169* <p>170* @return a directory to load large classes from.171*172*/173public String getLargeClassesPath() {174return options.getProperty(LARGE_CLASSES_PATH);175}176177/**178* Returns number of threads to start in a test. If <code>threads</code>179* is not set, the method returns specified number of threads.180* <p>181* @param defaultValue default value, if <code>threads</code> is not set.182* @return number of threads to start in a test.183*184*/185public int getThreads(int defaultValue) {186String value = options.getProperty(THREADS);187188if (value == null)189return defaultValue;190191try {192return Integer.parseInt(value);193} catch (NumberFormatException e) {194throw new TestBug("Not an integer value of \"" + THREADS195+ "\" argument: " + value);196}197}198199/**200* Returns true if single thread should be used to eat the whole heap,201* false otherwise.202*203* @return true if single thread should be used to eat the whole heap,204* false otherwise.205*206*/207public boolean isSingleMemoryEater() {208String value = options.getProperty(MEM_EATER);209210if (value == null)211return true;212else if (value.equals(ME_SINGLE))213return true;214else if (value.equals(ME_MULTI))215return false;216else217throw new TestBug("Value for \"" + MEM_EATER + "\" must be either "218+ ME_SINGLE + ", or " + ME_MULTI);219}220221/**222* Returns true if classes with number of fileds over limitation should be223* loaded, false otherwise.224*225* @return true if classes with number of fileds over limitation should be226* loaded, false otherwise.227*228*/229public boolean isOverFieldsLimitation() {230String value = options.getProperty(FIELDS_LIMITATION);231232if (value == null)233return false;234else if (value.equals(FL_OVER))235return true;236else if (value.equals(FL_UNDER))237return false;238else239throw new TestBug("Value for \"" + FIELDS_LIMITATION + "\" must be "240+ "either " + FL_OVER + ", or " + FL_UNDER);241}242243/**244* Checks if an option is allowed and has proper value.245* This method is invoked by <code>parseArguments()</code>246*247* @param option option name248* @param value string representation of value249* (could be an empty string too)250* null if this option has no value251* @return <i>true</i> if option is allowed and has proper value,252* <i>false</i> if option is not admissible253*254* @throws <i>BadOption</i> if option has an illegal value255*256* @see #parseArguments()257*/258protected boolean checkOption(String option, String value) {259260// Define iterations261if (option.equals(ITERATIONS)) {262if (INFINITY.equals(value))263return true;264265try {266int number = Integer.parseInt(value);267268if (number < 1)269throw new BadOption(option + ": value must be greater than "270+ "zero.");271} catch (NumberFormatException e) {272throw new BadOption("Value for option \"" + option + "\" must "273+ "be integer or \"" + INFINITY + "\": "274+ value);275}276return true;277}278279// Define timeout280if (option.equals(GC_TIMEOUT)) {281try {282int number = Integer.parseInt(value);283284if (number < 0)285throw new BadOption(option + ": value must be a positive "286+ "integer");287} catch (NumberFormatException e) {288throw new BadOption("Value for option \"" + option + "\" must "289+ "be integer: " + value);290}291return true;292}293294// Define threads295if (option.equals(THREADS)) {296try {297int number = Integer.parseInt(value);298299if (number < 0)300throw new BadOption(option + ": value must be a positive "301+ "integer");302} catch (NumberFormatException e) {303throw new BadOption("Value for option \"" + option + "\" must "304+ "be integer: " + value);305}306return true;307}308309// Define path to large classes310if (option.equals(LARGE_CLASSES_PATH))311return true;312313// Define memory eater314if (option.equals(MEM_EATER)) {315if ( (ME_SINGLE.equals(value)) || (ME_MULTI.equals(value)) )316return true;317else318throw new BadOption("Value for option \"" + option + "\" must "319+ "be either " + ME_SINGLE + ", or "320+ ME_MULTI + ": " + value);321}322323// Define fields limitation324if (option.equals(FIELDS_LIMITATION)) {325if ( (FL_OVER.equals(value)) || (FL_UNDER.equals(value)) )326return true;327else328throw new BadOption("Value for option \"" + option + "\" must "329+ "be either " + FL_OVER + ", or "330+ FL_UNDER + ": " + value);331}332333// Define aggregationDepth334if (option.equals(AGGREGATION_DEPTH)) {335try {336int number = Integer.parseInt(value);337338if (number < 0)339throw new BadOption(option + ": value must be a positive "340+ "integer");341} catch (NumberFormatException e) {342throw new BadOption("Value for option \"" + option + "\" must "343+ "be integer: " + value);344}345return true;346}347348return super.checkOption(option, value);349}350351/**352* Checks if the values of all options are consistent.353* This method is invoked by <code>parseArguments()</code>354*355* @throws <i>BadOption</i> if options have inconsistent values356*357* @see ArgumentParser#parseArguments()358*/359protected void checkOptions() {360super.checkOptions();361}362} // ArgumentHandler363364365