[release-branch.go1.12] cmd/godoc: fix -url flag, add tests

This change adds a small number of integration tests for the godoc
command's -url flag, confirming that the behavior matches the local http
server tests in those cases. It fixes three bugs which prevent the -url
flag from working currently.

Fixes golang/go#30314

Change-Id: I0ca1fe81f9f186d0ca02b31674cc8654af434e92
Reviewed-on: https://go-review.googlesource.com/c/162907
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
(cherry picked from commit bb2d4193192d16d7b4f740befc0ddd495bf6f86b)
Reviewed-on: https://go-review.googlesource.com/c/162985
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/cmd/godoc/godoc_test.go b/cmd/godoc/godoc_test.go
index 54fe540..28e1bae 100644
--- a/cmd/godoc/godoc_test.go
+++ b/cmd/godoc/godoc_test.go
@@ -134,6 +134,46 @@
 	cmd.Wait()
 }
 
+func TestURL(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping on plan9; fails to start up quickly enough")
+	}
+	bin, cleanup := buildGodoc(t)
+	defer cleanup()
+
+	testcase := func(url string, contents string) func(t *testing.T) {
+		return func(t *testing.T) {
+			stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
+
+			args := []string{fmt.Sprintf("-url=%s", url)}
+			cmd := exec.Command(bin, args...)
+			cmd.Stdout = stdout
+			cmd.Stderr = stderr
+			cmd.Args[0] = "godoc"
+
+			// Set GOPATH variable to non-existing path
+			// and GOPROXY=off to disable module fetches.
+			// We cannot just unset GOPATH variable because godoc would default it to ~/go.
+			// (We don't want the indexer looking at the local workspace during tests.)
+			cmd.Env = append(os.Environ(),
+				"GOPATH=does_not_exist",
+				"GOPROXY=off",
+				"GO111MODULE=off")
+
+			if err := cmd.Run(); err != nil {
+				t.Fatalf("failed to run godoc -url=%q: %s\nstderr:\n%s", url, err, stderr)
+			}
+
+			if !strings.Contains(stdout.String(), contents) {
+				t.Errorf("did not find substring %q in output of godoc -url=%q:\n%s", contents, url, stdout)
+			}
+		}
+	}
+
+	t.Run("index", testcase("/", "Go is an open source programming language"))
+	t.Run("fmt", testcase("/pkg/fmt", "Package fmt implements formatted I/O"))
+}
+
 // Basic integration test for godoc HTTP interface.
 func TestWeb(t *testing.T) {
 	testWeb(t, false)
@@ -150,7 +190,7 @@
 // Basic integration test for godoc HTTP interface.
 func testWeb(t *testing.T, withIndex bool) {
 	if runtime.GOOS == "plan9" {
-		t.Skip("skipping on plan9; files to start up quickly enough")
+		t.Skip("skipping on plan9; fails to start up quickly enough")
 	}
 	bin, cleanup := buildGodoc(t)
 	defer cleanup()
diff --git a/cmd/godoc/main.go b/cmd/godoc/main.go
index c27ede7..ac4509a 100644
--- a/cmd/godoc/main.go
+++ b/cmd/godoc/main.go
@@ -94,7 +94,7 @@
 }
 
 func (w *httpResponseRecorder) Header() http.Header         { return w.header }
-func (w *httpResponseRecorder) Write(b []byte) (int, error) { return len(b), nil }
+func (w *httpResponseRecorder) Write(b []byte) (int, error) { return w.body.Write(b) }
 func (w *httpResponseRecorder) WriteHeader(code int)        { w.code = code }
 
 func usage() {
@@ -168,8 +168,8 @@
 		fmt.Fprintln(os.Stderr, `Unexpected arguments. Use "go doc" for command-line help output instead. For example, "go doc fmt.Printf".`)
 		usage()
 	}
-	if *httpAddr != "" && *urlFlag != "" && !*writeIndex {
-		fmt.Fprintln(os.Stderr, "Missing args.")
+	if *httpAddr == "" && *urlFlag == "" && !*writeIndex {
+		fmt.Fprintln(os.Stderr, "At least one of -http, -url, or -write_index must be set to a non-zero value.")
 		usage()
 	}
 
@@ -228,7 +228,7 @@
 	corpus.IndexDirectory = indexDirectoryDefault
 	corpus.IndexThrottle = *indexThrottle
 	corpus.IndexInterval = *indexInterval
-	if *writeIndex {
+	if *writeIndex || *urlFlag != "" {
 		corpus.IndexThrottle = 1.0
 		corpus.IndexEnabled = true
 		initCorpus(corpus)