Нема описа

fetch_test.go 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package driver
  15. import (
  16. "fmt"
  17. "io/ioutil"
  18. "net/http"
  19. "net/url"
  20. "os"
  21. "path/filepath"
  22. "regexp"
  23. "testing"
  24. "time"
  25. "github.com/google/pprof/internal/plugin"
  26. "github.com/google/pprof/internal/proftest"
  27. "github.com/google/pprof/profile"
  28. )
  29. func TestSymbolizationPath(t *testing.T) {
  30. // Save environment variables to restore after test
  31. saveHome := os.Getenv("HOME")
  32. savePath := os.Getenv("PPROF_BINARY_PATH")
  33. tempdir, err := ioutil.TempDir("", "home")
  34. if err != nil {
  35. t.Fatal("creating temp dir: ", err)
  36. }
  37. defer os.RemoveAll(tempdir)
  38. os.MkdirAll(filepath.Join(tempdir, "pprof", "binaries", "abcde10001"), 0700)
  39. os.Create(filepath.Join(tempdir, "pprof", "binaries", "abcde10001", "binary"))
  40. obj := testObj{tempdir}
  41. os.Setenv("HOME", tempdir)
  42. for _, tc := range []struct {
  43. env, file, buildID, want string
  44. msgCount int
  45. }{
  46. {"", "/usr/bin/binary", "", "/usr/bin/binary", 0},
  47. {"", "/usr/bin/binary", "fedcb10000", "/usr/bin/binary", 0},
  48. {"", "/prod/path/binary", "abcde10001", filepath.Join(tempdir, "pprof/binaries/abcde10001/binary"), 0},
  49. {"/alternate/architecture", "/usr/bin/binary", "", "/alternate/architecture/binary", 0},
  50. {"/alternate/architecture", "/usr/bin/binary", "abcde10001", "/alternate/architecture/binary", 0},
  51. {"/nowhere:/alternate/architecture", "/usr/bin/binary", "fedcb10000", "/usr/bin/binary", 1},
  52. {"/nowhere:/alternate/architecture", "/usr/bin/binary", "abcde10002", "/usr/bin/binary", 1},
  53. } {
  54. os.Setenv("PPROF_BINARY_PATH", tc.env)
  55. p := &profile.Profile{
  56. Mapping: []*profile.Mapping{
  57. {
  58. File: tc.file,
  59. BuildID: tc.buildID,
  60. },
  61. },
  62. }
  63. s := &source{}
  64. locateBinaries(p, s, obj, &proftest.TestUI{t, tc.msgCount})
  65. if file := p.Mapping[0].File; file != tc.want {
  66. t.Errorf("%s:%s:%s, want %s, got %s", tc.env, tc.file, tc.buildID, tc.want, file)
  67. }
  68. }
  69. os.Setenv("HOME", saveHome)
  70. os.Setenv("PPROF_BINARY_PATH", savePath)
  71. }
  72. type testObj struct {
  73. home string
  74. }
  75. func (o testObj) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) {
  76. switch file {
  77. case "/alternate/architecture/binary":
  78. return testFile{file, "abcde10001"}, nil
  79. case "/usr/bin/binary":
  80. return testFile{file, "fedcb10000"}, nil
  81. case filepath.Join(o.home, "pprof/binaries/abcde10001/binary"):
  82. return testFile{file, "abcde10001"}, nil
  83. }
  84. return nil, fmt.Errorf("not found: %s", file)
  85. }
  86. func (testObj) Demangler(_ string) func(names []string) (map[string]string, error) {
  87. return func(names []string) (map[string]string, error) { return nil, nil }
  88. }
  89. func (testObj) Disasm(file string, start, end uint64) ([]plugin.Inst, error) { return nil, nil }
  90. type testFile struct{ name, buildID string }
  91. func (f testFile) Name() string { return f.name }
  92. func (testFile) Base() uint64 { return 0 }
  93. func (f testFile) BuildID() string { return f.buildID }
  94. func (testFile) SourceLine(addr uint64) ([]plugin.Frame, error) { return nil, nil }
  95. func (testFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) { return nil, nil }
  96. func (testFile) Close() error { return nil }
  97. func TestFetch(t *testing.T) {
  98. const path = "testdata/"
  99. // Intercept http.Get calls from HTTPFetcher.
  100. httpGet = stubHTTPGet
  101. for _, source := range [][2]string{
  102. {path + "go.crc32.cpu", "go.crc32.cpu"},
  103. {"http://localhost/profile?file=cppbench.cpu", "cppbench.cpu"},
  104. } {
  105. p, _, err := fetch(source[0], 0, 10*time.Second, &proftest.TestUI{t, 0})
  106. if err != nil {
  107. t.Fatalf("%s: %s", source[0], err)
  108. }
  109. if len(p.Sample) == 0 {
  110. t.Errorf("want non-zero samples")
  111. }
  112. }
  113. }
  114. // stubHTTPGet intercepts a call to http.Get and rewrites it to use
  115. // "file://" to get the profile directly from a file.
  116. func stubHTTPGet(source string, _ time.Duration) (*http.Response, error) {
  117. url, err := url.Parse(source)
  118. if err != nil {
  119. return nil, err
  120. }
  121. values := url.Query()
  122. file := values.Get("file")
  123. if file == "" {
  124. return nil, fmt.Errorf("want .../file?profile, got %s", source)
  125. }
  126. t := &http.Transport{}
  127. t.RegisterProtocol("file", http.NewFileTransport(http.Dir("testdata/")))
  128. c := &http.Client{Transport: t}
  129. return c.Get("file:///" + file)
  130. }