Skip to content

Commit

Permalink
Add errorsext & Stack Frame helpers
Browse files Browse the repository at this point in the history
Added Stack frame helper functions.
  • Loading branch information
deankarn committed May 10, 2019
1 parent ebc3eaf commit 19a86f2
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pkg
![Project status](https://img.shields.io/badge/version-2.0.0-green.svg)
![Project status](https://img.shields.io/badge/version-2.1.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/pkg.svg?branch=master)](https://travis-ci.org/go-playground/pkg)
[![Coverage Status](https://coveralls.io/repos/github/go-playground/pkg/badge.svg?branch=master)](https://coveralls.io/github/go-playground/pkg?branch=master)
[![GoDoc](https://godoc.org/github.com/go-playground/pkg?status.svg)](https://godoc.org/github.com/go-playground/pkg)
Expand Down
47 changes: 47 additions & 0 deletions errors/stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package errorsext

import (
"runtime"
"strings"
)

// Frame wraps a runtime.Frame to provide some helper functions while still allowing access to
// the original runtime.Frame
type Frame struct {
runtime.Frame
}

// File is the runtime.Frame.File stripped down to just the filename
func (f Frame) File() string {
name := f.Frame.File
i := strings.LastIndexByte(name, '/')
return name[i+1:]
}

// Line is the line of the runtime.Frame and exposed for convenience.
func (f Frame) Line() int {
return f.Frame.Line
}

// Function is the runtime.Frame.Function stripped down to just the function name
func (f Frame) Function() string {
name := f.Frame.Function
i := strings.LastIndexByte(name, '.')
return name[i+1:]
}

// Stack returns a stack Frame
func Stack() Frame {
return StackLevel(1)
}

// StackLevel returns a stack Frame skipping the number of supplied frames.
// This is primarily used by other libraries who use this package
// internally as the additional.
func StackLevel(skip int) (f Frame) {
var frame [3]uintptr
runtime.Callers(skip+2, frame[:])
frames := runtime.CallersFrames(frame[:])
f.Frame, _ = frames.Next()
return
}
54 changes: 54 additions & 0 deletions errors/stack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package errorsext

import (
"testing"
)

func nested(level int) Frame {
return StackLevel(level)
}

func TestStack(t *testing.T) {
tests := []struct {
name string
frame Frame
file string
line int
function string
}{
{
name: "stack",
frame: Stack(),
file: "stack_test.go",
line: 21,
function: "TestStack",
},
{
name: "stack-level1",
frame: nested(1),
file: "stack_test.go",
line: 28,
function: "TestStack",
},
{
name: "stack-level0",
frame: nested(0),
file: "stack_test.go",
line: 8,
function: "nested",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.frame.File() != tt.file {
t.Errorf("TestStack File() = %s, want %s", tt.frame.File(), tt.file)
}
if tt.frame.Line() != tt.line {
t.Errorf("TestStack Line() = %d, want %d", tt.frame.Line(), tt.line)
}
if tt.frame.Function() != tt.function {
t.Errorf("TestStack Function() = %s, want %s", tt.frame.Function(), tt.function)
}
})
}
}

0 comments on commit 19a86f2

Please sign in to comment.