From: Alberto Donizetti Date: Tue, 20 Jun 2017 15:40:21 +0000 (+0200) Subject: cmd/vendor/github.com/google/pprof: refresh from upstream X-Git-Tag: go1.9beta2~46 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=3d13b5e00c9bc065d83e27d787a64adc683cea02;p=gostls13.git cmd/vendor/github.com/google/pprof: refresh from upstream Updating to commit fffc5831a499a958516664a34cb7ba2b9e228793 from github.com/google/pprof Fixes #19380 Change-Id: I7a0c64101f42b494c4a469c41628374272eccf95 Reviewed-on: https://go-review.googlesource.com/46155 Run-TryBot: Alberto Donizetti TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/cmd/vendor/github.com/google/pprof/README.md b/src/cmd/vendor/github.com/google/pprof/README.md index a134872079..14a33daf78 100644 --- a/src/cmd/vendor/github.com/google/pprof/README.md +++ b/src/cmd/vendor/github.com/google/pprof/README.md @@ -1,3 +1,6 @@ +[![Build Status](https://travis-ci.org/google/pprof.svg?branch=master)](https://travis-ci.org/google/pprof) +[![codecov](https://codecov.io/gh/google/pprof/graph/badge.svg)](https://codecov.io/gh/google/pprof) + # Introduction pprof is a tool for visualization and analysis of profiling data. @@ -24,7 +27,7 @@ them through the use of the native binutils tools (addr2line and nm). Prerequisites: -- Go development kit. Known to work with Go 1.5. +- Go development kit. Requires Go 1.7 or newer. Follow [these instructions](http://golang.org/doc/code.html) to install the go tool and set up GOPATH. @@ -35,6 +38,10 @@ To build and install it, use the `go get` tool. go get github.com/google/pprof +Remember to set GOPATH to the directory where you want pprof to be +installed. The binary will be in $GOPATH/bin and the sources under +$GOPATH/src/github.com/google/pprof. + # Basic usage pprof can read a profile from a file or directly from a server via http. diff --git a/src/cmd/vendor/github.com/google/pprof/driver/driver.go b/src/cmd/vendor/github.com/google/pprof/driver/driver.go index d01d0fa344..ee7d67d784 100644 --- a/src/cmd/vendor/github.com/google/pprof/driver/driver.go +++ b/src/cmd/vendor/github.com/google/pprof/driver/driver.go @@ -29,10 +29,10 @@ import ( // manager. Then it generates a report formatted according to the // options selected through the flags package. func PProf(o *Options) error { - return internaldriver.PProf(o.InternalOptions()) + return internaldriver.PProf(o.internalOptions()) } -func (o *Options) InternalOptions() *plugin.Options { +func (o *Options) internalOptions() *plugin.Options { var obj plugin.ObjTool if o.Obj != nil { obj = &internalObjTool{o.Obj} @@ -273,9 +273,9 @@ type internalSymbolizer struct { } func (s *internalSymbolizer) Symbolize(mode string, srcs plugin.MappingSources, prof *profile.Profile) error { - isrcs := plugin.MappingSources{} + isrcs := MappingSources{} for m, s := range srcs { isrcs[m] = s } - return s.Symbolize(mode, isrcs, prof) + return s.Symbolizer.Symbolize(mode, isrcs, prof) } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/binutils/disasm_test.go b/src/cmd/vendor/github.com/google/pprof/internal/binutils/disasm_test.go index 7fc25741ce..3563198f48 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/binutils/disasm_test.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/binutils/disasm_test.go @@ -73,7 +73,7 @@ func TestFindSymbols(t *testing.T) { func checkSymbol(got []*plugin.Sym, want []plugin.Sym) error { if len(got) != len(want) { - return fmt.Errorf("unexpected number of symbols %d (want %d)\n", len(got), len(want)) + return fmt.Errorf("unexpected number of symbols %d (want %d)", len(got), len(want)) } for i, g := range got { @@ -134,8 +134,6 @@ func TestFunctionAssembly(t *testing.T) { }, } - const objdump = "testdata/wrapper/objdump" - for _, tc := range testcases { insts, err := disassemble([]byte(tc.asm)) if err != nil { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go index 5e54062771..5799b1f249 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go @@ -227,9 +227,6 @@ var pprofVariables = variables{ "functions": &variable{boolKind, "t", "granularity", helpText( "Aggregate at the function level.", "Takes into account the filename/lineno where the function was defined.")}, - "functionnameonly": &variable{boolKind, "f", "granularity", helpText( - "Aggregate at the function level.", - "Ignores the filename/lineno where the function was defined.")}, "files": &variable{boolKind, "f", "granularity", "Aggregate at the file level."}, "lines": &variable{boolKind, "f", "granularity", "Aggregate at the source code line level."}, "addresses": &variable{boolKind, "f", "granularity", helpText( @@ -471,7 +468,7 @@ func (vars variables) set(name, value string) error { case boolKind: var b bool if b, err = stringToBool(value); err == nil { - if v.group != "" && b == false { + if v.group != "" && !b { err = fmt.Errorf("%q can only be set to true", name) } } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go index 2ca09dfa32..32d60e6b1d 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go @@ -160,20 +160,20 @@ func applyCommandOverrides(cmd []string, v variables) variables { v.set("nodecount", "80") } } - if trim == false { + if !trim { v.set("nodecount", "0") v.set("nodefraction", "0") v.set("edgefraction", "0") } - if focus == false { + if !focus { v.set("focus", "") v.set("ignore", "") } - if tagfocus == false { + if !tagfocus { v.set("tagfocus", "") v.set("tagignore", "") } - if hide == false { + if !hide { v.set("hide", "") v.set("show", "") } @@ -196,18 +196,13 @@ func aggregate(prof *profile.Profile, v variables) error { case v["functions"].boolValue(): inlines = true function = true - filename = true case v["noinlines"].boolValue(): function = true - filename = true case v["addressnoinlines"].boolValue(): function = true filename = true linenumber = true address = true - case v["functionnameonly"].boolValue(): - inlines = true - function = true default: return fmt.Errorf("unexpected granularity") } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_focus.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_focus.go index c60ad8157e..e2591ffa7a 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_focus.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_focus.go @@ -59,7 +59,7 @@ func applyFocus(prof *profile.Profile, v variables, ui plugin.UI) error { if prunefrom != nil { prof.PruneFrom(prunefrom) } - return nil + return err } func compileRegexOption(name, value string, err error) (*regexp.Regexp, error) { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_test.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_test.go index 75eaebec39..0ef89751d1 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_test.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_test.go @@ -16,8 +16,11 @@ package driver import ( "bytes" + "flag" "fmt" "io/ioutil" + "net" + _ "net/http/pprof" "os" "regexp" "runtime" @@ -32,6 +35,8 @@ import ( "github.com/google/pprof/profile" ) +var updateFlag = flag.Bool("update", false, "Update the golden files") + func TestParse(t *testing.T) { // Override weblist command to collect output in buffer pprofCommands["weblist"].postProcess = nil @@ -43,13 +48,12 @@ func TestParse(t *testing.T) { savePath := os.Getenv("PPROF_BINARY_PATH") os.Setenv("PPROF_BINARY_PATH", "/path/to") defer os.Setenv("PPROF_BINARY_PATH", savePath) - testcase := []struct { flags, source string }{ {"text,functions,flat", "cpu"}, {"tree,addresses,flat,nodecount=4", "cpusmall"}, - {"text,functions,flat", "unknown"}, + {"text,functions,flat,nodecount=5,call_tree", "unknown"}, {"text,alloc_objects,flat", "heap_alloc"}, {"text,files,flat", "heap"}, {"text,inuse_objects,flat", "heap"}, @@ -59,8 +63,10 @@ func TestParse(t *testing.T) { {"tree,lines,cum,focus=[24]00", "heap"}, {"tree,relative_percentages,cum,focus=[24]00", "heap"}, {"callgrind", "cpu"}, + {"callgrind,call_tree", "cpu"}, {"callgrind", "heap"}, {"dot,functions,flat", "cpu"}, + {"dot,functions,flat,call_tree", "cpu"}, {"dot,lines,flat,focus=[12]00", "heap"}, {"dot,addresses,flat,ignore=[X3]002,focus=[X1]000", "contention"}, {"dot,files,cum", "contention"}, @@ -99,6 +105,7 @@ func TestParse(t *testing.T) { if err != nil { t.Errorf("cannot create tempfile: %v", err) } + defer os.Remove(protoTempFile.Name()) defer protoTempFile.Close() f.strings["output"] = protoTempFile.Name() @@ -124,6 +131,7 @@ func TestParse(t *testing.T) { if err != nil { t.Errorf("cannot create tempfile: %v", err) } + defer os.Remove(outputTempFile.Name()) defer outputTempFile.Close() f.strings["output"] = outputTempFile.Name() f.args = []string{protoTempFile.Name()} @@ -180,6 +188,12 @@ func TestParse(t *testing.T) { t.Fatalf("diff %s %v", solution, err) } t.Errorf("%s\n%s\n", solution, d) + if *updateFlag { + err := ioutil.WriteFile(solution, b, 0644) + if err != nil { + t.Errorf("failed to update the solution file %q: %v", solution, err) + } + } } } } @@ -214,14 +228,19 @@ func addFlags(f *testFlags, flags []string) { } } +func testSourceURL(port int) string { + return fmt.Sprintf("http://%s/", net.JoinHostPort(testSourceAddress, strconv.Itoa(port))) +} + // solutionFilename returns the name of the solution file for the test func solutionFilename(source string, f *testFlags) string { - name := []string{"pprof", strings.TrimPrefix(source, "http://host:8000/")} + name := []string{"pprof", strings.TrimPrefix(source, testSourceURL(8000))} name = addString(name, f, []string{"flat", "cum"}) name = addString(name, f, []string{"functions", "files", "lines", "addresses"}) name = addString(name, f, []string{"inuse_space", "inuse_objects", "alloc_space", "alloc_objects"}) name = addString(name, f, []string{"relative_percentages"}) name = addString(name, f, []string{"seconds"}) + name = addString(name, f, []string{"call_tree"}) name = addString(name, f, []string{"text", "tree", "callgrind", "dot", "svg", "tags", "dot", "traces", "disasm", "peek", "weblist", "topproto", "comments"}) if f.strings["focus"] != "" || f.strings["tagfocus"] != "" { name = append(name, "focus") @@ -345,9 +364,6 @@ func baseFlags() testFlags { } } -type testProfile struct { -} - const testStart = 0x1000 const testOffset = 0x5000 @@ -355,7 +371,6 @@ type testFetcher struct{} func (testFetcher) Fetch(s string, d, t time.Duration) (*profile.Profile, string, error) { var p *profile.Profile - s = strings.TrimPrefix(s, "http://host:8000/") switch s { case "cpu", "unknown": p = cpuProfile() @@ -373,17 +388,10 @@ func (testFetcher) Fetch(s string, d, t time.Duration) (*profile.Profile, string p = contentionProfile() case "symbolz": p = symzProfile() - case "http://host2/symbolz": - p = symzProfile() - p.Mapping[0].Start += testOffset - p.Mapping[0].Limit += testOffset - for i := range p.Location { - p.Location[i].Address += testOffset - } default: return nil, "", fmt.Errorf("unexpected source: %s", s) } - return p, s, nil + return p, testSourceURL(8000) + s, nil } type testSymbolizer struct{} @@ -406,7 +414,19 @@ func (testSymbolizeDemangler) Symbolize(_ string, _ plugin.MappingSources, p *pr func testFetchSymbols(source, post string) ([]byte, error) { var buf bytes.Buffer - if source == "http://host2/symbolz" { + switch source { + case testSourceURL(8000) + "symbolz": + for _, address := range strings.Split(post, "+") { + a, _ := strconv.ParseInt(address, 0, 64) + fmt.Fprintf(&buf, "%v\t", address) + if a-testStart > testOffset { + fmt.Fprintf(&buf, "wrong_source_%v_", address) + continue + } + fmt.Fprintf(&buf, "%#x\n", a-testStart) + } + return buf.Bytes(), nil + case testSourceURL(8001) + "symbolz": for _, address := range strings.Split(post, "+") { a, _ := strconv.ParseInt(address, 0, 64) fmt.Fprintf(&buf, "%v\t", address) @@ -417,17 +437,9 @@ func testFetchSymbols(source, post string) ([]byte, error) { fmt.Fprintf(&buf, "%#x\n", a-testStart-testOffset) } return buf.Bytes(), nil + default: + return nil, fmt.Errorf("unexpected source: %s", source) } - for _, address := range strings.Split(post, "+") { - a, _ := strconv.ParseInt(address, 0, 64) - fmt.Fprintf(&buf, "%v\t", address) - if a-testStart > testOffset { - fmt.Fprintf(&buf, "wrong_source_%v_", address) - continue - } - fmt.Fprintf(&buf, "%#x\n", a-testStart) - } - return buf.Bytes(), nil } type testSymbolzSymbolizer struct{} @@ -543,32 +555,32 @@ func cpuProfile() *profile.Profile { Location: []*profile.Location{cpuL[0], cpuL[1], cpuL[2]}, Value: []int64{1000, 1000}, Label: map[string][]string{ - "key1": []string{"tag1"}, - "key2": []string{"tag1"}, + "key1": {"tag1"}, + "key2": {"tag1"}, }, }, { Location: []*profile.Location{cpuL[0], cpuL[3]}, Value: []int64{100, 100}, Label: map[string][]string{ - "key1": []string{"tag2"}, - "key3": []string{"tag2"}, + "key1": {"tag2"}, + "key3": {"tag2"}, }, }, { Location: []*profile.Location{cpuL[1], cpuL[4]}, Value: []int64{10, 10}, Label: map[string][]string{ - "key1": []string{"tag3"}, - "key2": []string{"tag2"}, + "key1": {"tag3"}, + "key2": {"tag2"}, }, }, { Location: []*profile.Location{cpuL[2]}, Value: []int64{10, 10}, Label: map[string][]string{ - "key1": []string{"tag4"}, - "key2": []string{"tag1"}, + "key1": {"tag4"}, + "key2": {"tag1"}, }, }, }, @@ -745,28 +757,28 @@ func heapProfile() *profile.Profile { Location: []*profile.Location{heapL[0], heapL[1], heapL[2]}, Value: []int64{10, 1024000}, NumLabel: map[string][]int64{ - "bytes": []int64{102400}, + "bytes": {102400}, }, }, { Location: []*profile.Location{heapL[0], heapL[3]}, Value: []int64{20, 4096000}, NumLabel: map[string][]int64{ - "bytes": []int64{204800}, + "bytes": {204800}, }, }, { Location: []*profile.Location{heapL[1], heapL[4]}, Value: []int64{40, 65536000}, NumLabel: map[string][]int64{ - "bytes": []int64{1638400}, + "bytes": {1638400}, }, }, { Location: []*profile.Location{heapL[2]}, Value: []int64{80, 32768000}, NumLabel: map[string][]int64{ - "bytes": []int64{409600}, + "bytes": {409600}, }, }, }, @@ -977,13 +989,36 @@ func TestTagFilter(t *testing.T) { } } +type testSymbolzMergeFetcher struct{} + +func (testSymbolzMergeFetcher) Fetch(s string, d, t time.Duration) (*profile.Profile, string, error) { + var p *profile.Profile + switch s { + case testSourceURL(8000) + "symbolz": + p = symzProfile() + case testSourceURL(8001) + "symbolz": + p = symzProfile() + p.Mapping[0].Start += testOffset + p.Mapping[0].Limit += testOffset + for i := range p.Location { + p.Location[i].Address += testOffset + } + default: + return nil, "", fmt.Errorf("unexpected source: %s", s) + } + return p, s, nil +} + func TestSymbolzAfterMerge(t *testing.T) { baseVars := pprofVariables pprofVariables = baseVars.makeCopy() defer func() { pprofVariables = baseVars }() f := baseFlags() - f.args = []string{"symbolz", "http://host2/symbolz"} + f.args = []string{ + testSourceURL(8000) + "symbolz", + testSourceURL(8001) + "symbolz", + } o := setDefaults(nil) o.Flagset = f @@ -997,7 +1032,7 @@ func TestSymbolzAfterMerge(t *testing.T) { t.Fatalf("parseFlags returned command %v, want [proto]", cmd) } - o.Fetch = testFetcher{} + o.Fetch = testSymbolzMergeFetcher{} o.Sym = testSymbolzSymbolizer{} p, err := fetchProfiles(src, o) if err != nil { @@ -1028,10 +1063,10 @@ func (m *mockObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, err switch start { case 0x1000: return []plugin.Inst{ - {Addr: 0x1000, Text: "instruction one"}, - {Addr: 0x1001, Text: "instruction two"}, - {Addr: 0x1002, Text: "instruction three"}, - {Addr: 0x1003, Text: "instruction four"}, + {Addr: 0x1000, Text: "instruction one", File: "file1000.src", Line: 1}, + {Addr: 0x1001, Text: "instruction two", File: "file1000.src", Line: 1}, + {Addr: 0x1002, Text: "instruction three", File: "file1000.src", Line: 2}, + {Addr: 0x1003, Text: "instruction four", File: "file1000.src", Line: 1}, }, nil case 0x3000: return []plugin.Inst{ @@ -1046,7 +1081,7 @@ func (m *mockObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, err } type mockFile struct { - name, buildId string + name, buildID string base uint64 } @@ -1062,7 +1097,7 @@ func (m *mockFile) Base() uint64 { // BuildID returns the GNU build ID of the file, or an empty string. func (m *mockFile) BuildID() string { - return m.buildId + return m.buildID } // SourceLine reports the source line information for a given diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go index f9e8231419..7c365734b2 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go @@ -242,6 +242,8 @@ func setTmpDir(ui plugin.UI) (string, error) { return "", fmt.Errorf("failed to identify temp dir") } +const testSourceAddress = "pproftest.local" + // grabProfile fetches a profile. Returns the profile, sources for the // profile mappings, a bool indicating if the profile was fetched // remotely, and an error. @@ -276,6 +278,11 @@ func grabProfile(s *source, source string, scale float64, fetcher plugin.Fetcher if src != "" { msrc = collectMappingSources(p, src) remote = true + if strings.HasPrefix(src, "http://"+testSourceAddress) { + // Treat test inputs as local to avoid saving + // testcase profiles during driver testing. + remote = false + } } return } @@ -366,20 +373,20 @@ mapping: } } } + if len(p.Mapping) == 0 { + // If there are no mappings, add a fake mapping to attempt symbolization. + // This is useful for some profiles generated by the golang runtime, which + // do not include any mappings. Symbolization with a fake mapping will only + // be successful against a non-PIE binary. + m := &profile.Mapping{ID: 1} + p.Mapping = []*profile.Mapping{m} + for _, l := range p.Location { + l.Mapping = m + } + } // Replace executable filename/buildID with the overrides from source. // Assumes the executable is the first Mapping entry. if execName, buildID := s.ExecName, s.BuildID; execName != "" || buildID != "" { - if len(p.Mapping) == 0 { - // If there are no mappings, add a fake mapping to attempt symbolization. - // This is useful for some profiles generated by the golang runtime, which - // do not include any mappings. Symbolization with a fake mapping will only - // be successful against a non-PIE binary. - m := &profile.Mapping{ID: 1} - p.Mapping = []*profile.Mapping{m} - for _, l := range p.Location { - l.Mapping = m - } - } m := p.Mapping[0] if execName != "" { m.File = execName diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go index 90b84b27c5..5ac3b734ad 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go @@ -15,8 +15,15 @@ package driver import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "encoding/pem" "fmt" "io/ioutil" + "math/big" "net/http" "net/url" "os" @@ -24,11 +31,14 @@ import ( "reflect" "regexp" "runtime" + "strings" "testing" "time" + "github.com/google/pprof/internal/binutils" "github.com/google/pprof/internal/plugin" "github.com/google/pprof/internal/proftest" + "github.com/google/pprof/internal/symbolizer" "github.com/google/pprof/profile" ) @@ -165,6 +175,8 @@ func TestFetch(t *testing.T) { const path = "testdata/" // Intercept http.Get calls from HTTPFetcher. + savedHTTPGet := httpGet + defer func() { httpGet = savedHTTPGet }() httpGet = stubHTTPGet type testcase struct { @@ -227,3 +239,108 @@ func stubHTTPGet(source string, _ time.Duration) (*http.Response, error) { c := &http.Client{Transport: t} return c.Get("file:///" + file) } + +func TestHttpsInsecure(t *testing.T) { + + if runtime.GOOS == "nacl" { + t.Skip("test assumes tcp available") + } + + baseVars := pprofVariables + pprofVariables = baseVars.makeCopy() + defer func() { pprofVariables = baseVars }() + + tlsConfig := &tls.Config{Certificates: []tls.Certificate{selfSignedCert(t)}} + + l, err := tls.Listen("tcp", "localhost:0", tlsConfig) + if err != nil { + t.Fatalf("net.Listen: got error %v, want no error", err) + } + + donec := make(chan error, 1) + go func(donec chan<- error) { + donec <- http.Serve(l, nil) + }(donec) + defer func() { + if got, want := <-donec, "use of closed"; !strings.Contains(got.Error(), want) { + t.Fatalf("Serve got error %v, want %q", got, want) + } + }() + defer l.Close() + + go func() { + deadline := time.Now().Add(5 * time.Second) + for time.Now().Before(deadline) { + // Simulate a hotspot function. + } + }() + + outputTempFile, err := ioutil.TempFile("", "profile_output") + if err != nil { + t.Fatalf("Failed to create tempfile: %v", err) + } + defer os.Remove(outputTempFile.Name()) + defer outputTempFile.Close() + + address := "https+insecure://" + l.Addr().String() + "/debug/pprof/profile" + s := &source{ + Sources: []string{address}, + Seconds: 10, + Timeout: 10, + Symbolize: "remote", + } + o := &plugin.Options{ + Obj: &binutils.Binutils{}, + UI: &proftest.TestUI{T: t, IgnoreRx: "Saved profile in"}, + } + o.Sym = &symbolizer.Symbolizer{Obj: o.Obj, UI: o.UI} + p, err := fetchProfiles(s, o) + if err != nil { + t.Fatal(err) + } + if len(p.SampleType) == 0 { + t.Fatalf("grabProfile(%s) got empty profile: len(p.SampleType)==0", address) + } + if err := checkProfileHasFunction(p, "TestHttpsInsecure"); err != nil { + t.Fatalf("grabProfile(%s) %v", address, err) + } +} + +func checkProfileHasFunction(p *profile.Profile, fname string) error { + for _, f := range p.Function { + if strings.Contains(f.Name, fname) { + return nil + } + } + return fmt.Errorf("got %s, want function %q", p.String(), fname) +} + +func selfSignedCert(t *testing.T) tls.Certificate { + privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("failed to generate private key: %v", err) + } + b, err := x509.MarshalECPrivateKey(privKey) + if err != nil { + t.Fatalf("failed to marshal private key: %v", err) + } + bk := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) + + tmpl := x509.Certificate{ + SerialNumber: big.NewInt(1), + NotBefore: time.Now(), + NotAfter: time.Now().Add(10 * time.Minute), + } + + b, err = x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, privKey.Public(), privKey) + if err != nil { + t.Fatalf("failed to create cert: %v", err) + } + bc := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: b}) + + cert, err := tls.X509KeyPair(bc, bk) + if err != nil { + t.Fatalf("failed to create TLS key pair: %v", err) + } + return cert +} diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.call_tree.callgrind b/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.call_tree.callgrind new file mode 100644 index 0000000000..e2286f631a --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.call_tree.callgrind @@ -0,0 +1,99 @@ +positions: instr line +events: cpu(ms) + +ob=(1) /path/to/testbinary +fl=(1) testdata/file1000.src +fn=(1) line1000 +0x1000 1 1000 +* 1 100 + +ob=(1) +fl=(2) testdata/file2000.src +fn=(2) line2001 ++4096 9 10 + +ob=(1) +fl=(3) testdata/file3000.src +fn=(3) line3002 ++4096 2 10 +cfl=(2) +cfn=(4) line2000 [1/2] +calls=0 * 4 +* * 1000 + +ob=(1) +fl=(2) +fn=(5) line2000 +-4096 4 0 +cfl=(2) +cfn=(6) line2001 [2/2] +calls=0 -4096 9 +* * 1000 +* 4 0 +cfl=(2) +cfn=(7) line2001 [1/2] +calls=0 * 9 +* * 10 + +ob=(1) +fl=(2) +fn=(2) +* 9 0 +cfl=(1) +cfn=(8) line1000 [1/2] +calls=0 -4096 1 +* * 1000 + +ob=(1) +fl=(3) +fn=(9) line3000 ++4096 6 0 +cfl=(3) +cfn=(10) line3001 [1/2] +calls=0 +4096 5 +* * 1010 + +ob=(1) +fl=(3) +fn=(11) line3001 +* 5 0 +cfl=(3) +cfn=(12) line3002 [1/2] +calls=0 * 2 +* * 1010 + +ob=(1) +fl=(3) +fn=(9) ++1 9 0 +cfl=(3) +cfn=(13) line3001 [2/2] +calls=0 +1 8 +* * 100 + +ob=(1) +fl=(3) +fn=(11) +* 8 0 +cfl=(1) +cfn=(14) line1000 [2/2] +calls=0 -8193 1 +* * 100 + +ob=(1) +fl=(3) +fn=(9) ++1 9 0 +cfl=(3) +cfn=(15) line3002 [2/2] +calls=0 +1 5 +* * 10 + +ob=(1) +fl=(3) +fn=(3) +* 5 0 +cfl=(2) +cfn=(16) line2000 [2/2] +calls=0 -4098 4 +* * 10 diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.disasm b/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.disasm index 9c8e603195..e1df7b1b64 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.disasm +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.disasm @@ -2,9 +2,9 @@ Total: 1.12s ROUTINE ======================== line1000 1.10s 1.10s (flat, cum) 98.21% of Total 1.10s 1.10s 1000: instruction one ;line1000 file1000.src:1 - . . 1001: instruction two - . . 1002: instruction three - . . 1003: instruction four + . . 1001: instruction two ;file1000.src:1 + . . 1002: instruction three ;file1000.src:2 + . . 1003: instruction four ;file1000.src:1 ROUTINE ======================== line3000 10ms 1.12s (flat, cum) 100% of Total 10ms 1.01s 3000: instruction one ;line3000 file3000.src:6 diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.weblist b/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.weblist index ccf4ee8449..d624f19015 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.weblist +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/testdata/pprof.cpu.flat.addresses.weblist @@ -2,6 +2,7 @@ + Pprof listing