internal/testenv: use 'go env CGO_ENABLED' instead of a build constraint

A build constraint reports whether the test binary was compiled with
cgo enabled, but that doesn't necessarily imply that cgo can be used
in the environment in which the test binary is run.

In particular, cross-compiled builders (such as Android) may compile
the test binaries on the host with CGO enabled but not provide a C
toolchain on the device that runs the test.

For #58775.

Change-Id: Ibf2f44c9e956cd3fa898c3de67af4449e8ef2dd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/472215
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
This commit is contained in:
Bryan C. Mills 2023-02-28 19:16:54 +00:00 committed by Gopher Robot
parent ea75b9458f
commit a5f3cb6f75
2 changed files with 54 additions and 35 deletions

View File

@ -193,28 +193,40 @@ func GOROOT(t testing.TB) string {
// GoTool reports the path to the Go tool.
func GoTool() (string, error) {
if !HasGoBuild() {
return "", errors.New("platform cannot run go tool")
}
var exeSuffix string
if runtime.GOOS == "windows" {
exeSuffix = ".exe"
}
goroot, err := findGOROOT()
if err != nil {
return "", fmt.Errorf("cannot find go tool: %w", err)
}
path := filepath.Join(goroot, "bin", "go"+exeSuffix)
if _, err := os.Stat(path); err == nil {
return path, nil
}
goBin, err := exec.LookPath("go" + exeSuffix)
if err != nil {
return "", errors.New("cannot find go tool: " + err.Error())
}
return goBin, nil
goToolOnce.Do(func() {
goToolPath, goToolErr = func() (string, error) {
if !HasGoBuild() {
return "", errors.New("platform cannot run go tool")
}
var exeSuffix string
if runtime.GOOS == "windows" {
exeSuffix = ".exe"
}
goroot, err := findGOROOT()
if err != nil {
return "", fmt.Errorf("cannot find go tool: %w", err)
}
path := filepath.Join(goroot, "bin", "go"+exeSuffix)
if _, err := os.Stat(path); err == nil {
return path, nil
}
goBin, err := exec.LookPath("go" + exeSuffix)
if err != nil {
return "", errors.New("cannot find go tool: " + err.Error())
}
return goBin, nil
}()
})
return goToolPath, goToolErr
}
var (
goToolOnce sync.Once
goToolPath string
goToolErr error
)
// HasSrc reports whether the entire source tree is available under GOROOT.
func HasSrc() bool {
switch runtime.GOOS {
@ -242,16 +254,34 @@ func MustHaveExternalNetwork(t testing.TB) {
}
}
var haveCGO bool
// HasCGO reports whether the current system can use cgo.
func HasCGO() bool {
return haveCGO
hasCgoOnce.Do(func() {
goTool, err := GoTool()
if err != nil {
return
}
cmd := exec.Command(goTool, "env", "CGO_ENABLED")
out, err := cmd.Output()
if err != nil {
panic(fmt.Sprintf("%v: %v", cmd, out))
}
hasCgo, err = strconv.ParseBool(string(bytes.TrimSpace(out)))
if err != nil {
panic(fmt.Sprintf("%v: non-boolean output %q", cmd, out))
}
})
return hasCgo
}
var (
hasCgoOnce sync.Once
hasCgo bool
)
// MustHaveCGO calls t.Skip if cgo is not available.
func MustHaveCGO(t testing.TB) {
if !haveCGO {
if !HasCGO() {
t.Skipf("skipping test: no cgo")
}
}

View File

@ -1,11 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build cgo
package testenv
func init() {
haveCGO = true
}