mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:10 -07:00
a02cf32866
This can be used either to directly parse runtime.Stack output or process text that includes stack dumps, like test timeouts or panics. It includes a binary, gostacks that processes stdin to stdout replacing stack dumps in place. Change-Id: Id7b1cfd69b8aea36c66f12ec0bdf38b68cba5afb Reviewed-on: https://go-review.googlesource.com/c/tools/+/232658 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
194 lines
3.9 KiB
Go
194 lines
3.9 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package stack_test
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/tools/internal/stack"
|
|
)
|
|
|
|
func TestProcess(t *testing.T) {
|
|
for _, test := range []struct{ name, input, expect string }{{
|
|
name: `empty`,
|
|
input: ``,
|
|
expect: ``,
|
|
}, {
|
|
name: `no_frame`,
|
|
input: `goroutine 1 [running]:`,
|
|
expect: `
|
|
[running]: $1
|
|
|
|
1 goroutines, 1 unique
|
|
`,
|
|
}, {
|
|
name: `one_frame`,
|
|
input: `
|
|
goroutine 1 [running]:
|
|
package.function(args)
|
|
file.go:10
|
|
`,
|
|
expect: `
|
|
[running]: $1
|
|
file.go:10: function
|
|
|
|
1 goroutines, 1 unique
|
|
`,
|
|
}, {
|
|
name: `one_call`,
|
|
input: `
|
|
goroutine 1 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
package2.functionB(args)
|
|
file2.go:20
|
|
package3.functionC(args)
|
|
file3.go:30
|
|
`,
|
|
expect: `
|
|
[running]: $1
|
|
file1.go:10: functionA
|
|
file2.go:20: functionB
|
|
file3.go:30: functionC
|
|
|
|
1 goroutines, 1 unique
|
|
`,
|
|
}, {
|
|
name: `two_call`,
|
|
input: `
|
|
goroutine 1 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
goroutine 2 [running]:
|
|
package2.functionB(args)
|
|
file2.go:20
|
|
`,
|
|
expect: `
|
|
[running]: $1
|
|
file1.go:10: functionA
|
|
|
|
[running]: $2
|
|
file2.go:20: functionB
|
|
|
|
2 goroutines, 2 unique
|
|
`,
|
|
}, {
|
|
name: `merge_call`,
|
|
input: `
|
|
goroutine 1 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
goroutine 2 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
`,
|
|
expect: `
|
|
[running]: $1, $2
|
|
file1.go:10: functionA
|
|
|
|
2 goroutines, 1 unique
|
|
`,
|
|
}, {
|
|
name: `alternating_call`,
|
|
input: `
|
|
goroutine 1 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
goroutine 2 [running]:
|
|
package2.functionB(args)
|
|
file2.go:20
|
|
goroutine 3 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
goroutine 4 [running]:
|
|
package2.functionB(args)
|
|
file2.go:20
|
|
goroutine 5 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
goroutine 6 [running]:
|
|
package2.functionB(args)
|
|
file2.go:20
|
|
`,
|
|
expect: `
|
|
[running]: $1, $3, $5
|
|
file1.go:10: functionA
|
|
|
|
[running]: $2, $4, $6
|
|
file2.go:20: functionB
|
|
|
|
6 goroutines, 2 unique
|
|
`,
|
|
}, {
|
|
name: `sort_calls`,
|
|
input: `
|
|
goroutine 1 [running]:
|
|
package3.functionC(args)
|
|
file3.go:30
|
|
goroutine 2 [running]:
|
|
package2.functionB(args)
|
|
file2.go:20
|
|
goroutine 3 [running]:
|
|
package1.functionA(args)
|
|
file1.go:10
|
|
`,
|
|
expect: `
|
|
[running]: $3
|
|
file1.go:10: functionA
|
|
|
|
[running]: $2
|
|
file2.go:20: functionB
|
|
|
|
[running]: $1
|
|
file3.go:30: functionC
|
|
|
|
3 goroutines, 3 unique
|
|
`,
|
|
}, {
|
|
name: `real_single`,
|
|
input: `
|
|
panic: oops
|
|
|
|
goroutine 53 [running]:
|
|
golang.org/x/tools/internal/jsonrpc2_test.testHandler.func1(0x1240c20, 0xc000013350, 0xc0000133b0, 0x1240ca0, 0xc00002ab00, 0x3, 0x3)
|
|
/work/tools/internal/jsonrpc2/jsonrpc2_test.go:160 +0x74c
|
|
golang.org/x/tools/internal/jsonrpc2.(*Conn).Run(0xc000204330, 0x1240c20, 0xc000204270, 0x1209570, 0xc000212120, 0x1242700)
|
|
/work/tools/internal/jsonrpc2/jsonrpc2.go:187 +0x777
|
|
golang.org/x/tools/internal/jsonrpc2_test.run.func1(0x123ebe0, 0xc000206018, 0x123ec20, 0xc000206010, 0xc0002080a0, 0xc000204330, 0x1240c20, 0xc000204270, 0xc000212120)
|
|
/work/tools/internal/jsonrpc2/jsonrpc2_test.go:131 +0xe2
|
|
created by golang.org/x/tools/internal/jsonrpc2_test.run
|
|
/work/tools/internal/jsonrpc2/jsonrpc2_test.go:121 +0x263
|
|
FAIL golang.org/x/tools/internal/jsonrpc2 0.252s
|
|
FAIL
|
|
`,
|
|
expect: `
|
|
panic: oops
|
|
|
|
[running]: $53
|
|
/work/tools/internal/jsonrpc2/jsonrpc2_test.go:160: testHandler.func1
|
|
/work/tools/internal/jsonrpc2/jsonrpc2.go:187: (*Conn).Run
|
|
/work/tools/internal/jsonrpc2/jsonrpc2_test.go:131: run.func1
|
|
/work/tools/internal/jsonrpc2/jsonrpc2_test.go:121: run
|
|
|
|
1 goroutines, 1 unique
|
|
|
|
FAIL golang.org/x/tools/internal/jsonrpc2 0.252s
|
|
FAIL
|
|
`,
|
|
}} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
buf := &bytes.Buffer{}
|
|
stack.Process(buf, strings.NewReader(test.input))
|
|
expect := strings.TrimSpace(test.expect)
|
|
got := strings.TrimSpace(buf.String())
|
|
if got != expect {
|
|
t.Errorf("got:\n%s\nexpect:\n%s", got, expect)
|
|
}
|
|
})
|
|
}
|
|
}
|