mirror of https://github.com/sbt/sbt.git
Merge pull request #8271 from eed3si9n/wip/forked-test
[2.x] fix: Fixes forked test error handling on JDK 17
This commit is contained in:
commit
649f071247
|
|
@ -36,6 +36,10 @@ jobs:
|
||||||
# java: 8
|
# java: 8
|
||||||
# distribution: zulu
|
# distribution: zulu
|
||||||
# jobtype: 6
|
# jobtype: 6
|
||||||
|
- os: ubuntu-latest
|
||||||
|
java: 21
|
||||||
|
distribution: zulu
|
||||||
|
jobtype: 7
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
java: 11
|
java: 11
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
|
|
@ -164,6 +168,11 @@ jobs:
|
||||||
# sbt -Dsbtzinc.path=$HOME/work/sbt/sbt/zinc -Dsbt.build.version=$BUILD_VERSION -Dsbt.build.fatal=false "+lowerUtils/publishLocal; {zinc}/publishLocal; upperModules/publishLocal"
|
# sbt -Dsbtzinc.path=$HOME/work/sbt/sbt/zinc -Dsbt.build.version=$BUILD_VERSION -Dsbt.build.fatal=false "+lowerUtils/publishLocal; {zinc}/publishLocal; upperModules/publishLocal"
|
||||||
# rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true
|
# rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true
|
||||||
# sbt -v -Dsbt.version=$BUILD_VERSION "++$SCALA_213; all $UTIL_TESTS; ++$SCALA_212; all $UTIL_TESTS; scripted actions/* source-dependencies/*1of3 dependency-management/*1of4 java/*"
|
# sbt -v -Dsbt.version=$BUILD_VERSION "++$SCALA_213; all $UTIL_TESTS; ++$SCALA_212; all $UTIL_TESTS; scripted actions/* source-dependencies/*1of3 dependency-management/*1of4 java/*"
|
||||||
|
- name: Scripted (tests)
|
||||||
|
if: ${{ matrix.jobtype == 7 }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
./sbt -v "scripted tests/*"
|
||||||
- name: Build and test lm-coursier (10)
|
- name: Build and test lm-coursier (10)
|
||||||
if: ${{ matrix.jobtype == 10 }}
|
if: ${{ matrix.jobtype == 10 }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
|
val scalatest = "org.scalatest" %% "scalatest" % "3.2.19"
|
||||||
|
|
||||||
scalaVersion := "2.12.20"
|
scalaVersion := "3.7.2"
|
||||||
fork := true
|
fork := true
|
||||||
libraryDependencies += scalatest % Test
|
libraryDependencies += scalatest % Test
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import org.scalatest.funsuite.AnyFunSuite
|
||||||
|
|
||||||
|
class Test extends AnyFunSuite:
|
||||||
|
test("bad") {
|
||||||
|
sys.error("boom")
|
||||||
|
}
|
||||||
|
end Test
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import org.scalatest.FlatSpec
|
import org.scalatest.funsuite.AnyFunSuite
|
||||||
|
|
||||||
class Test extends FlatSpec {
|
class Test extends AnyFunSuite:
|
||||||
val v = sys.env.getOrElse("tests.max.value", Int.MaxValue)
|
val v = sys.env.getOrElse("tests.max.value", Int.MaxValue)
|
||||||
"A simple equation" should "hold" in {
|
test("A simple equation should hold") {
|
||||||
assert(Int.MaxValue == v)
|
assert(Int.MaxValue == v)
|
||||||
}
|
}
|
||||||
}
|
end Test
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
> testFull
|
> testFull
|
||||||
|
|
||||||
$ copy-file changes/Test.scala src/test/scala/Test.scala
|
$ copy-file changes/Bad.scala src/test/scala/Test.scala
|
||||||
|
|
||||||
|
-> testFull
|
||||||
|
|
||||||
|
$ copy-file changes/Test.scala src/test/scala/Test.scala
|
||||||
|
|
||||||
> testFull
|
> testFull
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,13 @@ import java.io.{ CharArrayWriter, PrintWriter }
|
||||||
|
|
||||||
val marker = new File("marker")
|
val marker = new File("marker")
|
||||||
val check = TaskKey[Unit]("check", "Check correct error has been returned.")
|
val check = TaskKey[Unit]("check", "Check correct error has been returned.")
|
||||||
val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
|
val scalatest = "org.scalatest" %% "scalatest" % "3.2.19"
|
||||||
val scalaxml = "org.scala-lang.modules" %% "scala-xml" % "1.1.1"
|
|
||||||
|
|
||||||
ThisBuild / scalaVersion := "2.12.20"
|
ThisBuild / scalaVersion := "3.7.2"
|
||||||
|
|
||||||
lazy val root = (project in file(".")).
|
lazy val root = (project in file(".")).
|
||||||
settings(
|
settings(
|
||||||
libraryDependencies ++= List(scalaxml, scalatest),
|
libraryDependencies ++= List(scalatest),
|
||||||
fork := true,
|
fork := true,
|
||||||
testListeners += new TestReportListener {
|
testListeners += new TestReportListener {
|
||||||
def testEvent(event: TestEvent): Unit = {
|
def testEvent(event: TestEvent): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import org.scalatest.FunSuite
|
import org.scalatest.funsuite.AnyFunSuite
|
||||||
|
|
||||||
class SBT543 extends FunSuite {
|
class SBT543 extends AnyFunSuite {
|
||||||
class MyCustomException(message: String) extends RuntimeException(message)
|
class MyCustomException(message: String) extends RuntimeException(message)
|
||||||
test("throws a custom exception") {
|
test("throws a custom exception") {
|
||||||
throw new MyCustomException("this is a custom exception")
|
throw new MyCustomException("this is a custom exception")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
-> test
|
-> testFull
|
||||||
|
|
||||||
> check
|
> check
|
||||||
|
|
@ -167,8 +167,8 @@ public class ForkTestMain {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ForkErrorInfo implements Serializable {
|
public static class ForkErrorInfo implements Serializable {
|
||||||
public final long id;
|
public long id;
|
||||||
public final ForkError error;
|
public ForkError error;
|
||||||
|
|
||||||
public ForkErrorInfo(long id, ForkError error) {
|
public ForkErrorInfo(long id, ForkError error) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* sbt
|
||||||
|
* Copyright 2023, Scala center
|
||||||
|
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||||
|
* Copyright 2008 - 2010, Mark Harrah
|
||||||
|
* Licensed under Apache License 2.0 (see LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sbt.internal.worker1;
|
||||||
|
|
||||||
|
public class PersistedException extends Throwable {
|
||||||
|
private String className;
|
||||||
|
|
||||||
|
public PersistedException(String message, Throwable cause, String className) {
|
||||||
|
super(message, cause);
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* sbt
|
||||||
|
* Copyright 2023, Scala center
|
||||||
|
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||||
|
* Copyright 2008 - 2010, Mark Harrah
|
||||||
|
* Licensed under Apache License 2.0 (see LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sbt.internal.worker1;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.TypeAdapterFactory;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
class ThrowableAdapterFactory implements TypeAdapterFactory {
|
||||||
|
private ThrowableAdapterFactory() {}
|
||||||
|
|
||||||
|
public static final ThrowableAdapterFactory INSTANCE = new ThrowableAdapterFactory();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||||
|
// Only handles Throwable and subclasses; let other factories handle any other type
|
||||||
|
if (!Throwable.class.isAssignableFrom(type.getRawType())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
TypeAdapter<T> adapter =
|
||||||
|
(TypeAdapter<T>)
|
||||||
|
new TypeAdapter<Throwable>() {
|
||||||
|
@Override
|
||||||
|
public Throwable read(JsonReader in) throws IOException {
|
||||||
|
String message = null;
|
||||||
|
String type = null;
|
||||||
|
ArrayList<StackTraceElement> stackTraces = new ArrayList<>();
|
||||||
|
in.beginObject();
|
||||||
|
while (in.hasNext()) {
|
||||||
|
String name = in.nextName();
|
||||||
|
if (name.equals("message")) {
|
||||||
|
message = in.nextString();
|
||||||
|
} else if (name.equals("type")) {
|
||||||
|
type = in.nextString();
|
||||||
|
} else if (name.equals("staceTrace")) {
|
||||||
|
in.beginArray();
|
||||||
|
while (in.hasNext()) {
|
||||||
|
StackTraceElement item = readStaceTraceElement(in);
|
||||||
|
stackTraces.add(item);
|
||||||
|
}
|
||||||
|
in.endArray();
|
||||||
|
} else {
|
||||||
|
in.skipValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.endObject();
|
||||||
|
Throwable ex = new PersistedException(message, null, type);
|
||||||
|
StackTraceElement array[] = new StackTraceElement[stackTraces.size()];
|
||||||
|
ex.setStackTrace(stackTraces.toArray(array));
|
||||||
|
return new ForkTestMain.ForkError(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, Throwable value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.beginObject();
|
||||||
|
// Include exception type name to give more context; for example
|
||||||
|
// NullPointerException might
|
||||||
|
// not have a message
|
||||||
|
out.name("type");
|
||||||
|
out.value(value.getClass().getSimpleName());
|
||||||
|
|
||||||
|
out.name("message");
|
||||||
|
out.value(value.getMessage());
|
||||||
|
|
||||||
|
Throwable cause = value.getCause();
|
||||||
|
if (cause != null) {
|
||||||
|
out.name("cause");
|
||||||
|
write(out, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
Throwable[] suppressedArray = value.getSuppressed();
|
||||||
|
if (suppressedArray.length > 0) {
|
||||||
|
out.name("suppressed");
|
||||||
|
out.beginArray();
|
||||||
|
|
||||||
|
for (Throwable suppressed : suppressedArray) {
|
||||||
|
write(out, suppressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
StackTraceElement[] staceTrace = value.getStackTrace();
|
||||||
|
if (staceTrace.length > 0) {
|
||||||
|
out.name("staceTrace");
|
||||||
|
out.beginArray();
|
||||||
|
for (StackTraceElement item : staceTrace) {
|
||||||
|
writeStaceTraceElement(out, item);
|
||||||
|
}
|
||||||
|
out.endArray();
|
||||||
|
}
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackTraceElement readStaceTraceElement(JsonReader in) throws IOException {
|
||||||
|
in.beginObject();
|
||||||
|
String className = null;
|
||||||
|
String methodName = null;
|
||||||
|
String fileName = null;
|
||||||
|
Integer lineNumber = null;
|
||||||
|
while (in.hasNext()) {
|
||||||
|
String name = in.nextName();
|
||||||
|
if (name.equals("className")) {
|
||||||
|
className = in.nextString();
|
||||||
|
} else if (name.equals("methodName")) {
|
||||||
|
methodName = in.nextString();
|
||||||
|
} else if (name.equals("fileName")) {
|
||||||
|
fileName = in.nextString();
|
||||||
|
} else if (name.equals("lineNumber")) {
|
||||||
|
lineNumber = in.nextInt();
|
||||||
|
} else {
|
||||||
|
in.skipValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.endObject();
|
||||||
|
StackTraceElement retval =
|
||||||
|
new StackTraceElement(className, methodName, fileName, lineNumber);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeStaceTraceElement(JsonWriter out, StackTraceElement value)
|
||||||
|
throws IOException {
|
||||||
|
out.beginObject();
|
||||||
|
out.name("className");
|
||||||
|
out.value(value.getClassName());
|
||||||
|
out.name("methodName");
|
||||||
|
out.value(value.getMethodName());
|
||||||
|
out.name("fileName");
|
||||||
|
out.value(value.getFileName());
|
||||||
|
out.name("lineNumber");
|
||||||
|
out.value(value.getLineNumber());
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,6 +51,7 @@ public final class WorkerMain {
|
||||||
return new GsonBuilder()
|
return new GsonBuilder()
|
||||||
.registerTypeAdapterFactory(fingerprintFac)
|
.registerTypeAdapterFactory(fingerprintFac)
|
||||||
.registerTypeAdapterFactory(selectorFac)
|
.registerTypeAdapterFactory(selectorFac)
|
||||||
|
.registerTypeAdapterFactory(ThrowableAdapterFactory.INSTANCE)
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue