Imported Upstream version 4.8.1
[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.Skip("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)")
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         l := len(bytes) / int(unsafe.Sizeof(uintptr(0)))
53         val := *(*[]uintptr)(unsafe.Pointer(&bytes))
54         val = val[:l]
55
56         if l < 13 {
57                 t.Fatalf("profile too short: %#x", val)
58         }
59
60         fmt.Println(val, l)
61         hd, val, tl := val[:5], val[5:l-3], val[l-3:]
62         fmt.Println(hd, val, tl)
63         if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
64                 t.Fatalf("unexpected header %#x", hd)
65         }
66
67         if tl[0] != 0 || tl[1] != 1 || tl[2] != 0 {
68                 t.Fatalf("malformed end-of-data marker %#x", tl)
69         }
70
71         // Check that profile is well formed and contains ChecksumIEEE.
72         found := false
73         for len(val) > 0 {
74                 if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
75                         t.Fatalf("malformed profile.  leftover: %#x", val)
76                 }
77                 for _, pc := range val[2 : 2+val[1]] {
78                         f := runtime.FuncForPC(pc)
79                         if f == nil {
80                                 continue
81                         }
82                         if strings.Contains(f.Name(), "ChecksumIEEE") ||
83                                 (strings.Contains(f.Name(), "update") && strings.Contains(f.Name(), "crc32")) {
84                                 found = true
85                         }
86                 }
87                 val = val[2+val[1]:]
88         }
89
90         if !found {
91                 t.Fatal("did not find ChecksumIEEE in the profile")
92         }
93 }