Nenhuma descrição

source_test.go 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package report
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "regexp"
  8. "runtime"
  9. "strings"
  10. "testing"
  11. "github.com/google/pprof/internal/binutils"
  12. "github.com/google/pprof/profile"
  13. )
  14. func TestWebList(t *testing.T) {
  15. if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
  16. t.Skip("weblist only tested on x86-64 linux")
  17. }
  18. cpu := readProfile(filepath.Join("testdata", "sample.cpu"), t)
  19. rpt := New(cpu, &Options{
  20. OutputFormat: WebList,
  21. Symbol: regexp.MustCompile("busyLoop"),
  22. SampleValue: func(v []int64) int64 { return v[1] },
  23. SampleUnit: cpu.SampleType[1].Unit,
  24. })
  25. var buf bytes.Buffer
  26. if err := Generate(&buf, rpt, &binutils.Binutils{}); err != nil {
  27. t.Fatalf("could not generate weblist: %v", err)
  28. }
  29. output := buf.String()
  30. for _, expect := range []string{"func busyLoop", "callq", "math.Abs"} {
  31. if !strings.Contains(output, expect) {
  32. t.Errorf("weblist output does not contain '%s':\n%s", expect, output)
  33. }
  34. }
  35. }
  36. func TestOpenSourceFile(t *testing.T) {
  37. tempdir, err := ioutil.TempDir("", "")
  38. if err != nil {
  39. t.Fatalf("failed to create temp dir: %v", err)
  40. }
  41. const lsep = string(filepath.ListSeparator)
  42. for _, tc := range []struct {
  43. desc string
  44. searchPath string
  45. fs []string
  46. path string
  47. wantPath string // If empty, error is wanted.
  48. }{
  49. {
  50. desc: "exact absolute path is found",
  51. fs: []string{"foo/bar.txt"},
  52. path: "$dir/foo/bar.txt",
  53. wantPath: "$dir/foo/bar.txt",
  54. },
  55. {
  56. desc: "exact relative path is found",
  57. searchPath: "$dir",
  58. fs: []string{"foo/bar.txt"},
  59. path: "foo/bar.txt",
  60. wantPath: "$dir/foo/bar.txt",
  61. },
  62. {
  63. desc: "multiple search path",
  64. searchPath: "some/path" + lsep + "$dir",
  65. fs: []string{"foo/bar.txt"},
  66. path: "foo/bar.txt",
  67. wantPath: "$dir/foo/bar.txt",
  68. },
  69. {
  70. desc: "relative path is found in parent dir",
  71. searchPath: "$dir/foo/bar",
  72. fs: []string{"bar.txt", "foo/bar/baz.txt"},
  73. path: "bar.txt",
  74. wantPath: "$dir/bar.txt",
  75. },
  76. {
  77. desc: "error when not found",
  78. path: "foo.txt",
  79. },
  80. } {
  81. t.Run(tc.desc, func(t *testing.T) {
  82. defer func() {
  83. if err := os.RemoveAll(tempdir); err != nil {
  84. t.Fatalf("failed to remove dir %q: %v", tempdir, err)
  85. }
  86. }()
  87. for _, f := range tc.fs {
  88. path := filepath.Join(tempdir, filepath.FromSlash(f))
  89. dir := filepath.Dir(path)
  90. if err := os.MkdirAll(dir, 0755); err != nil {
  91. t.Fatalf("failed to create dir %q: %v", dir, err)
  92. }
  93. if err := ioutil.WriteFile(path, nil, 0644); err != nil {
  94. t.Fatalf("failed to create file %q: %v", path, err)
  95. }
  96. }
  97. tc.searchPath = filepath.FromSlash(strings.Replace(tc.searchPath, "$dir", tempdir, -1))
  98. tc.path = filepath.FromSlash(strings.Replace(tc.path, "$dir", tempdir, 1))
  99. tc.wantPath = filepath.FromSlash(strings.Replace(tc.wantPath, "$dir", tempdir, 1))
  100. if file, err := openSourceFile(tc.path, tc.searchPath); err != nil && tc.wantPath != "" {
  101. t.Errorf("openSourceFile(%q, %q) = err %v, want path %q", tc.path, tc.searchPath, err, tc.wantPath)
  102. } else if err == nil {
  103. defer file.Close()
  104. gotPath := file.Name()
  105. if tc.wantPath == "" {
  106. t.Errorf("openSourceFile(%q, %q) = %q, want error", tc.path, tc.searchPath, gotPath)
  107. } else if gotPath != tc.wantPath {
  108. t.Errorf("openSourceFile(%q, %q) = %q, want path %q", tc.path, tc.searchPath, gotPath, tc.wantPath)
  109. }
  110. }
  111. })
  112. }
  113. }
  114. func TestIndentation(t *testing.T) {
  115. for _, c := range []struct {
  116. str string
  117. wantIndent int
  118. }{
  119. {"", 0},
  120. {"foobar", 0},
  121. {" foo", 2},
  122. {"\tfoo", 8},
  123. {"\t foo", 9},
  124. {" \tfoo", 8},
  125. {" \tfoo", 8},
  126. {" \tfoo", 16},
  127. } {
  128. if n := indentation(c.str); n != c.wantIndent {
  129. t.Errorf("indentation(%v): got %d, want %d", c.str, n, c.wantIndent)
  130. }
  131. }
  132. }
  133. func readProfile(fname string, t *testing.T) *profile.Profile {
  134. file, err := os.Open(fname)
  135. if err != nil {
  136. t.Fatalf("%s: could not open profile: %v", fname, err)
  137. }
  138. defer file.Close()
  139. p, err := profile.Parse(file)
  140. if err != nil {
  141. t.Fatalf("%s: could not parse profile: %v", fname, err)
  142. }
  143. // Fix file names so they do not include absolute path names.
  144. fix := func(s string) string {
  145. const testdir = "/internal/report/"
  146. pos := strings.Index(s, testdir)
  147. if pos == -1 {
  148. return s
  149. }
  150. return s[pos+len(testdir):]
  151. }
  152. for _, m := range p.Mapping {
  153. m.File = fix(m.File)
  154. }
  155. for _, f := range p.Function {
  156. f.Filename = fix(f.Filename)
  157. }
  158. return p
  159. }