diff options
Diffstat (limited to 'compiler/test/dotty/tools/vulpix/SummaryReport.scala')
-rw-r--r-- | compiler/test/dotty/tools/vulpix/SummaryReport.scala | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/compiler/test/dotty/tools/vulpix/SummaryReport.scala b/compiler/test/dotty/tools/vulpix/SummaryReport.scala new file mode 100644 index 000000000..678d88809 --- /dev/null +++ b/compiler/test/dotty/tools/vulpix/SummaryReport.scala @@ -0,0 +1,145 @@ +package dotty +package tools +package vulpix + +import scala.collection.mutable +import dotc.reporting.TestReporter + +/** `SummaryReporting` can be used by unit tests by utilizing `@AfterClass` to + * call `echoSummary` + * + * This is used in vulpix by passing the companion object's `SummaryReporting` + * to each test, the `@AfterClass def` then calls the `SummaryReport`'s + * `echoSummary` method in order to dump the summary to both stdout and a log + * file + */ +trait SummaryReporting { + /** Report a failed test */ + def reportFailed(): Unit + + /** Report a test as passing */ + def reportPassed(): Unit + + /** Add the name of the failed test */ + def addFailedTest(msg: String): Unit + + /** Add instructions to reproduce the error */ + def addReproduceInstruction(instr: String): Unit + + /** Add a message that will be issued in the beginning of the summary */ + def addStartingMessage(msg: String): Unit + + /** Add a cleanup hook to be run upon completion */ + def addCleanup(f: () => Unit): Unit + + /** Echo the summary report to the appropriate locations */ + def echoSummary(): Unit + + /** Echoes *immediately* to file */ + def echoToLog(msg: String): Unit + + /** Echoes contents of `it` to file *immediately* then flushes */ + def echoToLog(it: Iterator[String]): Unit +} + +/** A summary report that doesn't do anything */ +final class NoSummaryReport extends SummaryReporting { + def reportFailed(): Unit = () + def reportPassed(): Unit = () + def addFailedTest(msg: String): Unit = () + def addReproduceInstruction(instr: String): Unit = () + def addStartingMessage(msg: String): Unit = () + def addCleanup(f: () => Unit): Unit = () + def echoSummary(): Unit = () + def echoToLog(msg: String): Unit = () + def echoToLog(it: Iterator[String]): Unit = () +} + +/** A summary report that logs to both stdout and the `TestReporter.logWriter` + * which outputs to a log file in `./testlogs/` + */ +final class SummaryReport extends SummaryReporting { + + private val startingMessages = mutable.ArrayBuffer.empty[String] + private val failedTests = mutable.ArrayBuffer.empty[String] + private val reproduceInstructions = mutable.ArrayBuffer.empty[String] + private val cleanUps = mutable.ArrayBuffer.empty[() => Unit] + + private[this] var passed = 0 + private[this] var failed = 0 + + def reportFailed(): Unit = + failed += 1 + + def reportPassed(): Unit = + passed += 1 + + def addFailedTest(msg: String): Unit = + failedTests.append(msg) + + def addReproduceInstruction(instr: String): Unit = + reproduceInstructions.append(instr) + + def addStartingMessage(msg: String): Unit = + startingMessages.append(msg) + + def addCleanup(f: () => Unit): Unit = + cleanUps.append(f) + + /** Both echoes the summary to stdout and prints to file */ + def echoSummary(): Unit = { + import SummaryReport._ + + val rep = new StringBuilder + rep.append( + s"""| + |================================================================================ + |Test Report + |================================================================================ + | + |$passed passed, $failed failed, ${passed + failed} total + |""".stripMargin + ) + + startingMessages.foreach(rep.append) + + failedTests.map(x => s" $x\n").foreach(rep.append) + + // If we're compiling locally, we don't need instructions on how to + // reproduce failures + if (isInteractive) { + println(rep.toString) + if (failed > 0) println { + s"""| + |-------------------------------------------------------------------------------- + |Note - reproduction instructions have been dumped to log file: + | ${TestReporter.logPath} + |--------------------------------------------------------------------------------""".stripMargin + } + } + + rep += '\n' + + reproduceInstructions.foreach(rep.append) + + // If we're on the CI, we want everything + if (!isInteractive) println(rep.toString) + + TestReporter.logPrintln(rep.toString) + + // Perform cleanup callback: + if (cleanUps.nonEmpty) cleanUps.foreach(_.apply()) + } + + def echoToLog(msg: String): Unit = + TestReporter.logPrintln(msg) + + def echoToLog(it: Iterator[String]): Unit = { + it.foreach(TestReporter.logPrint) + TestReporter.logFlush() + } +} + +object SummaryReport { + val isInteractive = Properties.testsInteractive && !Properties.isRunByDrone +} |