Skip to content

Commit 5a59516

Browse files
committed
net/http: deflake BenchmarkClient and its use of a fixed port for testing
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 52fcff3 commit 5a59516

File tree

1 file changed

+34
-17
lines changed

1 file changed

+34
-17
lines changed

src/net/http/serve_test.go

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4416,13 +4416,19 @@ func BenchmarkClient(b *testing.B) {
44164416
b.StopTimer()
44174417
defer afterTest(b)
44184418

4419-
port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
4420-
if port == "" {
4421-
port = "39207"
4422-
}
44234419
var data = []byte("Hello world.\n")
44244420
if server := os.Getenv("TEST_BENCH_SERVER"); server != "" {
44254421
// Server process mode.
4422+
port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
4423+
if port == "" {
4424+
port = "0"
4425+
}
4426+
ln, err := net.Listen("tcp", "localhost:"+port)
4427+
if err != nil {
4428+
fmt.Fprintln(os.Stderr, err.Error())
4429+
os.Exit(1)
4430+
}
4431+
fmt.Println(ln.Addr().String())
44264432
HandleFunc("/", func(w ResponseWriter, r *Request) {
44274433
r.ParseForm()
44284434
if r.Form.Get("stop") != "" {
@@ -4431,33 +4437,44 @@ func BenchmarkClient(b *testing.B) {
44314437
w.Header().Set("Content-Type", "text/html; charset=utf-8")
44324438
w.Write(data)
44334439
})
4434-
log.Fatal(ListenAndServe("localhost:"+port, nil))
4440+
var srv Server
4441+
log.Fatal(srv.Serve(ln))
44354442
}
44364443

44374444
// Start server process.
44384445
cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkClient$")
44394446
cmd.Env = append(os.Environ(), "TEST_BENCH_SERVER=yes")
4447+
cmd.Stderr = os.Stderr
4448+
stdout, err := cmd.StdoutPipe()
4449+
if err != nil {
4450+
b.Fatal(err)
4451+
}
44404452
if err := cmd.Start(); err != nil {
44414453
b.Fatalf("subprocess failed to start: %v", err)
44424454
}
44434455
defer cmd.Process.Kill()
4456+
4457+
// Wait for the server in the child process to respond and tell us
4458+
// its listening address, once it's started listening:
4459+
timer := time.AfterFunc(10*time.Second, func() {
4460+
cmd.Process.Kill()
4461+
})
4462+
defer timer.Stop()
4463+
bs := bufio.NewScanner(stdout)
4464+
if !bs.Scan() {
4465+
b.Fatalf("failed to read listening URL from child: %v", bs.Err())
4466+
}
4467+
url := "http://" + strings.TrimSpace(bs.Text()) + "/"
4468+
timer.Stop()
4469+
if _, err := getNoBody(url); err != nil {
4470+
b.Fatalf("initial probe of child process failed: %v", err)
4471+
}
4472+
44444473
done := make(chan error)
44454474
go func() {
44464475
done <- cmd.Wait()
44474476
}()
44484477

4449-
// Wait for the server process to respond.
4450-
url := "http://localhost:" + port + "/"
4451-
for i := 0; i < 100; i++ {
4452-
time.Sleep(100 * time.Millisecond)
4453-
if _, err := getNoBody(url); err == nil {
4454-
break
4455-
}
4456-
if i == 99 {
4457-
b.Fatalf("subprocess does not respond")
4458-
}
4459-
}
4460-
44614478
// Do b.N requests to the server.
44624479
b.StartTimer()
44634480
for i := 0; i < b.N; i++ {

0 commit comments

Comments
 (0)