From 3689f999135407bdcf3d6036aab57e090a7b13a5 Mon Sep 17 00:00:00 2001 From: Jiri Date: Sat, 4 Jan 2025 15:39:26 +0100 Subject: [PATCH 1/4] 7903889: jcstress: document used properites (and env variables) Known properties unifed in one class and printed in verbose help: The verbose help can be removed, the individual properties with defaults can be wrapped to its class. Even the OptionSpec and OptionFormatter can be used if needed --- .../java/org/openjdk/jcstress/Options.java | 82 ++++++---- .../java/org/openjdk/jcstress/TimeBudget.java | 6 +- .../org/openjdk/jcstress/UsedProperties.java | 152 ++++++++++++++++++ .../infra/grading/ConsoleReportPrinter.java | 9 +- .../jcstress/link/BinaryLinkClient.java | 3 +- .../jcstress/link/BinaryLinkServer.java | 20 +-- .../jcstress/util/OptionFormatter.java | 2 +- 7 files changed, 214 insertions(+), 60 deletions(-) create mode 100644 jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java index 90c97825..a33477b9 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java @@ -46,6 +46,8 @@ * @author Aleksey Shipilev (aleksey.shipilev@oracle.com) */ public class Options { + public static final String TIME_BUDGET_SWITCH = "tb"; + private String resultDir; private String testFilter; private int strideSize; @@ -89,11 +91,11 @@ public boolean parse() throws IOException { .withRequiredArg().ofType(String.class).describedAs("regexp"); OptionSpec strideSize = parser.accepts("strideSize", "Internal stride size. Larger value decreases " + - "the synchronization overhead, but also reduces the number of collisions.") + "the synchronization overhead, but also reduces the number of collisions.") .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec strideCount = parser.accepts("strideCount", "Internal stride count per epoch. " + - "Larger value increases cache footprint.") + "Larger value increases cache footprint.") .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec optTime = parser.accepts("time", "(Deprecated, to be removed in next releases.)") @@ -103,36 +105,36 @@ public boolean parse() throws IOException { .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec cpus = parser.accepts("c", "Number of CPUs to use. Defaults to all CPUs in the system. " + - "Reducing the number of CPUs limits the amount of resources (including memory) the run is using.") + "Reducing the number of CPUs limits the amount of resources (including memory) the run is using.") .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec heapPerFork = parser.accepts("hs", "Java heap size per fork, in megabytes. This " + - "affects the stride size: maximum footprint will never be exceeded, regardless of min/max stride sizes.") + "affects the stride size: maximum footprint will never be exceeded, regardless of min/max stride sizes.") .withRequiredArg().ofType(Integer.class).describedAs("MB"); OptionSpec spinStyle = parser.accepts("spinStyle", "Busy loop wait style. " + - "HARD = hard busy loop; THREAD_YIELD = use Thread.yield(); THREAD_SPIN_WAIT = use Thread.onSpinWait(); LOCKSUPPORT_PARK_NANOS = use LockSupport.parkNanos().") + "HARD = hard busy loop; THREAD_YIELD = use Thread.yield(); THREAD_SPIN_WAIT = use Thread.onSpinWait(); LOCKSUPPORT_PARK_NANOS = use LockSupport.parkNanos().") .withRequiredArg().ofType(SpinLoopStyle.class).describedAs("style"); OptionSpec forks = parser.accepts("f", "Should fork each test N times. \"0\" to run in the embedded mode " + - "with occasional forking.") + "with occasional forking.") .withOptionalArg().ofType(Integer.class).describedAs("count"); OptionSpec forksStressMultiplier = parser.accepts("fsm", "Fork multiplier for randomized/stress tests. " + - "This allows more efficient randomized testing, as each fork would use a different seed.") + "This allows more efficient randomized testing, as each fork would use a different seed.") .withOptionalArg().ofType(Integer.class).describedAs("multiplier"); OptionSpec optModeStr = parser.accepts("m", "(Deprecated, to be removed in next releases).") .withRequiredArg().ofType(String.class).describedAs("mode"); OptionSpec optJvmArgs = parser.accepts("jvmArgs", "Use given JVM arguments. This disables JVM flags auto-detection, " + - "and runs only the single JVM mode. Either a single space-separated option line, or multiple options are accepted. " + - "This option only affects forked runs.") + "and runs only the single JVM mode. Either a single space-separated option line, or multiple options are accepted. " + + "This option only affects forked runs.") .withRequiredArg().ofType(String.class).describedAs("string"); OptionSpec optJvmArgsPrepend = parser.accepts("jvmArgsPrepend", "Prepend given JVM arguments to auto-detected configurations. " + - "Either a single space-separated option line, or multiple options are accepted. " + - "This option only affects forked runs.") + "Either a single space-separated option line, or multiple options are accepted. " + + "This option only affects forked runs.") .withRequiredArg().ofType(String.class).describedAs("string"); OptionSpec optSplitCompilation = parser.accepts("sc", "Use split per-actor compilation mode, if available.") @@ -144,13 +146,13 @@ public boolean parse() throws IOException { OptionSpec optPretouchHeap = parser.accepts("pth", "Pre-touch Java heap, if possible.") .withOptionalArg().ofType(Boolean.class).describedAs("bool"); - OptionSpec optTimeBudget = parser.accepts("tb", "Time budget to run the tests. Harness code would try to fit the entire " + - "run in the desired timeframe. This value is expected to be reasonable, as it is not guaranteed that tests would succeed " + - "in arbitrarily low time budget. If not set, harness would try to decide a reasonable time, given the number of tests to run. " + - "Common time suffixes (s/m/h/d) are accepted.") + OptionSpec optTimeBudget = parser.accepts(TIME_BUDGET_SWITCH, "Time budget to run the tests. Harness code would try to fit the entire " + + "run in the desired timeframe. This value is expected to be reasonable, as it is not guaranteed that tests would succeed " + + "in arbitrarily low time budget. If not set, harness would try to decide a reasonable time, given the number of tests to run. " + + "Common time suffixes (s/m/h/d) are accepted.") .withRequiredArg().ofType(TimeValue.class).describedAs("time"); - parser.accepts("v", "Be verbose."); + parser.accepts("v", "Be verbose. Will print known properties in help"); parser.accepts("vv", "Be extra verbose."); parser.accepts("vvv", "Be extra extra verbose."); parser.accepts("h", "Print this help."); @@ -161,12 +163,13 @@ public boolean parse() throws IOException { } catch (OptionException e) { System.err.println("ERROR: " + e.getMessage()); System.err.println(); - parser.printHelpOn(System.err); + printHelp(parser, System.err); return false; } + setVerbosity(set); if (set.has("h")) { - parser.printHelpOn(System.out); + printHelp(parser, System.out); return false; } @@ -185,15 +188,6 @@ public boolean parse() throws IOException { this.resultFile = "jcstress-results-" + timestamp + ".bin.gz"; } this.list = orDefault(set.has(list), false); - if (set.has("vvv")) { - this.verbosity = new Verbosity(3); - } else if (set.has("vv")) { - this.verbosity = new Verbosity(2); - } else if (set.has("v")) { - this.verbosity = new Verbosity(1); - } else { - this.verbosity = new Verbosity(0); - } int totalCpuCount = VMSupport.figureOutHotCPUs(); cpuCount = orDefault(set.valueOf(cpus), totalCpuCount); @@ -201,7 +195,7 @@ public boolean parse() throws IOException { if (cpuCount > totalCpuCount) { System.err.println("Requested to use " + cpuCount + " CPUs, but system has only " + totalCpuCount + " CPUs."); System.err.println(); - parser.printHelpOn(System.err); + printHelp(parser, System.err); return false; } @@ -227,21 +221,21 @@ public boolean parse() throws IOException { if (optModeStr.value(set) != null) { System.err.println("-m option is not supported anymore, please use -tb."); System.err.println(); - parser.printHelpOn(System.err); + printHelp(parser, System.err); return false; } if (optTime.value(set) != null) { System.err.println("-time option is not supported anymore, please use -tb."); System.err.println(); - parser.printHelpOn(System.err); + printHelp(parser, System.err); return false; } if (optIters.value(set) != null) { System.err.println("-iters option is not supported anymore, please use -tb."); System.err.println(); - parser.printHelpOn(System.err); + printHelp(parser, System.err); return false; } @@ -263,6 +257,26 @@ public boolean parse() throws IOException { return true; } + private void setVerbosity(OptionSet set) { + if (set.has("vvv")) { + this.verbosity = new Verbosity(3); + } else if (set.has("vv")) { + this.verbosity = new Verbosity(2); + } else if (set.has("v")) { + this.verbosity = new Verbosity(1); + } else { + this.verbosity = new Verbosity(0); + } + } + + private void printHelp(OptionParser parser, PrintStream ouer) throws IOException { + parser.printHelpOn(ouer); + ouer.println(); + if (verbosity != null && verbosity.printAllTests()) { + UsedProperties.printHelpOn(ouer); + } + } + private List processArgs(OptionSpec op, OptionSet set) { if (set.hasArgument(op)) { try { @@ -297,7 +311,7 @@ public void printSettingsOn(PrintStream out) { out.printf(" Hardware CPUs in use: %d%n", getCPUCount()); out.printf(" Spinning style: %s%n", getSpinStyle()); out.printf(" Test selection: \"%s\"%n", getTestFilter()); - out.printf(" Forks per test: %d normal, %d stress%n", getForks(), getForks()*getForksStressMultiplier()); + out.printf(" Forks per test: %d normal, %d stress%n", getForks(), getForks() * getForksStressMultiplier()); out.printf(" Test stride: %d strides x %d tests, but taking no more than %d Mb%n", getStrideCount(), getStrideSize(), getMaxFootprintMb()); out.printf(" Test result blob: \"%s\"%n", resultFile); out.printf(" Test results: \"%s\"%n", resultDir); @@ -392,6 +406,8 @@ public boolean isPretouchHeap() { return pretouchHeap; } - public TimeValue timeBudget() { return timeBudget; } + public TimeValue timeBudget() { + return timeBudget; + } } diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java b/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java index 4b885ad1..e03b5595 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java @@ -34,9 +34,9 @@ public class TimeBudget { - static final int DEFAULT_PER_TEST_MS = Integer.getInteger("jcstress.timeBudget.defaultPerTestMs", 3000); - static final int MIN_TIME_MS = Integer.getInteger("jcstress.timeBudget.minTimeMs", 30); - static final int MAX_TIME_MS = Integer.getInteger("jcstress.timeBudget.maxTimeMs", 60_000); + static final int DEFAULT_PER_TEST_MS = UsedProperties.getJcstressTimeBudgetDefaultPerTestMs(); + static final int MIN_TIME_MS = UsedProperties.getJcstressTimeBudgetMinTimeMs(); + static final int MAX_TIME_MS = UsedProperties.getJcstressTimeBudgetMaxTimeMs(); final long endTime; final int expectedTests; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java new file mode 100644 index 00000000..8c9105bd --- /dev/null +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2005, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.openjdk.jcstress; + +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Known Properties affecting JCStress. Some of them publicly document themselves, some do not need to. + */ +public class UsedProperties { + private static final String JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS = "jcstress.timeBudget.defaultPerTestMs"; + private static final int JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_DEFAULT = 3000; + private static final String JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_COMMENT = JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS + + " set default time the individual test executes. Defaults to " + JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_DEFAULT + + "ms set to " + getJcstressTimeBudgetDefaultPerTestMs() + "ms"; + + private static final String JCSTRESS_TIMEBUDGET_MINTIMEMS = "jcstress.timeBudget.minTimeMs"; + private static final int JCSTRESS_TIMEBUDGET_MINTIMEMS_DEFAULT = 30; + private static final String JCSTRESS_TIMEBUDGET_MINTIMEMS_COMMENT = JCSTRESS_TIMEBUDGET_MINTIMEMS + + " set minimal time the individual test executes. Defaults to " + JCSTRESS_TIMEBUDGET_MINTIMEMS_DEFAULT + + "ms set to " + getJcstressTimeBudgetMinTimeMs() + "ms"; + + private static final String JCSTRESS_TIMEBUDGET_MAXTIMEMS = "jcstress.timeBudget.maxTimeMs"; + private static final int JCSTRESS_TIMEBUDGET_MAXTIMEMS_DEFAULT = 60_000; + private static final String JCSTRESS_TIMEBUDGET_MAXTIMEMS_COMMENT = JCSTRESS_TIMEBUDGET_MAXTIMEMS + + " set maximum time the individual test executes. Defaults to " + JCSTRESS_TIMEBUDGET_MAXTIMEMS_DEFAULT + + "ms set to " + getJcstressTimeBudgetMaxTimeMs() + "ms"; + + private static final String JCSTRESS_TIMEBUDGET_ADDITIONAL_COMMENT = "The time each test is run is (simplified) calculated as value of " + Options.TIME_BUDGET_SWITCH + " switch divided by number of tests (after all filters applied)" + + " If te resulting time is smaller then " + JCSTRESS_TIMEBUDGET_MINTIMEMS + ", it is used. If it si bigger then " + JCSTRESS_TIMEBUDGET_MAXTIMEMS + " it is used. If no " + Options.TIME_BUDGET_SWITCH + " is set," + + " then " + JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS + " is used. See " + Options.TIME_BUDGET_SWITCH + " for more info. Properties do not accept unit suffixes."; + + private static final String JCSTRESS_LINK_ADDRESS = "jcstress.link.address"; + private static final String JCSTRESS_LINK_ADDRESS_COMMENT = JCSTRESS_LINK_ADDRESS + " is address where to connect to forked VMs. Defaults to loop-back. Set to '" + getListenAddressForInfo() + "'"; + + private static final String JCSTRESS_LINK_PORT = "jcstress.link.port"; + private static final int JCSTRESS_LINK_PORT_DEFAULT = 0; + private static final String JCSTRESS_LINK_PORT_COMMENT = JCSTRESS_LINK_PORT + " is port where to connect to forked VMs on " + JCSTRESS_LINK_ADDRESS + ". Defaults to " + JCSTRESS_LINK_PORT_DEFAULT + " (random free port)." + + " Set to " + getJcstressLinkPort(); + + private static final String JCSTRESS_LINK_TIMEOUTMS = "jcstress.link.timeoutMs"; + private static final int JCSTRESS_LINK_TIMEOUTMS_DEFAULT = 30 * 1000; + private static final String JCSTRESS_LINK_TIMEOUTMS_COMMENT = JCSTRESS_LINK_TIMEOUTMS + " set timeout to forked VM communication ms." + + " Defaults to " + JCSTRESS_LINK_TIMEOUTMS_DEFAULT + "ms. Set to " + getJcstressLinkTimeoutMs() + "ms."; + + private static final String JCSTRESS_CONSOLE_PRINTINTERVALMS = "jcstress.console.printIntervalMs"; + private static final long JCSTRESS_CONSOLE_PRINTINTERVALMS_INTERACTIVE_DEFAULT = 1_000; + private static final long JCSTRESS_CONSOLE_PRINTINTERVALMS_NONINTERACTIVE_DEFAULT = 15_000; + private static final String JCSTRESS_CONSOLE_PRINTINTERVALMS_COMMENT = JCSTRESS_CONSOLE_PRINTINTERVALMS + " sets interval how often to print results to console in ms. Have two defaults: " + + JCSTRESS_CONSOLE_PRINTINTERVALMS_INTERACTIVE_DEFAULT + "ms in interactive mode and " + + JCSTRESS_CONSOLE_PRINTINTERVALMS_NONINTERACTIVE_DEFAULT + "ms in noninteractive mode. Set to " + + getPrintIntervalMs() + "ms"; + + public static int getJcstressTimeBudgetDefaultPerTestMs() { + return Integer.getInteger(JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS, JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_DEFAULT); + } + + public static int getJcstressTimeBudgetMinTimeMs() { + return Integer.getInteger(JCSTRESS_TIMEBUDGET_MINTIMEMS, JCSTRESS_TIMEBUDGET_MINTIMEMS_DEFAULT); + } + + public static int getJcstressTimeBudgetMaxTimeMs() { + return Integer.getInteger(JCSTRESS_TIMEBUDGET_MAXTIMEMS, JCSTRESS_TIMEBUDGET_MAXTIMEMS_DEFAULT); + } + + private static String getJcstressLinkAddress() { + return System.getProperty(JCSTRESS_LINK_ADDRESS); + } + + public static String getListenAddressForInfo() { + try { + return getListenAddress().toString(); + } catch (Exception ex) { + return ex.getMessage(); + } + } + + public static InetAddress getListenAddress() { + // Try to use user-provided override first. + if (getJcstressLinkAddress() != null) { + try { + return InetAddress.getByName(getJcstressLinkAddress()); + } catch (UnknownHostException e) { + // override failed, notify user + throw new IllegalStateException("Can not initialize binary link.", e); + } + } + + return InetAddress.getLoopbackAddress(); + } + + public static int getJcstressLinkPort() { + return Integer.getInteger(JCSTRESS_LINK_PORT, JCSTRESS_LINK_PORT_DEFAULT); + } + + + public static int getJcstressLinkTimeoutMs() { + return Integer.getInteger(JCSTRESS_LINK_TIMEOUTMS, JCSTRESS_LINK_TIMEOUTMS_DEFAULT); + } + + public static boolean isProgressInteractive() { + return System.console() != null; + } + + private static String getJcstressConsolePrintIntervalMs() { + return System.getProperty(JCSTRESS_CONSOLE_PRINTINTERVALMS); + } + + public static long getPrintIntervalMs() { + return (getJcstressConsolePrintIntervalMs() != null) ? + Long.parseLong(getJcstressConsolePrintIntervalMs()) : + isProgressInteractive() ? JCSTRESS_CONSOLE_PRINTINTERVALMS_INTERACTIVE_DEFAULT : JCSTRESS_CONSOLE_PRINTINTERVALMS_NONINTERACTIVE_DEFAULT; + } + + public static void printHelpOn(PrintStream ouer) { + ouer.println("JCStress recognize several internal properties:"); + ouer.println(" " + JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_COMMENT); + ouer.println(" " + JCSTRESS_TIMEBUDGET_MINTIMEMS_COMMENT); + ouer.println(" " + JCSTRESS_TIMEBUDGET_MAXTIMEMS_COMMENT); + ouer.println(" " + JCSTRESS_TIMEBUDGET_ADDITIONAL_COMMENT); + ouer.println(" " + JCSTRESS_LINK_ADDRESS_COMMENT); + ouer.println(" " + JCSTRESS_LINK_PORT_COMMENT); + ouer.println(" " + JCSTRESS_LINK_TIMEOUTMS_COMMENT); + ouer.println(" " + JCSTRESS_CONSOLE_PRINTINTERVALMS_COMMENT); + + + } +} \ No newline at end of file diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java index bda69cb7..bd300484 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java @@ -27,6 +27,7 @@ import org.openjdk.jcstress.Options; import org.openjdk.jcstress.TestExecutor; import org.openjdk.jcstress.TimeBudget; +import org.openjdk.jcstress.UsedProperties; import org.openjdk.jcstress.Verbosity; import org.openjdk.jcstress.infra.collectors.TestResult; import org.openjdk.jcstress.infra.collectors.TestResultCollector; @@ -43,8 +44,6 @@ */ public class ConsoleReportPrinter implements TestResultCollector { - private static final Integer PRINT_INTERVAL_MS = Integer.getInteger("jcstress.console.printIntervalMs"); - private final Verbosity verbosity; private final PrintWriter output; @@ -80,13 +79,11 @@ public ConsoleReportPrinter(Options opts, PrintWriter pw, long expectedForks, Ti Arrays.fill(progressLen, 1); progressFirstLine = true; - progressInteractive = (System.console() != null); + progressInteractive = UsedProperties.isProgressInteractive(); progressAnsi = VMSupport.isLinux(); output.println(" Attached the " + (progressInteractive ? "interactive console" : "non-interactive output stream") + "."); - printIntervalMs = (PRINT_INTERVAL_MS != null) ? - PRINT_INTERVAL_MS : - progressInteractive ? 1_000 : 15_000; + printIntervalMs = UsedProperties.getPrintIntervalMs(); output.println(" Printing the progress line at most every " + printIntervalMs + " milliseconds."); output.println(); diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java index 3033647d..c39c477a 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java @@ -24,6 +24,7 @@ */ package org.openjdk.jcstress.link; +import org.openjdk.jcstress.UsedProperties; import org.openjdk.jcstress.infra.collectors.TestResult; import org.openjdk.jcstress.infra.runners.ForkedTestConfig; @@ -32,7 +33,7 @@ public final class BinaryLinkClient { - private static final int LINK_TIMEOUT_MS = Integer.getInteger("jcstress.link.timeoutMs", 30 * 1000); + private static final int LINK_TIMEOUT_MS = UsedProperties.getJcstressLinkTimeoutMs(); private final String hostName; private final int hostPort; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java index a7c74335..a5e34f48 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java @@ -24,6 +24,7 @@ */ package org.openjdk.jcstress.link; +import org.openjdk.jcstress.UsedProperties; import org.openjdk.jcstress.infra.collectors.TestResult; import org.openjdk.jcstress.infra.runners.ForkedTestConfig; @@ -37,9 +38,8 @@ */ public final class BinaryLinkServer { - private static final String LINK_ADDRESS = System.getProperty("jcstress.link.address"); - private static final int LINK_PORT = Integer.getInteger("jcstress.link.port", 0); - private static final int LINK_TIMEOUT_MS = Integer.getInteger("jcstress.link.timeoutMs", 30 * 1000); + private static final int LINK_PORT = UsedProperties.getJcstressLinkPort(); + private static final int LINK_TIMEOUT_MS = UsedProperties.getJcstressLinkTimeoutMs(); private final ServerSocket server; private final InetAddress listenAddress; @@ -49,7 +49,7 @@ public final class BinaryLinkServer { public BinaryLinkServer(ServerListener listener) throws IOException { this.listener = listener; - listenAddress = getListenAddress(); + listenAddress = UsedProperties.getListenAddress(); server = new ServerSocket(LINK_PORT, 50, listenAddress); server.setSoTimeout(LINK_TIMEOUT_MS); @@ -57,19 +57,7 @@ public BinaryLinkServer(ServerListener listener) throws IOException { handler.start(); } - private InetAddress getListenAddress() { - // Try to use user-provided override first. - if (LINK_ADDRESS != null) { - try { - return InetAddress.getByName(LINK_ADDRESS); - } catch (UnknownHostException e) { - // override failed, notify user - throw new IllegalStateException("Can not initialize binary link.", e); - } - } - return InetAddress.getLoopbackAddress(); - } public void terminate() { // set interrupt flag diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/util/OptionFormatter.java b/jcstress-core/src/main/java/org/openjdk/jcstress/util/OptionFormatter.java index 51823f52..e1702f49 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/util/OptionFormatter.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/util/OptionFormatter.java @@ -35,7 +35,7 @@ public class OptionFormatter implements HelpFormatter { public String format(Map options) { StringBuilder sb = new StringBuilder(); - sb.append("Usage: java -jar jcstress.jar [options]"); + sb.append("Usage: java [properties] -jar jcstress.jar [options]"); sb.append(System.lineSeparator()); sb.append(" [opt] means optional argument."); sb.append(System.lineSeparator()); From 77ffebab5009b78e9f615ec9df5bde8dd00d8227 Mon Sep 17 00:00:00 2001 From: Jiri Date: Sat, 4 Jan 2025 15:50:37 +0100 Subject: [PATCH 2/4] Removed autoformatted whitespaces --- .../java/org/openjdk/jcstress/Options.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java index a33477b9..75231f51 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java @@ -91,11 +91,11 @@ public boolean parse() throws IOException { .withRequiredArg().ofType(String.class).describedAs("regexp"); OptionSpec strideSize = parser.accepts("strideSize", "Internal stride size. Larger value decreases " + - "the synchronization overhead, but also reduces the number of collisions.") + "the synchronization overhead, but also reduces the number of collisions.") .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec strideCount = parser.accepts("strideCount", "Internal stride count per epoch. " + - "Larger value increases cache footprint.") + "Larger value increases cache footprint.") .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec optTime = parser.accepts("time", "(Deprecated, to be removed in next releases.)") @@ -105,36 +105,36 @@ public boolean parse() throws IOException { .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec cpus = parser.accepts("c", "Number of CPUs to use. Defaults to all CPUs in the system. " + - "Reducing the number of CPUs limits the amount of resources (including memory) the run is using.") + "Reducing the number of CPUs limits the amount of resources (including memory) the run is using.") .withRequiredArg().ofType(Integer.class).describedAs("N"); OptionSpec heapPerFork = parser.accepts("hs", "Java heap size per fork, in megabytes. This " + - "affects the stride size: maximum footprint will never be exceeded, regardless of min/max stride sizes.") + "affects the stride size: maximum footprint will never be exceeded, regardless of min/max stride sizes.") .withRequiredArg().ofType(Integer.class).describedAs("MB"); OptionSpec spinStyle = parser.accepts("spinStyle", "Busy loop wait style. " + - "HARD = hard busy loop; THREAD_YIELD = use Thread.yield(); THREAD_SPIN_WAIT = use Thread.onSpinWait(); LOCKSUPPORT_PARK_NANOS = use LockSupport.parkNanos().") + "HARD = hard busy loop; THREAD_YIELD = use Thread.yield(); THREAD_SPIN_WAIT = use Thread.onSpinWait(); LOCKSUPPORT_PARK_NANOS = use LockSupport.parkNanos().") .withRequiredArg().ofType(SpinLoopStyle.class).describedAs("style"); OptionSpec forks = parser.accepts("f", "Should fork each test N times. \"0\" to run in the embedded mode " + - "with occasional forking.") + "with occasional forking.") .withOptionalArg().ofType(Integer.class).describedAs("count"); OptionSpec forksStressMultiplier = parser.accepts("fsm", "Fork multiplier for randomized/stress tests. " + - "This allows more efficient randomized testing, as each fork would use a different seed.") + "This allows more efficient randomized testing, as each fork would use a different seed.") .withOptionalArg().ofType(Integer.class).describedAs("multiplier"); OptionSpec optModeStr = parser.accepts("m", "(Deprecated, to be removed in next releases).") .withRequiredArg().ofType(String.class).describedAs("mode"); OptionSpec optJvmArgs = parser.accepts("jvmArgs", "Use given JVM arguments. This disables JVM flags auto-detection, " + - "and runs only the single JVM mode. Either a single space-separated option line, or multiple options are accepted. " + - "This option only affects forked runs.") + "and runs only the single JVM mode. Either a single space-separated option line, or multiple options are accepted. " + + "This option only affects forked runs.") .withRequiredArg().ofType(String.class).describedAs("string"); OptionSpec optJvmArgsPrepend = parser.accepts("jvmArgsPrepend", "Prepend given JVM arguments to auto-detected configurations. " + - "Either a single space-separated option line, or multiple options are accepted. " + - "This option only affects forked runs.") + "Either a single space-separated option line, or multiple options are accepted. " + + "This option only affects forked runs.") .withRequiredArg().ofType(String.class).describedAs("string"); OptionSpec optSplitCompilation = parser.accepts("sc", "Use split per-actor compilation mode, if available.") @@ -147,9 +147,9 @@ public boolean parse() throws IOException { .withOptionalArg().ofType(Boolean.class).describedAs("bool"); OptionSpec optTimeBudget = parser.accepts(TIME_BUDGET_SWITCH, "Time budget to run the tests. Harness code would try to fit the entire " + - "run in the desired timeframe. This value is expected to be reasonable, as it is not guaranteed that tests would succeed " + - "in arbitrarily low time budget. If not set, harness would try to decide a reasonable time, given the number of tests to run. " + - "Common time suffixes (s/m/h/d) are accepted.") + "run in the desired timeframe. This value is expected to be reasonable, as it is not guaranteed that tests would succeed " + + "in arbitrarily low time budget. If not set, harness would try to decide a reasonable time, given the number of tests to run. " + + "Common time suffixes (s/m/h/d) are accepted.") .withRequiredArg().ofType(TimeValue.class).describedAs("time"); parser.accepts("v", "Be verbose. Will print known properties in help"); From ba4b52fa0c16567be4da995713a39b408ec2e1a7 Mon Sep 17 00:00:00 2001 From: Jiri Date: Sat, 4 Jan 2025 18:33:58 +0100 Subject: [PATCH 3/4] Extracted properties encapsualted in objects --- .../org/openjdk/jcstress/UsedProperties.java | 223 ++++++++++++------ 1 file changed, 157 insertions(+), 66 deletions(-) diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java index 8c9105bd..a166baea 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java @@ -27,71 +27,168 @@ import java.io.PrintStream; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * Known Properties affecting JCStress. Some of them publicly document themselves, some do not need to. */ public class UsedProperties { - private static final String JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS = "jcstress.timeBudget.defaultPerTestMs"; - private static final int JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_DEFAULT = 3000; - private static final String JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_COMMENT = JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS + - " set default time the individual test executes. Defaults to " + JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_DEFAULT + - "ms set to " + getJcstressTimeBudgetDefaultPerTestMs() + "ms"; - - private static final String JCSTRESS_TIMEBUDGET_MINTIMEMS = "jcstress.timeBudget.minTimeMs"; - private static final int JCSTRESS_TIMEBUDGET_MINTIMEMS_DEFAULT = 30; - private static final String JCSTRESS_TIMEBUDGET_MINTIMEMS_COMMENT = JCSTRESS_TIMEBUDGET_MINTIMEMS + - " set minimal time the individual test executes. Defaults to " + JCSTRESS_TIMEBUDGET_MINTIMEMS_DEFAULT + - "ms set to " + getJcstressTimeBudgetMinTimeMs() + "ms"; - - private static final String JCSTRESS_TIMEBUDGET_MAXTIMEMS = "jcstress.timeBudget.maxTimeMs"; - private static final int JCSTRESS_TIMEBUDGET_MAXTIMEMS_DEFAULT = 60_000; - private static final String JCSTRESS_TIMEBUDGET_MAXTIMEMS_COMMENT = JCSTRESS_TIMEBUDGET_MAXTIMEMS + - " set maximum time the individual test executes. Defaults to " + JCSTRESS_TIMEBUDGET_MAXTIMEMS_DEFAULT + - "ms set to " + getJcstressTimeBudgetMaxTimeMs() + "ms"; - - private static final String JCSTRESS_TIMEBUDGET_ADDITIONAL_COMMENT = "The time each test is run is (simplified) calculated as value of " + Options.TIME_BUDGET_SWITCH + " switch divided by number of tests (after all filters applied)" + - " If te resulting time is smaller then " + JCSTRESS_TIMEBUDGET_MINTIMEMS + ", it is used. If it si bigger then " + JCSTRESS_TIMEBUDGET_MAXTIMEMS + " it is used. If no " + Options.TIME_BUDGET_SWITCH + " is set," + - " then " + JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS + " is used. See " + Options.TIME_BUDGET_SWITCH + " for more info. Properties do not accept unit suffixes."; - - private static final String JCSTRESS_LINK_ADDRESS = "jcstress.link.address"; - private static final String JCSTRESS_LINK_ADDRESS_COMMENT = JCSTRESS_LINK_ADDRESS + " is address where to connect to forked VMs. Defaults to loop-back. Set to '" + getListenAddressForInfo() + "'"; - - private static final String JCSTRESS_LINK_PORT = "jcstress.link.port"; - private static final int JCSTRESS_LINK_PORT_DEFAULT = 0; - private static final String JCSTRESS_LINK_PORT_COMMENT = JCSTRESS_LINK_PORT + " is port where to connect to forked VMs on " + JCSTRESS_LINK_ADDRESS + ". Defaults to " + JCSTRESS_LINK_PORT_DEFAULT + " (random free port)." + - " Set to " + getJcstressLinkPort(); - - private static final String JCSTRESS_LINK_TIMEOUTMS = "jcstress.link.timeoutMs"; - private static final int JCSTRESS_LINK_TIMEOUTMS_DEFAULT = 30 * 1000; - private static final String JCSTRESS_LINK_TIMEOUTMS_COMMENT = JCSTRESS_LINK_TIMEOUTMS + " set timeout to forked VM communication ms." + - " Defaults to " + JCSTRESS_LINK_TIMEOUTMS_DEFAULT + "ms. Set to " + getJcstressLinkTimeoutMs() + "ms."; - - private static final String JCSTRESS_CONSOLE_PRINTINTERVALMS = "jcstress.console.printIntervalMs"; - private static final long JCSTRESS_CONSOLE_PRINTINTERVALMS_INTERACTIVE_DEFAULT = 1_000; - private static final long JCSTRESS_CONSOLE_PRINTINTERVALMS_NONINTERACTIVE_DEFAULT = 15_000; - private static final String JCSTRESS_CONSOLE_PRINTINTERVALMS_COMMENT = JCSTRESS_CONSOLE_PRINTINTERVALMS + " sets interval how often to print results to console in ms. Have two defaults: " + - JCSTRESS_CONSOLE_PRINTINTERVALMS_INTERACTIVE_DEFAULT + "ms in interactive mode and " + - JCSTRESS_CONSOLE_PRINTINTERVALMS_NONINTERACTIVE_DEFAULT + "ms in noninteractive mode. Set to " + - getPrintIntervalMs() + "ms"; + + private static abstract class JcstressProperty { + private final String key; + private final List defaults; + + public JcstressProperty(String key, T[] defaults) { + this.key = key; + this.defaults = Collections.unmodifiableList(Arrays.asList(defaults)); + } + + public String getKey() { + return key; + } + + public List getDefaults() { + return defaults; + } + + public T getDefault() { + return defaults.get(0); + } + + public boolean isCustom(){ + return System.getProperty(getKey()) != null; + } + + public abstract String getDescription(); + + public abstract T getValue(); + } + + private static abstract class IntJcstressProperty extends JcstressProperty { + + public IntJcstressProperty(String key, Integer... defaults) { + super(key, defaults); + } + + @Override + public Integer getValue() { + return Integer.getInteger(getKey(), getDefault()); + } + } + + private static abstract class LongJcstressProperty extends JcstressProperty { + + public LongJcstressProperty(String key, Long... defaults) { + super(key, defaults); + } + + @Override + public Long getValue() { + return Long.getLong(getKey(), getDefault()); + } + } + + + private static abstract class StringJcstressProperty extends JcstressProperty { + + public StringJcstressProperty(String key, String... defaults) { + super(key, defaults); + } + + @Override + public String getValue() { + return System.getProperty(getKey(), getDefault()); + } + } + + private static final IntJcstressProperty TIMEBUDGET_DEFAULTPERTESTMS = new IntJcstressProperty("jcstress.timeBudget.defaultPerTestMs", 3000) { + @Override + public String getDescription() { + return getKey() + " set default time the individual test executes. Defaults to " + getDefault() + + "ms set to " + getValue() + "ms"; + } + }; + + private static final IntJcstressProperty TIMEBUDGET_MINTIMEMS = new IntJcstressProperty("jcstress.timeBudget.minTimeMs", 30) { + @Override + public String getDescription() { + return getKey() + " set minimal time the individual test executes. Defaults to " + getDefault() + + "ms set to " + getValue() + "ms"; + } + }; + + private static final IntJcstressProperty TIMEBUDGET_MAXTIMEMS = new IntJcstressProperty("jcstress.timeBudget.maxTimeMs", 60_000) { + @Override + public String getDescription() { + return getKey() + + " set maximum time the individual test executes. Defaults to " + getDefault() + + "ms set to " + getValue() + "ms"; + } + }; + + private static final String TIMEBUDGET_ADDITIONAL_COMMENT = "The time each test is run is (simplified) calculated as value of " + Options.TIME_BUDGET_SWITCH + " switch divided by number of tests (after all filters applied)" + + " If te resulting time is smaller then " + TIMEBUDGET_MINTIMEMS.getKey() + ", it is used. If it si bigger then " + TIMEBUDGET_MAXTIMEMS.getKey() + " it is used. If no " + Options.TIME_BUDGET_SWITCH + " is set," + + " then " + TIMEBUDGET_DEFAULTPERTESTMS.getKey() + " is used. See " + Options.TIME_BUDGET_SWITCH + " for more info. Properties do not accept unit suffixes."; + + private static final StringJcstressProperty LINK_ADDRESS = new StringJcstressProperty("jcstress.link.address", new String[]{null}) { + @Override + public String getDescription() { + return getKey() + " is address where to connect to forked VMs. Defaults to loop-back. Set to '" + getListenAddressForInfo() + "'"; + } + }; + + + private static final IntJcstressProperty LINK_PORT = new IntJcstressProperty("jcstress.link.port", 0) { + @Override + public String getDescription() { + return getKey() + " is port where to connect to forked VMs on " + LINK_ADDRESS.getKey() + ". Defaults to " + getDefault() + " (random free port)." + + " Set to " + getJcstressLinkPort(); + } + }; + + private static final IntJcstressProperty LINK_TIMEOUTMS = new IntJcstressProperty("jcstress.link.timeoutMs", 30 * 1000) { + @Override + public String getDescription() { + return getKey() + " set timeout to forked VM communication ms." + + " Defaults to " + getDefault() + "ms. Set to " + getValue() + "ms."; + } + }; + + private static final LongJcstressProperty CONSOLE_PRINTINTERVALMS = new LongJcstressProperty("jcstress.console.printIntervalMs", 1_000L, 15_000L) { + + @Override + public Long getValue() { + return Long.getLong(getKey(), null); + } + + @Override + public String getDescription() { + return getKey() + " sets interval how often to print results to console in ms. Have two defaults: " + + getDefaults().get(0) + "ms in interactive mode and " + + getDefaults().get(1) + "ms in noninteractive mode. Set to " + + getPrintIntervalMs() + "ms"; + } + }; public static int getJcstressTimeBudgetDefaultPerTestMs() { - return Integer.getInteger(JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS, JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_DEFAULT); + return TIMEBUDGET_DEFAULTPERTESTMS.getValue(); } public static int getJcstressTimeBudgetMinTimeMs() { - return Integer.getInteger(JCSTRESS_TIMEBUDGET_MINTIMEMS, JCSTRESS_TIMEBUDGET_MINTIMEMS_DEFAULT); + return TIMEBUDGET_MINTIMEMS.getValue(); } public static int getJcstressTimeBudgetMaxTimeMs() { - return Integer.getInteger(JCSTRESS_TIMEBUDGET_MAXTIMEMS, JCSTRESS_TIMEBUDGET_MAXTIMEMS_DEFAULT); + return TIMEBUDGET_MAXTIMEMS.getValue(); } private static String getJcstressLinkAddress() { - return System.getProperty(JCSTRESS_LINK_ADDRESS); + return LINK_ADDRESS.getValue(); } - public static String getListenAddressForInfo() { + private static String getListenAddressForInfo() { try { return getListenAddress().toString(); } catch (Exception ex) { @@ -114,39 +211,33 @@ public static InetAddress getListenAddress() { } public static int getJcstressLinkPort() { - return Integer.getInteger(JCSTRESS_LINK_PORT, JCSTRESS_LINK_PORT_DEFAULT); + return LINK_PORT.getValue(); } public static int getJcstressLinkTimeoutMs() { - return Integer.getInteger(JCSTRESS_LINK_TIMEOUTMS, JCSTRESS_LINK_TIMEOUTMS_DEFAULT); + return LINK_TIMEOUTMS.getValue(); } public static boolean isProgressInteractive() { return System.console() != null; } - private static String getJcstressConsolePrintIntervalMs() { - return System.getProperty(JCSTRESS_CONSOLE_PRINTINTERVALMS); - } - public static long getPrintIntervalMs() { - return (getJcstressConsolePrintIntervalMs() != null) ? - Long.parseLong(getJcstressConsolePrintIntervalMs()) : - isProgressInteractive() ? JCSTRESS_CONSOLE_PRINTINTERVALMS_INTERACTIVE_DEFAULT : JCSTRESS_CONSOLE_PRINTINTERVALMS_NONINTERACTIVE_DEFAULT; + return (CONSOLE_PRINTINTERVALMS.isCustom()) ? + CONSOLE_PRINTINTERVALMS.getValue() : + isProgressInteractive() ? CONSOLE_PRINTINTERVALMS.getDefaults().get(0) : CONSOLE_PRINTINTERVALMS.getDefaults().get(1); } public static void printHelpOn(PrintStream ouer) { ouer.println("JCStress recognize several internal properties:"); - ouer.println(" " + JCSTRESS_TIMEBUDGET_DEFAULTPERTESTMS_COMMENT); - ouer.println(" " + JCSTRESS_TIMEBUDGET_MINTIMEMS_COMMENT); - ouer.println(" " + JCSTRESS_TIMEBUDGET_MAXTIMEMS_COMMENT); - ouer.println(" " + JCSTRESS_TIMEBUDGET_ADDITIONAL_COMMENT); - ouer.println(" " + JCSTRESS_LINK_ADDRESS_COMMENT); - ouer.println(" " + JCSTRESS_LINK_PORT_COMMENT); - ouer.println(" " + JCSTRESS_LINK_TIMEOUTMS_COMMENT); - ouer.println(" " + JCSTRESS_CONSOLE_PRINTINTERVALMS_COMMENT); - - + ouer.println(" " + TIMEBUDGET_DEFAULTPERTESTMS.getDescription()); + ouer.println(" " + TIMEBUDGET_MINTIMEMS.getDescription()); + ouer.println(" " + TIMEBUDGET_MAXTIMEMS.getDescription()); + ouer.println(" " + TIMEBUDGET_ADDITIONAL_COMMENT); + ouer.println(" " + LINK_ADDRESS.getDescription()); + ouer.println(" " + LINK_PORT.getDescription()); + ouer.println(" " + LINK_TIMEOUTMS.getDescription()); + ouer.println(" " + CONSOLE_PRINTINTERVALMS.getDescription()); } } \ No newline at end of file From 9702a5b937a4786286f52bc0eb6c48fab0711875 Mon Sep 17 00:00:00 2001 From: Jiri Date: Sat, 25 Jan 2025 13:22:11 +0100 Subject: [PATCH 4/4] Moved declaration of individual proeprties to ceparate classes by family --- .../java/org/openjdk/jcstress/Options.java | 1 + .../java/org/openjdk/jcstress/TimeBudget.java | 1 + .../org/openjdk/jcstress/UsedProperties.java | 243 ------------------ .../infra/grading/ConsoleReportPrinter.java | 2 +- .../jcstress/link/BinaryLinkClient.java | 2 +- .../jcstress/link/BinaryLinkServer.java | 2 +- .../properties/ForkedVmProperties.java | 79 ++++++ .../properties/TestTimeProperties.java | 77 ++++++ .../jcstress/properties/UiProperties.java | 58 +++++ .../jcstress/properties/UsedProperties.java | 182 +++++++++++++ 10 files changed, 401 insertions(+), 246 deletions(-) delete mode 100644 jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java create mode 100644 jcstress-core/src/main/java/org/openjdk/jcstress/properties/ForkedVmProperties.java create mode 100644 jcstress-core/src/main/java/org/openjdk/jcstress/properties/TestTimeProperties.java create mode 100644 jcstress-core/src/main/java/org/openjdk/jcstress/properties/UiProperties.java create mode 100644 jcstress-core/src/main/java/org/openjdk/jcstress/properties/UsedProperties.java diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java index 75231f51..e6d8f10d 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java @@ -30,6 +30,7 @@ import joptsimple.OptionSpec; import org.openjdk.jcstress.infra.runners.SpinLoopStyle; import org.openjdk.jcstress.os.AffinityMode; +import org.openjdk.jcstress.properties.UsedProperties; import org.openjdk.jcstress.util.OptionFormatter; import org.openjdk.jcstress.util.StringUtils; import org.openjdk.jcstress.util.TimeValue; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java b/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java index e03b5595..e7c9019d 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/TimeBudget.java @@ -25,6 +25,7 @@ package org.openjdk.jcstress; import org.openjdk.jcstress.infra.grading.ReportUtils; +import org.openjdk.jcstress.properties.UsedProperties; import org.openjdk.jcstress.util.TimeValue; import org.openjdk.jcstress.vm.VMSupport; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java deleted file mode 100644 index a166baea..00000000 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/UsedProperties.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2005, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.openjdk.jcstress; - -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Known Properties affecting JCStress. Some of them publicly document themselves, some do not need to. - */ -public class UsedProperties { - - private static abstract class JcstressProperty { - private final String key; - private final List defaults; - - public JcstressProperty(String key, T[] defaults) { - this.key = key; - this.defaults = Collections.unmodifiableList(Arrays.asList(defaults)); - } - - public String getKey() { - return key; - } - - public List getDefaults() { - return defaults; - } - - public T getDefault() { - return defaults.get(0); - } - - public boolean isCustom(){ - return System.getProperty(getKey()) != null; - } - - public abstract String getDescription(); - - public abstract T getValue(); - } - - private static abstract class IntJcstressProperty extends JcstressProperty { - - public IntJcstressProperty(String key, Integer... defaults) { - super(key, defaults); - } - - @Override - public Integer getValue() { - return Integer.getInteger(getKey(), getDefault()); - } - } - - private static abstract class LongJcstressProperty extends JcstressProperty { - - public LongJcstressProperty(String key, Long... defaults) { - super(key, defaults); - } - - @Override - public Long getValue() { - return Long.getLong(getKey(), getDefault()); - } - } - - - private static abstract class StringJcstressProperty extends JcstressProperty { - - public StringJcstressProperty(String key, String... defaults) { - super(key, defaults); - } - - @Override - public String getValue() { - return System.getProperty(getKey(), getDefault()); - } - } - - private static final IntJcstressProperty TIMEBUDGET_DEFAULTPERTESTMS = new IntJcstressProperty("jcstress.timeBudget.defaultPerTestMs", 3000) { - @Override - public String getDescription() { - return getKey() + " set default time the individual test executes. Defaults to " + getDefault() + - "ms set to " + getValue() + "ms"; - } - }; - - private static final IntJcstressProperty TIMEBUDGET_MINTIMEMS = new IntJcstressProperty("jcstress.timeBudget.minTimeMs", 30) { - @Override - public String getDescription() { - return getKey() + " set minimal time the individual test executes. Defaults to " + getDefault() + - "ms set to " + getValue() + "ms"; - } - }; - - private static final IntJcstressProperty TIMEBUDGET_MAXTIMEMS = new IntJcstressProperty("jcstress.timeBudget.maxTimeMs", 60_000) { - @Override - public String getDescription() { - return getKey() + - " set maximum time the individual test executes. Defaults to " + getDefault() + - "ms set to " + getValue() + "ms"; - } - }; - - private static final String TIMEBUDGET_ADDITIONAL_COMMENT = "The time each test is run is (simplified) calculated as value of " + Options.TIME_BUDGET_SWITCH + " switch divided by number of tests (after all filters applied)" + - " If te resulting time is smaller then " + TIMEBUDGET_MINTIMEMS.getKey() + ", it is used. If it si bigger then " + TIMEBUDGET_MAXTIMEMS.getKey() + " it is used. If no " + Options.TIME_BUDGET_SWITCH + " is set," + - " then " + TIMEBUDGET_DEFAULTPERTESTMS.getKey() + " is used. See " + Options.TIME_BUDGET_SWITCH + " for more info. Properties do not accept unit suffixes."; - - private static final StringJcstressProperty LINK_ADDRESS = new StringJcstressProperty("jcstress.link.address", new String[]{null}) { - @Override - public String getDescription() { - return getKey() + " is address where to connect to forked VMs. Defaults to loop-back. Set to '" + getListenAddressForInfo() + "'"; - } - }; - - - private static final IntJcstressProperty LINK_PORT = new IntJcstressProperty("jcstress.link.port", 0) { - @Override - public String getDescription() { - return getKey() + " is port where to connect to forked VMs on " + LINK_ADDRESS.getKey() + ". Defaults to " + getDefault() + " (random free port)." + - " Set to " + getJcstressLinkPort(); - } - }; - - private static final IntJcstressProperty LINK_TIMEOUTMS = new IntJcstressProperty("jcstress.link.timeoutMs", 30 * 1000) { - @Override - public String getDescription() { - return getKey() + " set timeout to forked VM communication ms." + - " Defaults to " + getDefault() + "ms. Set to " + getValue() + "ms."; - } - }; - - private static final LongJcstressProperty CONSOLE_PRINTINTERVALMS = new LongJcstressProperty("jcstress.console.printIntervalMs", 1_000L, 15_000L) { - - @Override - public Long getValue() { - return Long.getLong(getKey(), null); - } - - @Override - public String getDescription() { - return getKey() + " sets interval how often to print results to console in ms. Have two defaults: " + - getDefaults().get(0) + "ms in interactive mode and " + - getDefaults().get(1) + "ms in noninteractive mode. Set to " + - getPrintIntervalMs() + "ms"; - } - }; - - public static int getJcstressTimeBudgetDefaultPerTestMs() { - return TIMEBUDGET_DEFAULTPERTESTMS.getValue(); - } - - public static int getJcstressTimeBudgetMinTimeMs() { - return TIMEBUDGET_MINTIMEMS.getValue(); - } - - public static int getJcstressTimeBudgetMaxTimeMs() { - return TIMEBUDGET_MAXTIMEMS.getValue(); - } - - private static String getJcstressLinkAddress() { - return LINK_ADDRESS.getValue(); - } - - private static String getListenAddressForInfo() { - try { - return getListenAddress().toString(); - } catch (Exception ex) { - return ex.getMessage(); - } - } - - public static InetAddress getListenAddress() { - // Try to use user-provided override first. - if (getJcstressLinkAddress() != null) { - try { - return InetAddress.getByName(getJcstressLinkAddress()); - } catch (UnknownHostException e) { - // override failed, notify user - throw new IllegalStateException("Can not initialize binary link.", e); - } - } - - return InetAddress.getLoopbackAddress(); - } - - public static int getJcstressLinkPort() { - return LINK_PORT.getValue(); - } - - - public static int getJcstressLinkTimeoutMs() { - return LINK_TIMEOUTMS.getValue(); - } - - public static boolean isProgressInteractive() { - return System.console() != null; - } - - public static long getPrintIntervalMs() { - return (CONSOLE_PRINTINTERVALMS.isCustom()) ? - CONSOLE_PRINTINTERVALMS.getValue() : - isProgressInteractive() ? CONSOLE_PRINTINTERVALMS.getDefaults().get(0) : CONSOLE_PRINTINTERVALMS.getDefaults().get(1); - } - - public static void printHelpOn(PrintStream ouer) { - ouer.println("JCStress recognize several internal properties:"); - ouer.println(" " + TIMEBUDGET_DEFAULTPERTESTMS.getDescription()); - ouer.println(" " + TIMEBUDGET_MINTIMEMS.getDescription()); - ouer.println(" " + TIMEBUDGET_MAXTIMEMS.getDescription()); - ouer.println(" " + TIMEBUDGET_ADDITIONAL_COMMENT); - ouer.println(" " + LINK_ADDRESS.getDescription()); - ouer.println(" " + LINK_PORT.getDescription()); - ouer.println(" " + LINK_TIMEOUTMS.getDescription()); - ouer.println(" " + CONSOLE_PRINTINTERVALMS.getDescription()); - } -} \ No newline at end of file diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java index bd300484..7a6603a8 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java @@ -27,7 +27,7 @@ import org.openjdk.jcstress.Options; import org.openjdk.jcstress.TestExecutor; import org.openjdk.jcstress.TimeBudget; -import org.openjdk.jcstress.UsedProperties; +import org.openjdk.jcstress.properties.UsedProperties; import org.openjdk.jcstress.Verbosity; import org.openjdk.jcstress.infra.collectors.TestResult; import org.openjdk.jcstress.infra.collectors.TestResultCollector; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java index c39c477a..18d188e7 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkClient.java @@ -24,7 +24,7 @@ */ package org.openjdk.jcstress.link; -import org.openjdk.jcstress.UsedProperties; +import org.openjdk.jcstress.properties.UsedProperties; import org.openjdk.jcstress.infra.collectors.TestResult; import org.openjdk.jcstress.infra.runners.ForkedTestConfig; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java index a5e34f48..8e66c8da 100644 --- a/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/link/BinaryLinkServer.java @@ -24,7 +24,7 @@ */ package org.openjdk.jcstress.link; -import org.openjdk.jcstress.UsedProperties; +import org.openjdk.jcstress.properties.UsedProperties; import org.openjdk.jcstress.infra.collectors.TestResult; import org.openjdk.jcstress.infra.runners.ForkedTestConfig; diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/properties/ForkedVmProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/ForkedVmProperties.java new file mode 100644 index 00000000..c2d7cf03 --- /dev/null +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/ForkedVmProperties.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.openjdk.jcstress.properties; + +import java.util.Arrays; +import java.util.List; + +class ForkedVmProperties implements UsedProperties.ProeprtiesHelpProvider { + + static final UsedProperties.StringJcstressProperty LINK_ADDRESS = new UsedProperties.StringJcstressProperty("jcstress.link.address", new String[]{null}) { + @Override + public String getDescription() { + return getKey() + " is address where to connect to forked VMs. Defaults to loop-back. Set to '" + getListenAddressForInfo() + "'"; + } + }; + + + static final UsedProperties.IntJcstressProperty LINK_PORT = new UsedProperties.IntJcstressProperty("jcstress.link.port", 0) { + @Override + public String getDescription() { + return getKey() + " is port where to connect to forked VMs on " + LINK_ADDRESS.getKey() + ". Defaults to " + getDefault() + " (random free port)." + + " Set to " + UsedProperties.getJcstressLinkPort(); + } + }; + + static final UsedProperties.IntJcstressProperty LINK_TIMEOUTMS = new UsedProperties.IntJcstressProperty("jcstress.link.timeoutMs", 30 * 1000) { + @Override + public String getDescription() { + return getKey() + " set timeout to forked VM communication ms." + + " Defaults to " + getDefault() + "ms. Set to " + getValue() + "ms."; + } + }; + + + private static String getListenAddressForInfo() { + try { + return UsedProperties.getListenAddress().toString(); + } catch (Exception ex) { + return ex.getMessage(); + } + } + + @Override + public List getHelp() { + return Arrays.asList( + LINK_ADDRESS.getDescription(), + LINK_PORT.getDescription(), + LINK_TIMEOUTMS.getDescription()); + } + + @Override + public String getTitle() { + return "Properties handling forked VMs. Modify only if you are sure what youa re doing"; + } + +} diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/properties/TestTimeProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/TestTimeProperties.java new file mode 100644 index 00000000..98afb622 --- /dev/null +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/TestTimeProperties.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2005, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.openjdk.jcstress.properties; + +import org.openjdk.jcstress.Options; + +import java.util.Arrays; +import java.util.List; + +class TestTimeProperties implements UsedProperties.ProeprtiesHelpProvider { + + static final UsedProperties.IntJcstressProperty TIMEBUDGET_DEFAULTPERTESTMS = new UsedProperties.IntJcstressProperty("jcstress.timeBudget.defaultPerTestMs", 3000) { + @Override + public String getDescription() { + return getKey() + " set default time the individual test executes. Defaults to " + getDefault() + + "ms set to " + getValue() + "ms"; + } + }; + + static final UsedProperties.IntJcstressProperty TIMEBUDGET_MINTIMEMS = new UsedProperties.IntJcstressProperty("jcstress.timeBudget.minTimeMs", 30) { + @Override + public String getDescription() { + return getKey() + " set minimal time the individual test executes. Defaults to " + getDefault() + + "ms set to " + getValue() + "ms"; + } + }; + + static final UsedProperties.IntJcstressProperty TIMEBUDGET_MAXTIMEMS = new UsedProperties.IntJcstressProperty("jcstress.timeBudget.maxTimeMs", 60_000) { + @Override + public String getDescription() { + return getKey() + + " set maximum time the individual test executes. Defaults to " + getDefault() + + "ms set to " + getValue() + "ms"; + } + }; + + static final String TIMEBUDGET_ADDITIONAL_COMMENT = "The time each test is run is (simplified) calculated as value of " + Options.TIME_BUDGET_SWITCH + " switch divided by number of tests (after all filters applied)" + + " If te resulting time is smaller then " + TIMEBUDGET_MINTIMEMS.getKey() + ", it is used. If it si bigger then " + TIMEBUDGET_MAXTIMEMS.getKey() + " it is used. If no " + Options.TIME_BUDGET_SWITCH + " is set," + + " then " + TIMEBUDGET_DEFAULTPERTESTMS.getKey() + " is used. See " + Options.TIME_BUDGET_SWITCH + " for more info. Properties do not accept unit suffixes."; + + @Override + public List getHelp() { + return Arrays.asList( + TIMEBUDGET_DEFAULTPERTESTMS.getDescription(), + TIMEBUDGET_MINTIMEMS.getDescription(), + TIMEBUDGET_MAXTIMEMS.getDescription(), + TIMEBUDGET_ADDITIONAL_COMMENT); + } + + @Override + public String getTitle() { + return "Individual test time execution properties"; + } +} diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/properties/UiProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/UiProperties.java new file mode 100644 index 00000000..c20d8c90 --- /dev/null +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/UiProperties.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2005, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.openjdk.jcstress.properties; + +import java.util.Arrays; +import java.util.List; + +class UiProperties implements UsedProperties.ProeprtiesHelpProvider { + + static final UsedProperties.LongJcstressProperty CONSOLE_PRINTINTERVALMS = new UsedProperties.LongJcstressProperty("jcstress.console.printIntervalMs", 1_000L, 15_000L) { + + @Override + public Long getValue() { + return Long.getLong(getKey(), null); + } + + @Override + public String getDescription() { + return getKey() + " sets interval how often to print results to console in ms. Have two defaults: " + + getDefaults().get(0) + "ms in interactive mode and " + + getDefaults().get(1) + "ms in noninteractive mode. Set to " + + UsedProperties.getPrintIntervalMs() + "ms"; + } + }; + + @Override + public List getHelp() { + return Arrays.asList(CONSOLE_PRINTINTERVALMS.getDescription()); + } + + @Override + public String getTitle() { + return "Properties modyfying user appearance"; + } +} diff --git a/jcstress-core/src/main/java/org/openjdk/jcstress/properties/UsedProperties.java b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/UsedProperties.java new file mode 100644 index 00000000..9a6a80f6 --- /dev/null +++ b/jcstress-core/src/main/java/org/openjdk/jcstress/properties/UsedProperties.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2005, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.openjdk.jcstress.properties; + + +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.openjdk.jcstress.properties.TestTimeProperties.*; +import static org.openjdk.jcstress.properties.ForkedVmProperties.*; +import static org.openjdk.jcstress.properties.UiProperties.*; + +/** + * Known Properties affecting JCStress. Some of them publicly document themselves, some do not need to. + */ +public class UsedProperties { + + interface ProeprtiesHelpProvider { + List getHelp(); + + String getTitle(); + } + + static abstract class JcstressProperty { + private final String key; + private final List defaults; + + public JcstressProperty(String key, T[] defaults) { + this.key = key; + this.defaults = Collections.unmodifiableList(Arrays.asList(defaults)); + } + + public String getKey() { + return key; + } + + public List getDefaults() { + return defaults; + } + + public T getDefault() { + return defaults.get(0); + } + + public boolean isCustom() { + return System.getProperty(getKey()) != null; + } + + public abstract String getDescription(); + + public abstract T getValue(); + } + + static abstract class IntJcstressProperty extends JcstressProperty { + + public IntJcstressProperty(String key, Integer... defaults) { + super(key, defaults); + } + + @Override + public Integer getValue() { + return Integer.getInteger(getKey(), getDefault()); + } + } + + static abstract class LongJcstressProperty extends JcstressProperty { + + public LongJcstressProperty(String key, Long... defaults) { + super(key, defaults); + } + + @Override + public Long getValue() { + return Long.getLong(getKey(), getDefault()); + } + } + + + static abstract class StringJcstressProperty extends JcstressProperty { + + public StringJcstressProperty(String key, String... defaults) { + super(key, defaults); + } + + @Override + public String getValue() { + return System.getProperty(getKey(), getDefault()); + } + } + + /** + * utility class + */ + private UsedProperties() { + } + + public static int getJcstressTimeBudgetDefaultPerTestMs() { + return TIMEBUDGET_DEFAULTPERTESTMS.getValue(); + } + + public static int getJcstressTimeBudgetMinTimeMs() { + return TIMEBUDGET_MINTIMEMS.getValue(); + } + + public static int getJcstressTimeBudgetMaxTimeMs() { + return TIMEBUDGET_MAXTIMEMS.getValue(); + } + + private static String getJcstressLinkAddress() { + return LINK_ADDRESS.getValue(); + } + + public static InetAddress getListenAddress() { + // Try to use user-provided override first. + if (UsedProperties.getJcstressLinkAddress() != null) { + try { + return InetAddress.getByName(UsedProperties.getJcstressLinkAddress()); + } catch (UnknownHostException e) { + // override failed, notify user + throw new IllegalStateException("Can not initialize binary link.", e); + } + } + + return InetAddress.getLoopbackAddress(); + } + + + public static int getJcstressLinkPort() { + return LINK_PORT.getValue(); + } + + + public static int getJcstressLinkTimeoutMs() { + return LINK_TIMEOUTMS.getValue(); + } + + public static boolean isProgressInteractive() { + return System.console() != null; + } + + public static long getPrintIntervalMs() { + return (CONSOLE_PRINTINTERVALMS.isCustom()) ? + CONSOLE_PRINTINTERVALMS.getValue() : + isProgressInteractive() ? CONSOLE_PRINTINTERVALMS.getDefaults().get(0) : CONSOLE_PRINTINTERVALMS.getDefaults().get(1); + } + + public static void printHelpOn(PrintStream ouer) { + ouer.println("JCStress recognize several internal properties:"); + for (ProeprtiesHelpProvider provider : new ProeprtiesHelpProvider[]{new TestTimeProperties(), new ForkedVmProperties(), new UiProperties()}) { + ouer.println(" " + provider.getTitle()); + for (String line : provider.getHelp()) { + ouer.println(" * " + line); + } + } + } +} \ No newline at end of file