This repository has been archived by the owner on Aug 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split out TestFailedException into ScalaTest env (#27)
- Loading branch information
Showing
3 changed files
with
79 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// See LICENSE for license details. | ||
|
||
package chisel3.tester | ||
|
||
import scala.collection.mutable | ||
|
||
class FailedExpectException(val message: String, val failedCodeStackDepth: Int) extends Exception(message) | ||
|
||
/** Interface into the testing environment, like ScalaTest | ||
*/ | ||
trait TestEnvInterface { | ||
protected val batchedFailures: mutable.ArrayBuffer[Exception] = new mutable.ArrayBuffer | ||
|
||
def topFileName: Option[String] | ||
|
||
/** Logs a tester failure at this point. | ||
* Failures queued until the next checkpoint. | ||
*/ | ||
def testerFail(msg: String): Unit = { | ||
batchedFailures += new FailedExpectException(msg, 4) | ||
} | ||
|
||
protected def getExpectDetailedTrace(trace: Seq[StackTraceElement], inFile: String): String = { | ||
val fullTrace = Context().backend.getParentTraceElements ++ trace | ||
|
||
// In the threading case, this needs to be overridden to trace through parent threads | ||
val lineNumbers = fullTrace.collect { | ||
case ste if ste.getFileName == inFile => ste.getLineNumber | ||
}.mkString(", ") | ||
if (lineNumbers.isEmpty) { | ||
s" (no lines in $inFile)" | ||
} else { | ||
s" (lines in $inFile: $lineNumbers)" | ||
} | ||
} | ||
|
||
/** Expect a specific value on a wire, calling testerFail if the expectation isn't met. | ||
* Failures queued until the next checkpoint. | ||
*/ | ||
def testerExpect(expected: Any, actual: Any, signal: String, msg: Option[String]): Unit = { | ||
if (expected != actual) { | ||
val appendMsg = msg match { | ||
case Some(_) => s": $msg" | ||
case _ => "" | ||
} | ||
|
||
val trace = new Throwable | ||
val expectStackDepth = trace.getStackTrace.indexWhere(ste => | ||
ste.getClassName == "chisel3.tester.package$testableData" && ste.getMethodName == "expect") | ||
require(expectStackDepth != -1, | ||
s"Failed to find expect in stack trace:\r\n${trace.getStackTrace.mkString("\r\n")}") | ||
|
||
val trimmedTrace = trace.getStackTrace.drop(expectStackDepth + 2) | ||
val detailedTrace = topFileName.map(getExpectDetailedTrace(trimmedTrace.toSeq, _)).getOrElse("") | ||
|
||
val message = s"$signal=$actual did not equal expected=$expected$appendMsg$detailedTrace" | ||
val stackIndex = expectStackDepth + 1 | ||
batchedFailures += new FailedExpectException(message, stackIndex) | ||
} | ||
} | ||
|
||
/** If there are any failures, reports them and end the test now. | ||
*/ | ||
def checkpoint(): Unit = { | ||
// TODO: report multiple exceptions simultaneously | ||
for (failure <- batchedFailures) { | ||
throw failure | ||
} | ||
} | ||
} |