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
|
||||
# distribution: zulu
|
||||
# jobtype: 6
|
||||
- os: ubuntu-latest
|
||||
java: 21
|
||||
distribution: zulu
|
||||
jobtype: 7
|
||||
- os: ubuntu-latest
|
||||
java: 11
|
||||
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"
|
||||
# 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/*"
|
||||
- name: Scripted (tests)
|
||||
if: ${{ matrix.jobtype == 7 }}
|
||||
shell: bash
|
||||
run: |
|
||||
./sbt -v "scripted tests/*"
|
||||
- name: Build and test lm-coursier (10)
|
||||
if: ${{ matrix.jobtype == 10 }}
|
||||
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
|
||||
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)
|
||||
"A simple equation" should "hold" in {
|
||||
test("A simple equation should hold") {
|
||||
assert(Int.MaxValue == v)
|
||||
}
|
||||
}
|
||||
end Test
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
> testFull
|
||||
|
||||
$ copy-file changes/Bad.scala src/test/scala/Test.scala
|
||||
|
||||
-> testFull
|
||||
|
||||
$ copy-file changes/Test.scala src/test/scala/Test.scala
|
||||
|
||||
> testFull
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@ import java.io.{ CharArrayWriter, PrintWriter }
|
|||
|
||||
val marker = new File("marker")
|
||||
val check = TaskKey[Unit]("check", "Check correct error has been returned.")
|
||||
val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
|
||||
val scalaxml = "org.scala-lang.modules" %% "scala-xml" % "1.1.1"
|
||||
val scalatest = "org.scalatest" %% "scalatest" % "3.2.19"
|
||||
|
||||
ThisBuild / scalaVersion := "2.12.20"
|
||||
ThisBuild / scalaVersion := "3.7.2"
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
settings(
|
||||
libraryDependencies ++= List(scalaxml, scalatest),
|
||||
libraryDependencies ++= List(scalatest),
|
||||
fork := true,
|
||||
testListeners += new TestReportListener {
|
||||
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)
|
||||
test("throws a custom exception") {
|
||||
throw new MyCustomException("this is a custom exception")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
-> test
|
||||
-> testFull
|
||||
|
||||
> check
|
||||
|
|
@ -167,8 +167,8 @@ public class ForkTestMain {
|
|||
}
|
||||
|
||||
public static class ForkErrorInfo implements Serializable {
|
||||
public final long id;
|
||||
public final ForkError error;
|
||||
public long id;
|
||||
public ForkError error;
|
||||
|
||||
public ForkErrorInfo(long id, ForkError error) {
|
||||
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()
|
||||
.registerTypeAdapterFactory(fingerprintFac)
|
||||
.registerTypeAdapterFactory(selectorFac)
|
||||
.registerTypeAdapterFactory(ThrowableAdapterFactory.INSTANCE)
|
||||
.create();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue