Skip to content

Commit c6aff42

Browse files
authored
Print stack trace for all unknown errors (#219)
1 parent 71b744f commit c6aff42

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

src/main/scala/eu/neverblink/jelly/cli/ErrorHandler.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@ object ErrorHandler:
99
t match
1010
case e: CriticalException =>
1111
command.printLine(f"${e.getMessage}", toStderr = true)
12+
printStackTraceIfDebug(command, t)
1213
case e: Throwable =>
1314
command.printLine("Unknown error", toStderr = true)
14-
printStackTrace(command, t)
15+
// Always print stack trace for unknown exceptions,
16+
// as otherwise the user has no clue what happened.
17+
t.printStackTrace(command.err)
1518
command.exit(1, t)
1619

1720
/** Print out stack trace or debugging information
1821
* @param command
1922
* @param t
2023
*/
21-
private def printStackTrace(
24+
private def printStackTraceIfDebug(
2225
command: JellyCommand[?],
2326
t: Throwable,
2427
): Unit =
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package eu.neverblink.jelly.cli.command
2+
3+
import caseapp.core.RemainingArgs
4+
import eu.neverblink.jelly.cli.{CriticalException, ExitException, JellyCommand}
5+
import org.scalatest.matchers.should.Matchers
6+
import org.scalatest.wordspec.AnyWordSpec
7+
8+
class ErrorHandlerSpec extends AnyWordSpec, Matchers:
9+
def makeMockCommand(ex: Throwable): JellyCommand[VersionOptions] =
10+
val command = new JellyCommand[VersionOptions] {
11+
override def names: List[List[String]] = List(List("test"))
12+
override def doRun(options: VersionOptions, remainingArgs: RemainingArgs): Unit =
13+
throw ex
14+
}
15+
command.testMode(true)
16+
command
17+
18+
"ErrorHandler" should {
19+
"not print stack trace for known exceptions if not in debug mode" in {
20+
val command = makeMockCommand(new CriticalException("Known error!"))
21+
intercept[ExitException] {
22+
command.main("test", Array())
23+
}
24+
val err = command.getErrString
25+
err should include("Known error!")
26+
err should include("Run with --debug to see the complete stack trace.")
27+
}
28+
29+
"print stack trace for known exceptions in debug mode" in {
30+
val command = makeMockCommand(new CriticalException("Known error!"))
31+
intercept[ExitException] {
32+
command.main("test", Array("--debug"))
33+
}
34+
val err = command.getErrString
35+
err should include("Known error!")
36+
err should include("CriticalException")
37+
err should include("at eu.neverblink.jelly.cli.command.ErrorHandlerSpec")
38+
}
39+
40+
"print stack trace for unknown exceptions if not in debug mode" in {
41+
val command = makeMockCommand(new RuntimeException("Unknown error!"))
42+
intercept[ExitException] {
43+
command.main("test", Array())
44+
}
45+
val err = command.getErrString
46+
err should include("Unknown error")
47+
err should include("RuntimeException")
48+
err should include("at eu.neverblink.jelly.cli.command.ErrorHandlerSpec")
49+
}
50+
51+
"print stack trace for unknown exceptions in debug mode" in {
52+
val command = makeMockCommand(new RuntimeException("Unknown error!"))
53+
intercept[ExitException] {
54+
command.main("test", Array("--debug"))
55+
}
56+
val err = command.getErrString
57+
err should include("Unknown error")
58+
err should include("RuntimeException")
59+
err should include("at eu.neverblink.jelly.cli.command.ErrorHandlerSpec")
60+
}
61+
}

0 commit comments

Comments
 (0)