Nessuna descrizione

symbolizer_test.go 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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 symbolizer
  15. import (
  16. "fmt"
  17. "regexp"
  18. "testing"
  19. "github.com/google/pprof/internal/plugin"
  20. "github.com/google/pprof/internal/proftest"
  21. "github.com/google/pprof/profile"
  22. )
  23. var testM = []*profile.Mapping{
  24. {
  25. ID: 1,
  26. Start: 0x1000,
  27. Limit: 0x5000,
  28. File: "mapping",
  29. },
  30. }
  31. var testL = []*profile.Location{
  32. {
  33. ID: 1,
  34. Mapping: testM[0],
  35. Address: 1000,
  36. },
  37. {
  38. ID: 2,
  39. Mapping: testM[0],
  40. Address: 2000,
  41. },
  42. {
  43. ID: 3,
  44. Mapping: testM[0],
  45. Address: 3000,
  46. },
  47. {
  48. ID: 4,
  49. Mapping: testM[0],
  50. Address: 4000,
  51. },
  52. {
  53. ID: 5,
  54. Mapping: testM[0],
  55. Address: 5000,
  56. },
  57. }
  58. var testProfile = profile.Profile{
  59. DurationNanos: 10e9,
  60. SampleType: []*profile.ValueType{
  61. {Type: "cpu", Unit: "cycles"},
  62. },
  63. Sample: []*profile.Sample{
  64. {
  65. Location: []*profile.Location{testL[0]},
  66. Value: []int64{1},
  67. },
  68. {
  69. Location: []*profile.Location{testL[1], testL[0]},
  70. Value: []int64{10},
  71. },
  72. {
  73. Location: []*profile.Location{testL[2], testL[0]},
  74. Value: []int64{100},
  75. },
  76. {
  77. Location: []*profile.Location{testL[3], testL[0]},
  78. Value: []int64{1},
  79. },
  80. {
  81. Location: []*profile.Location{testL[4], testL[3], testL[0]},
  82. Value: []int64{10000},
  83. },
  84. },
  85. Location: testL,
  86. Mapping: testM,
  87. PeriodType: &profile.ValueType{Type: "cpu", Unit: "milliseconds"},
  88. Period: 10,
  89. }
  90. func TestSymbolization(t *testing.T) {
  91. prof := testProfile
  92. if prof.HasFunctions() {
  93. t.Error("unexpected function names")
  94. }
  95. if prof.HasFileLines() {
  96. t.Error("unexpected filenames or line numbers")
  97. }
  98. b := mockObjTool{}
  99. if err := localSymbolize("", &prof, b, &proftest.TestUI{T: t}); err != nil {
  100. t.Fatalf("Symbolize(): %v", err)
  101. }
  102. for _, loc := range prof.Location {
  103. if err := checkSymbolizedLocation(loc.Address, loc.Line); err != nil {
  104. t.Errorf("location %d: %v", loc.Address, err)
  105. }
  106. }
  107. if !prof.HasFunctions() {
  108. t.Error("missing function names")
  109. }
  110. if !prof.HasFileLines() {
  111. t.Error("missing filenames or line numbers")
  112. }
  113. }
  114. func checkSymbolizedLocation(a uint64, got []profile.Line) error {
  115. want, ok := mockAddresses[a]
  116. if !ok {
  117. return fmt.Errorf("unexpected address")
  118. }
  119. if len(want) != len(got) {
  120. return fmt.Errorf("want len %d, got %d", len(want), len(got))
  121. }
  122. for i, w := range want {
  123. g := got[i]
  124. if g.Function.Name != w.Func {
  125. return fmt.Errorf("want function: %q, got %q", w.Func, g.Function.Name)
  126. }
  127. if g.Function.Filename != w.File {
  128. return fmt.Errorf("want filename: %q, got %q", w.File, g.Function.Filename)
  129. }
  130. if g.Line != int64(w.Line) {
  131. return fmt.Errorf("want lineno: %d, got %d", w.Line, g.Line)
  132. }
  133. }
  134. return nil
  135. }
  136. var mockAddresses = map[uint64][]plugin.Frame{
  137. 1000: []plugin.Frame{{"fun11", "file11.src", 10}},
  138. 2000: []plugin.Frame{{"fun21", "file21.src", 20}, {"fun22", "file22.src", 20}},
  139. 3000: []plugin.Frame{{"fun31", "file31.src", 30}, {"fun32", "file32.src", 30}, {"fun33", "file33.src", 30}},
  140. 4000: []plugin.Frame{{"fun41", "file41.src", 40}, {"fun42", "file42.src", 40}, {"fun43", "file43.src", 40}, {"fun44", "file44.src", 40}},
  141. 5000: []plugin.Frame{{"fun51", "file51.src", 50}, {"fun52", "file52.src", 50}, {"fun53", "file53.src", 50}, {"fun54", "file54.src", 50}, {"fun55", "file55.src", 50}},
  142. }
  143. type mockObjTool struct{}
  144. func (mockObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) {
  145. return mockObjFile{frames: mockAddresses}, nil
  146. }
  147. func (mockObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
  148. return nil, fmt.Errorf("disassembly not supported")
  149. }
  150. type mockObjFile struct {
  151. frames map[uint64][]plugin.Frame
  152. }
  153. func (mockObjFile) Name() string {
  154. return ""
  155. }
  156. func (mockObjFile) Base() uint64 {
  157. return 0
  158. }
  159. func (mockObjFile) BuildID() string {
  160. return ""
  161. }
  162. func (mf mockObjFile) SourceLine(addr uint64) ([]plugin.Frame, error) {
  163. return mf.frames[addr], nil
  164. }
  165. func (mockObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) {
  166. return []*plugin.Sym{}, nil
  167. }
  168. func (mockObjFile) Close() error {
  169. return nil
  170. }