This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-rng.git
commit bf55f9444b38cda328cd1d9ca9731a65cc72922e Author: aherbert <[email protected]> AuthorDate: Fri Sep 27 14:09:37 2019 +0100 Fix PMD errors in stress test code. --- .../rng/examples/stress/BridgeTestCommand.java | 18 ++- .../examples/stress/ExamplesStressApplication.java | 2 +- .../commons/rng/examples/stress/ListCommand.java | 6 +- .../examples/stress/ManifestVersionProvider.java | 2 +- .../commons/rng/examples/stress/OutputCommand.java | 35 +++-- .../commons/rng/examples/stress/ProcessUtils.java | 4 +- .../rng/examples/stress/ResultsCommand.java | 141 ++++++++++++--------- .../rng/examples/stress/StressTestCommand.java | 126 ++++++++++-------- 8 files changed, 191 insertions(+), 143 deletions(-) diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/BridgeTestCommand.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/BridgeTestCommand.java index 311eff9..b0cc26e 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/BridgeTestCommand.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/BridgeTestCommand.java @@ -87,7 +87,7 @@ class BridgeTestCommand implements Callable<Void> { * of the executable. Captures stdout of the executable to a file. */ private void runBridgeTest() { - final ArrayList<String> command = ProcessUtils.buildSubProcessCommand(executable, executableArguments); + final List<String> command = ProcessUtils.buildSubProcessCommand(executable, executableArguments); try { final File dataFile = new File(fileOutputPrefix + ".data"); @@ -123,17 +123,17 @@ class BridgeTestCommand implements Callable<Void> { } } - Integer exitValue = ProcessUtils.getExitValue(testingProcess); - if (exitValue != null) { + final Integer exitValue = ProcessUtils.getExitValue(testingProcess); + if (exitValue == null) { + LogUtils.error("%s did not exit. Process was killed.", command.get(0)); + } else { if (exitValue.intValue() != 0) { LogUtils.error("%s exit code = %d", command.get(0), exitValue.intValue()); } - } else { - LogUtils.error("%s did not exit. Process was killed.", command.get(0)); } } catch (IOException ex) { - throw new ApplicationException("Failed to run process: " + ex.getMessage()); + throw new ApplicationException("Failed to run process: " + ex.getMessage(), ex); } } @@ -154,9 +154,7 @@ class BridgeTestCommand implements Callable<Void> { int value, boolean littleEndian) throws IOException { OutputCommand.writeInt(textOutput, value); - if (littleEndian) { - value = Integer.reverseBytes(value); - } - dataOutput.writeInt(value); + final int binaryValue = littleEndian ? Integer.reverseBytes(value) : value; + dataOutput.writeInt(binaryValue); } } diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ExamplesStressApplication.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ExamplesStressApplication.java index 495dfec..83f7f2b 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ExamplesStressApplication.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ExamplesStressApplication.java @@ -73,7 +73,7 @@ public final class ExamplesStressApplication { try { // Parse the command line and invokes the Callable program (RNGUtilities) cmd.parseWithHandler(new RunLast(), args); - } catch (final picocli.CommandLine.ExecutionException ex) { + } catch (final CommandLine.ExecutionException ex) { final Throwable cause = ex.getCause(); if (cause != null) { // If this was an exception generated by the application then the full diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ListCommand.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ListCommand.java index 5f774e4..16fa969 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ListCommand.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ListCommand.java @@ -167,10 +167,10 @@ class ListCommand implements Callable<Void> { format = String.format("%%-%ds %%-%ds ", idWidth + 2, randomSourceWidth); for (final StressTestData data : testData) { formatter.format(format, data.getId(), data.getRandomSource().name()); - if (data.getArgs() != null) { - formatter.format("%-7d %s", data.getTrials(), Arrays.toString(data.getArgs())); - } else { + if (data.getArgs() == null) { appendable.append(Integer.toString(data.getTrials())); + } else { + formatter.format("%-7d %s", data.getTrials(), Arrays.toString(data.getArgs())); } appendable.append(newLine); } diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ManifestVersionProvider.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ManifestVersionProvider.java index 52b55c9..608197d 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ManifestVersionProvider.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ManifestVersionProvider.java @@ -36,7 +36,7 @@ class ManifestVersionProvider implements IVersionProvider { /** {@inheritDoc} */ @Override public String[] getVersion() throws Exception { - final Enumeration<URL> resources = ManifestVersionProvider.class.getClassLoader() + final Enumeration<URL> resources = Thread.currentThread().getContextClassLoader() .getResources("META-INF/MANIFEST.MF"); while (resources.hasMoreElements()) { final URL url = resources.nextElement(); diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/OutputCommand.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/OutputCommand.java index f5d46cb..6e15d3a 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/OutputCommand.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/OutputCommand.java @@ -28,8 +28,6 @@ import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -37,6 +35,7 @@ import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Formatter; import java.util.List; @@ -52,6 +51,10 @@ import java.util.concurrent.Callable; class OutputCommand implements Callable<Void> { /** The new line characters. */ private static final String NEW_LINE = System.lineSeparator(); + /** Character '['. */ + private static final char LEFT_SQUARE_BRACKET = '['; + /** Character ']'. */ + private static final char RIGHT_SQUARE_BRACKET = ']'; /** Lookup table for binary representation of bytes. */ private static final String[] BIT_REP = { @@ -170,7 +173,7 @@ class OutputCommand implements Callable<Void> { // Strip these for convenience. stripArrayFormatting(arguments); - for (String argument : arguments) { + for (final String argument : arguments) { data.add(RNGUtils.parseArgument(argument)); } try { @@ -193,11 +196,11 @@ class OutputCommand implements Callable<Void> { if (size > 1) { // These will not be empty as they were created from command-line args. final String first = arguments.get(0); - if (first.charAt(0) == '[') { + if (first.charAt(0) == LEFT_SQUARE_BRACKET) { arguments.set(0, first.substring(1)); } final String last = arguments.get(size - 1); - if (last.charAt(last.length() - 1) == ']') { + if (last.charAt(last.length() - 1) == RIGHT_SQUARE_BRACKET) { arguments.set(size - 1, last.substring(0, last.length() - 1)); } } @@ -217,8 +220,8 @@ class OutputCommand implements Callable<Void> { private OutputStream createOutputStream() { if (fileOutput != null) { try { - return new FileOutputStream(fileOutput); - } catch (FileNotFoundException ex) { + Files.newOutputStream(fileOutput.toPath()); + } catch (IOException ex) { throw new ApplicationException("Failed to create output: " + fileOutput, ex); } } @@ -283,12 +286,11 @@ class OutputCommand implements Callable<Void> { output.write(NEW_LINE); output.write("numbit: 32"); output.write(NEW_LINE); - while (count > 0) { - count--; + for (long c = 0; c < count; c++) { // Unsigned integers final String text = Long.toString(rng.nextInt() & 0xffffffffL); // Left pad with spaces - for (int i = 10 - text.length(); i-- > 0;) { + for (int i = 10 - text.length(); i > 0; i--) { output.write(' '); } output.write(text); @@ -319,14 +321,12 @@ class OutputCommand implements Callable<Void> { static void writeBinaryIntData(final UniformRandomProvider rng, long count, final OutputStream out) throws IOException { - if (count < 1) { - // Effectively unlimited: program must be killed - count = Long.MAX_VALUE; - } + // If count is not positive use max value. + // This is effectively unlimited: program must be killed. + final long limit = (count < 1) ? Long.MAX_VALUE : count; try (DataOutputStream data = new DataOutputStream( new BufferedOutputStream(out))) { - while (count > 0) { - count--; + for (long c = 0; c < limit; c++) { data.writeInt(rng.nextInt()); } } @@ -347,8 +347,7 @@ class OutputCommand implements Callable<Void> { checkCount(count, OutputFormat.BITS); try (BufferedWriter output = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) { - while (count > 0) { - count--; + for (long c = 0; c < count; c++) { writeInt(output, rng.nextInt()); } } diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ProcessUtils.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ProcessUtils.java index b07aab1..3c94cc0 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ProcessUtils.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ProcessUtils.java @@ -67,8 +67,8 @@ final class ProcessUtils { * @return the command * @throws ApplicationException If the executable path cannot be resolved */ - static ArrayList<String> buildSubProcessCommand(File executable, - List<String> executableArguments) { + static List<String> buildSubProcessCommand(File executable, + List<String> executableArguments) { final ArrayList<String> command = new ArrayList<>(); try { command.add(executable.getCanonicalPath()); diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ResultsCommand.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ResultsCommand.java index a564617..2f20252 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ResultsCommand.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/ResultsCommand.java @@ -26,8 +26,6 @@ import picocli.CommandLine.Parameters; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -80,6 +78,12 @@ class ResultsCommand implements Callable<Void> { private static final String DIEHARDER_SUMS = "diehard_sums"; /** The string identifying a bit-reversed generator. */ private static final String BIT_REVERSED = "Bit-reversed"; + /** Character '\'. */ + private static final char FORWARD_SLASH = '\\'; + /** Character '/'. */ + private static final char BACK_SLASH = '\\'; + /** Character '|'. */ + private static final char PIPE = '|'; /** The standard options. */ @Mixin @@ -154,7 +158,7 @@ class ResultsCommand implements Callable<Void> { /** The test application format. */ private final TestFormat testFormat; /** The names of the failed tests. */ - private final ArrayList<String> failedTests = new ArrayList<>(); + private final List<String> failedTests = new ArrayList<>(); /** The test application name. */ private String testApplicationName; /** Flag to indicate results are complete (i.e. not still in progress). */ @@ -226,7 +230,7 @@ class ResultsCommand implements Callable<Void> { * * @return the failed tests */ - ArrayList<String> getFailedTests() { + List<String> getFailedTests() { return failedTests; } @@ -263,7 +267,7 @@ class ResultsCommand implements Callable<Void> { * @return the test application name */ String getTestApplicationName() { - return testApplicationName != null ? testApplicationName : getTestFormat().toString(); + return testApplicationName == null ? getTestFormat().toString() : testApplicationName; } /** @@ -309,7 +313,7 @@ class ResultsCommand implements Callable<Void> { default: throw new ApplicationException("Unknown output format: " + outputFormat); } - } catch (IOException ex) { + } catch (final IOException ex) { throw new ApplicationException("IO error: " + ex.getMessage(), ex); } return null; @@ -322,7 +326,7 @@ class ResultsCommand implements Callable<Void> { */ private List<TestResult> readResults() { final ArrayList<TestResult> results = new ArrayList<>(); - for (File resultFile : resultsFiles) { + for (final File resultFile : resultsFiles) { readResults(results, resultFile); } return results; @@ -336,13 +340,13 @@ class ResultsCommand implements Callable<Void> { */ private void readResults(List<TestResult> results, File resultFile) { - final ArrayList<String> contents = readFileContents(resultFile); + final List<String> contents = readFileContents(resultFile); // Files may have multiple test results per file (i.e. appended output) final List<List<String>> outputs = splitContents(contents); if (outputs.isEmpty()) { - LogUtils.error("No test output in file: " + resultFile); + LogUtils.error("No test output in file: %s", resultFile); } else { - for (List<String> testOutput : outputs) { + for (final List<String> testOutput : outputs) { results.add(readResult(resultFile, testOutput)); } } @@ -355,14 +359,13 @@ class ResultsCommand implements Callable<Void> { * @return the file contents * @throws ApplicationException If the file cannot be read. */ - private static ArrayList<String> readFileContents(File resultFile) { + private static List<String> readFileContents(File resultFile) { final ArrayList<String> contents = new ArrayList<>(); try (BufferedReader reader = Files.newBufferedReader(resultFile.toPath())) { - String line; - while ((line = reader.readLine()) != null) { + for (String line = reader.readLine(); line != null; line = reader.readLine()) { contents.add(line); } - } catch (IOException ex) { + } catch (final IOException ex) { throw new ApplicationException("Failed to read file contents: " + resultFile, ex); } return contents; @@ -544,8 +547,8 @@ class ResultsCommand implements Callable<Void> { // Note: // This will count sub-parts of the same test as distinct failures. while (iter.hasNext()) { - String line = iter.next(); - Matcher matcher = TESTU01_TEST_RESULT_PATTERN.matcher(line); + final String line = iter.next(); + final Matcher matcher = TESTU01_TEST_RESULT_PATTERN.matcher(line); if (matcher.find()) { testResult.addFailedTest(matcher.group(1).trim()); } else if (TEST_DURATION_PATTERN.matcher(line).find()) { @@ -580,8 +583,8 @@ class ResultsCommand implements Callable<Void> { private OutputStream createOutputStream() { if (fileOutput != null) { try { - return new FileOutputStream(fileOutput); - } catch (FileNotFoundException ex) { + Files.newOutputStream(fileOutput.toPath()); + } catch (final IOException ex) { throw new ApplicationException("Failed to create output: " + fileOutput, ex); } } @@ -674,8 +677,8 @@ class ResultsCommand implements Callable<Void> { .append(result.getFailureCountString()).append("}}"); // Convert to web-link name separators for (int i = 0; i < sb.length(); i++) { - if (sb.charAt(i) == '\\') { - sb.setCharAt(i, '/'); + if (sb.charAt(i) == BACK_SLASH) { + sb.setCharAt(i, FORWARD_SLASH); } } return sb.toString(); @@ -697,14 +700,14 @@ class ResultsCommand implements Callable<Void> { output.write(separator); // This will collate results for each combination of 'RandomSource + bitReversed' - for (RandomSource randomSource : randomSources) { - for (boolean reversed : bitReversed) { + for (final RandomSource randomSource : randomSources) { + for (final boolean reversed : bitReversed) { output.write('|'); writeAPTColumn(output, randomSource.toString()); if (showBitReversedColumn) { writeAPTColumn(output, Boolean.toString(reversed)); } - for (String testName : testNames) { + for (final String testName : testNames) { final List<TestResult> testResults = getTestResults(results, randomSource, reversed, testName); writeAPTColumn(output, testResults.stream() .map(toAPTString) @@ -725,7 +728,7 @@ class ResultsCommand implements Callable<Void> { */ private static List<RandomSource> getRandomSources(List<TestResult> results) { final EnumSet<RandomSource> set = EnumSet.noneOf(RandomSource.class); - for (TestResult result : results) { + for (final TestResult result : results) { set.add(result.getRandomSource()); } final ArrayList<RandomSource> list = new ArrayList<>(set); @@ -741,18 +744,18 @@ class ResultsCommand implements Callable<Void> { */ private static List<Boolean> getBitReversed(List<TestResult> results) { final ArrayList<Boolean> list = new ArrayList<>(2); - if (!results.isEmpty()) { + if (results.isEmpty()) { + // Default to no bit-reversed results + list.add(Boolean.FALSE); + } else { final boolean first = results.get(0).isBitReversed(); list.add(first); - for (TestResult result : results) { + for (final TestResult result : results) { if (first != result.isBitReversed()) { list.add(!first); break; } } - } else { - // Default to no bit-reversed results - list.add(Boolean.FALSE); } Collections.sort(list); return list; @@ -766,7 +769,7 @@ class ResultsCommand implements Callable<Void> { */ private static List<String> getTestNames(List<TestResult> results) { final HashSet<String> set = new HashSet<>(); - for (TestResult result : results) { + for (final TestResult result : results) { set.add(result.getTestApplicationName()); } final ArrayList<String> list = new ArrayList<>(set); @@ -808,7 +811,7 @@ class ResultsCommand implements Callable<Void> { */ private static String getPathPrefix(TestResult testResult) { final String parent = testResult.getResultFile().getParent(); - return parent != null ? parent : ""; + return parent == null ? "" : parent; } /** @@ -820,11 +823,11 @@ class ResultsCommand implements Callable<Void> { */ private static String createAPTHeader(boolean showBitReversedColumn, List<String> testNames) { - final StringBuilder sb = new StringBuilder("|| RNG identifier ||"); + final StringBuilder sb = new StringBuilder(100).append("|| RNG identifier ||"); if (showBitReversedColumn) { - sb.append(' ').append("Bit-reversed ||"); + sb.append(" Bit-reversed ||"); } - for (String name : testNames) { + for (final String name : testNames) { sb.append(' ').append(name).append(" ||"); } return sb.toString(); @@ -843,7 +846,7 @@ class ResultsCommand implements Callable<Void> { // character, "+-" for all other occurrences except "-+" at the end final StringBuilder sb = new StringBuilder(header); for (int i = 0; i < header.length(); i++) { - if (sb.charAt(i) == '|') { + if (sb.charAt(i) == PIPE) { sb.setCharAt(i, i == 0 ? '*' : '+'); sb.setCharAt(i + 1, '-'); } else { @@ -885,7 +888,7 @@ class ResultsCommand implements Callable<Void> { boolean bitReversed, String testName) { final ArrayList<TestResult> list = new ArrayList<>(); - for (TestResult result : results) { + for (final TestResult result : results) { if (result.getRandomSource() == randomSource && result.bitReversed == bitReversed && result.getTestApplicationName().equals(testName)) { @@ -914,14 +917,7 @@ class ResultsCommand implements Callable<Void> { // Make bit-reversed column optional if no generators are bit reversed. final boolean showBitReversedColumn = bitReversed.contains(Boolean.TRUE); - final ArrayList<List<String>> columns = new ArrayList<>(); - columns.add(createColumn("RNG")); - if (showBitReversedColumn) { - columns.add(createColumn(BIT_REVERSED)); - } - for (String testName : testNames) { - columns.add(createColumn(testName)); - } + final List<List<String>> columns = createColumns(testNames, showBitReversedColumn); // Add all data // This will collate results for each combination of 'RandomSource + bitReversed' @@ -932,7 +928,7 @@ class ResultsCommand implements Callable<Void> { if (showBitReversedColumn) { columns.get(i++).add(Boolean.toString(reversed)); } - for (String testName : testNames) { + for (final String testName : testNames) { final List<TestResult> testResults = getTestResults(results, randomSource, reversed, testName); columns.get(i++).add(testResults.stream() @@ -943,17 +939,7 @@ class ResultsCommand implements Callable<Void> { } // Create format using the column widths - final StringBuilder sb = new StringBuilder(); - try (Formatter formatter = new Formatter(sb)) { - for (int i = 0; i < columns.size(); i++) { - if (i != 0) { - sb.append('\t'); - } - formatter.format("%%-%ds", getColumnWidth(columns.get(i))); - } - } - sb.append(System.lineSeparator()); - final String format = sb.toString(); + final String format = createTextFormatFromColumnWidths(columns); // Output try (BufferedWriter output = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)); @@ -970,6 +956,26 @@ class ResultsCommand implements Callable<Void> { } /** + * Creates the columns. + * + * @param testNames the test names + * @param showBitReversedColumn Set to true to show the bit reversed column + * @return the list of columns + */ + private static List<List<String>> createColumns(final List<String> testNames, + final boolean showBitReversedColumn) { + final ArrayList<List<String>> columns = new ArrayList<>(); + columns.add(createColumn("RNG")); + if (showBitReversedColumn) { + columns.add(createColumn(BIT_REVERSED)); + } + for (final String testName : testNames) { + columns.add(createColumn(testName)); + } + return columns; + } + + /** * Creates the column. * * @param columnName Column name. @@ -981,6 +987,27 @@ class ResultsCommand implements Callable<Void> { return list; } + + /** + * Creates the text format from column widths. + * + * @param columns Columns. + * @return the text format string + */ + private static String createTextFormatFromColumnWidths(final List<List<String>> columns) { + final StringBuilder sb = new StringBuilder(); + try (Formatter formatter = new Formatter(sb)) { + for (int i = 0; i < columns.size(); i++) { + if (i != 0) { + sb.append('\t'); + } + formatter.format("%%-%ds", getColumnWidth(columns.get(i))); + } + } + sb.append(System.lineSeparator()); + return sb.toString(); + } + /** * Gets the column width using the maximum length of the column items. * @@ -989,7 +1016,7 @@ class ResultsCommand implements Callable<Void> { */ private static int getColumnWidth(List<String> column) { int width = 0; - for (String text : column) { + for (final String text : column) { width = Math.max(width, text.length()); } return width; diff --git a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/StressTestCommand.java b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/StressTestCommand.java index 9eaa405..2bc87fd 100644 --- a/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/StressTestCommand.java +++ b/commons-rng-examples/examples-stress/src/main/java/org/apache/commons/rng/examples/stress/StressTestCommand.java @@ -44,6 +44,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; /** * Specification for the "stress" command. @@ -57,6 +58,9 @@ import java.util.concurrent.TimeUnit; description = {"Run repeat trials of random data generators using a provided test application.", "Data is transferred to the application sub-process via standard input."}) class StressTestCommand implements Callable<Void> { + /** 1000. Any value below this can be exactly represented to 3 significant figures. */ + private static final int ONE_THOUSAND = 1000; + /** The standard options. */ @Mixin private StandardOptions reusableOptions; @@ -160,11 +164,16 @@ class StressTestCommand implements Callable<Void> { @Option(names = {"--dry-run"}, description = "Perform a dry run where the generators and output files are created " + "but the stress test is not executed.") - private boolean dryRun = false; + private boolean dryRun; - /** The stop file exists flag. This is set in a synchronised method. */ + /** The locl to hold when checking the stop file. */ + private ReentrantLock stopFileLock = new ReentrantLock(false); + /** The stop file exists flag. This should be read/updated when holding the lock. */ private boolean stopFileExists; - /** The timestamp when the stop file was last checked. */ + /** + * The timestamp when the stop file was last checked. + * This should be read/updated when holding the lock. + */ private long stopFileTimestamp; /** @@ -215,26 +224,41 @@ class StressTestCommand implements Callable<Void> { /** * Check if the stop file exists. * - * <p>This method is synchronized. It will log a message if the file exists one time only. + * <p>This method is thread-safe. It will log a message if the file exists one time only. * * @return true if the stop file exists */ - private synchronized boolean stopFileExists() { - if (!stopFileExists) { - // This should hit the filesystem each time it is called. - // To prevent this happening a lot when all the first set of tasks run use - // a timestamp to limit the check to 1 time each interval. - final long timestamp = System.currentTimeMillis(); - if (timestamp > stopFileTimestamp) { - stopFileTimestamp = timestamp + TimeUnit.SECONDS.toMillis(2); - stopFileExists = stopFile.exists(); - if (stopFileExists) { - LogUtils.info("Stop file detected: " + stopFile); - LogUtils.info("No further tasks will start"); + private boolean isStopFileExists() { + stopFileLock.lock(); + try { + if (!stopFileExists) { + // This should hit the filesystem each time it is called. + // To prevent this happening a lot when all the first set of tasks run use + // a timestamp to limit the check to 1 time each interval. + final long timestamp = System.currentTimeMillis(); + if (timestamp > stopFileTimestamp) { + checkStopFile(timestamp); } } + return stopFileExists; + } finally { + stopFileLock.unlock(); + } + } + + /** + * Check if the stop file exists. Update the timestamp for the next check. If the stop file + * does exists then log a message. + * + * @param timestamp Timestamp of the last check. + */ + private void checkStopFile(final long timestamp) { + stopFileTimestamp = timestamp + TimeUnit.SECONDS.toMillis(2); + stopFileExists = stopFile.exists(); + if (stopFileExists) { + LogUtils.info("Stop file detected: %s", stopFile); + LogUtils.info("No further tasks will start"); } - return stopFileExists; } /** @@ -282,14 +306,14 @@ class StressTestCommand implements Callable<Void> { * @param stressTestData List of generators to be tested. */ private void runStressTest(Iterable<StressTestData> stressTestData) { - final ArrayList<String> command = ProcessUtils.buildSubProcessCommand(executable, executableArguments); + final List<String> command = ProcessUtils.buildSubProcessCommand(executable, executableArguments); // Check existing output files before starting the tasks. final String basePath = fileOutputPrefix.getAbsolutePath(); checkExistingOutputFiles(basePath, stressTestData); LogUtils.info("Running stress test ..."); - LogUtils.info("Shutdown by creating stop file: " + stopFile); + LogUtils.info("Shutdown by creating stop file: %s", stopFile); final ProgressTracker progressTracker = new ProgressTracker(countTrials(stressTestData)); // Run tasks with parallel execution. @@ -398,7 +422,7 @@ class StressTestCommand implements Callable<Void> { */ private void submitTasks(ExecutorService service, List<Future<?>> taskList, - ArrayList<String> command, + List<String> command, String basePath, StressTestData testData, ProgressTracker progressTracker) { @@ -472,9 +496,11 @@ class StressTestCommand implements Callable<Void> { /** * Increment the progress. */ - synchronized void incrementProgress() { - count++; - showProgress(); + void incrementProgress() { + synchronized (this) { + count++; + showProgress(); + } } /** @@ -558,7 +584,7 @@ class StressTestCommand implements Callable<Void> { /** {@inheritDoc} */ @Override public void run() { - if (cmd.stopFileExists()) { + if (cmd.isStopFileExists()) { // Do nothing return; } @@ -609,7 +635,7 @@ class StressTestCommand implements Callable<Void> { sink.writeInt(rng.nextInt()); numbersUsed++; } - } catch (final IOException e) { + } catch (final IOException ignored) { // Hopefully getting here when the analyzing software terminates. } @@ -624,33 +650,32 @@ class StressTestCommand implements Callable<Void> { * {@code output} file. */ private void printHeader() throws IOException { - final StringBuilder sb = new StringBuilder(); - sb.append(C).append(N); - sb.append(C).append("RandomSource: ").append(randomSource.name()).append(N); - sb.append(C).append("RNG: ").append(rng.toString()).append(N); - sb.append(C).append("Seed: ").append(RNGUtils.encodeHex(seed)).append(N); - sb.append(C).append(N); + final StringBuilder sb = new StringBuilder(200); + sb.append(C).append(N) + .append(C).append("RandomSource: ").append(randomSource.name()).append(N) + .append(C).append("RNG: ").append(rng.toString()).append(N) + .append(C).append("Seed: ").append(RNGUtils.encodeHex(seed)).append(N) + .append(C).append(N) // Match the output of 'java -version', e.g. // java version "1.8.0_131" // Java(TM) SE Runtime Environment (build 1.8.0_131-b11) // Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode) - sb.append(C).append("Java: ").append(System.getProperty("java.version")).append(N); + .append(C).append("Java: ").append(System.getProperty("java.version")).append(N); appendNameAndVersion(sb, "Runtime", "java.runtime.name", "java.runtime.version"); appendNameAndVersion(sb, "JVM", "java.vm.name", "java.vm.version", "java.vm.info"); sb.append(C).append("OS: ").append(System.getProperty("os.name")) .append(' ').append(System.getProperty("os.version")) - .append(' ').append(System.getProperty("os.arch")).append(N); - sb.append(C).append("Native byte-order: ").append(ByteOrder.nativeOrder()).append(N); - sb.append(C).append(N); - - sb.append(C).append("Analyzer: "); + .append(' ').append(System.getProperty("os.arch")).append(N) + .append(C).append("Native byte-order: ").append(ByteOrder.nativeOrder()).append(N) + .append(C).append(N) + .append(C).append("Analyzer: "); for (final String s : command) { sb.append(s).append(' '); } - sb.append(N); - sb.append(C).append(N); + sb.append(N) + .append(C).append(N); appendDate(sb, "Start").append(C).append(N); @@ -667,21 +692,20 @@ class StressTestCommand implements Callable<Void> { */ private void printFooter(long nanoTime, Object exitValue) throws IOException { - final StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(200); sb.append(C).append(N); appendDate(sb, "End").append(C).append(N); - sb.append(C).append("Exit value: ").append(exitValue).append(N); - sb.append(C).append("Numbers used: ").append(numbersUsed) - .append(" >= 2^").append(log2(numbersUsed)) - .append(" (").append(bytesToString(numbersUsed * 4)).append(')').append(N); - sb.append(C).append(N); + sb.append(C).append("Exit value: ").append(exitValue).append(N) + .append(C).append("Numbers used: ").append(numbersUsed) + .append(" >= 2^").append(log2(numbersUsed)) + .append(" (").append(bytesToString(numbersUsed * 4)).append(')').append(N) + .append(C).append(N); final double duration = nanoTime * 1e-9 / 60; - sb.append(C).append("Test duration: ").append(duration).append(" minutes").append(N); - - sb.append(C).append(N); + sb.append(C).append("Test duration: ").append(duration).append(" minutes").append(N) + .append(C).append(N); write(sb, output, true); } @@ -726,7 +750,7 @@ class StressTestCommand implements Callable<Void> { .append(System.getProperty(nameKey, "?")) .append(" (build ") .append(System.getProperty(versionKey, "?")); - for (String key : infoKeys) { + for (final String key : infoKeys) { final String value = System.getProperty(key, ""); if (!value.isEmpty()) { sb.append(", ").append(value); @@ -748,7 +772,7 @@ class StressTestCommand implements Callable<Void> { private static StringBuilder appendDate(StringBuilder sb, String prefix) { // Use local date format. It is not thread safe. - final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); + final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US); return appendPrefix(sb, prefix).append(dateFormat.format(new Date())).append(N); } @@ -796,7 +820,7 @@ class StressTestCommand implements Callable<Void> { */ static String bytesToString(long bytes) { // When using the smallest unit no decimal point is needed, because it's the exact number. - if (bytes < 1000) { + if (bytes < ONE_THOUSAND) { return bytes + " " + SI_UNITS[0]; }
