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