Imported Upstream version 4.7.2
[platform/upstream/gcc48.git] / libgo / go / runtime / pprof / pprof_test.go
1 // Copyright 2011 The Go Authors.  All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package pprof_test
6
7 import (
8         "bytes"
9         "hash/crc32"
10         "os/exec"
11         "runtime"
12         . "runtime/pprof"
13         "strings"
14         "testing"
15         "unsafe"
16 )
17
18 func TestCPUProfile(t *testing.T) {
19         switch runtime.GOOS {
20         case "darwin":
21                 out, err := exec.Command("uname", "-a").CombinedOutput()
22                 if err != nil {
23                         t.Fatal(err)
24                 }
25                 vers := string(out)
26                 t.Logf("uname -a: %v", vers)
27                 // Lion uses "Darwin Kernel Version 11".
28                 if strings.Contains(vers, "Darwin Kernel Version 10") && strings.Contains(vers, "RELEASE_X86_64") {
29                         t.Logf("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)")
30                         return
31                 }
32         case "plan9":
33                 // unimplemented
34                 return
35         }
36
37         buf := make([]byte, 100000)
38         var prof bytes.Buffer
39         if err := StartCPUProfile(&prof); err != nil {
40                 t.Fatal(err)
41         }
42         // This loop takes about a quarter second on a 2 GHz laptop.
43         // We only need to get one 100 Hz clock tick, so we've got
44         // a 25x safety buffer.
45         for i := 0; i < 1000; i++ {
46                 crc32.ChecksumIEEE(buf)
47         }
48         StopCPUProfile()
49
50         // Convert []byte to []uintptr.
51         bytes := prof.Bytes()
52         val := *(*[]uintptr)(unsafe.Pointer(&bytes))
53         val = val[:len(bytes)/int(unsafe.Sizeof(uintptr(0)))]
54
55         if len(val) < 10 {
56                 t.Fatalf("profile too short: %#x", val)
57         }
58         if val[0] != 0 || val[1] != 3 || val[2] != 0 || val[3] != 1e6/100 || val[4] != 0 {
59                 t.Fatalf("unexpected header %#x", val[:5])
60         }
61
62         // Check that profile is well formed and contains ChecksumIEEE.
63         found := false
64         val = val[5:]
65         for len(val) > 0 {
66                 if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
67                         t.Fatalf("malformed profile.  leftover: %#x", val)
68                 }
69                 for _, pc := range val[2 : 2+val[1]] {
70                         f := runtime.FuncForPC(pc)
71                         if f == nil {
72                                 continue
73                         }
74                         if strings.Contains(f.Name(), "ChecksumIEEE") ||
75                                 (strings.Contains(f.Name(), "update") && strings.Contains(f.Name(), "crc32")) {
76                                 found = true
77                         }
78                 }
79                 val = val[2+val[1]:]
80         }
81
82         if !found {
83                 t.Fatal("did not find ChecksumIEEE in the profile")
84         }
85 }