Skip to content

Commit d04c33d

Browse files
committed
cmd/godoc: check if server exited when waiting
Previously, the waitForServer family of helpers would wait anywhere between 15 seconds to 2 minutes for the server to become ready. But if there's a problem that results in the server exiting early, that wasn't being detected quickly. This change modifies tests to also wait for command to exit, and fail the test quickly if so. This helps during development. Updates golang/go#33655 Change-Id: I16195715449015d7250a2d0de5e55ab9a1ef078d Reviewed-on: https://go-review.googlesource.com/c/tools/+/196979 Run-TryBot: Dmitri Shuralyov <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Andrew Bonventre <[email protected]>
1 parent e461004 commit d04c33d

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

cmd/godoc/godoc_test.go

+44-23
Original file line numberDiff line numberDiff line change
@@ -75,56 +75,77 @@ func serverAddress(t *testing.T) string {
7575
return ln.Addr().String()
7676
}
7777

78-
func waitForServerReady(t *testing.T, addr string) {
79-
waitForServer(t,
78+
func waitForServerReady(t *testing.T, cmd *exec.Cmd, addr string) {
79+
ch := make(chan error, 1)
80+
go func() { ch <- fmt.Errorf("server exited early: %v", cmd.Wait()) }()
81+
go waitForServer(t, ch,
8082
fmt.Sprintf("http://%v/", addr),
8183
"The Go Programming Language",
8284
15*time.Second,
8385
false)
86+
if err := <-ch; err != nil {
87+
t.Fatal(err)
88+
}
8489
}
8590

86-
func waitForSearchReady(t *testing.T, addr string) {
87-
waitForServer(t,
91+
func waitForSearchReady(t *testing.T, cmd *exec.Cmd, addr string) {
92+
ch := make(chan error, 1)
93+
go func() { ch <- fmt.Errorf("server exited early: %v", cmd.Wait()) }()
94+
go waitForServer(t, ch,
8895
fmt.Sprintf("http://%v/search?q=FALLTHROUGH", addr),
8996
"The list of tokens.",
9097
2*time.Minute,
9198
false)
99+
if err := <-ch; err != nil {
100+
t.Fatal(err)
101+
}
92102
}
93103

94104
func waitUntilScanComplete(t *testing.T, addr string) {
95-
waitForServer(t,
105+
ch := make(chan error)
106+
go waitForServer(t, ch,
96107
fmt.Sprintf("http://%v/pkg", addr),
97108
"Scan is not yet complete",
98109
2*time.Minute,
110+
// setting reverse as true, which means this waits
111+
// until the string is not returned in the response anymore
99112
true,
100113
)
101-
// setting reverse as true, which means this waits
102-
// until the string is not returned in the response anymore
114+
if err := <-ch; err != nil {
115+
t.Fatal(err)
116+
}
103117
}
104118

105119
const pollInterval = 200 * time.Millisecond
106120

107-
func waitForServer(t *testing.T, url, match string, timeout time.Duration, reverse bool) {
108-
// "health check" duplicated from x/tools/cmd/tipgodoc/tip.go
121+
// waitForServer waits for server to meet the required condition.
122+
// It sends a single error value to ch, unless the test has failed.
123+
// The error value is nil if the required condition was met within
124+
// timeout, or non-nil otherwise.
125+
func waitForServer(t *testing.T, ch chan<- error, url, match string, timeout time.Duration, reverse bool) {
109126
deadline := time.Now().Add(timeout)
110127
for time.Now().Before(deadline) {
111-
time.Sleep(pollInterval)
128+
if t.Failed() {
129+
return
130+
}
112131
res, err := http.Get(url)
113132
if err != nil {
114133
continue
115134
}
116-
rbody, err := ioutil.ReadAll(res.Body)
135+
body, err := ioutil.ReadAll(res.Body)
117136
res.Body.Close()
118-
if err == nil && res.StatusCode == http.StatusOK {
119-
if bytes.Contains(rbody, []byte(match)) && !reverse {
120-
return
121-
}
122-
if !bytes.Contains(rbody, []byte(match)) && reverse {
123-
return
124-
}
137+
if err != nil || res.StatusCode != http.StatusOK {
138+
continue
139+
}
140+
switch {
141+
case !reverse && bytes.Contains(body, []byte(match)),
142+
reverse && !bytes.Contains(body, []byte(match)):
143+
ch <- nil
144+
return
125145
}
146+
time.Sleep(pollInterval)
126147
}
127-
t.Fatalf("Server failed to respond in %v", timeout)
148+
ch <- fmt.Errorf("server failed to respond in %v", timeout)
128149
}
129150

130151
// hasTag checks whether a given release tag is contained in the current version
@@ -140,7 +161,7 @@ func hasTag(t string) bool {
140161

141162
func killAndWait(cmd *exec.Cmd) {
142163
cmd.Process.Kill()
143-
cmd.Wait()
164+
cmd.Process.Wait()
144165
}
145166

146167
func TestURL(t *testing.T) {
@@ -228,9 +249,9 @@ func testWeb(t *testing.T, withIndex bool) {
228249
defer killAndWait(cmd)
229250

230251
if withIndex {
231-
waitForSearchReady(t, addr)
252+
waitForSearchReady(t, cmd, addr)
232253
} else {
233-
waitForServerReady(t, addr)
254+
waitForServerReady(t, cmd, addr)
234255
waitUntilScanComplete(t, addr)
235256
}
236257

@@ -444,7 +465,7 @@ func main() { print(lib.V) }
444465
t.Fatalf("failed to start godoc: %s", err)
445466
}
446467
defer killAndWait(cmd)
447-
waitForServerReady(t, addr)
468+
waitForServerReady(t, cmd, addr)
448469

449470
// Wait for type analysis to complete.
450471
reader := bufio.NewReader(stderr)

0 commit comments

Comments
 (0)