/
goleaktest.go
37 lines (34 loc) · 944 Bytes
/
goleaktest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package leaktest
import (
"runtime"
"testing"
"time"
"github.com/bradfitz/iter"
)
// Put defer GoroutineLeakCheck(t)() at the top of your test. Make sure the
// goroutine count is steady before your test begins.
func GoroutineLeakCheck(t testing.TB) func() {
if !testing.Verbose() {
return func() {}
}
numStart := runtime.NumGoroutine()
return func() {
var numNow int
wait := time.Millisecond
started := time.Now()
for range iter.N(10) { // 1 second
numNow = runtime.NumGoroutine()
if numNow <= numStart {
break
}
t.Logf("%d excess goroutines after %s", numNow-numStart, time.Since(started))
time.Sleep(wait)
wait *= 2
}
// I'd print stacks, or treat this as fatal, but I think
// runtime.NumGoroutine is including system routines for which we are
// not provided the stacks, and are spawned unpredictably.
t.Logf("have %d goroutines, started with %d", numNow, numStart)
// select {}
}
}