aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/pprof/pprof_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/pprof/pprof_test.go')
-rw-r--r--src/pkg/runtime/pprof/pprof_test.go82
1 files changed, 66 insertions, 16 deletions
diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/pkg/runtime/pprof/pprof_test.go
index 94d19f741c..995c2fe68d 100644
--- a/src/pkg/runtime/pprof/pprof_test.go
+++ b/src/pkg/runtime/pprof/pprof_test.go
@@ -19,6 +19,38 @@ import (
)
func TestCPUProfile(t *testing.T) {
+ buf := make([]byte, 100000)
+ testCPUProfile(t, []string{"crc32.ChecksumIEEE"}, func() {
+ // This loop takes about a quarter second on a 2 GHz laptop.
+ // We only need to get one 100 Hz clock tick, so we've got
+ // a 25x safety buffer.
+ for i := 0; i < 1000; i++ {
+ crc32.ChecksumIEEE(buf)
+ }
+ })
+}
+
+func TestCPUProfileMultithreaded(t *testing.T) {
+ buf := make([]byte, 100000)
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+ testCPUProfile(t, []string{"crc32.ChecksumIEEE", "crc32.Update"}, func() {
+ c := make(chan int)
+ go func() {
+ for i := 0; i < 2000; i++ {
+ crc32.Update(0, crc32.IEEETable, buf)
+ }
+ c <- 1
+ }()
+ // This loop takes about a quarter second on a 2 GHz laptop.
+ // We only need to get one 100 Hz clock tick, so we've got
+ // a 25x safety buffer.
+ for i := 0; i < 2000; i++ {
+ crc32.ChecksumIEEE(buf)
+ }
+ })
+}
+
+func testCPUProfile(t *testing.T, need []string, f func()) {
switch runtime.GOOS {
case "darwin":
out, err := exec.Command("uname", "-a").CombinedOutput()
@@ -27,26 +59,16 @@ func TestCPUProfile(t *testing.T) {
}
vers := string(out)
t.Logf("uname -a: %v", vers)
- // Lion uses "Darwin Kernel Version 11".
- if strings.Contains(vers, "Darwin Kernel Version 10") && strings.Contains(vers, "RELEASE_X86_64") {
- t.Skip("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)")
- }
case "plan9":
// unimplemented
return
}
- buf := make([]byte, 100000)
var prof bytes.Buffer
if err := StartCPUProfile(&prof); err != nil {
t.Fatal(err)
}
- // This loop takes about a quarter second on a 2 GHz laptop.
- // We only need to get one 100 Hz clock tick, so we've got
- // a 25x safety buffer.
- for i := 0; i < 1000; i++ {
- crc32.ChecksumIEEE(buf)
- }
+ f()
StopCPUProfile()
// Convert []byte to []uintptr.
@@ -56,6 +78,10 @@ func TestCPUProfile(t *testing.T) {
val = val[:l]
if l < 13 {
+ if runtime.GOOS == "darwin" {
+ t.Logf("ignoring failure on OS X; see golang.org/issue/6047")
+ return
+ }
t.Fatalf("profile too short: %#x", val)
}
@@ -69,7 +95,7 @@ func TestCPUProfile(t *testing.T) {
}
// Check that profile is well formed and contains ChecksumIEEE.
- found := false
+ have := make([]uintptr, len(need))
for len(val) > 0 {
if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
t.Fatalf("malformed profile. leftover: %#x", val)
@@ -79,14 +105,38 @@ func TestCPUProfile(t *testing.T) {
if f == nil {
continue
}
- if strings.Contains(f.Name(), "ChecksumIEEE") {
- found = true
+ for i, name := range need {
+ if strings.Contains(f.Name(), name) {
+ have[i] += val[0]
+ }
}
}
val = val[2+val[1]:]
}
- if !found {
- t.Fatal("did not find ChecksumIEEE in the profile")
+ var total uintptr
+ for i, name := range need {
+ total += have[i]
+ t.Logf("%s: %d\n", name, have[i])
+ }
+ ok := true
+ if total == 0 {
+ t.Logf("no CPU profile samples collected")
+ ok = false
+ }
+ min := total / uintptr(len(have)) / 2
+ for i, name := range need {
+ if have[i] < min {
+ t.Logf("%s has %d samples out of %d, want at least %d, ideally %d", name, have[i], total, min, total/uintptr(len(have)))
+ ok = false
+ }
+ }
+
+ if !ok {
+ if runtime.GOOS == "darwin" {
+ t.Logf("ignoring failure on OS X; see golang.org/issue/6047")
+ return
+ }
+ t.FailNow()
}
}