Skip to content

Commit 7f38067

Browse files
ianlancetaylorgopherbot
authored andcommitted
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>
1 parent e8543a6 commit 7f38067

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

api/next/52600.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg testing, func Testing() bool #52600

src/cmd/go/internal/load/test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
253253
pxtest.collectDeps()
254254
}
255255

256+
// Arrange for testing.Testing to report true.
257+
ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
258+
gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
259+
256260
// Build main package.
257261
pmain = &Package{
258262
PackagePublic: PackagePublic{
@@ -269,8 +273,8 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
269273
BuildInfo: p.Internal.BuildInfo,
270274
Asmflags: p.Internal.Asmflags,
271275
Gcflags: p.Internal.Gcflags,
272-
Ldflags: p.Internal.Ldflags,
273-
Gccgoflags: p.Internal.Gccgoflags,
276+
Ldflags: ldflags,
277+
Gccgoflags: gccgoflags,
274278
OrigImportPath: p.Internal.OrigImportPath,
275279
PGOProfile: p.Internal.PGOProfile,
276280
},

src/testing/testing.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,22 @@ func Short() bool {
644644
return *short
645645
}
646646

647+
// testBinary is set by cmd/go to "1" if this is a binary built by "go test".
648+
// The value is set to "1" by a -X option to cmd/link. We assume that
649+
// because this is possible, the compiler will not optimize testBinary
650+
// into a constant on the basis that it is an unexported package-scope
651+
// variable that is never changed. If the compiler ever starts implementing
652+
// such an optimization, we will need some technique to mark this variable
653+
// as "changed by a cmd/link -X option".
654+
var testBinary = "0"
655+
656+
// Testing reports whether the current code is being run in a test.
657+
// This will report true in programs created by "go test",
658+
// false in programs created by "go build".
659+
func Testing() bool {
660+
return testBinary == "1"
661+
}
662+
647663
// CoverMode reports what the test coverage mode is set to. The
648664
// values are "set", "count", or "atomic". The return value will be
649665
// empty if test coverage is not enabled.

src/testing/testing_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package testing_test
66

77
import (
8+
"bytes"
9+
"internal/testenv"
810
"os"
911
"path/filepath"
1012
"testing"
@@ -232,3 +234,62 @@ func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) {
232234
})
233235
})
234236
}
237+
238+
// testingTrueInInit is part of TestTesting.
239+
var testingTrueInInit = false
240+
241+
// testingTrueInPackageVarInit is part of TestTesting.
242+
var testingTrueInPackageVarInit = testing.Testing()
243+
244+
// init is part of TestTesting.
245+
func init() {
246+
if testing.Testing() {
247+
testingTrueInInit = true
248+
}
249+
}
250+
251+
var testingProg = `
252+
package main
253+
254+
import (
255+
"fmt"
256+
"testing"
257+
)
258+
259+
func main() {
260+
fmt.Println(testing.Testing())
261+
}
262+
`
263+
264+
func TestTesting(t *testing.T) {
265+
if !testing.Testing() {
266+
t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
267+
}
268+
if !testingTrueInInit {
269+
t.Errorf("testing.Testing() called by init function == %t, want %t", testingTrueInInit, true)
270+
}
271+
if !testingTrueInPackageVarInit {
272+
t.Errorf("testing.Testing() variable initialized as %t, want %t", testingTrueInPackageVarInit, true)
273+
}
274+
275+
if testing.Short() {
276+
t.Skip("skipping building a binary in short mode")
277+
}
278+
testenv.MustHaveGoRun(t)
279+
280+
fn := filepath.Join(t.TempDir(), "x.go")
281+
if err := os.WriteFile(fn, []byte(testingProg), 0644); err != nil {
282+
t.Fatal(err)
283+
}
284+
285+
cmd := testenv.Command(t, testenv.GoToolPath(t), "run", fn)
286+
out, err := cmd.CombinedOutput()
287+
if err != nil {
288+
t.Fatalf("%v failed: %v\n%s", cmd, err, out)
289+
}
290+
291+
s := string(bytes.TrimSpace(out))
292+
if s != "false" {
293+
t.Errorf("in non-test testing.Test() returned %q, want %q", s, "false")
294+
}
295+
}

0 commit comments

Comments
 (0)