Skip to content

Commit cbb7b96

Browse files
committed
Add implementations of fmt.Stringer to stack.Call and stack.CallStack.
1 parent 9240976 commit cbb7b96

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

stack.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ func Caller(skip int) Call {
4545
return c
4646
}
4747

48+
// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
49+
func (c Call) String() string {
50+
return fmt.Sprint(c)
51+
}
52+
4853
// Format implements fmt.Formatter with support for the following verbs.
4954
//
5055
// %s source file
@@ -171,6 +176,11 @@ func (c Call) line() int {
171176
// stack.
172177
type CallStack []Call
173178

179+
// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs).
180+
func (cs CallStack) String() string {
181+
return fmt.Sprint(cs)
182+
}
183+
174184
// Format implements fmt.Formatter by printing the CallStack as square brackes
175185
// ([, ]) surrounding a space separated list of Calls each formatted with the
176186
// supplied verb and options.
@@ -268,12 +278,12 @@ func inGoroot(c Call) bool {
268278
if runtime.GOOS == "windows" {
269279
file = strings.ToLower(file)
270280
}
271-
return strings.HasPrefix(file, goroot)
281+
return strings.HasPrefix(file, goroot) || strings.HasSuffix(file, "/_testmain.go")
272282
}
273283

274284
// TrimRuntime returns a slice of the CallStack with the topmost entries from
275285
// the go runtime removed. It considers any calls originating from unknown
276-
// files or files under GOROOT as part of the runtime.
286+
// files, files under GOROOT, or _testmain.go as part of the runtime.
277287
func (cs CallStack) TrimRuntime() CallStack {
278288
for len(cs) > 0 && inGoroot(cs[len(cs)-1]) {
279289
cs = cs[:len(cs)-1]

stack_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,62 @@ func TestCallFormat(t *testing.T) {
7777
}
7878
}
7979

80+
func TestCallString(t *testing.T) {
81+
t.Parallel()
82+
83+
c := stack.Caller(0)
84+
_, file, line, ok := runtime.Caller(0)
85+
line--
86+
if !ok {
87+
t.Fatal("runtime.Caller(0) failed")
88+
}
89+
90+
c2, _, file2, line2, ok2 := testType{}.testMethod()
91+
if !ok2 {
92+
t.Fatal("runtime.Caller(0) failed")
93+
}
94+
95+
data := []struct {
96+
c stack.Call
97+
desc string
98+
out string
99+
}{
100+
{stack.Call{}, "error", "%!v(NOFUNC)"},
101+
{c, "func", fmt.Sprint(path.Base(file), ":", line)},
102+
{c2, "meth", fmt.Sprint(path.Base(file2), ":", line2)},
103+
}
104+
105+
for _, d := range data {
106+
got := d.c.String()
107+
if got != d.out {
108+
t.Errorf("got %s, want %s", got, d.out)
109+
}
110+
}
111+
}
112+
113+
func TestCallStackString(t *testing.T) {
114+
cs, line0 := getTrace(t)
115+
_, file, line1, ok := runtime.Caller(0)
116+
line1--
117+
if !ok {
118+
t.Fatal("runtime.Caller(0) failed")
119+
}
120+
file = path.Base(file)
121+
if got, want := cs.String(), fmt.Sprintf("[%s:%d %s:%d]", file, line0, file, line1); got != want {
122+
t.Errorf("\n got %v\nwant %v", got, want)
123+
}
124+
}
125+
126+
func getTrace(t *testing.T) (stack.CallStack, int) {
127+
cs := stack.Trace().TrimRuntime()
128+
_, _, line, ok := runtime.Caller(0)
129+
line--
130+
if !ok {
131+
t.Fatal("runtime.Caller(0) failed")
132+
}
133+
return cs, line
134+
}
135+
80136
func TestTrimAbove(t *testing.T) {
81137
trace := trimAbove()
82138
if got, want := len(trace), 2; got != want {

0 commit comments

Comments
 (0)