golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer_test.go (about) 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 15 package symbolizer 16 17 import ( 18 "fmt" 19 "regexp" 20 "strings" 21 "testing" 22 23 "github.com/google/pprof/internal/plugin" 24 "github.com/google/pprof/internal/proftest" 25 "github.com/google/pprof/profile" 26 ) 27 28 var testM = []*profile.Mapping{ 29 { 30 ID: 1, 31 Start: 0x1000, 32 Limit: 0x5000, 33 File: "mapping", 34 }, 35 } 36 37 var testL = []*profile.Location{ 38 { 39 ID: 1, 40 Mapping: testM[0], 41 Address: 1000, 42 }, 43 { 44 ID: 2, 45 Mapping: testM[0], 46 Address: 2000, 47 }, 48 { 49 ID: 3, 50 Mapping: testM[0], 51 Address: 3000, 52 }, 53 { 54 ID: 4, 55 Mapping: testM[0], 56 Address: 4000, 57 }, 58 { 59 ID: 5, 60 Mapping: testM[0], 61 Address: 5000, 62 }, 63 } 64 65 var testProfile = profile.Profile{ 66 DurationNanos: 10e9, 67 SampleType: []*profile.ValueType{ 68 {Type: "cpu", Unit: "cycles"}, 69 }, 70 Sample: []*profile.Sample{ 71 { 72 Location: []*profile.Location{testL[0]}, 73 Value: []int64{1}, 74 }, 75 { 76 Location: []*profile.Location{testL[1], testL[0]}, 77 Value: []int64{10}, 78 }, 79 { 80 Location: []*profile.Location{testL[2], testL[0]}, 81 Value: []int64{100}, 82 }, 83 { 84 Location: []*profile.Location{testL[3], testL[0]}, 85 Value: []int64{1}, 86 }, 87 { 88 Location: []*profile.Location{testL[4], testL[3], testL[0]}, 89 Value: []int64{10000}, 90 }, 91 }, 92 Location: testL, 93 Mapping: testM, 94 PeriodType: &profile.ValueType{Type: "cpu", Unit: "milliseconds"}, 95 Period: 10, 96 } 97 98 func TestSymbolization(t *testing.T) { 99 sSym := symbolzSymbolize 100 lSym := localSymbolize 101 defer func() { 102 symbolzSymbolize = sSym 103 localSymbolize = lSym 104 }() 105 symbolzSymbolize = symbolzMock 106 localSymbolize = localMock 107 108 type testcase struct { 109 mode string 110 wantComment string 111 } 112 113 s := Symbolizer{ 114 mockObjTool{}, 115 &proftest.TestUI{T: t}, 116 } 117 for i, tc := range []testcase{ 118 { 119 "local", 120 "local=local", 121 }, 122 { 123 "fastlocal", 124 "local=fastlocal", 125 }, 126 { 127 "remote", 128 "symbolz", 129 }, 130 { 131 "", 132 "local=:symbolz", 133 }, 134 } { 135 prof := testProfile.Copy() 136 if err := s.Symbolize(tc.mode, nil, prof); err != nil { 137 t.Errorf("symbolize #%d: %v", i, err) 138 continue 139 } 140 if got, want := strings.Join(prof.Comments, ":"), tc.wantComment; got != want { 141 t.Errorf("got %s, want %s", got, want) 142 continue 143 } 144 } 145 } 146 147 func symbolzMock(sources plugin.MappingSources, syms func(string, string) ([]byte, error), p *profile.Profile, ui plugin.UI) error { 148 p.Comments = append(p.Comments, "symbolz") 149 return nil 150 } 151 152 func localMock(mode string, p *profile.Profile, obj plugin.ObjTool, ui plugin.UI) error { 153 p.Comments = append(p.Comments, "local="+mode) 154 return nil 155 } 156 157 func TestLocalSymbolization(t *testing.T) { 158 prof := testProfile.Copy() 159 160 if prof.HasFunctions() { 161 t.Error("unexpected function names") 162 } 163 if prof.HasFileLines() { 164 t.Error("unexpected filenames or line numbers") 165 } 166 167 b := mockObjTool{} 168 if err := localSymbolize("", prof, b, &proftest.TestUI{T: t}); err != nil { 169 t.Fatalf("localSymbolize(): %v", err) 170 } 171 172 for _, loc := range prof.Location { 173 if err := checkSymbolizedLocation(loc.Address, loc.Line); err != nil { 174 t.Errorf("location %d: %v", loc.Address, err) 175 } 176 } 177 if !prof.HasFunctions() { 178 t.Error("missing function names") 179 } 180 if !prof.HasFileLines() { 181 t.Error("missing filenames or line numbers") 182 } 183 } 184 185 func checkSymbolizedLocation(a uint64, got []profile.Line) error { 186 want, ok := mockAddresses[a] 187 if !ok { 188 return fmt.Errorf("unexpected address") 189 } 190 if len(want) != len(got) { 191 return fmt.Errorf("want len %d, got %d", len(want), len(got)) 192 } 193 194 for i, w := range want { 195 g := got[i] 196 if g.Function.Name != w.Func { 197 return fmt.Errorf("want function: %q, got %q", w.Func, g.Function.Name) 198 } 199 if g.Function.Filename != w.File { 200 return fmt.Errorf("want filename: %q, got %q", w.File, g.Function.Filename) 201 } 202 if g.Line != int64(w.Line) { 203 return fmt.Errorf("want lineno: %d, got %d", w.Line, g.Line) 204 } 205 } 206 return nil 207 } 208 209 var mockAddresses = map[uint64][]plugin.Frame{ 210 1000: []plugin.Frame{frame("fun11", "file11.src", 10)}, 211 2000: []plugin.Frame{frame("fun21", "file21.src", 20), frame("fun22", "file22.src", 20)}, 212 3000: []plugin.Frame{frame("fun31", "file31.src", 30), frame("fun32", "file32.src", 30), frame("fun33", "file33.src", 30)}, 213 4000: []plugin.Frame{frame("fun41", "file41.src", 40), frame("fun42", "file42.src", 40), frame("fun43", "file43.src", 40), frame("fun44", "file44.src", 40)}, 214 5000: []plugin.Frame{frame("fun51", "file51.src", 50), frame("fun52", "file52.src", 50), frame("fun53", "file53.src", 50), frame("fun54", "file54.src", 50), frame("fun55", "file55.src", 50)}, 215 } 216 217 func frame(fname, file string, line int) plugin.Frame { 218 return plugin.Frame{ 219 Func: fname, 220 File: file, 221 Line: line} 222 } 223 224 type mockObjTool struct{} 225 226 func (mockObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) { 227 return mockObjFile{frames: mockAddresses}, nil 228 } 229 230 func (mockObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) { 231 return nil, fmt.Errorf("disassembly not supported") 232 } 233 234 type mockObjFile struct { 235 frames map[uint64][]plugin.Frame 236 } 237 238 func (mockObjFile) Name() string { 239 return "" 240 } 241 242 func (mockObjFile) Base() uint64 { 243 return 0 244 } 245 246 func (mockObjFile) BuildID() string { 247 return "" 248 } 249 250 func (mf mockObjFile) SourceLine(addr uint64) ([]plugin.Frame, error) { 251 return mf.frames[addr], nil 252 } 253 254 func (mockObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) { 255 return []*plugin.Sym{}, nil 256 } 257 258 func (mockObjFile) Close() error { 259 return nil 260 }