Skip to content

Commit 19a86f2

Browse files
author
Dean Karn
committed
Add errorsext & Stack Frame helpers
Added Stack frame helper functions.
1 parent ebc3eaf commit 19a86f2

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pkg
2-
![Project status](https://img.shields.io/badge/version-2.0.0-green.svg)
2+
![Project status](https://img.shields.io/badge/version-2.1.0-green.svg)
33
[![Build Status](https://travis-ci.org/go-playground/pkg.svg?branch=master)](https://travis-ci.org/go-playground/pkg)
44
[![Coverage Status](https://coveralls.io/repos/github/go-playground/pkg/badge.svg?branch=master)](https://coveralls.io/github/go-playground/pkg?branch=master)
55
[![GoDoc](https://godoc.org/github.com/go-playground/pkg?status.svg)](https://godoc.org/github.com/go-playground/pkg)

errors/stack.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package errorsext
2+
3+
import (
4+
"runtime"
5+
"strings"
6+
)
7+
8+
// Frame wraps a runtime.Frame to provide some helper functions while still allowing access to
9+
// the original runtime.Frame
10+
type Frame struct {
11+
runtime.Frame
12+
}
13+
14+
// File is the runtime.Frame.File stripped down to just the filename
15+
func (f Frame) File() string {
16+
name := f.Frame.File
17+
i := strings.LastIndexByte(name, '/')
18+
return name[i+1:]
19+
}
20+
21+
// Line is the line of the runtime.Frame and exposed for convenience.
22+
func (f Frame) Line() int {
23+
return f.Frame.Line
24+
}
25+
26+
// Function is the runtime.Frame.Function stripped down to just the function name
27+
func (f Frame) Function() string {
28+
name := f.Frame.Function
29+
i := strings.LastIndexByte(name, '.')
30+
return name[i+1:]
31+
}
32+
33+
// Stack returns a stack Frame
34+
func Stack() Frame {
35+
return StackLevel(1)
36+
}
37+
38+
// StackLevel returns a stack Frame skipping the number of supplied frames.
39+
// This is primarily used by other libraries who use this package
40+
// internally as the additional.
41+
func StackLevel(skip int) (f Frame) {
42+
var frame [3]uintptr
43+
runtime.Callers(skip+2, frame[:])
44+
frames := runtime.CallersFrames(frame[:])
45+
f.Frame, _ = frames.Next()
46+
return
47+
}

errors/stack_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package errorsext
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func nested(level int) Frame {
8+
return StackLevel(level)
9+
}
10+
11+
func TestStack(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
frame Frame
15+
file string
16+
line int
17+
function string
18+
}{
19+
{
20+
name: "stack",
21+
frame: Stack(),
22+
file: "stack_test.go",
23+
line: 21,
24+
function: "TestStack",
25+
},
26+
{
27+
name: "stack-level1",
28+
frame: nested(1),
29+
file: "stack_test.go",
30+
line: 28,
31+
function: "TestStack",
32+
},
33+
{
34+
name: "stack-level0",
35+
frame: nested(0),
36+
file: "stack_test.go",
37+
line: 8,
38+
function: "nested",
39+
},
40+
}
41+
for _, tt := range tests {
42+
t.Run(tt.name, func(t *testing.T) {
43+
if tt.frame.File() != tt.file {
44+
t.Errorf("TestStack File() = %s, want %s", tt.frame.File(), tt.file)
45+
}
46+
if tt.frame.Line() != tt.line {
47+
t.Errorf("TestStack Line() = %d, want %d", tt.frame.Line(), tt.line)
48+
}
49+
if tt.frame.Function() != tt.function {
50+
t.Errorf("TestStack Function() = %s, want %s", tt.frame.Function(), tt.function)
51+
}
52+
})
53+
}
54+
}

0 commit comments

Comments
 (0)