1
0
mirror of https://github.com/golang/go synced 2024-11-26 06:27:58 -07:00

testing: add Testing function

The Testing function reports whether the program is a test created
by "go test".

Fixes #52600

Change-Id: Ie0fff7c7dfdfdf997c18b4b6112632600b327cc8
Reviewed-on: https://go-review.googlesource.com/c/go/+/475496
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
Ian Lance Taylor 2023-03-08 16:16:59 -08:00 committed by Gopher Robot
parent e8543a6fa6
commit 7f38067acb
4 changed files with 84 additions and 2 deletions

1
api/next/52600.txt Normal file
View File

@ -0,0 +1 @@
pkg testing, func Testing() bool #52600

View File

@ -253,6 +253,10 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
pxtest.collectDeps() pxtest.collectDeps()
} }
// Arrange for testing.Testing to report true.
ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
// Build main package. // Build main package.
pmain = &Package{ pmain = &Package{
PackagePublic: PackagePublic{ PackagePublic: PackagePublic{
@ -269,8 +273,8 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
BuildInfo: p.Internal.BuildInfo, BuildInfo: p.Internal.BuildInfo,
Asmflags: p.Internal.Asmflags, Asmflags: p.Internal.Asmflags,
Gcflags: p.Internal.Gcflags, Gcflags: p.Internal.Gcflags,
Ldflags: p.Internal.Ldflags, Ldflags: ldflags,
Gccgoflags: p.Internal.Gccgoflags, Gccgoflags: gccgoflags,
OrigImportPath: p.Internal.OrigImportPath, OrigImportPath: p.Internal.OrigImportPath,
PGOProfile: p.Internal.PGOProfile, PGOProfile: p.Internal.PGOProfile,
}, },

View File

@ -644,6 +644,22 @@ func Short() bool {
return *short return *short
} }
// testBinary is set by cmd/go to "1" if this is a binary built by "go test".
// The value is set to "1" by a -X option to cmd/link. We assume that
// because this is possible, the compiler will not optimize testBinary
// into a constant on the basis that it is an unexported package-scope
// variable that is never changed. If the compiler ever starts implementing
// such an optimization, we will need some technique to mark this variable
// as "changed by a cmd/link -X option".
var testBinary = "0"
// Testing reports whether the current code is being run in a test.
// This will report true in programs created by "go test",
// false in programs created by "go build".
func Testing() bool {
return testBinary == "1"
}
// CoverMode reports what the test coverage mode is set to. The // CoverMode reports what the test coverage mode is set to. The
// values are "set", "count", or "atomic". The return value will be // values are "set", "count", or "atomic". The return value will be
// empty if test coverage is not enabled. // empty if test coverage is not enabled.

View File

@ -5,6 +5,8 @@
package testing_test package testing_test
import ( import (
"bytes"
"internal/testenv"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -232,3 +234,62 @@ func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) {
}) })
}) })
} }
// testingTrueInInit is part of TestTesting.
var testingTrueInInit = false
// testingTrueInPackageVarInit is part of TestTesting.
var testingTrueInPackageVarInit = testing.Testing()
// init is part of TestTesting.
func init() {
if testing.Testing() {
testingTrueInInit = true
}
}
var testingProg = `
package main
import (
"fmt"
"testing"
)
func main() {
fmt.Println(testing.Testing())
}
`
func TestTesting(t *testing.T) {
if !testing.Testing() {
t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
}
if !testingTrueInInit {
t.Errorf("testing.Testing() called by init function == %t, want %t", testingTrueInInit, true)
}
if !testingTrueInPackageVarInit {
t.Errorf("testing.Testing() variable initialized as %t, want %t", testingTrueInPackageVarInit, true)
}
if testing.Short() {
t.Skip("skipping building a binary in short mode")
}
testenv.MustHaveGoRun(t)
fn := filepath.Join(t.TempDir(), "x.go")
if err := os.WriteFile(fn, []byte(testingProg), 0644); err != nil {
t.Fatal(err)
}
cmd := testenv.Command(t, testenv.GoToolPath(t), "run", fn)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("%v failed: %v\n%s", cmd, err, out)
}
s := string(bytes.TrimSpace(out))
if s != "false" {
t.Errorf("in non-test testing.Test() returned %q, want %q", s, "false")
}
}