Skip to content

Commit 88206b8

Browse files
committed
test: improve runtime/pprof tests for gccgo
In the CPU profile tests for gccgo, check to make sure that the runtime's sigprof handler itself doesn't appear in the profile. Add a "skip if gccgo" guard to one testpoint. Updates #26595 Change-Id: I92a44161d61f17b9305ce09532134edd229745a7 Reviewed-on: https://go-review.googlesource.com/126316 Run-TryBot: Than McIntosh <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent dbd8af7 commit 88206b8

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

src/runtime/pprof/pprof_test.go

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,24 @@ func cpuHog2(x int) int {
7272
return foo
7373
}
7474

75+
// Return a list of functions that we don't want to ever appear in CPU
76+
// profiles. For gccgo, that list includes the sigprof handler itself.
77+
func avoidFunctions() []string {
78+
if runtime.Compiler == "gccgo" {
79+
return []string{"runtime.sigprof"}
80+
}
81+
return nil
82+
}
83+
7584
func TestCPUProfile(t *testing.T) {
76-
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1"}, func(dur time.Duration) {
85+
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1"}, avoidFunctions(), func(dur time.Duration) {
7786
cpuHogger(cpuHog1, &salt1, dur)
7887
})
7988
}
8089

8190
func TestCPUProfileMultithreaded(t *testing.T) {
8291
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
83-
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog2"}, func(dur time.Duration) {
92+
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog2"}, avoidFunctions(), func(dur time.Duration) {
8493
c := make(chan int)
8594
go func() {
8695
cpuHogger(cpuHog1, &salt1, dur)
@@ -92,7 +101,7 @@ func TestCPUProfileMultithreaded(t *testing.T) {
92101
}
93102

94103
func TestCPUProfileInlining(t *testing.T) {
95-
testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, func(dur time.Duration) {
104+
testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, avoidFunctions(), func(dur time.Duration) {
96105
cpuHogger(inlinedCaller, &salt1, dur)
97106
})
98107
}
@@ -132,7 +141,7 @@ func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []*profile.Loca
132141

133142
// testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need,
134143
// as interpreted by matches.
135-
func testCPUProfile(t *testing.T, matches matchFunc, need []string, f func(dur time.Duration)) {
144+
func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) {
136145
switch runtime.GOOS {
137146
case "darwin":
138147
switch runtime.GOARCH {
@@ -171,7 +180,7 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, f func(dur t
171180
f(duration)
172181
StopCPUProfile()
173182

174-
if profileOk(t, need, matches, prof, duration) {
183+
if profileOk(t, matches, need, avoid, prof, duration) {
175184
return
176185
}
177186

@@ -218,11 +227,13 @@ func stackContains(spec string, count uintptr, stk []*profile.Location, labels m
218227

219228
type matchFunc func(spec string, count uintptr, stk []*profile.Location, labels map[string][]string) bool
220229

221-
func profileOk(t *testing.T, need []string, matches matchFunc, prof bytes.Buffer, duration time.Duration) (ok bool) {
230+
func profileOk(t *testing.T, matches matchFunc, need []string, avoid []string, prof bytes.Buffer, duration time.Duration) (ok bool) {
222231
ok = true
223232

224-
// Check that profile is well formed and contains need.
233+
// Check that profile is well formed, contains 'need', and does not contain
234+
// anything from 'avoid'.
225235
have := make([]uintptr, len(need))
236+
avoidSamples := make([]uintptr, len(avoid))
226237
var samples uintptr
227238
var buf bytes.Buffer
228239
parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, labels map[string][]string) {
@@ -234,6 +245,15 @@ func profileOk(t *testing.T, need []string, matches matchFunc, prof bytes.Buffer
234245
have[i] += count
235246
}
236247
}
248+
for i, name := range avoid {
249+
for _, loc := range stk {
250+
for _, line := range loc.Line {
251+
if strings.Contains(line.Function.Name, name) {
252+
avoidSamples[i] += count
253+
}
254+
}
255+
}
256+
}
237257
fmt.Fprintf(&buf, "\n")
238258
})
239259
t.Logf("total %d CPU profile samples collected:\n%s", samples, buf.String())
@@ -256,6 +276,14 @@ func profileOk(t *testing.T, need []string, matches matchFunc, prof bytes.Buffer
256276
ok = false
257277
}
258278

279+
for i, name := range avoid {
280+
bad := avoidSamples[i]
281+
if bad != 0 {
282+
t.Logf("found %d samples in avoid-function %s\n", bad, name)
283+
ok = false
284+
}
285+
}
286+
259287
if len(need) == 0 {
260288
return ok
261289
}
@@ -323,6 +351,9 @@ func TestCPUProfileWithFork(t *testing.T) {
323351
// If it did, it would see inconsistent state and would either record an incorrect stack
324352
// or crash because the stack was malformed.
325353
func TestGoroutineSwitch(t *testing.T) {
354+
if runtime.Compiler == "gccgo" {
355+
t.Skip("not applicable for gccgo")
356+
}
326357
// How much to try. These defaults take about 1 seconds
327358
// on a 2012 MacBook Pro. The ones in short mode take
328359
// about 0.1 seconds.
@@ -382,7 +413,7 @@ func fprintStack(w io.Writer, stk []*profile.Location) {
382413

383414
// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
384415
func TestMathBigDivide(t *testing.T) {
385-
testCPUProfile(t, nil, nil, func(duration time.Duration) {
416+
testCPUProfile(t, nil, nil, nil, func(duration time.Duration) {
386417
t := time.After(duration)
387418
pi := new(big.Int)
388419
for {
@@ -411,7 +442,7 @@ func stackContainsAll(spec string, count uintptr, stk []*profile.Location, label
411442
}
412443

413444
func TestMorestack(t *testing.T) {
414-
testCPUProfile(t, stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, func(duration time.Duration) {
445+
testCPUProfile(t, stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, avoidFunctions(), func(duration time.Duration) {
415446
t := time.After(duration)
416447
c := make(chan bool)
417448
for {
@@ -913,7 +944,7 @@ func stackContainsLabeled(spec string, count uintptr, stk []*profile.Location, l
913944
}
914945

915946
func TestCPUProfileLabel(t *testing.T) {
916-
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, func(dur time.Duration) {
947+
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, avoidFunctions(), func(dur time.Duration) {
917948
Do(context.Background(), Labels("key", "value"), func(context.Context) {
918949
cpuHogger(cpuHog1, &salt1, dur)
919950
})
@@ -924,7 +955,7 @@ func TestLabelRace(t *testing.T) {
924955
// Test the race detector annotations for synchronization
925956
// between settings labels and consuming them from the
926957
// profile.
927-
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, func(dur time.Duration) {
958+
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, nil, func(dur time.Duration) {
928959
start := time.Now()
929960
var wg sync.WaitGroup
930961
for time.Since(start) < dur {

0 commit comments

Comments
 (0)