-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Stack frame helper functions.
- Loading branch information
Showing
3 changed files
with
102 additions
and
1 deletion.
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
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 | ||
} |
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,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) | ||
} | ||
}) | ||
} | ||
} |