golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils_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 binutils 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/google/pprof/internal/plugin" 22 ) 23 24 var testAddrMap = map[int]string{ 25 1000: "_Z3fooid.clone2", 26 2000: "_ZNSaIiEC1Ev.clone18", 27 3000: "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", 28 } 29 30 func functionName(level int) (name string) { 31 if name = testAddrMap[level]; name != "" { 32 return name 33 } 34 return fmt.Sprintf("fun%d", level) 35 } 36 37 func TestAddr2Liner(t *testing.T) { 38 const offset = 0x500 39 40 a := addr2Liner{&mockAddr2liner{}, offset, nil} 41 for i := 1; i < 8; i++ { 42 addr := i*0x1000 + offset 43 s, err := a.addrInfo(uint64(addr)) 44 if err != nil { 45 t.Fatalf("addrInfo(%#x): %v", addr, err) 46 } 47 if len(s) != i { 48 t.Fatalf("addrInfo(%#x): got len==%d, want %d", addr, len(s), i) 49 } 50 for l, f := range s { 51 level := (len(s) - l) * 1000 52 want := plugin.Frame{Func: functionName(level), File: fmt.Sprintf("file%d", level), Line: level} 53 54 if f != want { 55 t.Errorf("AddrInfo(%#x)[%d]: = %+v, want %+v", addr, l, f, want) 56 } 57 } 58 } 59 s, err := a.addrInfo(0xFFFF) 60 if err != nil { 61 t.Fatalf("addrInfo(0xFFFF): %v", err) 62 } 63 if len(s) != 0 { 64 t.Fatalf("AddrInfo(0xFFFF): got len==%d, want 0", len(s)) 65 } 66 a.rw.close() 67 } 68 69 type mockAddr2liner struct { 70 output []string 71 } 72 73 func (a *mockAddr2liner) write(s string) error { 74 var lines []string 75 switch s { 76 case "1000": 77 lines = []string{"_Z3fooid.clone2", "file1000:1000"} 78 case "2000": 79 lines = []string{"_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 80 case "3000": 81 lines = []string{"_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 82 case "4000": 83 lines = []string{"fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 84 case "5000": 85 lines = []string{"fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 86 case "6000": 87 lines = []string{"fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 88 case "7000": 89 lines = []string{"fun7000", "file7000:7000", "fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 90 case "8000": 91 lines = []string{"fun8000", "file8000:8000", "fun7000", "file7000:7000", "fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 92 case "9000": 93 lines = []string{"fun9000", "file9000:9000", "fun8000", "file8000:8000", "fun7000", "file7000:7000", "fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"} 94 default: 95 lines = []string{"??", "??:0"} 96 } 97 a.output = append(a.output, "0x"+s) 98 a.output = append(a.output, lines...) 99 return nil 100 } 101 102 func (a *mockAddr2liner) readLine() (string, error) { 103 if len(a.output) == 0 { 104 return "", fmt.Errorf("end of file") 105 } 106 next := a.output[0] 107 a.output = a.output[1:] 108 return next, nil 109 } 110 111 func (a *mockAddr2liner) close() { 112 } 113 114 func TestAddr2LinerLookup(t *testing.T) { 115 oddSizedMap := addr2LinerNM{ 116 m: []symbolInfo{ 117 {0x1000, "0x1000"}, 118 {0x2000, "0x2000"}, 119 {0x3000, "0x3000"}, 120 }, 121 } 122 evenSizedMap := addr2LinerNM{ 123 m: []symbolInfo{ 124 {0x1000, "0x1000"}, 125 {0x2000, "0x2000"}, 126 {0x3000, "0x3000"}, 127 {0x4000, "0x4000"}, 128 }, 129 } 130 for _, a := range []*addr2LinerNM{ 131 &oddSizedMap, &evenSizedMap, 132 } { 133 for address, want := range map[uint64]string{ 134 0x1000: "0x1000", 135 0x1001: "0x1000", 136 0x1FFF: "0x1000", 137 0x2000: "0x2000", 138 0x2001: "0x2000", 139 } { 140 if got, _ := a.addrInfo(address); !checkAddress(got, address, want) { 141 t.Errorf("%x: got %v, want %s", address, got, want) 142 } 143 } 144 } 145 } 146 147 func checkAddress(got []plugin.Frame, address uint64, want string) bool { 148 if len(got) != 1 { 149 return false 150 } 151 return got[0].Func == want 152 }