38 lignes
945 o
Go
38 lignes
945 o
Go
|
package missinggo
|
||
|
|
||
|
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 {}
|
||
|
}
|
||
|
}
|