testutil: add CheckAfterTest for calling AfterTest without a testing.T

This commit is contained in:
Anthony Romano 2017-03-10 12:18:24 -08:00
parent 0a692b0524
commit eb6a47f87e

View File

@ -62,10 +62,11 @@ func CheckLeakedGoroutine() bool {
return true return true
} }
func AfterTest(t *testing.T) { // CheckAfterTest returns an error if AfterTest would fail with an error.
func CheckAfterTest(d time.Duration) error {
http.DefaultTransport.(*http.Transport).CloseIdleConnections() http.DefaultTransport.(*http.Transport).CloseIdleConnections()
if testing.Short() { if testing.Short() {
return return nil
} }
var bad string var bad string
badSubstring := map[string]string{ badSubstring := map[string]string{
@ -78,7 +79,8 @@ func AfterTest(t *testing.T) {
} }
var stacks string var stacks string
for i := 0; i < 6; i++ { begin := time.Now()
for time.Since(begin) < d {
bad = "" bad = ""
stacks = strings.Join(interestingGoroutines(), "\n\n") stacks = strings.Join(interestingGoroutines(), "\n\n")
for substr, what := range badSubstring { for substr, what := range badSubstring {
@ -87,13 +89,22 @@ func AfterTest(t *testing.T) {
} }
} }
if bad == "" { if bad == "" {
return return nil
} }
// Bad stuff found, but goroutines might just still be // Bad stuff found, but goroutines might just still be
// shutting down, so give it some time. // shutting down, so give it some time.
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
} }
t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks) return fmt.Errorf("appears to have leaked %s:\n%s", bad, stacks)
}
// AfterTest is meant to run in a defer that executes after a test completes.
// It will detect common goroutine leaks, retrying in case there are goroutines
// not synchronously torn down, and fail the test if any goroutines are stuck.
func AfterTest(t *testing.T) {
if err := CheckAfterTest(300 * time.Millisecond); err != nil {
t.Errorf("Test %v", err)
}
} }
func interestingGoroutines() (gs []string) { func interestingGoroutines() (gs []string) {