libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / http / main_test.go
blob7936fb3044e65d7a77962b34b72d86e6a82c594e
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.
5 package http_test
7 import (
8 "fmt"
9 "io/ioutil"
10 "log"
11 "net/http"
12 "os"
13 "runtime"
14 "sort"
15 "strings"
16 "testing"
17 "time"
20 var quietLog = log.New(ioutil.Discard, "", 0)
22 func TestMain(m *testing.M) {
23 v := m.Run()
24 if v == 0 && goroutineLeaked() {
25 os.Exit(1)
27 os.Exit(v)
30 func interestingGoroutines() (gs []string) {
31 buf := make([]byte, 2<<20)
32 buf = buf[:runtime.Stack(buf, true)]
33 for _, g := range strings.Split(string(buf), "\n\n") {
34 sl := strings.SplitN(g, "\n", 2)
35 if len(sl) != 2 {
36 continue
38 stack := strings.TrimSpace(sl[1])
39 if stack == "" ||
40 strings.Contains(stack, "testing.(*M).before.func1") ||
41 strings.Contains(stack, "os/signal.signal_recv") ||
42 strings.Contains(stack, "created by net.startServer") ||
43 strings.Contains(stack, "created by testing.RunTests") ||
44 strings.Contains(stack, "closeWriteAndWait") ||
45 strings.Contains(stack, "testing.Main(") ||
46 // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
47 strings.Contains(stack, "runtime.goexit") ||
48 strings.Contains(stack, "created by runtime.gc") ||
49 strings.Contains(stack, "net/http_test.interestingGoroutines") ||
50 strings.Contains(stack, "runtime.MHeap_Scavenger") {
51 continue
53 gs = append(gs, stack)
55 sort.Strings(gs)
56 return
59 // Verify the other tests didn't leave any goroutines running.
60 func goroutineLeaked() bool {
61 if testing.Short() || runningBenchmarks() {
62 // Don't worry about goroutine leaks in -short mode or in
63 // benchmark mode. Too distracting when there are false positives.
64 return false
67 var stackCount map[string]int
68 for i := 0; i < 5; i++ {
69 n := 0
70 stackCount = make(map[string]int)
71 gs := interestingGoroutines()
72 for _, g := range gs {
73 stackCount[g]++
74 n++
76 if n == 0 {
77 return false
79 // Wait for goroutines to schedule and die off:
80 time.Sleep(100 * time.Millisecond)
82 fmt.Fprintf(os.Stderr, "Too many goroutines running after net/http test(s).\n")
83 for stack, count := range stackCount {
84 fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
86 return true
89 // setParallel marks t as a parallel test if we're in short mode
90 // (all.bash), but as a serial test otherwise. Using t.Parallel isn't
91 // compatible with the afterTest func in non-short mode.
92 func setParallel(t *testing.T) {
93 if testing.Short() {
94 t.Parallel()
98 func runningBenchmarks() bool {
99 for i, arg := range os.Args {
100 if strings.HasPrefix(arg, "-test.bench=") && !strings.HasSuffix(arg, "=") {
101 return true
103 if arg == "-test.bench" && i < len(os.Args)-1 && os.Args[i+1] != "" {
104 return true
107 return false
110 func afterTest(t testing.TB) {
111 http.DefaultTransport.(*http.Transport).CloseIdleConnections()
112 if testing.Short() {
113 return
115 var bad string
116 badSubstring := map[string]string{
117 ").readLoop(": "a Transport",
118 ").writeLoop(": "a Transport",
119 "created by net/http/httptest.(*Server).Start": "an httptest.Server",
120 "timeoutHandler": "a TimeoutHandler",
121 "net.(*netFD).connect(": "a timing out dial",
122 ").noteClientGone(": "a closenotifier sender",
124 var stacks string
125 for i := 0; i < 4; i++ {
126 bad = ""
127 stacks = strings.Join(interestingGoroutines(), "\n\n")
128 for substr, what := range badSubstring {
129 if strings.Contains(stacks, substr) {
130 bad = what
133 if bad == "" {
134 return
136 // Bad stuff found, but goroutines might just still be
137 // shutting down, so give it some time.
138 time.Sleep(250 * time.Millisecond)
140 t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
143 // waitCondition reports whether fn eventually returned true,
144 // checking immediately and then every checkEvery amount,
145 // until waitFor has elapsed, at which point it returns false.
146 func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool {
147 deadline := time.Now().Add(waitFor)
148 for time.Now().Before(deadline) {
149 if fn() {
150 return true
152 time.Sleep(checkEvery)
154 return false
157 // waitErrCondition is like waitCondition but with errors instead of bools.
158 func waitErrCondition(waitFor, checkEvery time.Duration, fn func() error) error {
159 deadline := time.Now().Add(waitFor)
160 var err error
161 for time.Now().Before(deadline) {
162 if err = fn(); err == nil {
163 return nil
165 time.Sleep(checkEvery)
167 return err