github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/net/http/z_last_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package http_test 6 7 import ( 8 "net/http" 9 "runtime" 10 "sort" 11 "strings" 12 "testing" 13 "time" 14 ) 15 16 func interestingGoroutines() (gs []string) { 17 buf := make([]byte, 2<<20) 18 buf = buf[:runtime.Stack(buf, true)] 19 for _, g := range strings.Split(string(buf), "\n\n") { 20 sl := strings.SplitN(g, "\n", 2) 21 if len(sl) != 2 { 22 continue 23 } 24 stack := strings.TrimSpace(sl[1]) 25 if stack == "" || 26 strings.Contains(stack, "created by net.startServer") || 27 strings.Contains(stack, "created by testing.RunTests") || 28 strings.Contains(stack, "closeWriteAndWait") || 29 strings.Contains(stack, "testing.Main(") || 30 // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28) 31 strings.Contains(stack, "runtime.goexit") || 32 strings.Contains(stack, "created by runtime.gc") || 33 strings.Contains(stack, "runtime.MHeap_Scavenger") { 34 continue 35 } 36 gs = append(gs, stack) 37 } 38 sort.Strings(gs) 39 return 40 } 41 42 // Verify the other tests didn't leave any goroutines running. 43 // This is in a file named z_last_test.go so it sorts at the end. 44 func TestGoroutinesRunning(t *testing.T) { 45 if testing.Short() { 46 t.Skip("not counting goroutines for leakage in -short mode") 47 } 48 gs := interestingGoroutines() 49 50 n := 0 51 stackCount := make(map[string]int) 52 for _, g := range gs { 53 stackCount[g]++ 54 n++ 55 } 56 57 t.Logf("num goroutines = %d", n) 58 if n > 0 { 59 t.Error("Too many goroutines.") 60 for stack, count := range stackCount { 61 t.Logf("%d instances of:\n%s", count, stack) 62 } 63 } 64 } 65 66 func afterTest(t *testing.T) { 67 http.DefaultTransport.(*http.Transport).CloseIdleConnections() 68 if testing.Short() { 69 return 70 } 71 var bad string 72 badSubstring := map[string]string{ 73 ").readLoop(": "a Transport", 74 ").writeLoop(": "a Transport", 75 "created by net/http/httptest.(*Server).Start": "an httptest.Server", 76 "timeoutHandler": "a TimeoutHandler", 77 "net.(*netFD).connect(": "a timing out dial", 78 ").noteClientGone(": "a closenotifier sender", 79 } 80 var stacks string 81 for i := 0; i < 4; i++ { 82 bad = "" 83 stacks = strings.Join(interestingGoroutines(), "\n\n") 84 for substr, what := range badSubstring { 85 if strings.Contains(stacks, substr) { 86 bad = what 87 } 88 } 89 if bad == "" { 90 return 91 } 92 // Bad stuff found, but goroutines might just still be 93 // shutting down, so give it some time. 94 time.Sleep(250 * time.Millisecond) 95 } 96 t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks) 97 }