]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: deflake BenchmarkClient and its use of a fixed port for testing
authorBrad Fitzpatrick <bradfitz@golang.org>
Mon, 15 Aug 2016 17:20:21 +0000 (17:20 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 16 Aug 2016 01:46:41 +0000 (01:46 +0000)
Let the kernel pick a port for testing, and have the server in the
child process tell the parent (benchmarking) process the port that
was selected.

Fixes flakes like seen in https://golang.org/cl/27050 (and previously)

Change-Id: Ia2b705dc4152f70e0a5725015bdae09984d09d53
Reviewed-on: https://go-review.googlesource.com/27051
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/net/http/serve_test.go

index 13e5f283e4c4d6dbc8285e70ed64885583aed927..3cfe57dd04844a07ff50e8863a2b38db323b7840 100644 (file)
@@ -4416,13 +4416,19 @@ func BenchmarkClient(b *testing.B) {
        b.StopTimer()
        defer afterTest(b)
 
-       port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
-       if port == "" {
-               port = "39207"
-       }
        var data = []byte("Hello world.\n")
        if server := os.Getenv("TEST_BENCH_SERVER"); server != "" {
                // Server process mode.
+               port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
+               if port == "" {
+                       port = "0"
+               }
+               ln, err := net.Listen("tcp", "localhost:"+port)
+               if err != nil {
+                       fmt.Fprintln(os.Stderr, err.Error())
+                       os.Exit(1)
+               }
+               fmt.Println(ln.Addr().String())
                HandleFunc("/", func(w ResponseWriter, r *Request) {
                        r.ParseForm()
                        if r.Form.Get("stop") != "" {
@@ -4431,33 +4437,44 @@ func BenchmarkClient(b *testing.B) {
                        w.Header().Set("Content-Type", "text/html; charset=utf-8")
                        w.Write(data)
                })
-               log.Fatal(ListenAndServe("localhost:"+port, nil))
+               var srv Server
+               log.Fatal(srv.Serve(ln))
        }
 
        // Start server process.
        cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkClient$")
        cmd.Env = append(os.Environ(), "TEST_BENCH_SERVER=yes")
+       cmd.Stderr = os.Stderr
+       stdout, err := cmd.StdoutPipe()
+       if err != nil {
+               b.Fatal(err)
+       }
        if err := cmd.Start(); err != nil {
                b.Fatalf("subprocess failed to start: %v", err)
        }
        defer cmd.Process.Kill()
+
+       // Wait for the server in the child process to respond and tell us
+       // its listening address, once it's started listening:
+       timer := time.AfterFunc(10*time.Second, func() {
+               cmd.Process.Kill()
+       })
+       defer timer.Stop()
+       bs := bufio.NewScanner(stdout)
+       if !bs.Scan() {
+               b.Fatalf("failed to read listening URL from child: %v", bs.Err())
+       }
+       url := "http://" + strings.TrimSpace(bs.Text()) + "/"
+       timer.Stop()
+       if _, err := getNoBody(url); err != nil {
+               b.Fatalf("initial probe of child process failed: %v", err)
+       }
+
        done := make(chan error)
        go func() {
                done <- cmd.Wait()
        }()
 
-       // Wait for the server process to respond.
-       url := "http://localhost:" + port + "/"
-       for i := 0; i < 100; i++ {
-               time.Sleep(100 * time.Millisecond)
-               if _, err := getNoBody(url); err == nil {
-                       break
-               }
-               if i == 99 {
-                       b.Fatalf("subprocess does not respond")
-               }
-       }
-
        // Do b.N requests to the server.
        b.StartTimer()
        for i := 0; i < b.N; i++ {