Skip to content

Commit 2bd7949

Browse files
committed
x/tools: don't parse CombinedOutput
This change fixes a bug in internal/testenv in which it would gather the combined output (2>&1) of the "go env" command and parse it as an environment variable. However, certain environment variables (e.g. GODEBUG) cause "go env" to log to stderr, so that the parser reads garbage. Use Output instead. Also, preemptively fix a number of similar occurrences in x/tools. CombinedOutput should be used only when the whole output is ultimately sent to stderr or a log for human eyes, or for tests that look for specific error messages in the unstructured combined log. In those cases, the scope of the 'out' variable can be reduced to avoid temptation. Fixes golang/go#65729 Change-Id: Ifc0fd494fcde0e339bb5283e39c7696a34f5a699 . Change-Id: I6eadd0e76498dc5f4d91e0904af2d52e610df683 Reviewed-on: https://go-review.googlesource.com/c/tools/+/564516 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 7240af8 commit 2bd7949

File tree

9 files changed

+21
-14
lines changed

9 files changed

+21
-14
lines changed

go/analysis/unitchecker/unitchecker_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ func _() {
169169
cmd.Env = append(exported.Config.Env, "ENTRYPOINT=minivet")
170170
cmd.Dir = exported.Config.Dir
171171

172+
// TODO(golang/go#65729): this is unsound: any extra
173+
// logging by the child process (e.g. due to GODEBUG
174+
// options) will add noise to stderr, causing the
175+
// CombinedOutput to be unparseable as JSON. But we
176+
// can't simply use Output here as some of the tests
177+
// look for substrings of stderr. Rework the test to
178+
// be specific about which output stream to match.
172179
out, err := cmd.CombinedOutput()
173180
exitcode := 0
174181
if exitErr, ok := err.(*exec.ExitError); ok {

go/gcexportdata/gcexportdata.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import (
4747
func Find(importPath, srcDir string) (filename, path string) {
4848
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
4949
cmd.Dir = srcDir
50-
out, err := cmd.CombinedOutput()
50+
out, err := cmd.Output()
5151
if err != nil {
5252
return "", ""
5353
}

go/internal/cgo/cgo_pkgconfig.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
// pkgConfig runs pkg-config with the specified arguments and returns the flags it prints.
1616
func pkgConfig(mode string, pkgs []string) (flags []string, err error) {
1717
cmd := exec.Command("pkg-config", append([]string{mode}, pkgs...)...)
18-
out, err := cmd.CombinedOutput()
18+
out, err := cmd.Output()
1919
if err != nil {
2020
s := fmt.Sprintf("%s failed: %v", strings.Join(cmd.Args, " "), err)
2121
if len(out) > 0 {

go/internal/gccgoimporter/importer_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func TestObjImporter(t *testing.T) {
140140
t.Skip("no support yet for debug/xcoff")
141141
}
142142

143-
verout, err := exec.Command(gpath, "--version").CombinedOutput()
143+
verout, err := exec.Command(gpath, "--version").Output()
144144
if err != nil {
145145
t.Logf("%s", verout)
146146
t.Fatal(err)
@@ -182,17 +182,15 @@ func TestObjImporter(t *testing.T) {
182182
afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a")
183183

184184
cmd := exec.Command(gpath, "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile)
185-
out, err := cmd.CombinedOutput()
186-
if err != nil {
185+
if out, err := cmd.CombinedOutput(); err != nil {
187186
t.Logf("%s", out)
188187
t.Fatalf("gccgo %s failed: %s", gofile, err)
189188
}
190189

191190
runImporterTest(t, imp, initmap, &test)
192191

193192
cmd = exec.Command("ar", "cr", afile, ofile)
194-
out, err = cmd.CombinedOutput()
195-
if err != nil {
193+
if out, err := cmd.CombinedOutput(); err != nil {
196194
t.Logf("%s", out)
197195
t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err)
198196
}

internal/diff/difftest/difftest_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func getDiffOutput(a, b string) (string, error) {
6464
}
6565
cmd := exec.Command("diff", "-u", fileA.Name(), fileB.Name())
6666
cmd.Env = append(cmd.Env, "LANG=en_US.UTF-8")
67-
out, err := cmd.CombinedOutput()
67+
out, err := cmd.Output()
6868
if err != nil {
6969
if _, ok := err.(*exec.ExitError); !ok {
7070
return "", fmt.Errorf("failed to run diff -u %v %v: %v\n%v", fileA.Name(), fileB.Name(), err, string(out))

internal/gcimporter/gcimporter_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ func compilePkg(t *testing.T, dirname, filename, outdirname string, packagefiles
8484
importreldir := strings.ReplaceAll(outdirname, string(os.PathSeparator), "/")
8585
cmd := exec.Command("go", "tool", "compile", "-p", pkg, "-D", importreldir, "-importcfg", importcfgfile, "-o", outname, filename)
8686
cmd.Dir = dirname
87-
out, err := cmd.CombinedOutput()
88-
if err != nil {
87+
if out, err := cmd.CombinedOutput(); err != nil {
8988
t.Logf("%s", out)
9089
t.Fatalf("go tool compile %s failed: %s", filename, err)
9190
}

internal/testenv/testenv.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func hasTool(tool string) error {
8383
// GOROOT. Otherwise, 'some/path/go test ./...' will test against some
8484
// version of the 'go' binary other than 'some/path/go', which is almost
8585
// certainly not what the user intended.
86-
out, err := exec.Command(tool, "env", "GOROOT").CombinedOutput()
86+
out, err := exec.Command(tool, "env", "GOROOT").Output()
8787
if err != nil {
8888
checkGoBuild.err = err
8989
return
@@ -141,7 +141,7 @@ func cgoEnabled(bypassEnvironment bool) (bool, error) {
141141
if bypassEnvironment {
142142
cmd.Env = append(append([]string(nil), os.Environ()...), "CGO_ENABLED=")
143143
}
144-
out, err := cmd.CombinedOutput()
144+
out, err := cmd.Output()
145145
if err != nil {
146146
return false, err
147147
}
@@ -199,6 +199,9 @@ func NeedsTool(t testing.TB, tool string) {
199199

200200
t.Helper()
201201
if allowMissingTool(tool) {
202+
// TODO(adonovan): might silently skipping because of
203+
// (e.g.) mismatched go env GOROOT and runtime.GOROOT
204+
// risk some users not getting the coverage they expect?
202205
t.Skipf("skipping because %s tool not available: %v", tool, err)
203206
} else {
204207
t.Fatalf("%s tool not available: %v", tool, err)

present/parse_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func diff(prefix string, name1 string, b1 []byte, name2 string, b2 []byte) ([]by
7979
cmd = "/bin/ape/diff"
8080
}
8181

82-
data, err := exec.Command(cmd, "-u", f1, f2).CombinedOutput()
82+
data, err := exec.Command(cmd, "-u", f1, f2).Output()
8383
if len(data) > 0 {
8484
// diff exits with a non-zero status when the files don't match.
8585
// Ignore that failure as long as we get output.

refactor/rename/rename.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ func diff(filename string, content []byte) error {
588588
}
589589
defer os.Remove(renamed)
590590

591-
diff, err := exec.Command(DiffCmd, "-u", filename, renamed).CombinedOutput()
591+
diff, err := exec.Command(DiffCmd, "-u", filename, renamed).Output()
592592
if len(diff) > 0 {
593593
// diff exits with a non-zero status when the files don't match.
594594
// Ignore that failure as long as we get output.

0 commit comments

Comments
 (0)