github.com/wader/devd@v0.0.0-20221031103345-441c7e455249/fileserver/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 fileserver 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 func afterTest(t *testing.T) { 43 http.DefaultTransport.(*http.Transport).CloseIdleConnections() 44 if testing.Short() { 45 return 46 } 47 var bad string 48 badSubstring := map[string]string{ 49 ").readLoop(": "a Transport", 50 ").writeLoop(": "a Transport", 51 "created by net/http/httptest.(*Server).Start": "an httptest.Server", 52 "timeoutHandler": "a TimeoutHandler", 53 "net.(*netFD).connect(": "a timing out dial", 54 ").noteClientGone(": "a closenotifier sender", 55 } 56 var stacks string 57 for i := 0; i < 4; i++ { 58 bad = "" 59 stacks = strings.Join(interestingGoroutines(), "\n\n") 60 for substr, what := range badSubstring { 61 if strings.Contains(stacks, substr) { 62 bad = what 63 } 64 } 65 if bad == "" { 66 return 67 } 68 // Bad stuff found, but goroutines might just still be 69 // shutting down, so give it some time. 70 time.Sleep(250 * time.Millisecond) 71 } 72 t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks) 73 }