cworthy/assert/assert.go
2021-08-29 18:27:05 +02:00

71 lines
1.4 KiB
Go

package assert
import (
"fmt"
"os"
"runtime"
eval "github.com/novalagung/go-eek"
"gitlab.com/CRThaze/cworthy/exits"
)
type EvalVar eval.Var
type EvalVal eval.ExecVar
const (
stdAssertFailureFmt = "%s%s%s:%d %s%sAssertion `%s` failed.\n"
)
var (
AssertFailureFmt = stdAssertFailureFmt
AssertionStream = os.Stderr
)
func assertFailBase(frmt, assertion, file string, line int, function string) {
fmt.Fprintf(AssertionStream, frmt, file, line, function, assertion)
exits.Abort()
}
func assertFail(frmt, expr string) {
if pc, file, line, ok := runtime.Caller(2); ok {
frames := runtime.CallersFrames([]uintptr{pc})
firstFrame, _ := frames.Next()
assertFailBase(frmt, expr, file, line, firstFrame.Function)
}
}
func Assert(exprResult bool) {
if exprResult {
return
}
assertFail(AssertFailureFmt, "")
}
func AssertEval(expr string, vals EvalVal, vars ...EvalVar) {
defer func() {
if paniced := recover(); paniced != nil {
assertFail("Assertion paniced", expr)
}
}()
obj := eval.New("Assertion Eval", expr)
for _, v := range vars {
obj.DefineVariable(v)
}
obj.PrepareEvaluation(expr)
if err := obj.Build(); err != nil {
assertFail("Assertion cannot build", expr)
}
resultItf, err := obj.Evaluate(vals)
if err != nil {
assertFail("Assertion could not be evaluated", expr)
}
if result, ok := resultItf.(bool); !ok {
panic("Invalid assertion")
} else if result {
return
}
assertFail(AssertFailureFmt, expr)
}