}
}
-func testCgoPprof(t *testing.T, buildArg, runArg string) {
+func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
t.Parallel()
if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le") {
t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
defer os.Remove(fn)
for try := 0; try < 2; try++ {
- cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1"))
+ cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-traces"))
// Check that pprof works both with and without explicit executable on command line.
if try == 0 {
cmd.Args = append(cmd.Args, exe, fn)
cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
}
- top, err := cmd.CombinedOutput()
- t.Logf("%s:\n%s", cmd.Args, top)
+ out, err := cmd.CombinedOutput()
+ t.Logf("%s:\n%s", cmd.Args, out)
if err != nil {
t.Error(err)
- } else if !bytes.Contains(top, []byte("cpuHog")) {
- t.Error("missing cpuHog in pprof output")
+ continue
+ }
+
+ trace := findTrace(string(out), top)
+ if len(trace) == 0 {
+ t.Errorf("%s traceback missing.", top)
+ continue
+ }
+ if trace[len(trace)-1] != bottom {
+ t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
}
}
}
func TestCgoPprof(t *testing.T) {
- testCgoPprof(t, "", "CgoPprof")
+ testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
}
func TestCgoPprofPIE(t *testing.T) {
- testCgoPprof(t, "-buildmode=pie", "CgoPprof")
+ testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
}
func TestCgoPprofThread(t *testing.T) {
- testCgoPprof(t, "", "CgoPprofThread")
+ testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
}
func TestCgoPprofThreadNoTraceback(t *testing.T) {
- testCgoPprof(t, "", "CgoPprofThreadNoTraceback")
+ testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
}
func TestRaceProf(t *testing.T) {
t.Errorf("expected %q got %v", want, got)
}
}
+
+func nextTrace(lines []string) ([]string, []string) {
+ var trace []string
+ for n, line := range lines {
+ if strings.HasPrefix(line, "---") {
+ return trace, lines[n+1:]
+ }
+ fields := strings.Fields(strings.TrimSpace(line))
+ if len(fields) == 0 {
+ continue
+ }
+ // Last field contains the function name.
+ trace = append(trace, fields[len(fields)-1])
+ }
+ return nil, nil
+}
+
+func findTrace(text, top string) []string {
+ lines := strings.Split(text, "\n")
+ _, lines = nextTrace(lines) // Skip the header.
+ for len(lines) > 0 {
+ var t []string
+ t, lines = nextTrace(lines)
+ if len(t) == 0 {
+ continue
+ }
+ if t[0] == top {
+ return t
+ }
+ }
+ return nil
+}