Ingen beskrivning

symbolizer_test.go 4.5KB

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