Browse Source

Ensure symbolz is called after local symbolization

Even after local symbolization completes successfully we should
call remote symbolization in case there are some mapping that couldn't
be symbolized otherwise.

Add some tests to ensure both local and symbolz symbolization are called.
Raul Silvera 8 years ago
parent
commit
3f456ae43b
2 changed files with 72 additions and 8 deletions
  1. 9
    5
      internal/symbolizer/symbolizer.go
  2. 63
    3
      internal/symbolizer/symbolizer_test.go

+ 9
- 5
internal/symbolizer/symbolizer.go View File

@@ -38,6 +38,10 @@ type Symbolizer struct {
38 38
 	UI  plugin.UI
39 39
 }
40 40
 
41
+// test taps for dependency injection
42
+var symbolzSymbolize = symbolz.Symbolize
43
+var localSymbolize = doLocalSymbolize
44
+
41 45
 // Symbolize attempts to symbolize profile p. First uses binutils on
42 46
 // local binaries; if the source is a URL it attempts to get any
43 47
 // missed entries using symbolz.
@@ -70,12 +74,12 @@ func (s *Symbolizer) Symbolize(mode string, sources plugin.MappingSources, p *pr
70 74
 	var err error
71 75
 	if local {
72 76
 		// Symbolize locally using binutils.
73
-		if err = localSymbolize(mode, p, s.Obj, s.UI); err == nil {
74
-			remote = false // Already symbolized, no need to apply remote symbolization.
77
+		if err = localSymbolize(mode, p, s.Obj, s.UI); err != nil {
78
+			s.UI.PrintErr("local symbolization: " + err.Error())
75 79
 		}
76 80
 	}
77 81
 	if remote {
78
-		if err = symbolz.Symbolize(sources, postURL, p, s.UI); err != nil {
82
+		if err = symbolzSymbolize(sources, postURL, p, s.UI); err != nil {
79 83
 			return err // Ran out of options.
80 84
 		}
81 85
 	}
@@ -97,10 +101,10 @@ func postURL(source, post string) ([]byte, error) {
97 101
 	return ioutil.ReadAll(resp.Body)
98 102
 }
99 103
 
100
-// localSymbolize adds symbol and line number information to all locations
104
+// doLocalSymbolize adds symbol and line number information to all locations
101 105
 // in a profile. mode enables some options to control
102 106
 // symbolization.
103
-func localSymbolize(mode string, prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI) error {
107
+func doLocalSymbolize(mode string, prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI) error {
104 108
 	force := false
105 109
 	// Disable some mechanisms based on mode string.
106 110
 	for _, o := range strings.Split(strings.ToLower(mode), ":") {

+ 63
- 3
internal/symbolizer/symbolizer_test.go View File

@@ -17,6 +17,7 @@ package symbolizer
17 17
 import (
18 18
 	"fmt"
19 19
 	"regexp"
20
+	"strings"
20 21
 	"testing"
21 22
 
22 23
 	"github.com/google/pprof/internal/plugin"
@@ -95,7 +96,66 @@ var testProfile = profile.Profile{
95 96
 }
96 97
 
97 98
 func TestSymbolization(t *testing.T) {
98
-	prof := testProfile
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()
99 159
 
100 160
 	if prof.HasFunctions() {
101 161
 		t.Error("unexpected function names")
@@ -105,8 +165,8 @@ func TestSymbolization(t *testing.T) {
105 165
 	}
106 166
 
107 167
 	b := mockObjTool{}
108
-	if err := localSymbolize("", &prof, b, &proftest.TestUI{T: t}); err != nil {
109
-		t.Fatalf("Symbolize(): %v", err)
168
+	if err := localSymbolize("", prof, b, &proftest.TestUI{T: t}); err != nil {
169
+		t.Fatalf("localSymbolize(): %v", err)
110 170
 	}
111 171
 
112 172
 	for _, loc := range prof.Location {