summaryrefslogtreecommitdiffstats
path: root/src/cmd/pprof/pprof_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/pprof/pprof_test.go')
-rw-r--r--src/cmd/pprof/pprof_test.go128
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)
+ }
+}