Skip to content

Commit

Permalink
Make tests resilient to exceptions thrown while reporting exceptions (#…
Browse files Browse the repository at this point in the history
…19566)

Part of #19542. We protect against the case where `Exception.getMessage`
or `Exception.getStackTrace` throw an exception.

This change makes `testCompilation tests/neg/i8984.scala` fail as
expected. `tests/neg/i8984.scala` is currently disabled (see #19561).

`tests/neg/i8984.scala` will not be fixed in this PR. Making the test
framework more resilient is a priority. Fixing this is the last part of
#19542.
  • Loading branch information
nicolasstucki authored Jan 30, 2024
2 parents fbe06c0 + b427ba6 commit 23efb89
Showing 1 changed file with 18 additions and 8 deletions.
26 changes: 18 additions & 8 deletions compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -290,15 +290,25 @@ trait ParallelTesting extends RunnerOrchestration { self =>

/** This callback is executed once the compilation of this test source finished */
private final def onComplete(testSource: TestSource, reportersOrCrash: Try[Seq[TestReporter]], logger: LoggedRunnable): Unit =
reportersOrCrash match {
case TryFailure(exn) => onFailure(testSource, Nil, logger, Some(s"Fatal compiler crash when compiling: ${testSource.title}:\n${exn.getMessage}${exn.getStackTrace.map("\n\tat " + _).mkString}"))
case TrySuccess(reporters) if !reporters.exists(_.skipped) =>
maybeFailureMessage(testSource, reporters) match {
case Some(msg) => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty))
case None => onSuccess(testSource, reporters, logger)
try
reportersOrCrash match
case TryFailure(exn) => onFailure(testSource, Nil, logger, Some(s"Fatal compiler crash when compiling: ${testSource.title}:\n${exn.getMessage}${exn.getStackTrace.map("\n\tat " + _).mkString}"))
case TrySuccess(reporters) if !reporters.exists(_.skipped) =>
maybeFailureMessage(testSource, reporters) match {
case Some(msg) => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty))
case None => onSuccess(testSource, reporters, logger)
}
case _ =>
catch case ex: Throwable =>
echo(s"Exception thrown onComplete (probably by a reporter) in $testSource: ${ex.getClass}")
Try(ex.printStackTrace())
.recover{ _ =>
val trace = ex.getStackTrace.map(_.toString) // compute this first in case getStackTrace throws an exception
echo(s"${ex.getClass.getName} message could not be printed due to an exception while computing the message.")
if trace.nonEmpty then trace.foreach(echo) else echo(s"${ex.getClass.getName} stack trace is empty.")
}
case _ =>
}
.getOrElse(echo(s"${ex.getClass.getName} stack trace could not be printed due to an exception while printing the stack trace."))
failTestSource(testSource)

/**
* Based on the reporters obtained after the compilation, determines if this test has failed.
Expand Down

0 comments on commit 23efb89

Please sign in to comment.