removed herror
This commit is contained in:
parent
b313767026
commit
4326fb11d6
|
@ -1,29 +0,0 @@
|
||||||
package herror_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.sr.ht/~ewintr/go-kit/herror"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrTaskFailed = herror.New("task has failed")
|
|
||||||
|
|
||||||
func step() error {
|
|
||||||
return fmt.Errorf("cannot move")
|
|
||||||
}
|
|
||||||
|
|
||||||
func performTask() error {
|
|
||||||
if err := step(); err != nil {
|
|
||||||
return ErrTaskFailed.Wrap(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Example() {
|
|
||||||
if err := performTask(); err != nil {
|
|
||||||
fmt.Print(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Output: task has failed
|
|
||||||
//-> cannot move
|
|
||||||
}
|
|
161
herror/herror.go
161
herror/herror.go
|
@ -1,161 +0,0 @@
|
||||||
package herror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Err represents an error
|
|
||||||
type Err struct {
|
|
||||||
error string
|
|
||||||
wrapped *Err
|
|
||||||
details string
|
|
||||||
stack *Stacktrace
|
|
||||||
}
|
|
||||||
|
|
||||||
type errJSON struct {
|
|
||||||
E string `json:"error"`
|
|
||||||
W *Err `json:"wrapped"`
|
|
||||||
D string `json:"details"`
|
|
||||||
S *Stacktrace `json:"stack"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new instance for Err type with assigned error
|
|
||||||
func New(err interface{}) *Err {
|
|
||||||
newerror := new(Err)
|
|
||||||
|
|
||||||
switch e := err.(type) {
|
|
||||||
case string:
|
|
||||||
newerror.error = e
|
|
||||||
|
|
||||||
case error:
|
|
||||||
if castErr, ok := e.(*Err); ok {
|
|
||||||
return castErr
|
|
||||||
}
|
|
||||||
newerror.error = e.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
return newerror
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap set an error that is wrapped by Err
|
|
||||||
func Wrap(err, errwrapped error) error {
|
|
||||||
newerr := New(err)
|
|
||||||
return newerr.Wrap(errwrapped)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap returns a wrapped error if present
|
|
||||||
func Unwrap(err error) error {
|
|
||||||
return xerrors.Unwrap(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is reports whether any error in err's chain matches target.
|
|
||||||
func Is(err, target error) bool {
|
|
||||||
return xerrors.Is(err, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap set an error that is wrapped by Err
|
|
||||||
func (e *Err) Wrap(err error) *Err {
|
|
||||||
wrapped := New(err)
|
|
||||||
|
|
||||||
if deeper := xerrors.Unwrap(err); deeper != nil {
|
|
||||||
Wrap(wrapped, deeper)
|
|
||||||
}
|
|
||||||
|
|
||||||
newerr := &Err{
|
|
||||||
error: e.error,
|
|
||||||
wrapped: e.wrapped,
|
|
||||||
details: e.details,
|
|
||||||
stack: e.stack,
|
|
||||||
}
|
|
||||||
newerr.wrapped = wrapped
|
|
||||||
return newerr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap returns wrapped error
|
|
||||||
func (e *Err) Unwrap() error {
|
|
||||||
if e.wrapped == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return e.wrapped
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is reports whether an error matches.
|
|
||||||
func (e *Err) Is(err error) bool {
|
|
||||||
if e.wrapped != nil {
|
|
||||||
return e.error == err.Error() || e.wrapped.Is(err)
|
|
||||||
}
|
|
||||||
return e.error == err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaptureStack sets stack traces when the method is called
|
|
||||||
func (e *Err) CaptureStack() *Err {
|
|
||||||
e.stack = NewStacktrace()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stack returns full stack traces
|
|
||||||
func (e *Err) Stack() *Stacktrace {
|
|
||||||
return e.stack
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDetails is a alias for AppendDetail [DEPRECATED]
|
|
||||||
func (e *Err) AddDetails(v ...interface{}) *Err {
|
|
||||||
return e.AppendDetails(v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppendDetails appends formated variable information at the end of a text
|
|
||||||
// field in the error mostly for debugging purposes.
|
|
||||||
func (e *Err) AppendDetails(v ...interface{}) *Err {
|
|
||||||
buff := new(bytes.Buffer)
|
|
||||||
fmt.Fprintln(buff, e.details)
|
|
||||||
spew.Fdump(buff, v...)
|
|
||||||
e.details = buff.String()
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Details returns error's details
|
|
||||||
func (e *Err) Details() string {
|
|
||||||
return e.details
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errors return a composed message of the assigned error e wrapped error
|
|
||||||
func (e *Err) Error() string {
|
|
||||||
if e.wrapped == nil {
|
|
||||||
return e.error
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s\n-> %s", e.error, e.wrapped.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON
|
|
||||||
func (e *Err) UnmarshalJSON(b []byte) error {
|
|
||||||
var errJSON errJSON
|
|
||||||
if err := json.Unmarshal(b, &errJSON); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*e = Err{
|
|
||||||
error: errJSON.E,
|
|
||||||
wrapped: errJSON.W,
|
|
||||||
details: errJSON.D,
|
|
||||||
stack: errJSON.S,
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON
|
|
||||||
func (e *Err) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(errJSON{
|
|
||||||
E: e.error,
|
|
||||||
W: e.wrapped,
|
|
||||||
D: e.details,
|
|
||||||
S: e.stack,
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,150 +0,0 @@
|
||||||
package herror_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.sr.ht/~ewintr/go-kit/herror"
|
|
||||||
"git.sr.ht/~ewintr/go-kit/test"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHError(t *testing.T) {
|
|
||||||
|
|
||||||
t.Run("new error", func(t *testing.T) {
|
|
||||||
errDefault := "this is an error"
|
|
||||||
for _, tc := range []struct {
|
|
||||||
m string
|
|
||||||
input interface{}
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
m: "empty",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "string",
|
|
||||||
input: errDefault,
|
|
||||||
expected: errDefault,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "error",
|
|
||||||
input: fmt.Errorf(errDefault),
|
|
||||||
expected: errDefault,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "herror.Err",
|
|
||||||
input: herror.New(errDefault),
|
|
||||||
expected: errDefault,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "invalid type",
|
|
||||||
input: 123456789,
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tc.m, func(t *testing.T) {
|
|
||||||
test.Equals(t, tc.expected, herror.New(tc.input).Error())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("wrap", func(t *testing.T) {
|
|
||||||
errmain := herror.New("MAIN ERROR")
|
|
||||||
errfmt := fmt.Errorf("ERROR FORMATTED")
|
|
||||||
errA := herror.New("ERR A")
|
|
||||||
errB := herror.New("ERR B")
|
|
||||||
errC := herror.New("ERR C")
|
|
||||||
errD := herror.New("ERR D")
|
|
||||||
errNested := errmain.Wrap(
|
|
||||||
errA.Wrap(
|
|
||||||
errB.Wrap(
|
|
||||||
errC.Wrap(errD),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, tc := range []struct {
|
|
||||||
m string
|
|
||||||
err error
|
|
||||||
expected []error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
m: "error",
|
|
||||||
err: errfmt,
|
|
||||||
expected: []error{
|
|
||||||
errfmt,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "deeper nested wrap",
|
|
||||||
err: errNested,
|
|
||||||
expected: []error{
|
|
||||||
errA, errB, errC, errD,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tc.m, func(t *testing.T) {
|
|
||||||
newerr := errmain.Wrap(tc.err)
|
|
||||||
|
|
||||||
for _, e := range tc.expected {
|
|
||||||
test.Equals(t, true, newerr.Is(e))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("json marshalling", func(t *testing.T) {
|
|
||||||
hError := herror.New("this is an error").
|
|
||||||
Wrap(fmt.Errorf("this is another error")).
|
|
||||||
CaptureStack()
|
|
||||||
marshalled, err := json.Marshal(hError)
|
|
||||||
test.OK(t, err)
|
|
||||||
|
|
||||||
var unmarshalled *herror.Err
|
|
||||||
test.OK(t, json.Unmarshal(marshalled, &unmarshalled))
|
|
||||||
test.Equals(t, hError, unmarshalled)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleErr_Wrap() {
|
|
||||||
errA := herror.New("something went wrong")
|
|
||||||
errB := fmt.Errorf("because of this error")
|
|
||||||
newerr := herror.Wrap(errA, errB)
|
|
||||||
|
|
||||||
fmt.Print(herror.Unwrap(newerr), "\n", newerr)
|
|
||||||
// Output: because of this error
|
|
||||||
// something went wrong
|
|
||||||
// -> because of this error
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleErr_Is() {
|
|
||||||
errA := herror.New("something went wrong")
|
|
||||||
errB := func() error {
|
|
||||||
return errA
|
|
||||||
}()
|
|
||||||
|
|
||||||
fmt.Print(herror.Is(errA, errB))
|
|
||||||
// Output: true
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleErr_CaptureStack() {
|
|
||||||
err := herror.New("something went wrong")
|
|
||||||
err.CaptureStack()
|
|
||||||
|
|
||||||
fmt.Print(err, "\n", err.Stack().Frames[2].Function)
|
|
||||||
// Output: something went wrong
|
|
||||||
// ExampleErr_CaptureStack
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleErr_AddDetails() {
|
|
||||||
err := herror.New("something went wrong")
|
|
||||||
err.AddDetails(struct {
|
|
||||||
number int
|
|
||||||
}{123})
|
|
||||||
|
|
||||||
fmt.Print(err, err.Details())
|
|
||||||
// Output: something went wrong
|
|
||||||
// (struct { number int }) {
|
|
||||||
// number: (int) 123
|
|
||||||
// }
|
|
||||||
}
|
|
|
@ -1,151 +0,0 @@
|
||||||
package herror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Stacktrace holds information about the frames of the stack.
|
|
||||||
type Stacktrace struct {
|
|
||||||
Frames []Frame `json:"frames,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frame represents parsed information from runtime.Frame
|
|
||||||
type Frame struct {
|
|
||||||
Function string `json:"function,omitempty"`
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Package string `json:"package,omitempty"`
|
|
||||||
Filename string `json:"filename,omitempty"`
|
|
||||||
AbsPath string `json:"abs_path,omitempty"`
|
|
||||||
Line int `json:"line,omitempty"`
|
|
||||||
InApp bool `json:"in_app,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FrameFilter represents function to filter frames
|
|
||||||
type FrameFilter func(Frame) bool
|
|
||||||
|
|
||||||
const unknown string = "unknown"
|
|
||||||
|
|
||||||
// NewStacktrace creates a stacktrace using `runtime.Callers`.
|
|
||||||
func NewStacktrace(filters ...FrameFilter) *Stacktrace {
|
|
||||||
pcs := make([]uintptr, 100)
|
|
||||||
n := runtime.Callers(1, pcs)
|
|
||||||
|
|
||||||
if n == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
frames := extractFrames(pcs[:n])
|
|
||||||
|
|
||||||
// default filter
|
|
||||||
frames = filterFrames(frames, func(f Frame) bool {
|
|
||||||
return f.Package == "runtime" || f.Package == "testing" ||
|
|
||||||
strings.HasSuffix(f.Package, "/herror")
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, filter := range filters {
|
|
||||||
frames = filterFrames(frames, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
stacktrace := Stacktrace{
|
|
||||||
Frames: frames,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &stacktrace
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFrame assembles a stacktrace frame out of `runtime.Frame`.
|
|
||||||
func NewFrame(f runtime.Frame) Frame {
|
|
||||||
abspath := unknown
|
|
||||||
filename := unknown
|
|
||||||
if f.File != "" {
|
|
||||||
abspath = f.File
|
|
||||||
_, filename = filepath.Split(f.File)
|
|
||||||
}
|
|
||||||
|
|
||||||
function := unknown
|
|
||||||
pkgname := unknown
|
|
||||||
typer := ""
|
|
||||||
if f.Function != "" {
|
|
||||||
pkgname, typer, function = deconstructFunctionName(f.Function)
|
|
||||||
}
|
|
||||||
|
|
||||||
inApp := func() bool {
|
|
||||||
out := strings.HasPrefix(abspath, build.Default.GOROOT) ||
|
|
||||||
strings.Contains(pkgname, "vendor")
|
|
||||||
return !out
|
|
||||||
}()
|
|
||||||
|
|
||||||
return Frame{
|
|
||||||
AbsPath: abspath,
|
|
||||||
Filename: filename,
|
|
||||||
Line: f.Line,
|
|
||||||
Package: pkgname,
|
|
||||||
Type: typer,
|
|
||||||
Function: function,
|
|
||||||
InApp: inApp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterFrames(frames []Frame, filter FrameFilter) []Frame {
|
|
||||||
filtered := make([]Frame, 0, len(frames))
|
|
||||||
|
|
||||||
for _, frame := range frames {
|
|
||||||
if filter(frame) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
filtered = append(filtered, frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractFrames(pcs []uintptr) []Frame {
|
|
||||||
frames := make([]Frame, 0, len(pcs))
|
|
||||||
callersFrames := runtime.CallersFrames(pcs)
|
|
||||||
|
|
||||||
for {
|
|
||||||
callerFrame, more := callersFrames.Next()
|
|
||||||
frames = append([]Frame{
|
|
||||||
NewFrame(callerFrame),
|
|
||||||
}, frames...)
|
|
||||||
|
|
||||||
if !more {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return frames
|
|
||||||
}
|
|
||||||
|
|
||||||
func deconstructFunctionName(name string) (pkg string, typer string, function string) {
|
|
||||||
if i := strings.LastIndex(name, "/"); i != -1 {
|
|
||||||
pkg = name[:i]
|
|
||||||
function = name[i+1:]
|
|
||||||
|
|
||||||
if d := strings.Index(function, "."); d != -1 {
|
|
||||||
pkg = fmt.Sprint(pkg, "/", function[:d])
|
|
||||||
function = function[d+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if o, c := strings.LastIndex(name, ".("), strings.LastIndex(name, ")."); o != -1 && c != -1 {
|
|
||||||
pkg = name[:o]
|
|
||||||
function = name[c+2:]
|
|
||||||
|
|
||||||
typer = name[o+2 : c]
|
|
||||||
if i := strings.Index(typer, "*"); i != -1 {
|
|
||||||
typer = typer[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if i := strings.LastIndex(name, "."); i != -1 {
|
|
||||||
pkg = name[:i]
|
|
||||||
function = name[i+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
package herror_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.sr.ht/~ewintr/go-kit/herror"
|
|
||||||
"git.sr.ht/~ewintr/go-kit/test"
|
|
||||||
)
|
|
||||||
|
|
||||||
func trace() *herror.Stacktrace {
|
|
||||||
return herror.NewStacktrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceStepIn(f []herror.FrameFilter) *herror.Stacktrace {
|
|
||||||
return traceWithFilter(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceWithFilter(f []herror.FrameFilter) *herror.Stacktrace {
|
|
||||||
return herror.NewStacktrace(f...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStacktrace(t *testing.T) {
|
|
||||||
t.Run("new", func(t *testing.T) {
|
|
||||||
stack := trace()
|
|
||||||
|
|
||||||
expectedFrames := []herror.Frame{
|
|
||||||
herror.Frame{
|
|
||||||
Function: "TestStacktrace.func1",
|
|
||||||
},
|
|
||||||
herror.Frame{
|
|
||||||
Function: "trace",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
test.Equals(t, len(expectedFrames), len(stack.Frames))
|
|
||||||
for i, frame := range expectedFrames {
|
|
||||||
test.Equals(t, frame.Function, stack.Frames[i].Function)
|
|
||||||
test.Equals(t, "git.sr.ht/~ewintr/go-kit/herror_test", stack.Frames[i].Package)
|
|
||||||
test.Equals(t, "stacktrace_test.go", stack.Frames[i].Filename)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("filter frames", func(t *testing.T) {
|
|
||||||
|
|
||||||
for _, tc := range []struct {
|
|
||||||
m string
|
|
||||||
filters []herror.FrameFilter
|
|
||||||
expected []herror.Frame
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
m: "no filter",
|
|
||||||
expected: []herror.Frame{
|
|
||||||
herror.Frame{
|
|
||||||
Function: "TestStacktrace.func2",
|
|
||||||
},
|
|
||||||
herror.Frame{
|
|
||||||
Function: "traceStepIn",
|
|
||||||
},
|
|
||||||
herror.Frame{
|
|
||||||
Function: "traceWithFilter",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "single filter",
|
|
||||||
expected: []herror.Frame{
|
|
||||||
herror.Frame{
|
|
||||||
Function: "traceStepIn",
|
|
||||||
},
|
|
||||||
herror.Frame{
|
|
||||||
Function: "traceWithFilter",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
filters: []herror.FrameFilter{
|
|
||||||
func(f herror.Frame) bool {
|
|
||||||
return f.Function == "TestStacktrace.func2"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
m: "multiple filters",
|
|
||||||
expected: []herror.Frame{
|
|
||||||
herror.Frame{
|
|
||||||
Function: "traceWithFilter",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
filters: []herror.FrameFilter{
|
|
||||||
func(f herror.Frame) bool {
|
|
||||||
return f.Function == "TestStacktrace.func2"
|
|
||||||
},
|
|
||||||
func(f herror.Frame) bool {
|
|
||||||
return f.Function == "traceStepIn"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
stack := traceStepIn(tc.filters)
|
|
||||||
|
|
||||||
t.Run(tc.m, func(t *testing.T) {
|
|
||||||
test.Equals(t, len(tc.expected), len(stack.Frames))
|
|
||||||
|
|
||||||
for i, frame := range tc.expected {
|
|
||||||
test.Equals(t, frame.Function, stack.Frames[i].Function)
|
|
||||||
test.Equals(t, "git.sr.ht/~ewintr/go-kit/herror_test", stack.Frames[i].Package)
|
|
||||||
test.Equals(t, "stacktrace_test.go", stack.Frames[i].Filename)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFrame(t *testing.T) {
|
|
||||||
t.Run("new", func(t *testing.T) {
|
|
||||||
f := func() herror.Frame {
|
|
||||||
pc := make([]uintptr, 1)
|
|
||||||
n := runtime.Callers(0, pc)
|
|
||||||
test.Assert(t, n == 1, "expected available pcs")
|
|
||||||
|
|
||||||
frames := runtime.CallersFrames(pc)
|
|
||||||
runtimeframe, _ := frames.Next()
|
|
||||||
return herror.NewFrame(runtimeframe)
|
|
||||||
}
|
|
||||||
|
|
||||||
frame := f()
|
|
||||||
test.Equals(t, "Callers", frame.Function)
|
|
||||||
test.Equals(t, "runtime", frame.Package)
|
|
||||||
test.Equals(t, "extern.go", frame.Filename)
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in New Issue