github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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.newPollServer") || 27 strings.Contains(stack, "created by net.startServer") || 28 strings.Contains(stack, "created by testing.RunTests") || 29 strings.Contains(stack, "closeWriteAndWait") || 30 strings.Contains(stack, "testing.Main(") || 31 // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28) 32 strings.Contains(stack, "runtime.goexit") || 33 strings.Contains(stack, "created by runtime.gc") || 34 strings.Contains(stack, "runtime.MHeap_Scavenger") { 35 continue 36 } 37 gs = append(gs, stack) 38 } 39 sort.Strings(gs) 40 return 41 } 42 43 // Verify the other tests didn't leave any goroutines running. 44 // This is in a file named z_last_test.go so it sorts at the end. 45 func TestGoroutinesRunning(t *testing.T) { 46 if testing.Short() { 47 t.Skip("not counting goroutines for leakage in -short mode") 48 } 49 gs := interestingGoroutines() 50 51 n := 0 52 stackCount := make(map[string]int) 53 for _, g := range gs { 54 stackCount[g]++ 55 n++ 56 } 57 58 t.Logf("num goroutines = %d", n) 59 if n > 0 { 60 t.Error("Too many goroutines.") 61 for stack, count := range stackCount { 62 t.Logf("%d instances of:\n%s", count, stack) 63 } 64 } 65 } 66 67 func afterTest(t *testing.T) { 68 http.DefaultTransport.(*http.Transport).CloseIdleConnections() 69 if testing.Short() { 70 return 71 } 72 var bad string 73 badSubstring := map[string]string{ 74 ").readLoop(": "a Transport", 75 ").writeLoop(": "a Transport", 76 "created by net/http/httptest.(*Server).Start": "an httptest.Server", 77 "timeoutHandler": "a TimeoutHandler", 78 "net.(*netFD).connect(": "a timing out dial", 79 ").noteClientGone(": "a closenotifier sender", 80 } 81 var stacks string 82 for i := 0; i < 4; i++ { 83 bad = "" 84 stacks = strings.Join(interestingGoroutines(), "\n\n") 85 for substr, what := range badSubstring { 86 if strings.Contains(stacks, substr) { 87 bad = what 88 } 89 } 90 if bad == "" { 91 return 92 } 93 // Bad stuff found, but goroutines might just still be 94 // shutting down, so give it some time. 95 time.Sleep(250 * time.Millisecond) 96 } 97 t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks) 98 }