How to diagnose forked jcstress execution problems?

Jerzy Krolak j.krolak at gmail.com
Thu Mar 23 19:19:29 UTC 2017


> Please resend both patches, I need them on mailing list record.

Here's all three patches. I've improved the 'error reporting' part - a new
test case added.

A note about the 'windows-grouping-character' - I'm not 100% sure if
jcstress code is the right place for this kind of fix. Any thoughts?

Thanks,
Jerzy
-------------- next part --------------
diff -r 9f21d933addf jcstress-core/src/main/java/org/openjdk/jcstress/EmbeddedExecutor.java
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/EmbeddedExecutor.java	Fri Mar 17 11:23:01 2017 +0100
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/EmbeddedExecutor.java	Wed Mar 22 22:21:18 2017 +0100
@@ -37,6 +37,8 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 
+import static org.openjdk.jcstress.util.StringUtils.getStacktrace;
+
 public class EmbeddedExecutor {
 
     private final ExecutorService pool;
@@ -80,11 +82,11 @@
                 o.run();
             } catch (ClassFormatError | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
                 TestResult result = new TestResult(config, Status.API_MISMATCH, 0);
-                result.addAuxData(e.getMessage());
+                result.addAuxData(getStacktrace(e));
                 sink.add(result);
             } catch (Throwable ex) {
                 TestResult result = new TestResult(config, Status.TEST_ERROR, 0);
-                result.addAuxData(ex.getMessage());
+                result.addAuxData(getStacktrace(ex));
                 sink.add(result);
             } finally {
                 if (onFinish != null) {
diff -r 9f21d933addf jcstress-core/src/main/java/org/openjdk/jcstress/infra/runners/Runner.java
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/runners/Runner.java	Fri Mar 17 11:23:01 2017 +0100
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/runners/Runner.java	Wed Mar 22 22:21:18 2017 +0100
@@ -30,8 +30,6 @@
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.vm.WhiteBoxSupport;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -41,6 +39,8 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import static org.openjdk.jcstress.util.StringUtils.getStacktrace;
+
 /**
  * Basic runner for concurrency tests.
  *
@@ -107,11 +107,7 @@
     protected void dumpFailure(int iteration, Status status, String message, Throwable aux) {
         messages.add(message);
         TestResult result = prepareResult(iteration, status);
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
-        aux.printStackTrace(pw);
-        pw.close();
-        result.addAuxData(sw.toString());
+        result.addAuxData(getStacktrace(aux));
         collector.add(result);
     }
 
diff -r 9f21d933addf jcstress-core/src/main/java/org/openjdk/jcstress/util/StringUtils.java
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/util/StringUtils.java	Fri Mar 17 11:23:01 2017 +0100
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/util/StringUtils.java	Wed Mar 22 22:21:18 2017 +0100
@@ -24,8 +24,9 @@
  */
 package org.openjdk.jcstress.util;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
@@ -101,4 +102,20 @@
         }
         return sb.toString();
     }
+
+    public static String getStacktrace(Throwable throwable) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        throwable.printStackTrace(pw);
+        pw.close();
+        return sw.toString();
+    }
+
+    public static String getFirstLine(String actual) {
+        int endLine = actual.indexOf("\n");
+        if (endLine > 0) {
+            return actual.substring(0, endLine).trim();
+        }
+        return actual;
+    }
 }
diff -r 9f21d933addf jcstress-core/src/test/java/org/openjdk/jcstress/EmbeddedExecutorTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-core/src/test/java/org/openjdk/jcstress/EmbeddedExecutorTest.java	Wed Mar 22 22:21:18 2017 +0100
@@ -0,0 +1,42 @@
+package org.openjdk.jcstress;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jcstress.infra.Status;
+import org.openjdk.jcstress.infra.TestInfo;
+import org.openjdk.jcstress.infra.collectors.InProcessCollector;
+import org.openjdk.jcstress.infra.collectors.TestResult;
+import org.openjdk.jcstress.infra.runners.TestConfig;
+
+import java.util.Collections;
+
+import static org.openjdk.jcstress.util.StringUtils.getFirstLine;
+
+public class EmbeddedExecutorTest {
+
+    private InProcessCollector sink = new InProcessCollector();
+
+    private EmbeddedExecutor embeddedExecutor = new EmbeddedExecutor(sink);
+
+    @Test
+    public void testReportTestError() {
+        TestConfig config = createSimpleConfigFor("my.missing.ClassName");
+        embeddedExecutor.run(config);
+
+        Assert.assertEquals("Should get exactly one test result", 1, sink.getTestResults().size());
+
+        TestResult testResult = sink.getTestResults().iterator().next();
+        Assert.assertEquals("Should report a test error", Status.TEST_ERROR, testResult.status());
+
+        String errorMessage = testResult.getAuxData().get(0);
+        Assert.assertEquals("Should report the test error reason", "java.lang.ClassNotFoundException: my.missing.ClassName",
+                getFirstLine(errorMessage));
+    }
+
+    private TestConfig createSimpleConfigFor(String runnerClassName) {
+        Options opts = new Options(new String[]{});
+        TestInfo info = new TestInfo("", runnerClassName, "", 4, false);
+        return new TestConfig(opts, info, TestConfig.RunMode.FORKED, 1, Collections.emptyList());
+    }
+
+}
\ No newline at end of file
diff -r 9f21d933addf jcstress-core/src/test/java/org/openjdk/jcstress/util/StringUtilsTest.java
--- a/jcstress-core/src/test/java/org/openjdk/jcstress/util/StringUtilsTest.java	Fri Mar 17 11:23:01 2017 +0100
+++ b/jcstress-core/src/test/java/org/openjdk/jcstress/util/StringUtilsTest.java	Wed Mar 22 22:21:18 2017 +0100
@@ -15,4 +15,18 @@
         Assert.assertEquals("...", StringUtils.cutoff(s, 3));
     }
 
+    @Test
+    public void testGetStacktrace() {
+        String actual = StringUtils.getStacktrace(new NullPointerException("my message"));
+        String firstLine = StringUtils.getFirstLine(actual);
+
+        Assert.assertEquals("java.lang.NullPointerException: my message", firstLine);
+    }
+
+    @Test
+    public void testGetFirstLine() {
+        Assert.assertEquals("First line", StringUtils.getFirstLine("First line"));
+        Assert.assertEquals("First line", StringUtils.getFirstLine("First line\nsecond line"));
+    }
+
 }
-------------- next part --------------
diff -r b64aaf61b6be jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ReportUtils.java
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ReportUtils.java	Wed Mar 08 20:52:43 2017 +0100
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ReportUtils.java	Mon Mar 13 22:01:58 2017 +0100
@@ -146,7 +146,7 @@
         pw.printf("%" + idLen + "s %" + occLen +"s %" + expectLen + "s  %-" + descLen + "s%n", "Observed state", "Occurrences", "Expectation", "Interpretation");
 
         for (GradingResult gradeRes : r.grading().gradingResults) {
-            pw.printf("%" + idLen + "s %," + occLen + "d %" + expectLen + "s  %-" + descLen + "s%n",
+            pw.printf(Locale.US, "%" + idLen + "s %," + occLen + "d %" + expectLen + "s  %-" + descLen + "s%n",
                     StringUtils.cutoff(gradeRes.id, idLen),
                     gradeRes.count,
                     gradeRes.expect,
-------------- next part --------------
diff -r b64aaf61b6be jcstress-core/src/main/java/org/openjdk/jcstress/Options.java
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java	Wed Mar 08 20:52:43 2017 +0100
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/Options.java	Mon Mar 13 21:42:59 2017 +0100
@@ -262,12 +262,12 @@
 
     public void printSettingsOn(PrintStream out) {
         out.printf("  Hardware threads in use/available: %d/%d, %s%n", getUserCPUs(), getSystemCPUs(), getSpinStyle());
-        out.printf("  Test preset mode: \"%s\"\n", mode);
-        out.printf("  Writing the test results to \"%s\"\n", resultFile);
-        out.printf("  Parsing results to \"%s\"\n", resultDir);
-        out.printf("  Running each test matching \"%s\" for %d forks, %d iterations, %d ms each\n", getTestFilter(), getForks(), getIterations(), getTime());
-        out.printf("  Each JVM would execute at most %d tests in the row.\n", getBatchSize());
-        out.printf("  Solo stride size will be autobalanced within [%d, %d] elements, but taking no more than %d Mb.\n", getMinStride(), getMaxStride(), getMaxFootprintMb());
+        out.printf("  Test preset mode: \"%s\"%n", mode);
+        out.printf("  Writing the test results to \"%s\"%n", resultFile);
+        out.printf("  Parsing results to \"%s\"%n", resultDir);
+        out.printf("  Running each test matching \"%s\" for %d forks, %d iterations, %d ms each%n", getTestFilter(), getForks(), getIterations(), getTime());
+        out.printf("  Each JVM would execute at most %d tests in the row.%n", getBatchSize());
+        out.printf("  Solo stride size will be autobalanced within [%d, %d] elements, but taking no more than %d Mb.%n", getMinStride(), getMaxStride(), getMaxFootprintMb());
 
         out.println();
     }
diff -r b64aaf61b6be jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java	Wed Mar 08 20:52:43 2017 +0100
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/grading/ConsoleReportPrinter.java	Mon Mar 13 21:42:59 2017 +0100
@@ -123,7 +123,7 @@
     private void printLine(TestResult r) {
         String label = ReportUtils.statusToLabel(r);
         output.printf("\r%" + progressLen + "s\r", "");
-        output.printf("%10s %s\n", "[" + label + "]", StringUtils.chunkName(r.getName()));
+        output.printf("%10s %s%n", "[" + label + "]", StringUtils.chunkName(r.getName()));
     }
 
     private void printProgress() {


More information about the jcstress-dev mailing list