diff options
Diffstat (limited to 'src/cmd/pprof/pprof_test.go')
-rw-r--r-- | src/cmd/pprof/pprof_test.go | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/cmd/pprof/pprof_test.go b/src/cmd/pprof/pprof_test.go new file mode 100644 index 0000000..353781a --- /dev/null +++ b/src/cmd/pprof/pprof_test.go @@ -0,0 +1,128 @@ +// Copyright 2021 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 main + +import ( + "internal/testenv" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "testing" +) + +// TestMain executes the test binary as the pprof command if +// GO_PPROFTEST_IS_PPROF is set, and runs the tests otherwise. +func TestMain(m *testing.M) { + if os.Getenv("GO_PPROFTEST_IS_PPROF") != "" { + main() + os.Exit(0) + } + + os.Setenv("GO_PPROFTEST_IS_PPROF", "1") // Set for subprocesses to inherit. + os.Exit(m.Run()) +} + +// pprofPath returns the path to the "pprof" binary to run. +func pprofPath(t testing.TB) string { + t.Helper() + testenv.MustHaveExec(t) + + pprofPathOnce.Do(func() { + pprofExePath, pprofPathErr = os.Executable() + }) + if pprofPathErr != nil { + t.Fatal(pprofPathErr) + } + return pprofExePath +} + +var ( + pprofPathOnce sync.Once + pprofExePath string + pprofPathErr error +) + +// See also runtime/pprof.cpuProfilingBroken. +func mustHaveCPUProfiling(t *testing.T) { + switch runtime.GOOS { + case "plan9": + t.Skipf("skipping on %s, unimplemented", runtime.GOOS) + case "aix": + t.Skipf("skipping on %s, issue 45170", runtime.GOOS) + case "ios", "dragonfly", "netbsd", "illumos", "solaris": + t.Skipf("skipping on %s, issue 13841", runtime.GOOS) + case "openbsd": + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + t.Skipf("skipping on %s/%s, issue 13841", runtime.GOOS, runtime.GOARCH) + } + } +} + +func mustHaveDisasm(t *testing.T) { + switch runtime.GOARCH { + case "loong64": + t.Skipf("skipping on %s.", runtime.GOARCH) + case "mips", "mipsle", "mips64", "mips64le": + t.Skipf("skipping on %s, issue 12559", runtime.GOARCH) + case "riscv64": + t.Skipf("skipping on %s, issue 36738", runtime.GOARCH) + case "s390x": + t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) + } + + // Skip PIE platforms, pprof can't disassemble PIE. + if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { + t.Skipf("skipping on %s/%s, issue 46639", runtime.GOOS, runtime.GOARCH) + } +} + +// TestDisasm verifies that cmd/pprof can successfully disassemble functions. +// +// This is a regression test for issue 46636. +func TestDisasm(t *testing.T) { + mustHaveCPUProfiling(t) + mustHaveDisasm(t) + testenv.MustHaveGoBuild(t) + + tmpdir := t.TempDir() + cpuExe := filepath.Join(tmpdir, "cpu.exe") + cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", cpuExe, "cpu.go") + cmd.Dir = "testdata/" + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("build failed: %v\n%s", err, out) + } + + profile := filepath.Join(tmpdir, "cpu.pprof") + cmd = testenv.Command(t, cpuExe, "-output", profile) + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("cpu failed: %v\n%s", err, out) + } + + cmd = testenv.Command(t, pprofPath(t), "-disasm", "main.main", cpuExe, profile) + out, err = cmd.CombinedOutput() + if err != nil { + t.Errorf("pprof -disasm failed: %v\n%s", err, out) + + // Try to print out profile content for debugging. + cmd = testenv.Command(t, pprofPath(t), "-raw", cpuExe, profile) + out, err = cmd.CombinedOutput() + if err != nil { + t.Logf("pprof -raw failed: %v\n%s", err, out) + } else { + t.Logf("profile content:\n%s", out) + } + return + } + + sout := string(out) + want := "ROUTINE ======================== main.main" + if !strings.Contains(sout, want) { + t.Errorf("pprof -disasm got %s want contains %q", sout, want) + } +} |