diff --git a/main-actions/src/main/scala/sbt/ForkTests.scala b/main-actions/src/main/scala/sbt/ForkTests.scala index 8402b4769..fce5e445f 100755 --- a/main-actions/src/main/scala/sbt/ForkTests.scala +++ b/main-actions/src/main/scala/sbt/ForkTests.scala @@ -5,6 +5,7 @@ package sbt import scala.collection.mutable import testing.{ Logger => _, _ } +import scala.util.control.NonFatal import java.net.ServerSocket import java.io._ import Tests.{ Output => TestOutput, _ } @@ -74,6 +75,12 @@ private[sbt] object ForkTests { os.flush() new React(is, os, log, opts.testListeners, resultsAcc).react() + } catch { + case NonFatal(e) => + def throwableToString(t: Throwable) = { + import java.io._; val sw = new StringWriter; t.printStackTrace(new PrintWriter(sw)); sw.toString + } + resultsAcc("Forked test harness failed: " + throwableToString(e)) = SuiteResult.Error } finally { is.close(); os.close(); socket.close() } diff --git a/notes/0.13.13/fork_test.md b/notes/0.13.13/fork_test.md new file mode 100644 index 000000000..4029c6b3c --- /dev/null +++ b/notes/0.13.13/fork_test.md @@ -0,0 +1,8 @@ +### Bug fixes + +- Fixes forked test succeeding when the test harness fails. [#2442][2442]/[#2730][2730] by [@eed3si9n][@eed3si9n]/[@dwijnand][@dwijnand} + + [2442]: https://github.com/sbt/sbt/issues/2442 + [2730]: https://github.com/sbt/sbt/pull/2730 + [@eed3si9n]: https://github.com/eed3si9n + [@dwijnand]: https://github.com/dwijnand diff --git a/sbt/src/sbt-test/tests/fork-uncaught2/build.sbt b/sbt/src/sbt-test/tests/fork-uncaught2/build.sbt new file mode 100644 index 000000000..b1fcc9ee4 --- /dev/null +++ b/sbt/src/sbt-test/tests/fork-uncaught2/build.sbt @@ -0,0 +1,17 @@ +scalaVersion := "2.11.8" + +libraryDependencies += "org.scala-sbt" % "test-interface" % "1.0" + +testFrameworks := new TestFramework("build.MyFramework") :: Nil + +fork := true + +definedTests in Test += new sbt.TestDefinition( + "my", + // marker fingerprint since there are no test classes + // to be discovered by sbt: + new sbt.testing.AnnotatedFingerprint { + def isModule = true + def annotationName = "my" + }, true, Array() + ) diff --git a/sbt/src/sbt-test/tests/fork-uncaught2/src/test/scala/build/MyFramework.scala b/sbt/src/sbt-test/tests/fork-uncaught2/src/test/scala/build/MyFramework.scala new file mode 100644 index 000000000..058630a68 --- /dev/null +++ b/sbt/src/sbt-test/tests/fork-uncaught2/src/test/scala/build/MyFramework.scala @@ -0,0 +1,24 @@ +package build + +import _root_.sbt.testing._ + +class MyFramework extends sbt.testing.Framework { + def fingerprints = Array(new AnnotatedFingerprint { def isModule = true; def annotationName = "my" }) + def name = "my" + def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader): Runner = + new MyRunner(args, remoteArgs, testClassLoader) +} + +class MyRunner(val args: Array[String], val remoteArgs: Array[String], + val testClassLoader: ClassLoader) extends sbt.testing.Runner { + + def tasks(taskDefs: Array[TaskDef]): Array[Task] = + if (args contains "task-boom") taskDefs map BoomTask else throw new Throwable() + def done(): String = "" + + private case class BoomTask(taskDef: TaskDef) extends Task { + def tags = Array.empty[String] + def execute(handler: EventHandler, loggers: Array[Logger]) = throw new Throwable() + } +} + diff --git a/sbt/src/sbt-test/tests/fork-uncaught2/test b/sbt/src/sbt-test/tests/fork-uncaught2/test new file mode 100644 index 000000000..38c301498 --- /dev/null +++ b/sbt/src/sbt-test/tests/fork-uncaught2/test @@ -0,0 +1,2 @@ +-> test +-> testOnly -- task-boom